Belle II Software  release-08-01-10
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 
19 using namespace std;
20 using namespace Belle2;
21 using namespace CDC;
22 
23 // register module
24 REG_MODULE(CDCCrossTalkAdder);
25 CDCCrossTalkAdderModule::CDCCrossTalkAdderModule() : Module()
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.
Structure for saving the x-talk information.