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 cross 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
65
74
75
77{
79
80 //Set Cross talk events and charge Share events
81 //
82 std::map<int, TOPDigit*> hitInfoMap;
83 for (auto& digit : digits) {
84
85 if (digit.getHitQuality() == TOPDigit::c_Junk) continue;
86
87 const auto* rawDigit = digit.getRelated<TOPRawDigit>();
88 if (!rawDigit) continue;
89
90 const auto* waveform = rawDigit->getRelated<TOPRawWaveform>();
91 if (waveform and isCrossTalk(waveform->getWaveform(), TMath::FloorNint(digit.getRawTime()), digit.getPulseHeight()))
92 digit.setHitQuality(TOPDigit::c_CrossTalk);
93 else {
94 //identify a ringing which follows a cross talk hit in the same channel as cross talk
95 int slotId = digit.getModuleID();
96 unsigned int channelId = digit.getChannel();
97 double rawTime = digit.getRawTime();
98 for (auto& digit2 : digits) {
99 if (digit2.getChannel() != channelId || digit2.getModuleID() != slotId) continue;
100 if (digit2.getHitQuality() == TOPDigit::c_CrossTalk
101 and TMath::Abs(rawTime - digit2.getRawTime() - m_nCrossTalkRingingSamples / 2.) < m_nCrossTalkRingingSamples / 2.)
102 digit.setHitQuality(TOPDigit::c_CrossTalk);
103 }//for(digit2)
104 }//if(waveform and isCrossTalk) else
105
106 if (digit.getHitQuality() == TOPDigit::c_CrossTalk) continue;
107
108 int globalPixelId = (digit.getModuleID() - 1) * 512 + digit.getPixelID() - 1;
109 while (hitInfoMap.count(globalPixelId) > 0)globalPixelId += 10000;
110 hitInfoMap[globalPixelId] = &digit;
111 }//for(digit)
112
113 for (auto& digit : digits) {
114
115 if (digit.getHitQuality() == TOPDigit::c_Junk
116 || digit.getHitQuality() == TOPDigit::c_CrossTalk) continue;
117
118 short pixelId = digit.getPixelID();
119 short slotId = digit.getModuleID();
120 short pmtId = digit.getPMTNumber();
121 double hitTime = digit.getTime();
122 double charge = digit.getIntegral();
123 bool isPrimaryChargeShare = true;
124 std::vector<TOPDigit*> vSecondaryCandidates;
125
126 const int adjacentPixelIds[] = { pixelId - 1 - c_NPixelsPerRow, pixelId - c_NPixelsPerRow, pixelId + 1 - c_NPixelsPerRow, pixelId + 1,
127 pixelId + 1 + c_NPixelsPerRow, pixelId + c_NPixelsPerRow, pixelId - 1 + c_NPixelsPerRow, pixelId - 1
128 };
129
130 for (const auto& adjacentPixelId : adjacentPixelIds) {
131 if (adjacentPixelId > 0 && adjacentPixelId <= 512) {
132 int globalPixelId = (slotId - 1) * 512 + adjacentPixelId - 1;
133 while (hitInfoMap.count(globalPixelId) > 0) {
134
135 if (pmtId != hitInfoMap[globalPixelId]->getPMTNumber()
136 or TMath::Abs(hitTime - hitInfoMap[globalPixelId]->getTime()) > m_timeCut) {
137 globalPixelId += 10000; continue;
138 }
139
140 float adjacentIntegral = hitInfoMap[globalPixelId]->getIntegral();
141
142 if (charge > adjacentIntegral
143 or (charge == adjacentIntegral && pixelId > hitInfoMap[globalPixelId]->getPixelID())) {
144 vSecondaryCandidates.push_back(hitInfoMap[globalPixelId]);
145 hitInfoMap[globalPixelId]->setSecondaryChargeShare();
146 } else {
147 isPrimaryChargeShare = false;
148 break;
149 }
150 globalPixelId += 10000;
151 }//while(hitInfoMap.count(globalPixelId)>0)
152 if (!isPrimaryChargeShare)break;
153 }//if(adjacentPixelId exist)
154 }//for(adjacentPixelIds)
155
156 if (isPrimaryChargeShare && vSecondaryCandidates.size() > 0) {
157 digit.setPrimaryChargeShare();
158
159 if (m_sumChargeShare) {
160 for (auto& vSecondaryCandidate : vSecondaryCandidates) {
161 digit.setPulseHeight(digit.getPulseHeight() + vSecondaryCandidate->getPulseHeight());
162 vSecondaryCandidate->setPulseHeight(0.0);
163
164 digit.setIntegral(digit.getIntegral() + vSecondaryCandidate->getIntegral());
165 vSecondaryCandidate->setIntegral(0.0);
166 }//for(vSecondaryCandidates)
167 }
168 }
169 }//for(digits)
170}//event()
171
172
173bool TOPXTalkChargeShareSetterModule::isCrossTalk(const std::vector<short>& wfm, int iRawTime, short height)
174{
175
176 int nWfmSampling = wfm.size();
177 for (int iWin = 0 ; iWin < 16 ; iWin++) {
178 //int jRawTime = iRawTime + (iWin - 20) * (TOPRawDigit::c_WindowSize)/4;//scan offset by 16-sample step
179 int jRawTime = iRawTime - TMath::FloorNint(iRawTime / (TOPRawDigit::c_WindowSize)) * (TOPRawDigit::c_WindowSize) +
180 (TOPRawDigit::c_WindowSize) / 4 * iWin;
181 if (jRawTime > 0 && jRawTime < nWfmSampling - 1 && wfm[jRawTime] < height / 2. && wfm[jRawTime + 1] > height / 2.) {
182 bool preValleyExist = false;
183 short preValleyDepth = -1;
184 if (!m_checkPreValleyForXTalkId) preValleyExist = true;
185 else {
186 for (int iSample = jRawTime ; iSample - 1 > 0 ; iSample--) {
187 if (jRawTime - iSample > m_nSampleBefore) return false;
188 else if (wfm[iSample] - wfm[iSample - 1] >= 0) continue;
189 else {
190 preValleyDepth = (-1) * wfm[iSample];
191 if (preValleyDepth < m_preValleyDepthLoose) return false;
192 else {
193 if (!m_checkPostValleyForXTalkId) return true;
194 preValleyExist = true;
195 break;
196 }
197 }
198 }//for( iSample )
199 }//if( m_checkPreValleyForXTalkId )
200 if (!preValleyExist) return false;
201
202 //check ringing (oscillation pattern) in trailing edge
203 short sign = 1;
204 short valley_adc = 9999;
205 for (int jSample = jRawTime ; jSample < nWfmSampling - 1 ; jSample++) {
206 if (jSample - jRawTime > m_nSampleAfter) return false;
207 if ((wfm[jSample + 1] - wfm[jSample])*sign > 0) continue;
208 else { //when peak or valley is found
209 if (sign < 0 && valley_adc > height + 1) //in case a valley is found
210 valley_adc = wfm[jSample];
211 if (sign > 0 && valley_adc < height) {//in case of second peak
212 if (wfm[jSample] - valley_adc > (height * m_2ndPeakAmplitudeRatioTight)
213 || (preValleyDepth > m_preValleyDepthTight
214 && (wfm[jSample] - valley_adc) > m_2ndPeakAmplitudeLoose))
215 return true;
216 else return false;
217 }
218 sign = (sign > 0 ? -1 : 1);
219 }
220 }//for( jSample0 )
221 return false;
222 }//if( jRawTime )
223 }//for( iWin )
224
225 return false;
226}
227
228
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
Module()
Constructor.
Definition Module.cc:30
@ 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 getPixelID() const
Returns pixel ID (1-based)
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 cross 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(const 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:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Abstract base class for different kinds of events.
STL namespace.