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