Belle II Software development
TOPXTalkChargeShareSetterModule.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9//own include
10#include <top/modules/TOPXTalkChargeShareSetter/TOPXTalkChargeShareSetterModule.h>
11
12// framework - DataStore
13#include <framework/datastore/StoreArray.h>
14
15// Dataobject classes
16#include <top/dataobjects/TOPRawDigit.h>
17#include <top/dataobjects/TOPRawWaveform.h>
18#include <top/dataobjects/TOPDigit.h>
19
20#include <TMath.h>
21
22using namespace std;
23
24using namespace Belle2;
25
26//-----------------------------------------------------------------
27// Register the Module
28//-----------------------------------------------------------------
29REG_MODULE(TOPXTalkChargeShareSetter);
30
31//-----------------------------------------------------------------
32// Implementation
33//-----------------------------------------------------------------
34
36{
37 // Set module properties
38 setDescription("Crosstalk & chargeshare flag setter");
40
41 // Add parameter
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",
50 50);
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",
53 30);
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);
62
63}
64
66
68{
70 digits.isRequired();
71
74}
75
77{
78}
79
81{
83
84 //Set Cross talk events and charge Share events
85 //
86 std::map<int, TOPDigit*> hitInfoMap;
87 for (auto& digit : digits) {
88
89 if (digit.getHitQuality() == TOPDigit::c_Junk) continue;
90
91 const auto* rawDigit = digit.getRelated<TOPRawDigit>();
92 if (!rawDigit) continue;
93
94 const auto* waveform = rawDigit->getRelated<TOPRawWaveform>();
95 if (waveform and isCrossTalk(waveform->getWaveform(), TMath::FloorNint(digit.getRawTime()), digit.getPulseHeight()))
96 digit.setHitQuality(TOPDigit::c_CrossTalk);
97 else {
98 //identify a ringing which follows a cross talk hit in the same channle as cross talk
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);
107 }//for(digit2)
108 }//if(waveform and isCrossTalk) else
109
110 if (digit.getHitQuality() == TOPDigit::c_CrossTalk) continue;
111
112 int globalPixelId = (digit.getModuleID() - 1) * 512 + digit.getPixelID() - 1;
113 while (hitInfoMap.count(globalPixelId) > 0)globalPixelId += 10000;
114 hitInfoMap[globalPixelId] = &digit;
115 }//for(digit)
116
117
118
119
120 for (auto& digit : digits) {
121
122 if (digit.getHitQuality() == TOPDigit::c_Junk
123 || digit.getHitQuality() == TOPDigit::c_CrossTalk) continue;
124
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;
132
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
135 };
136
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) {
141
142 if (pmtId != hitInfoMap[globalPixelId]->getPMTNumber()
143 or TMath::Abs(hitTime - hitInfoMap[globalPixelId]->getTime()) > m_timeCut) {
144 globalPixelId += 10000; continue;
145 }
146
147 float adjacentIntegral = hitInfoMap[globalPixelId]->getIntegral();
148
149 if (charge > adjacentIntegral
150 or (charge == adjacentIntegral && pixelId > hitInfoMap[globalPixelId]->getPixelID())) {
151 vSecondaryCandidates.push_back(hitInfoMap[globalPixelId]);
152 hitInfoMap[globalPixelId]->setSecondaryChargeShare();
153 } else {
154 isPrimaryChargeShare = false;
155 break;
156 }
157 globalPixelId += 10000;
158 }//while(hitInfoMap.count(globalPixelId)>0)
159 if (!isPrimaryChargeShare)break;
160 }//if(adjacentPixelId exist)
161 }//for(adjacentPixelIds)
162
163 if (isPrimaryChargeShare && vSecondaryCandidates.size() > 0) {
164 digit.setPrimaryChargeShare();
165
166 if (m_sumChargeShare) {
167 for (auto& vSecondaryCandidate : vSecondaryCandidates) {
168 digit.setPulseHeight(digit.getPulseHeight() + vSecondaryCandidate->getPulseHeight());
169 vSecondaryCandidate->setPulseHeight(0.0);
170
171 digit.setIntegral(digit.getIntegral() + vSecondaryCandidate->getIntegral());
172 vSecondaryCandidate->setIntegral(0.0);
173 }//for(vSecondaryCandidates)
174 }
175 }
176 }//for(digits)
177}//event()
178
180{
181}
182
184{
185}
186
187
188bool TOPXTalkChargeShareSetterModule::isCrossTalk(std::vector<short> wfm, int iRawTime, short height)
189{
190
191 int nWfmSampling = wfm.size();
192 for (int iWin = 0 ; iWin < 16 ; iWin++) {
193 //int jRawTime = iRawTime + (iWin - 20) * (TOPRawDigit::c_WindowSize)/4;//scan offset by 16-sample step
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;
200 else {
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;
204 else {
205 preValleyDepth = (-1) * wfm[iSample];
206 if (preValleyDepth < m_preValleyDepthLoose) return false;
207 else {
208 if (!m_checkPostValleyForXTalkId) return true;
209 preValleyExist = true;
210 break;
211 }
212 }
213 }//for( iSample )
214 }//if( m_checkPreValleyForXTalkId )
215 if (!preValleyExist) return false;
216
217 //check ringing (oscillation pattern) in trailing edge
218 short sign = 1;
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;
223 else { //when peak or valley is found
224 if (sign < 0 && valley_adc > height + 1) //in case a valley is found
225 valley_adc = wfm[jSample];
226 if (sign > 0 && valley_adc < height) {//in case of second peak
227 if (wfm[jSample] - valley_adc > (height * m_2ndPeakAmplitudeRatioTight)
228 || (preValleyDepth > m_preValleyDepthTight
229 && (wfm[jSample] - valley_adc) > m_2ndPeakAmplitudeLoose))
230 return true;
231 else return false;
232 }
233 sign = (sign > 0 ? -1 : 1);
234 }
235 }//for( jSample0 )
236 return false;
237 }//if( jRawTime )
238 }//for( iWin )
239
240 return false;
241}
242
243
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
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.
Definition: StoreArray.h:113
Class to store unpacked raw data (hits in feature-extraction format) It provides also calculation of ...
Definition: TOPRawDigit.h:24
@ c_WindowSize
number of samples per window
Definition: TOPRawDigit.h:54
Class to store raw data waveforms.
int getModuleID() const
Returns module ID.
int m_nSampleAfter
the number of samples by which the second peak should exist from the CFD timing, used for cross talk ...
double m_nCrossTalkRingingSamples
the number of samples to identify the hit as a cross talk hit when there is another cross talk hit in...
bool m_checkPreValleyForXTalkId
require existence of pre-valley.
int m_preValleyDepthLoose
loose threshold for depth of pre valley [ADC counts], for corss talk identification
TOPXTalkChargeShareSetterModule()
Constructor: Sets the description, the properties and the parameters of the module.
int m_2ndPeakAmplitudeLoose
loose threshold for amplitude of the second peak [ADC counts] for cross talk identification.
bool isCrossTalk(std::vector< short > wfm, int iRawTime, short height)
Examine whether the give hit is cross talk hits using waveform information Thresholds for such as pre...
float m_timeCut
cut range of hittiming for chargeshare
int m_preValleyDepthTight
tight threshold for depth of pre valley [ADC counts], identified as cross talk with loose threshold f...
double m_2ndPeakAmplitudeRatioTight
tight threshold for amplitude ratio of the second peak to the main peak height [ADC counts]
bool m_sumChargeShare
sum charge of PrimaryChargeShare and SecondaryChargeShare
bool m_checkPostValleyForXTalkId
require existence of post-valley and 2nd peak.
int m_nSampleBefore
the number of samples by which the pre-valley should exist from the CFD timing, used for cross talk i...
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.
STL namespace.