Belle II Software development
CDCCrossTalkAdderModule.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#include <cdc/modules/cdcCrossTalkAdder/CDCCrossTalkAdderModule.h>
10
11#include <framework/logging/Logger.h>
12
13#include <cdc/dataobjects/CDCSimHit.h>
14#include <mdst/dataobjects/MCParticle.h>
15
16#include <map>
17
18using namespace std;
19using namespace Belle2;
20using namespace CDC;
21
22// register module
23REG_MODULE(CDCCrossTalkAdder);
25{
26 // Set description
27 setDescription("Overlays signal-induced asic cross-talk to CDCHits.");
29
30 addParam("InputCDCHitsName", m_inputCDCHitsName, "Name of input array. Should consist of CDCHits.", string(""));
31 addParam("Issue2ndHitWarning", m_issue2ndHitWarning, "=true: issue a warning when a 2nd TDC hit is found.", true);
32 addParam("IncludeEarlyXTalks", m_includeEarlyXTalks, "=true: include earlier x-talks as well than the signal hit in question.",
33 true);
34 addParam("DebugLevel", m_debugLevel, "Debug level; 20-29 are usable.", 20);
35}
36
38{
39 m_hits.isRequired(m_inputCDCHitsName);
40
42
43 m_invOfTDCBinWidth = 1. / m_cdcgp->getTdcBinWidth();
44
46 if ((*m_xTalkFromDB).isValid()) {
47 } else {
48 B2FATAL("CDCCrossTalkLibrary invalid!");
49 }
50
52 if ((*m_fEElectronicsFromDB).isValid()) {
53 (*m_fEElectronicsFromDB).addCallback(this, &CDCCrossTalkAdderModule::setFEElectronics);
55 } else {
56 B2FATAL("CDCCrossTalkAdder:: CDCFEElectronics not valid!");
57 }
58}
59
61{
62 map<WireID, XTalkInfo> xTalkMap;
63 map<WireID, XTalkInfo> xTalkMap1;
65
66 // Loop over all cdc hits to create a xtalk map
67 int OriginalNoOfHits = m_hits.getEntries();
68 B2DEBUG(m_debugLevel, "\n \n" << "#CDCHits " << OriginalNoOfHits);
69 for (const auto& aHit : m_hits) {
70 if (m_issue2ndHitWarning && aHit.is2ndHit()) {
71 B2WARNING("2nd TDC hit found, but not ready for it!");
72 }
73 WireID wid(aHit.getID());
74 // B2DEBUG(m_debugLevel, "Encoded wireid of current CDCHit: " << wid);
75 short tdcCount = aHit.getTDCCount();
76 short adcCount = aHit.getADCCount();
77 short tot = aHit.getTOT();
78 short board = m_cdcgp->getBoardID(wid);
79 short channel = m_cdcgp->getChannelID(wid);
80 const vector<pair<short, asicChannel>> xTalks = (*m_xTalkFromDB)->getLibraryCrossTalk(channel, tdcCount, adcCount, tot);
81
82 int nXTalks = xTalks.size();
83 for (int i = 0; i < nXTalks; ++i) {
84 const unsigned short tdcCount4XTalk = xTalks[i].second.TDC;
85 if (i == 0) {
86 B2DEBUG(m_debugLevel, "\n" << " signal: " << channel << " " << tdcCount << " " << adcCount << " " << tot);
87 }
88 B2DEBUG(m_debugLevel, "xtalk: " << xTalks[i].first << " " << tdcCount4XTalk << " " << xTalks[i].second.ADC << " " <<
89 xTalks[i].second.TOT);
90 WireID widx = m_cdcgp->getWireID(board, xTalks[i].first);
91 if (!m_cdcgp->isBadWire(widx)) { // for non-bad wire
92 if (m_includeEarlyXTalks || (xTalks[i].second.TDC <= tdcCount)) {
93 const double t0 = m_cdcgp->getT0(widx);
94 const double ULOfTDC = (t0 - m_lowEdgeOfTimeWindow[board]) * m_invOfTDCBinWidth;
95 const double LLOfTDC = (t0 - m_uprEdgeOfTimeWindow[board]) * m_invOfTDCBinWidth;
96 if (LLOfTDC <= tdcCount4XTalk && tdcCount4XTalk <= ULOfTDC) {
97 const unsigned short status = 0;
98 xTalkMap.insert(make_pair(widx, XTalkInfo(tdcCount4XTalk, xTalks[i].second.ADC, xTalks[i].second.TOT, status)));
99 }
100 }
101 // } else {
102 // cout<<"badwire= " << widx.getICLayer() <<" "<< widx.getIWire() << endl;
103 }
104 } //end of xtalk loop
105 } //end of cdc hit loop
106
107 //Loop over all xtalk hits to creat a new xtalk map with only the fastest hits kept (approx.)
108 B2DEBUG(m_debugLevel, "#xtalk hits: " << xTalkMap.size());
109 for (const auto& aHit : xTalkMap) {
110 WireID wid = aHit.first;
111
112 iterXTalkMap1 = xTalkMap1.find(wid);
113 unsigned short tdcCount = aHit.second.m_tdc;
114 unsigned short adcCount = aHit.second.m_adc;
115 unsigned short tot = aHit.second.m_tot;
116 unsigned short status = aHit.second.m_status;
117
118 if (iterXTalkMap1 == xTalkMap1.end()) { // new entry
119 xTalkMap1.insert(make_pair(wid, XTalkInfo(tdcCount, adcCount, tot, status)));
120 // B2DEBUG(m_debugLevel, "Creating a new xtalk hit with encoded wire no.: " << wid);
121 } else { // not new; check if fastest
122 if (tdcCount < iterXTalkMap1->second.m_tdc) {
123 iterXTalkMap1->second.m_tdc = tdcCount;
124 B2DEBUG(m_debugLevel, "TDC-count of current xtalk: " << tdcCount);
125 }
126 iterXTalkMap1->second.m_adc += adcCount;
127 iterXTalkMap1->second.m_tot += tot; // approx.
128 }
129 } // end of xtalk loop
130
131 //add xtalk in the same way as the beam bg. overlay
132 B2DEBUG(m_debugLevel, "#xtalk1 hits: " << xTalkMap1.size());
133 for (const auto& aX : xTalkMap1) {
134 bool append = true;
135 const unsigned short tdc4Bg = aX.second.m_tdc;
136 const unsigned short adc4Bg = aX.second.m_adc;
137 const unsigned short tot4Bg = aX.second.m_tot;
138 const unsigned short status4Bg = aX.second.m_status;
139
140 for (int iHit = 0; iHit < OriginalNoOfHits; ++iHit) {
141 CDCHit& aH = *(m_hits[iHit]);
142 if (aH.getID() != aX.first.getEWire()) { //wire id unmatched
143 continue;
144 } else { //wire id matched
145 append = false;
146 const unsigned short tdc4Sg = aH.getTDCCount();
147 const unsigned short adc4Sg = aH.getADCCount();
148 const unsigned short tot4Sg = aH.getTOT();
149 // B2DEBUG(m_debuglevel, "Sg tdc,adc,tot= " << tdc4Sg << " " << adc4Sg << " " << tot4Sg);
150 // B2DEBUG(m_debugLevel, "Bg tdc,adc,tot= " << tdc4Bg << " " << adc4Bg << " " << tot4Bg);
151
152 // If the BG hit is faster than the true hit, the TDC count is replaced, and
153 // the relations are removed. ADC counts are summed up.
154 if (tdc4Sg < tdc4Bg) {
155 aH.setTDCCount(tdc4Bg);
156 aH.setStatus(status4Bg);
157 auto relSimHits = aH.getRelationsFrom<CDCSimHit>();
158 for (int i = relSimHits.size() - 1; i >= 0; --i) {
159 relSimHits.remove(i);
160 }
161 auto relMCParticles = aH.getRelationsFrom<MCParticle>();
162 for (int i = relMCParticles.size() - 1; i >= 0; --i) {
163 relMCParticles.remove(i);
164 }
165 }
166
167 aH.setADCCount(adc4Sg + adc4Bg);
168
169 //Set TOT for signal+background case. It is assumed that the start timing
170 //of a pulse (input to ADC) is given by the TDC-count. This is an
171 //approximation because analog (for ADC) and digital (for TDC) parts are
172 //different in the front-end electronics.
173 unsigned short s1 = tdc4Sg; //start time of 1st pulse
174 unsigned short s2 = tdc4Bg; //start time of 2nd pulse
175 unsigned short w1 = tot4Sg; //its width
176 unsigned short w2 = tot4Bg; //its width
177 if (tdc4Sg < tdc4Bg) {
178 s1 = tdc4Bg;
179 w1 = tot4Bg;
180 s2 = tdc4Sg;
181 w2 = tot4Sg;
182 }
183 w1 *= 32;
184 w2 *= 32;
185 const unsigned short e1 = s1 - w1; //end time of 1st pulse
186 const unsigned short e2 = s2 - w2; //end time of 2nd pulse
187 // B2DEBUG(m_debuglevel, "s1,e1,w1,s2,e2,w2= " << s1 << " " << e1 << " " << w1 << " " << s2 << " " << e2 << " " << w2);
188
189 double pulseW = w1 + w2;
190 if (e1 <= e2) {
191 pulseW = w1;
192 } else if (e1 <= s2) {
193 pulseW = s1 - e2;
194 }
195
196 unsigned short board = m_cdcgp->getBoardID(aX.first);
197 aH.setTOT(std::min(std::round(pulseW / 32.), static_cast<double>(m_widthOfTimeWindow[board])));
198 B2DEBUG(m_debugLevel, "replaced tdc,adc,tot,wid,status= " << aH.getTDCCount() << " " << aH.getADCCount() << " " << aH.getTOT() <<
199 " " << aH.getID() << " " << aH.getStatus());
200 break;
201 }
202 } //end of cdc hit loop
203
204 if (append) {
205 m_hits.appendNew(tdc4Bg, adc4Bg, aX.first, status4Bg, tot4Bg);
206 B2DEBUG(m_debugLevel, "appended tdc,adc,tot,wid,status= " << tdc4Bg << " " << adc4Bg << " " << tot4Bg << " " << aX.first << " " <<
207 status4Bg);
208 }
209 } //end of x-talk loop
210 B2DEBUG(m_debugLevel, "original #hits, #hits= " << OriginalNoOfHits << " " << m_hits.getEntries());
211}
212
213// Set FEE parameters (from DB)
215{
216 const double el1TrgLatency = m_cdcgp->getMeanT0(); // ns
217 B2DEBUG(m_debugLevel, "L1TRGLatency= " << el1TrgLatency);
218 const double c = 32. * m_cdcgp->getTdcBinWidth();
219
220 if (!m_fEElectronicsFromDB) B2FATAL("No FEEElectronics dbobject!");
221 const CDCFEElectronics& fp = *((*m_fEElectronicsFromDB)[0]);
222 int mode = (fp.getBoardID() == -1) ? 1 : 0;
223 int iNBoards = static_cast<int>(c_nBoards);
224
225 //set typical values for all channels first if mode=1
226 if (mode == 1) {
227 for (int bdi = 1; bdi < iNBoards; ++bdi) {
228 m_uprEdgeOfTimeWindow[bdi] = el1TrgLatency - c * (fp.getTrgDelay() + 1);
229 if (m_uprEdgeOfTimeWindow[bdi] < 0.) B2FATAL("Upper edge of time window < 0!");
230 m_lowEdgeOfTimeWindow[bdi] = m_uprEdgeOfTimeWindow[bdi] - c * (fp.getWidthOfTimeWindow() + 1);
231 if (m_lowEdgeOfTimeWindow[bdi] > 0.) B2FATAL("Lower edge of time window > 0!");
232 m_widthOfTimeWindow[bdi] = fp.getWidthOfTimeWindow() + 1;
233 }
234 }
235
236 //overwrite values for specific channels if mode=1
237 //set typical values for all channels if mode=0
238 for (const auto& fpp : (*m_fEElectronicsFromDB)) {
239 int bdi = fpp.getBoardID();
240 if (mode == 0 && bdi == 0) continue; //bdi=0 is dummy (not used)
241 if (mode == 1 && bdi == -1) continue; //skip typical case
242 if (bdi < 0 || bdi >= iNBoards) B2FATAL("Invalid no. of FEE board!");
243 m_uprEdgeOfTimeWindow[bdi] = el1TrgLatency - c * (fpp.getTrgDelay() + 1);
244 if (m_uprEdgeOfTimeWindow[bdi] < 0.) B2FATAL("Upper edge of time window < 0!");
245 m_lowEdgeOfTimeWindow[bdi] = m_uprEdgeOfTimeWindow[bdi] - c * (fpp.getWidthOfTimeWindow() + 1);
246 if (m_lowEdgeOfTimeWindow[bdi] > 0.) B2FATAL("Lower edge of time window > 0!");
247 m_widthOfTimeWindow[bdi] = fpp.getWidthOfTimeWindow() + 1;
248 }
249
250 //debug
251 B2DEBUG(m_debugLevel, "mode= " << mode);
252 for (int bdi = 1; bdi < iNBoards; ++bdi) {
253 B2DEBUG(m_debugLevel, bdi << " " << m_lowEdgeOfTimeWindow[bdi] << " " << m_uprEdgeOfTimeWindow[bdi]);
254 }
255}
bool m_includeEarlyXTalks
Flag to switch on/off xtalks earlier than the hit.
unsigned short m_widthOfTimeWindow[c_nBoards]
Width of time window.
std::string m_inputCDCHitsName
Input array name.
DBObjPtr< CDCCrossTalkLibrary > * m_xTalkFromDB
Pointer to cross-talk from DB.
float m_uprEdgeOfTimeWindow[c_nBoards]
Upper edge of time-window.
void initialize() override
Initialize variables.
StoreArray< CDCHit > m_hits
CDCHit array.
bool m_issue2ndHitWarning
Flag to switch on/off a warning on the 2nd TDC hit.
float m_lowEdgeOfTimeWindow[c_nBoards]
Lower edge of time-window.
DBArray< CDCFEElectronics > * m_fEElectronicsFromDB
Pointer to FE electronics params.
CDC::CDCGeometryPar * m_cdcgp
Cached Pointer to CDCGeometryPar.
void setFEElectronics()
Set FEE parameters (from DB)
Database object for Fron-endt electronics params.
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition CDCHit.h:40
void setTDCCount(short tdcCount)
Setter for TDC count.
Definition CDCHit.h:128
short getTDCCount() const
Getter for TDC count.
Definition CDCHit.h:219
void setTOT(unsigned short tot)
Setter for TOT.
Definition CDCHit.h:160
unsigned short getID() const
Getter for encoded wire number.
Definition CDCHit.h:193
unsigned short getStatus() const
Getter for CDCHit status.
Definition CDCHit.h:199
void setADCCount(unsigned short adcCount)
Setter for ADC count.
Definition CDCHit.h:135
unsigned short getADCCount() const
Getter for integrated charge.
Definition CDCHit.h:230
unsigned short getTOT() const
Getter for TOT.
Definition CDCHit.h:248
void setStatus(unsigned short status)
Setter for CDCHit status.
Definition CDCHit.h:106
Example Detector.
Definition CDCSimHit.h:21
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
Class for accessing arrays of objects in the database.
Definition DBArray.h:26
Class for accessing objects in the database.
Definition DBObjPtr.h:21
A Class to store the Monte Carlo particle information.
Definition MCParticle.h:32
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
RelationVector< FROM > getRelationsFrom(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from another store array to this object.
Class to identify a wire inside the CDC.
Definition WireID.h:34
STL iterator class.
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.
Structure for saving the x-talk information.