11 #include <top/modules/TOPInterimFENtuple/TOPInterimFENtupleModule.h>
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/datastore/StoreArray.h>
16 #include <framework/dataobjects/EventMetaData.h>
17 #include <top/dataobjects/TOPDigit.h>
18 #include <top/dataobjects/TOPRawDigit.h>
19 #include <top/dataobjects/TOPRawWaveform.h>
20 #include <top/dataobjects/TOPInterimFEInfo.h>
21 #include <top/dataobjects/TOPProductionEventDebug.h>
22 #include <rawdata/dataobjects/RawTOP.h>
44 setDescription(
"Create ntuple mainly from TOPDigit with double pulse identification. "
45 "Data taken with both InterimFE FW and production FW are available. (since Jan, 2017)");
47 addParam(
"calibrationChannel", m_calibrationChannel,
"asic channel # where calibration pulses routed",
49 addParam(
"saveWaveform", m_saveWaveform,
"whether to save waveform data or not",
51 addParam(
"useDoublePulse", m_useDoublePulse,
52 "set true when you require both of double calibration pulses for reference timing. You need to enable offline feature extraction.",
56 addParam(
"minHeightFirstCalPulse", m_calibrationPulseThreshold1,
"pulse height threshold for the first cal. pulse",
58 addParam(
"minHeightSecondCalPulse", m_calibrationPulseThreshold2,
"pulse height threshold for the second cal. pulse",
60 addParam(
"nominalDeltaT", m_calibrationPulseInterval,
"nominal DeltaT (time interval of the double calibration pulses) [ns]",
62 addParam(
"nominalDeltaTRange", m_calibrationPulseIntervalRange,
63 "acceptable DeltaT shift from the noinal value before calibration [ns]",
65 addParam(
"globalRefSlotNum", m_globalRefSlotNum,
66 "slot number where a global reference asic exists. slot01-asic0 (pixelId=1-8) is default.", 1);
67 addParam(
"globalRefAsicNum", m_globalRefAsicNum,
68 "asic number defined as int((pixelId-1)/8) of a global reference asic", 0);
70 addParam(
"timePerWin", m_timePerWin,
"time interval of a single window (=64 samples) [ns]", (
float)23.581939);
73 TOPInterimFENtupleModule::~TOPInterimFENtupleModule() {}
75 void TOPInterimFENtupleModule::initialize()
82 rawDigits.isRequired();
88 prodDebugs.isRequired();
90 waveforms.isRequired();
93 void TOPInterimFENtupleModule::defineHisto()
96 m_tree =
new TTree(
"tree",
"TTree for generator output");
98 std::ostringstream nModuleStr;
99 nModuleStr <<
"[" << c_NModule <<
"]";
101 m_tree->Branch(
"nHit", &m_nHit,
"nHit/I");
102 m_tree->Branch(
"eventNum", &m_eventNum,
"eventNum/i");
103 m_tree->Branch(
"eventNumCopper", m_eventNumCopper,
104 std::string(std::string(
"eventNumCopper") + nModuleStr.str() +
"/i").c_str());
105 m_tree->Branch(
"ttuTime", m_ttuTime,
106 std::string(std::string(
"ttuTime") + nModuleStr.str() +
"/i").c_str());
107 m_tree->Branch(
"ttcTime", m_ttcTime,
108 std::string(std::string(
"ttcTime") + nModuleStr.str() +
"/i").c_str());
109 m_tree->Branch(
"slotNum", m_slotNum,
"slotNum[nHit]/S");
110 m_tree->Branch(
"pixelId", m_pixelId,
"pixelId[nHit]/S");
111 m_tree->Branch(
"channelId", m_channelId,
"channel[nHit]/S");
112 m_tree->Branch(
"isCalCh", m_isCalCh,
"isCalCh[nHit]/O");
113 m_tree->Branch(
"winNum", m_winNum,
"winNum[nHit]/S");
114 m_tree->Branch(
"eventWinNum", m_eventWinNum,
"eventWinNum[nHit]/S");
115 m_tree->Branch(
"trigWinNum", m_trigWinNum,
"trigWinNum[nHit]/S");
116 m_tree->Branch(
"revo9Counter", m_revo9Counter,
"revo9Counter[nHit]/S");
117 m_tree->Branch(
"windowsInOrder", m_windowsInOrder,
"windowsInOrder[nHit]/O");
118 m_tree->Branch(
"hitQuality", m_hitQuality,
"hitQuality[nHit]/b");
119 m_tree->Branch(
"time", m_time,
"time[nHit]/F");
120 m_tree->Branch(
"rawTime", m_rawTime,
"rawTime[nHit]/F");
121 m_tree->Branch(
"refTime", m_refTime,
"refTime[nHit]/F");
122 m_tree->Branch(
"globalRefTime", &m_globalRefTime,
"globalRefTime/F");
123 m_tree->Branch(
"sample", m_sample,
"sample[nHit]/s");
124 m_tree->Branch(
"height", m_height,
"height[nHit]/F");
125 m_tree->Branch(
"integral", m_integral,
"integral[nHit]/F");
126 m_tree->Branch(
"width", m_width,
"width[nHit]/F");
127 m_tree->Branch(
"peakSample", m_peakSample,
"peakSampe[nHit]/s");
128 m_tree->Branch(
"offlineFlag", m_offlineFlag,
"offlineFlag[nHit]/B");
129 m_tree->Branch(
"nHitOfflineFE", m_nHitOfflineFE,
"nHitOfflineFE[nHit]/S");
130 std::ostringstream brstr[2];
131 brstr[0] <<
"winNumList[nHit][" << c_NWindow <<
"]/S";
132 m_tree->Branch(
"winNumList", m_winNumList, brstr[0].str().c_str());
133 if (m_saveWaveform) {
134 brstr[1] <<
"waveform[nHit][" << c_NWaveformSample <<
"]/S";
135 m_tree->Branch(
"waveform", m_waveform, brstr[1].str().c_str());
137 m_tree->Branch(
"waveformStartSample", m_waveformStartSample,
"waveformStartSample[nHit]/S");
138 m_tree->Branch(
"nWaveformSample", m_nWaveformSample,
"nWaveformSample[nHit]/s");
140 m_tree->Branch(
"nFEHeader", &m_nFEHeader,
"nFEHeader/S");
141 m_tree->Branch(
"nEmptyFEHeader", &m_nEmptyFEHeader,
"nEmptyFEHeader/S");
142 m_tree->Branch(
"nWaveform", &m_nWaveform,
"nWaveform/S");
143 m_tree->Branch(
"errorFlag", &m_errorFlag,
"errorFlag/i");
144 m_tree->Branch(
"eventErrorFlag", &m_eventErrorFlag,
"eventErrorFlag/i");
146 m_tree->Branch(
"nDebugInfo", &m_nDebugInfo,
"nDebugInfo/I");
147 m_tree->Branch(
"scordCtime", m_scrodCtime,
"scrodCtime[nDebugInfo]/s");
148 m_tree->Branch(
"phase", m_phase,
"phase[nDebugInfo]/s");
149 m_tree->Branch(
"asicMask", m_asicMask,
"asicMask[nDebugInfo]/s");
150 m_tree->Branch(
"eventQueuDepth", m_eventQueuDepth,
"eventQueuDepth[nDebugInfo]/s");
151 m_tree->Branch(
"eventNumberByte", m_eventNumberByte,
"eventNumberByte[nDebugInfo]/s");
154 void TOPInterimFENtupleModule::beginRun()
158 void TOPInterimFENtupleModule::event()
163 m_nEmptyFEHeader = 0;
171 for (
int iSlot = 0 ; iSlot < c_NModule ; iSlot++) {
172 m_eventNumCopper[iSlot] = -1;
173 m_ttuTime[iSlot] = -1;
174 m_ttcTime[iSlot] = -1;
177 short trigCtime = -1;
178 for (
auto& rawTOP : rawTOPs) {
179 if (iSlotTTC >= c_NModule) {
180 B2WARNING(
"too many TTC information");
183 m_eventNumCopper[iSlotTTC] = rawTOP.GetEveNo(0);
184 m_ttuTime[iSlotTTC] = rawTOP.GetTTUtime(0);
185 m_ttcTime[iSlotTTC] = rawTOP.GetTTCtime(0);
188 trigCtime = ((((long)m_ttcTime[iSlotTTC] + (
long)(m_ttuTime[iSlotTTC] - 1524741300) * 127216000) % 11520) % 3840) % 1284;
192 std::map<short, short> nHitOfflineFEMap;
193 static std::set<short> noisyChannelBlackListSet;
194 UInt_t EventNum = EventMetaDataPtr->getEvent();
195 m_eventNum = EventNum;
196 m_eventErrorFlag = EventMetaDataPtr->getErrorFlag();
197 for (
const auto& digit : digits) {
199 if (m_nHit >= c_NMaxHitEvent) {
200 B2WARNING(
"TOPInterimFENtuple : too many hits found (>=" << c_NMaxHitEvent
201 <<
"), EventNo = " << EventNum <<
", no more hits are recorded.");
205 m_slotNum[m_nHit] = digit.getModuleID();
206 m_pixelId[m_nHit] = (short)digit.getPixelID();
207 m_channelId[m_nHit] = (short)digit.getChannel();
208 m_isCalCh[m_nHit] = (digit.getASICChannel() == m_calibrationChannel);
209 m_winNum[m_nHit] = -1;
210 m_eventWinNum[m_nHit] = (short)digit.getFirstWindow();
211 m_trigWinNum[m_nHit] = trigCtime;
212 m_revo9Counter[m_nHit] = -1;
213 m_hitQuality[m_nHit] = (
unsigned char)digit.getHitQuality();
214 m_isReallyJunk[m_nHit] =
false;
215 m_windowsInOrder[m_nHit] =
true;
216 m_rawTime[m_nHit] = digit.getRawTime();
217 m_time[m_nHit] = digit.getTime() + m_winNum[m_nHit] * m_timePerWin;
218 m_sample[m_nHit] = TMath::FloorNint(m_rawTime[m_nHit] + m_winNum[m_nHit] * c_NSamplePerWindow) % c_NSampleTBC;
219 m_height[m_nHit] = digit.getPulseHeight();
220 m_integral[m_nHit] = digit.getIntegral();
221 m_width[m_nHit] = digit.getPulseWidth();
222 m_peakSample[m_nHit] = -1;
223 for (
int iWindow = 0 ; iWindow < c_NWindow ; iWindow++)
224 m_winNumList[m_nHit][iWindow] = -32767;
225 for (
int iSample = 0 ; iSample < c_NWaveformSample ; iSample++)
226 m_waveform[m_nHit][iSample] = -32767;
227 m_waveformStartSample[m_nHit] = -1;
229 short globalChannelId = m_pixelId[m_nHit] - 1 + (m_slotNum[m_nHit] - 1) * c_NPixelPerModule;
230 if (nHitOfflineFEMap.count(globalChannelId) == 0) nHitOfflineFEMap[globalChannelId] = 0;
231 else if (nHitOfflineFEMap[globalChannelId] > c_NMaxHitPerChannel) {
232 if (noisyChannelBlackListSet.count(globalChannelId) == 0) {
233 noisyChannelBlackListSet.insert(globalChannelId);
234 B2WARNING(
"TOPInterimFENtuple : noisy channel with too many hits (slotNum="
235 << (globalChannelId / c_NPixelPerModule + 1) <<
", pixelId = "
236 << (globalChannelId / c_NPixelPerModule + 1) <<
") ");
241 const auto* rawDigit = digit.getRelated<
TOPRawDigit>();
244 m_revo9Counter[m_nHit] = rawDigit->getRevo9Counter();
245 m_peakSample[m_nHit] = rawDigit->getSamplePeak();
246 m_windowsInOrder[m_nHit] = rawDigit->areWindowsInOrder();
247 if (rawDigit->getDataType() == TOPRawDigit::c_Interim)
248 m_trigWinNum[m_nHit] = (
short)rawDigit->getLastWriteAddr();
249 if (rawDigit->isPedestalJump()) m_isReallyJunk[m_nHit] =
true;
252 if (rawDigit->isMadeOffline()) {
255 nHitOfflineFEMap[globalChannelId]++;
256 m_offlineFlag[m_nHit] = nHitOfflineFEMap[globalChannelId];
258 m_offlineFlag[m_nHit] = 0;
261 unsigned nSampleWfm = waveform->getSize();
262 unsigned nSample = TMath::Min((UShort_t)nSampleWfm, (UShort_t)c_NWaveformSample);
263 if (nSample > c_NWaveformSample)
264 B2WARNING(
"TOPInterimFENtuple: too many waveform samples in TOPRawWaveform : " << nSampleWfm <<
", only first " << nSample <<
266 for (
unsigned iSample = 0 ; iSample < nSample ; iSample++)
267 m_waveform[m_nHit][iSample] = waveform->getWaveform()[iSample];
268 m_waveformStartSample[m_nHit] = (short)waveform->getStartSample();
269 m_nWaveformSample[m_nHit] = nSampleWfm;
272 for (
const auto& window : waveform->getStorageWindows()) {
273 if (iWin < c_NWindow)
274 m_winNumList[m_nHit][iWin] = window;
276 B2WARNING(
"TOPInterimFENtuple: too many windows were found");
283 else m_offlineFlag[m_nHit] = -1;
285 B2WARNING(
"TOPInterimFENtuple : no TOPRawDigit object found!");
286 m_offlineFlag[m_nHit] = -100;
293 for (
int iHit = 0 ; iHit < m_nHit ; iHit++) {
295 short globalChannelId = m_pixelId[iHit] - 1 + (m_slotNum[iHit] - 1) * c_NPixelPerModule;
296 m_nHitOfflineFE[iHit] = nHitOfflineFEMap[globalChannelId];
301 for (
const auto& info : infos) {
302 m_nFEHeader += info.getFEHeadersCount();
303 m_nEmptyFEHeader += info.getEmptyFEHeadersCount();
304 m_nWaveform += info.getWaveformsCount();
305 m_errorFlag |= info.getErrorFlags();
310 for (
const auto& prodDebug : prodDebugs) {
311 m_scrodCtime[m_nDebugInfo] = prodDebug.getCtime();
312 m_phase[m_nDebugInfo] = prodDebug.getPhase();
313 m_asicMask[m_nDebugInfo] = prodDebug.getAsicMask();
314 m_eventQueuDepth[m_nDebugInfo] = prodDebug.getEventQueueDepth();
315 m_eventNumberByte[m_nDebugInfo] = prodDebug.getEventNumberByte();
320 getReferenceTiming();
325 void TOPInterimFENtupleModule::endRun()
329 void TOPInterimFENtupleModule::terminate()
333 void TOPInterimFENtupleModule::getReferenceTiming()
335 static short globalRefAsic = m_globalRefAsicNum + 100 * m_globalRefSlotNum;
336 m_globalRefTime = -99999;
337 std::map<short, short> iRefHitMap;
338 for (
int iHit = 0 ; iHit < m_nHit ; iHit++) {
339 if (!m_isCalCh[iHit])
continue;
340 short reducedPixelId = (m_pixelId[iHit] - 1) / 8 + 100 * m_slotNum[iHit];
341 if (iRefHitMap.count(reducedPixelId) > 0)
continue;
343 if (!m_useDoublePulse) {
344 iRefHitMap[reducedPixelId] = iHit;
348 std::vector<short> iHitVec;
349 iHitVec.push_back(iHit);
350 for (
int jHit = iHit + 1 ; jHit < m_nHit ; jHit++) {
351 short jReducedPixelId = (m_pixelId[jHit] - 1) / 8 + 100 * m_slotNum[jHit];
352 if (m_isCalCh[jHit] && jReducedPixelId == reducedPixelId) iHitVec.push_back(jHit);
356 for (
unsigned int iVec = 0 ; iVec < iHitVec.size() ; iVec++) {
357 int jHit = iHitVec[iVec];
358 for (
unsigned int jVec = iVec + 1 ; jVec < iHitVec.size() ; jVec++) {
359 int kHit = iHitVec[jVec];
360 float timediff = m_time[kHit] - m_time[jHit];
361 if (m_height[jHit] > m_calibrationPulseThreshold1
362 && m_height[kHit] > m_calibrationPulseThreshold2
363 && TMath::Abs(timediff - m_calibrationPulseInterval) < m_calibrationPulseIntervalRange) {
365 iRefHitMap[reducedPixelId] = jHit;
366 m_hitQuality[jHit] += 100;
367 m_hitQuality[kHit] += 200;
372 else if (timediff < 0 && m_height[kHit] > m_calibrationPulseThreshold1
373 && m_height[jHit] > m_calibrationPulseThreshold2
374 && TMath::Abs(timediff + m_calibrationPulseInterval) < m_calibrationPulseIntervalRange) {
376 iRefHitMap[reducedPixelId] = kHit;
377 m_hitQuality[kHit] += 100;
378 m_hitQuality[jHit] += 200;
388 for (
int iHit = 0 ; iHit < m_nHit ; iHit++) {
389 short reducedPixelId = (m_pixelId[iHit] - 1) / 8 + 100 * m_slotNum[iHit];
390 if (iRefHitMap.count(reducedPixelId) > 0) {
391 int iRef = iRefHitMap[reducedPixelId];
392 m_refTime[iHit] = m_time[iRef];
393 if (reducedPixelId == globalRefAsic) m_globalRefTime = m_time[iRef];
394 if (!m_isReallyJunk[iHit] && m_hitQuality[iRef] >= 100) {
395 m_hitQuality[iHit] += 10;
397 }
else m_refTime[iHit] = -99999;