Belle II Software  release-08-01-10
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 
22 using namespace std;
23 
24 using namespace Belle2;
25 
26 //-----------------------------------------------------------------
27 // Register the Module
28 //-----------------------------------------------------------------
29 REG_MODULE(TOPXTalkChargeShareSetter);
30 
31 //-----------------------------------------------------------------
32 // Implementation
33 //-----------------------------------------------------------------
34 
35 TOPXTalkChargeShareSetterModule::TOPXTalkChargeShareSetterModule() : Module()
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 {
69  StoreArray<TOPDigit> digits;
70  digits.isRequired();
71 
74 }
75 
77 {
78 }
79 
81 {
82  StoreArray<TOPDigit> digits;
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 
188 bool 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
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.