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