10 #include <top/modules/TOPXTalkChargeShareSetter/TOPXTalkChargeShareSetterModule.h>
13 #include <framework/datastore/StoreArray.h>
16 #include <top/dataobjects/TOPRawDigit.h>
17 #include <top/dataobjects/TOPRawWaveform.h>
18 #include <top/dataobjects/TOPDigit.h>
38 setDescription(
"Crosstalk & chargeshare flag setter");
39 setPropertyFlags(c_ParallelProcessingCertified);
42 addParam(
"sumChargeShare", m_sumChargeShare,
43 "sum up charge of PrimaryChargeShare and SecondaryChargeShare", (
bool)
false);
44 addParam(
"timeCut", m_timeCut,
45 "cut range of hittiming for chargeshare flag [ns]", (
float) 1);
46 addParam(
"preValleyDepthLoose", m_preValleyDepthLoose,
47 "loose threshold for depth of pre valley [ADC counts], for corss talk identification", 20);
48 addParam(
"preValleyDepthTight", m_preValleyDepthTight,
49 "tight threshold for depth of pre valley [ADC counts], identified as cross talk with loose threshold for the second peak amplitude",
51 addParam(
"2ndPeakAmplitudeLoose", m_2ndPeakAmplitudeLoose,
52 "loose threshold for amplitude of the second peak [ADC counts] for cross talk identification. Defined as ADC count difference between the valley just after the main peak and the second peak, Used when the \"preValleyDepthTight\" was satisfied",
54 addParam(
"2ndPeakAmplitudeRatioTight", m_2ndPeakAmplitudeRatioTight,
55 "tight threshold for amplitude ratio of the second peak to the main peak height [ADC counts]", 0.2);
56 addParam(
"nSampleBefore", m_nSampleBefore,
57 "the number of samples by which the pre-valley should exist from the CFD timing, used for cross talk identification."
58 "Set negative value not to check existence of the pre-valley.", 5);
59 addParam(
"nSampleAfter", m_nSampleAfter,
60 "the number of samples by which the second peak should exist from the CFD timing, used for cross talk identification."
61 "Set negative value not to check existence of the second peak.", 10);
65 TOPXTalkChargeShareSetterModule::~TOPXTalkChargeShareSetterModule() {}
67 void TOPXTalkChargeShareSetterModule::initialize()
72 if (m_preValleyDepthLoose < 0 || m_preValleyDepthTight < 0 || m_nSampleBefore < 0) m_checkPreValleyForXTalkId =
false;
73 if (m_2ndPeakAmplitudeLoose < 0 || m_2ndPeakAmplitudeRatioTight < 0 || m_nSampleAfter < 0) m_checkPostValleyForXTalkId =
false;
76 void TOPXTalkChargeShareSetterModule::beginRun()
80 void TOPXTalkChargeShareSetterModule::event()
86 std::map<int, TOPDigit*> hitInfoMap;
87 for (
auto& digit : digits) {
89 if (digit.getHitQuality() == TOPDigit::c_Junk)
continue;
91 const auto* rawDigit = digit.getRelated<
TOPRawDigit>();
92 if (!rawDigit)
continue;
95 if (waveform and isCrossTalk(waveform->getWaveform(), TMath::FloorNint(digit.getRawTime()), digit.getPulseHeight()))
96 digit.setHitQuality(TOPDigit::c_CrossTalk);
99 int slotId = digit.getModuleID();
100 unsigned int channelId = digit.getChannel();
101 double rawTime = digit.getRawTime();
102 for (
auto& digit2 : digits) {
103 if (digit2.getChannel() != channelId || digit2.getModuleID() != slotId)
continue;
104 if (digit2.getHitQuality() == TOPDigit::c_CrossTalk
105 and TMath::Abs(rawTime - digit2.getRawTime() - m_nCrossTalkRingingSamples / 2.) < m_nCrossTalkRingingSamples / 2.)
106 digit.setHitQuality(TOPDigit::c_CrossTalk);
110 if (digit.getHitQuality() == TOPDigit::c_CrossTalk)
continue;
112 int globalPixelId = (digit.getModuleID() - 1) * 512 + digit.getPixelID() - 1;
113 while (hitInfoMap.count(globalPixelId) > 0)globalPixelId += 10000;
114 hitInfoMap[globalPixelId] = &digit;
120 for (
auto& digit : digits) {
122 if (digit.getHitQuality() == TOPDigit::c_Junk
123 || digit.getHitQuality() == TOPDigit::c_CrossTalk)
continue;
125 short pixelId = digit.getPixelID();
126 short slotId = digit.getModuleID();
127 short pmtId = digit.getPMTNumber();
128 double hitTime = digit.getTime();
129 double charge = digit.getIntegral();
130 bool isPrimaryChargeShare =
true;
131 std::vector<TOPDigit*> vSecondaryCandidates;
133 int adjacentPixelIds[] = { pixelId - 1 - c_NPixelsPerRow, pixelId - c_NPixelsPerRow, pixelId + 1 - c_NPixelsPerRow, pixelId + 1,
134 pixelId + 1 + c_NPixelsPerRow, pixelId + c_NPixelsPerRow, pixelId - 1 + c_NPixelsPerRow, pixelId - 1
137 for (
const auto& adjacentPixelId : adjacentPixelIds) {
138 if (adjacentPixelId > 0 && adjacentPixelId <= 512) {
139 int globalPixelId = (slotId - 1) * 512 + adjacentPixelId - 1;
140 while (hitInfoMap.count(globalPixelId) > 0) {
142 if (pmtId != hitInfoMap[globalPixelId]->getPMTNumber()
143 or TMath::Abs(hitTime - hitInfoMap[globalPixelId]->getTime()) > m_timeCut) {
144 globalPixelId += 10000;
continue;
147 float adjacentIntegral = hitInfoMap[globalPixelId]->getIntegral();
149 if (charge > adjacentIntegral
150 or (charge == adjacentIntegral && pixelId > hitInfoMap[globalPixelId]->getPixelID())) {
151 vSecondaryCandidates.push_back(hitInfoMap[globalPixelId]);
152 hitInfoMap[globalPixelId]->setSecondaryChargeShare();
154 isPrimaryChargeShare =
false;
157 globalPixelId += 10000;
159 if (!isPrimaryChargeShare)
break;
163 if (isPrimaryChargeShare && vSecondaryCandidates.size() > 0) {
164 digit.setPrimaryChargeShare();
166 if (m_sumChargeShare) {
167 for (
auto& vSecondaryCandidate : vSecondaryCandidates) {
168 digit.setPulseHeight(digit.getPulseHeight() + vSecondaryCandidate->getPulseHeight());
169 vSecondaryCandidate->setPulseHeight(0.0);
171 digit.setIntegral(digit.getIntegral() + vSecondaryCandidate->getIntegral());
172 vSecondaryCandidate->setIntegral(0.0);
179 void TOPXTalkChargeShareSetterModule::endRun()
183 void TOPXTalkChargeShareSetterModule::terminate()
188 bool TOPXTalkChargeShareSetterModule::isCrossTalk(std::vector<short> wfm,
int iRawTime,
short height)
191 int nWfmSampling = wfm.size();
192 for (
int iWin = 0 ; iWin < 16 ; iWin++) {
194 int jRawTime = iRawTime - TMath::FloorNint(iRawTime / (TOPRawDigit::c_WindowSize)) * (TOPRawDigit::c_WindowSize) +
195 (TOPRawDigit::c_WindowSize) / 4 * iWin;
196 if (jRawTime > 0 && jRawTime < nWfmSampling - 1 && wfm[jRawTime] < height / 2. && wfm[jRawTime + 1] > height / 2.) {
197 bool preValleyExist =
false;
198 short preValleyDepth = -1;
199 if (!m_checkPreValleyForXTalkId) preValleyExist =
true;
201 for (
int iSample = jRawTime ; iSample - 1 > 0 ; iSample--) {
202 if (jRawTime - iSample > m_nSampleBefore)
return false;
203 else if (wfm[iSample] - wfm[iSample - 1] >= 0)
continue;
205 preValleyDepth = (-1) * wfm[iSample];
206 if (preValleyDepth < m_preValleyDepthLoose)
return false;
208 if (!m_checkPostValleyForXTalkId)
return true;
209 preValleyExist =
true;
215 if (!preValleyExist)
return false;
219 short valley_adc = 9999;
220 for (
int jSample = jRawTime ; jSample < nWfmSampling - 1 ; jSample++) {
221 if (jSample - jRawTime > m_nSampleAfter)
return false;
222 if ((wfm[jSample + 1] - wfm[jSample])*sign > 0)
continue;
224 if (sign < 0 && valley_adc > height + 1)
225 valley_adc = wfm[jSample];
226 if (sign > 0 && valley_adc < height) {
227 if (wfm[jSample] - valley_adc > (height * m_2ndPeakAmplitudeRatioTight)
228 || (preValleyDepth > m_preValleyDepthTight
229 && (wfm[jSample] - valley_adc) > m_2ndPeakAmplitudeLoose))
233 sign = (sign > 0 ? -1 : 1);
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
Accessor to arrays stored in the data store.
Class to store unpacked raw data (hits in feature-extraction format) It provides also calculation of ...
Crosstalk & chargeshare flag setter.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.