9 #include <top/modules/TOPInterimFENtuple/TOPInterimFENtupleModule.h>
11 #include <framework/datastore/StoreObjPtr.h>
12 #include <framework/datastore/StoreArray.h>
14 #include <framework/dataobjects/EventMetaData.h>
15 #include <top/dataobjects/TOPDigit.h>
16 #include <top/dataobjects/TOPRawDigit.h>
17 #include <top/dataobjects/TOPRawWaveform.h>
18 #include <top/dataobjects/TOPInterimFEInfo.h>
19 #include <top/dataobjects/TOPProductionEventDebug.h>
20 #include <rawdata/dataobjects/RawTOP.h>
42 setDescription(
"Create ntuple mainly from TOPDigit with double pulse identification. "
43 "Data taken with both InterimFE FW and production FW are available. (since Jan, 2017)");
45 addParam(
"calibrationChannel", m_calibrationChannel,
"asic channel # where calibration pulses routed",
47 addParam(
"saveWaveform", m_saveWaveform,
"whether to save waveform data or not",
49 addParam(
"useDoublePulse", m_useDoublePulse,
50 "set true when you require both of double calibration pulses for reference timing. You need to enable offline feature extraction.",
54 addParam(
"minHeightFirstCalPulse", m_calibrationPulseThreshold1,
"pulse height threshold for the first cal. pulse",
56 addParam(
"minHeightSecondCalPulse", m_calibrationPulseThreshold2,
"pulse height threshold for the second cal. pulse",
58 addParam(
"nominalDeltaT", m_calibrationPulseInterval,
"nominal DeltaT (time interval of the double calibration pulses) [ns]",
60 addParam(
"nominalDeltaTRange", m_calibrationPulseIntervalRange,
61 "acceptable DeltaT shift from the noinal value before calibration [ns]",
63 addParam(
"globalRefSlotNum", m_globalRefSlotNum,
64 "slot number where a global reference asic exists. slot01-asic0 (pixelId=1-8) is default.", 1);
65 addParam(
"globalRefAsicNum", m_globalRefAsicNum,
66 "asic number defined as int((pixelId-1)/8) of a global reference asic", 0);
68 addParam(
"timePerWin", m_timePerWin,
"time interval of a single window (=64 samples) [ns]", (
float)23.581939);
71 TOPInterimFENtupleModule::~TOPInterimFENtupleModule() {}
73 void TOPInterimFENtupleModule::initialize()
91 void TOPInterimFENtupleModule::defineHisto()
94 m_tree =
new TTree(
"tree",
"TTree for generator output");
96 std::ostringstream nModuleStr;
97 nModuleStr <<
"[" << c_NModule <<
"]";
99 m_tree->Branch(
"nHit", &m_nHit,
"nHit/I");
100 m_tree->Branch(
"eventNum", &m_eventNum,
"eventNum/i");
101 m_tree->Branch(
"eventNumCopper", m_eventNumCopper,
102 std::string(std::string(
"eventNumCopper") + nModuleStr.str() +
"/i").c_str());
103 m_tree->Branch(
"ttuTime", m_ttuTime,
104 std::string(std::string(
"ttuTime") + nModuleStr.str() +
"/i").c_str());
105 m_tree->Branch(
"ttcTime", m_ttcTime,
106 std::string(std::string(
"ttcTime") + nModuleStr.str() +
"/i").c_str());
107 m_tree->Branch(
"slotNum", m_slotNum,
"slotNum[nHit]/S");
108 m_tree->Branch(
"pixelId", m_pixelId,
"pixelId[nHit]/S");
109 m_tree->Branch(
"channelId", m_channelId,
"channel[nHit]/S");
110 m_tree->Branch(
"isCalCh", m_isCalCh,
"isCalCh[nHit]/O");
111 m_tree->Branch(
"winNum", m_winNum,
"winNum[nHit]/S");
112 m_tree->Branch(
"eventWinNum", m_eventWinNum,
"eventWinNum[nHit]/S");
113 m_tree->Branch(
"trigWinNum", m_trigWinNum,
"trigWinNum[nHit]/S");
114 m_tree->Branch(
"revo9Counter", m_revo9Counter,
"revo9Counter[nHit]/S");
115 m_tree->Branch(
"windowsInOrder", m_windowsInOrder,
"windowsInOrder[nHit]/O");
116 m_tree->Branch(
"hitQuality", m_hitQuality,
"hitQuality[nHit]/b");
117 m_tree->Branch(
"time", m_time,
"time[nHit]/F");
118 m_tree->Branch(
"rawTime", m_rawTime,
"rawTime[nHit]/F");
119 m_tree->Branch(
"refTime", m_refTime,
"refTime[nHit]/F");
120 m_tree->Branch(
"globalRefTime", &m_globalRefTime,
"globalRefTime/F");
121 m_tree->Branch(
"sample", m_sample,
"sample[nHit]/s");
122 m_tree->Branch(
"height", m_height,
"height[nHit]/F");
123 m_tree->Branch(
"integral", m_integral,
"integral[nHit]/F");
124 m_tree->Branch(
"width", m_width,
"width[nHit]/F");
125 m_tree->Branch(
"peakSample", m_peakSample,
"peakSampe[nHit]/s");
126 m_tree->Branch(
"offlineFlag", m_offlineFlag,
"offlineFlag[nHit]/B");
127 m_tree->Branch(
"nHitOfflineFE", m_nHitOfflineFE,
"nHitOfflineFE[nHit]/S");
128 std::ostringstream brstr[2];
129 brstr[0] <<
"winNumList[nHit][" << c_NWindow <<
"]/S";
130 m_tree->Branch(
"winNumList", m_winNumList, brstr[0].str().c_str());
131 if (m_saveWaveform) {
132 brstr[1] <<
"waveform[nHit][" << c_NWaveformSample <<
"]/S";
133 m_tree->Branch(
"waveform", m_waveform, brstr[1].str().c_str());
135 m_tree->Branch(
"waveformStartSample", m_waveformStartSample,
"waveformStartSample[nHit]/S");
136 m_tree->Branch(
"nWaveformSample", m_nWaveformSample,
"nWaveformSample[nHit]/s");
138 m_tree->Branch(
"nFEHeader", &m_nFEHeader,
"nFEHeader/S");
139 m_tree->Branch(
"nEmptyFEHeader", &m_nEmptyFEHeader,
"nEmptyFEHeader/S");
140 m_tree->Branch(
"nWaveform", &m_nWaveform,
"nWaveform/S");
141 m_tree->Branch(
"errorFlag", &m_errorFlag,
"errorFlag/i");
142 m_tree->Branch(
"eventErrorFlag", &m_eventErrorFlag,
"eventErrorFlag/i");
144 m_tree->Branch(
"nDebugInfo", &m_nDebugInfo,
"nDebugInfo/I");
145 m_tree->Branch(
"scordCtime", m_scrodCtime,
"scrodCtime[nDebugInfo]/s");
146 m_tree->Branch(
"phase", m_phase,
"phase[nDebugInfo]/s");
147 m_tree->Branch(
"asicMask", m_asicMask,
"asicMask[nDebugInfo]/s");
148 m_tree->Branch(
"eventQueuDepth", m_eventQueuDepth,
"eventQueuDepth[nDebugInfo]/s");
149 m_tree->Branch(
"eventNumberByte", m_eventNumberByte,
"eventNumberByte[nDebugInfo]/s");
152 void TOPInterimFENtupleModule::beginRun()
156 void TOPInterimFENtupleModule::event()
161 m_nEmptyFEHeader = 0;
169 for (
int iSlot = 0 ; iSlot < c_NModule ; iSlot++) {
170 m_eventNumCopper[iSlot] = -1;
171 m_ttuTime[iSlot] = -1;
172 m_ttcTime[iSlot] = -1;
175 short trigCtime = -1;
176 for (
auto& rawTOP : rawTOPs) {
177 if (iSlotTTC >= c_NModule) {
178 B2WARNING(
"too many TTC information");
181 m_eventNumCopper[iSlotTTC] = rawTOP.GetEveNo(0);
182 m_ttuTime[iSlotTTC] = rawTOP.GetTTUtime(0);
183 m_ttcTime[iSlotTTC] = rawTOP.GetTTCtime(0);
186 trigCtime = ((((long)m_ttcTime[iSlotTTC] + (
long)(m_ttuTime[iSlotTTC] - 1524741300) * 127216000) % 11520) % 3840) % 1284;
190 std::map<short, short> nHitOfflineFEMap;
191 static std::set<short> noisyChannelBlackListSet;
192 UInt_t EventNum = EventMetaDataPtr->getEvent();
193 m_eventNum = EventNum;
194 m_eventErrorFlag = EventMetaDataPtr->getErrorFlag();
195 for (
const auto& digit : digits) {
197 if (m_nHit >= c_NMaxHitEvent) {
198 B2WARNING(
"TOPInterimFENtuple : too many hits found (>=" << c_NMaxHitEvent
199 <<
"), EventNo = " << EventNum <<
", no more hits are recorded.");
203 m_slotNum[m_nHit] = digit.getModuleID();
204 m_pixelId[m_nHit] = (short)digit.getPixelID();
205 m_channelId[m_nHit] = (short)digit.getChannel();
206 m_isCalCh[m_nHit] = (digit.getASICChannel() == m_calibrationChannel);
207 m_winNum[m_nHit] = -1;
208 m_eventWinNum[m_nHit] = (short)digit.getFirstWindow();
209 m_trigWinNum[m_nHit] = trigCtime;
210 m_revo9Counter[m_nHit] = -1;
211 m_hitQuality[m_nHit] = (
unsigned char)digit.getHitQuality();
212 m_isReallyJunk[m_nHit] =
false;
213 m_windowsInOrder[m_nHit] =
true;
214 m_rawTime[m_nHit] = digit.getRawTime();
215 m_time[m_nHit] = digit.getTime() + m_winNum[m_nHit] * m_timePerWin;
216 m_sample[m_nHit] = TMath::FloorNint(m_rawTime[m_nHit] + m_winNum[m_nHit] * c_NSamplePerWindow) % c_NSampleTBC;
217 m_height[m_nHit] = digit.getPulseHeight();
218 m_integral[m_nHit] = digit.getIntegral();
219 m_width[m_nHit] = digit.getPulseWidth();
220 m_peakSample[m_nHit] = -1;
221 for (
int iWindow = 0 ; iWindow < c_NWindow ; iWindow++)
222 m_winNumList[m_nHit][iWindow] = -32767;
223 for (
int iSample = 0 ; iSample < c_NWaveformSample ; iSample++)
224 m_waveform[m_nHit][iSample] = -32767;
225 m_waveformStartSample[m_nHit] = -1;
227 short globalChannelId = m_pixelId[m_nHit] - 1 + (m_slotNum[m_nHit] - 1) * c_NPixelPerModule;
228 if (nHitOfflineFEMap.count(globalChannelId) == 0) nHitOfflineFEMap[globalChannelId] = 0;
229 else if (nHitOfflineFEMap[globalChannelId] > c_NMaxHitPerChannel) {
230 if (noisyChannelBlackListSet.count(globalChannelId) == 0) {
232 noisyChannelBlackListSet.insert(globalChannelId);
233 B2WARNING(
"TOPInterimFENtuple : noisy channel with too many hits (slotNum="
234 << (globalChannelId / c_NPixelPerModule + 1) <<
", pixelId = "
235 << (globalChannelId / c_NPixelPerModule + 1) <<
") ");
240 const auto* rawDigit = digit.getRelated<
TOPRawDigit>();
243 m_revo9Counter[m_nHit] = rawDigit->getRevo9Counter();
244 m_peakSample[m_nHit] = rawDigit->getSamplePeak();
245 m_windowsInOrder[m_nHit] = rawDigit->areWindowsInOrder();
246 if (rawDigit->getDataType() == TOPRawDigit::c_Interim)
247 m_trigWinNum[m_nHit] = (
short)rawDigit->getLastWriteAddr();
248 if (rawDigit->isPedestalJump()) m_isReallyJunk[m_nHit] =
true;
251 if (rawDigit->isMadeOffline()) {
254 nHitOfflineFEMap[globalChannelId]++;
255 m_offlineFlag[m_nHit] = nHitOfflineFEMap[globalChannelId];
257 m_offlineFlag[m_nHit] = 0;
260 unsigned nSampleWfm = waveform->
getSize();
261 unsigned nSample = TMath::Min((UShort_t)nSampleWfm, (UShort_t)c_NWaveformSample);
262 if (nSample > c_NWaveformSample)
263 B2WARNING(
"TOPInterimFENtuple: too many waveform samples in TOPRawWaveform : " << nSampleWfm <<
", only first " << nSample <<
265 for (
unsigned iSample = 0 ; iSample < nSample ; iSample++)
266 m_waveform[m_nHit][iSample] = waveform->getWaveform()[iSample];
267 m_waveformStartSample[m_nHit] = (short)waveform->getStartSample();
268 m_nWaveformSample[m_nHit] = nSampleWfm;
271 for (
const auto& window : waveform->getStorageWindows()) {
272 if (iWin < c_NWindow)
273 m_winNumList[m_nHit][iWin] = window;
275 B2WARNING(
"TOPInterimFENtuple: too many windows were found");
282 else m_offlineFlag[m_nHit] = -1;
284 B2WARNING(
"TOPInterimFENtuple : no TOPRawDigit object found!");
285 m_offlineFlag[m_nHit] = -100;
292 for (
int iHit = 0 ; iHit < m_nHit ; iHit++) {
294 short globalChannelId = m_pixelId[iHit] - 1 + (m_slotNum[iHit] - 1) * c_NPixelPerModule;
295 m_nHitOfflineFE[iHit] = nHitOfflineFEMap[globalChannelId];
300 for (
const auto& info : infos) {
301 m_nFEHeader += info.getFEHeadersCount();
302 m_nEmptyFEHeader += info.getEmptyFEHeadersCount();
303 m_nWaveform += info.getWaveformsCount();
304 m_errorFlag |= info.getErrorFlags();
309 for (
const auto& prodDebug : prodDebugs) {
310 m_scrodCtime[m_nDebugInfo] = prodDebug.getCtime();
311 m_phase[m_nDebugInfo] = prodDebug.getPhase();
312 m_asicMask[m_nDebugInfo] = prodDebug.getAsicMask();
313 m_eventQueuDepth[m_nDebugInfo] = prodDebug.getEventQueueDepth();
314 m_eventNumberByte[m_nDebugInfo] = prodDebug.getEventNumberByte();
319 getReferenceTiming();
324 void TOPInterimFENtupleModule::endRun()
328 void TOPInterimFENtupleModule::terminate()
332 void TOPInterimFENtupleModule::getReferenceTiming()
334 static short globalRefAsic = m_globalRefAsicNum + 100 * m_globalRefSlotNum;
335 m_globalRefTime = -99999;
336 std::map<short, short> iRefHitMap;
337 for (
int iHit = 0 ; iHit < m_nHit ; iHit++) {
338 if (!m_isCalCh[iHit])
continue;
339 short reducedPixelId = (m_pixelId[iHit] - 1) / 8 + 100 * m_slotNum[iHit];
340 if (iRefHitMap.count(reducedPixelId) > 0)
continue;
342 if (!m_useDoublePulse) {
343 iRefHitMap[reducedPixelId] = iHit;
347 std::vector<short> iHitVec;
348 iHitVec.push_back(iHit);
349 for (
int jHit = iHit + 1 ; jHit < m_nHit ; jHit++) {
350 short jReducedPixelId = (m_pixelId[jHit] - 1) / 8 + 100 * m_slotNum[jHit];
351 if (m_isCalCh[jHit] && jReducedPixelId == reducedPixelId) iHitVec.push_back(jHit);
355 for (
unsigned int iVec = 0 ; iVec < iHitVec.size() ; iVec++) {
356 int jHit = iHitVec[iVec];
357 for (
unsigned int jVec = iVec + 1 ; jVec < iHitVec.size() ; jVec++) {
358 int kHit = iHitVec[jVec];
359 float timediff = m_time[kHit] - m_time[jHit];
360 if (m_height[jHit] > m_calibrationPulseThreshold1
361 && m_height[kHit] > m_calibrationPulseThreshold2
362 && TMath::Abs(timediff - m_calibrationPulseInterval) < m_calibrationPulseIntervalRange) {
364 iRefHitMap[reducedPixelId] = jHit;
365 m_hitQuality[jHit] += 100;
366 m_hitQuality[kHit] += 200;
371 else if (timediff < 0 && m_height[kHit] > m_calibrationPulseThreshold1
372 && m_height[jHit] > m_calibrationPulseThreshold2
373 && TMath::Abs(timediff + m_calibrationPulseInterval) < m_calibrationPulseIntervalRange) {
375 iRefHitMap[reducedPixelId] = kHit;
376 m_hitQuality[kHit] += 100;
377 m_hitQuality[jHit] += 200;
387 for (
int iHit = 0 ; iHit < m_nHit ; iHit++) {
388 short reducedPixelId = (m_pixelId[iHit] - 1) / 8 + 100 * m_slotNum[iHit];
389 if (iRefHitMap.count(reducedPixelId) > 0) {
390 int iRef = iRefHitMap[reducedPixelId];
391 m_refTime[iHit] = m_time[iRef];
392 if (reducedPixelId == globalRefAsic) m_globalRefTime = m_time[iRef];
393 if (!m_isReallyJunk[iHit] && m_hitQuality[iRef] >= 100) {
394 m_hitQuality[iHit] += 10;
396 }
else m_refTime[iHit] = -99999;
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Accessor to arrays stored in the data store.
Type-safe access to single objects in the data store.
Module to produce ntuple from TOPDigits and TOPRawDigits.
Class to store unpacked raw data (hits in feature-extraction format) It provides also calculation of ...
unsigned getASICWindow() const
Returns ASIC storage window number.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.