Belle II Software  release-05-02-19
TOPLaserHitSelectorModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2017 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Maeda Yosuke, Okuto Rikuya *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 // own include
12 #include <top/modules/TOPGainEfficiencyMonitor/TOPLaserHitSelectorModule.h>
13 
14 // framework - DataStore
15 #include <framework/datastore/StoreArray.h>
16 
17 // Hit classes
18 #include <top/dataobjects/TOPDigit.h>
19 
20 // standard libraries
21 #include <iostream>
22 #include <sstream>
23 #include <iomanip>
24 
25 #include <map>
26 
27 using namespace std;
28 
29 namespace Belle2 {
35  //-----------------------------------------------------------------
36  // Register the Module
37  //-----------------------------------------------------------------
38 
39  REG_MODULE(TOPLaserHitSelector)
40 
41 
42  //-----------------------------------------------------------------
43  // Implementation
44  //-----------------------------------------------------------------
45 
47  {
48  // Set description()
49  setDescription("TOP pixel-by-pixel gain analysis - first step : create hit timing-pulse charge histogram");
50 
51  // Add parameters
52  m_timeHistogramBinning.push_back(140);//140 for time axis
53  m_timeHistogramBinning.push_back(-55);//-25
54  m_timeHistogramBinning.push_back(15);//45
55  m_chargeHistogramBinning.push_back(125);//for height
56  m_chargeHistogramBinning.push_back(-50);//
57  m_chargeHistogramBinning.push_back(2450);//
58  m_chargeHistogramBinning.push_back(150);//for integral
59  m_chargeHistogramBinning.push_back(-500);//
60  m_chargeHistogramBinning.push_back(29500);//
61 
62  addParam("timeHistogramBinning", m_timeHistogramBinning,
63  "histogram binning (the number of bins, lower limit, upper limit) for hit timing distribution (should be integer value)",
64  m_timeHistogramBinning);
65  addParam("chargeHistogramBinning", m_chargeHistogramBinning,
66  "histogram binning (the number of bins, lower limit, upper limit) for pulse charge distribution (should be integer value)",
67  m_chargeHistogramBinning);
68 
69  // addParam("calibrationChannel", m_calibrationChannel, "asic channel # where calibration pulses routed",
70  // (unsigned)0);
71  addParam("useDoublePulse", m_useDoublePulse,
72  "set true when you require both of double calibration pulses for reference timing. You need to enable offline feature extraction.",
73  (bool)true);
74  addParam("minHeightFirstCalPulse", m_calibrationPulseThreshold1, "pulse height threshold for the first cal. pulse",
75  (float)300.);
76  addParam("minHeightSecondCalPulse", m_calibrationPulseThreshold2, "pulse height threshold for the second cal. pulse",
77  (float)100.);
78  addParam("nominalDeltaT", m_calibrationPulseInterval, "nominal DeltaT (time interval of the double calibration pulses) [ns]",
79  (float)25.5);
80  addParam("nominalDeltaTRange", m_calibrationPulseIntervalRange,
81  "acceptable DeltaT range from the nominal value before calibration [ns]",
82  (float)2.);
83  addParam("windowSelect", m_windowSelect,
84  "select window number (All=0, Odd=2, Even=1)",
85  0);
86  addParam("includePrimaryChargeShare", m_includePrimaryChargeShare,
87  "set ture when you require without primary chargeshare cut for making 2D histogram",
88  (bool)false);
89  addParam("includeAllChargeShare", m_includeAllChargeShare,
90  "set ture when you require without all chargeshare cut for making 2D histogram",
91  (bool)false);
92  }
93 
94  TOPLaserHitSelectorModule::~TOPLaserHitSelectorModule() {}
95 
96  void TOPLaserHitSelectorModule::initialize()
97  {
98  REG_HISTOGRAM;
99 
100  StoreArray<TOPDigit> digits;
101  digits.isRequired();
102  }
103 
104  void TOPLaserHitSelectorModule::defineHisto()
105  {
106  for (int iPixel = 0 ; iPixel < c_NPixelPerModule * c_NModule ; iPixel++) {
107 
108  short slotId = (iPixel / c_NPixelPerModule) + 1;
109  short pixelId = (iPixel % c_NPixelPerModule) + 1;
110  short pmtId = ((pixelId - 1) % c_NPixelPerRow) / c_NChannelPerPMTRow + c_NPMTPerRow * ((pixelId - 1) / (c_NPixelPerModule / 2)) + 1;
111  short pmtChId = (pixelId - 1) % c_NChannelPerPMTRow + c_NChannelPerPMTRow * ((pixelId - 1) %
112  (c_NPixelPerModule / 2) / c_NPixelPerRow) + 1;
113 
114  std::ostringstream pixelstr;
115  pixelstr << "s" << std::setw(2) << std::setfill('0') << slotId << "_PMT"
116  << std::setw(2) << std::setfill('0') << pmtId
117  << "_" << std::setw(2) << std::setfill('0') << pmtChId;
118 
119  std::ostringstream hnameForgain;
120  hnameForgain << "hTimeHeight_gain_" << pixelstr.str();
121  std::ostringstream htitleForgain;
122  htitleForgain << "2D distribution of hit timing and pulse height for Gain" << pixelstr.str();
123  m_TimeHeightHistogramForFit[iPixel] = new TH2F(hnameForgain.str().c_str(), htitleForgain.str().c_str(),
124  m_timeHistogramBinning[0], m_timeHistogramBinning[1], m_timeHistogramBinning[2],
125  m_chargeHistogramBinning[0], m_chargeHistogramBinning[1],
126  m_chargeHistogramBinning[2]);
127 
128  std::ostringstream hnameForIntegral;
129  hnameForIntegral << "hTimeIntegral_gain_" << pixelstr.str();
130  std::ostringstream htitleForIntegral;
131  htitleForIntegral << "2D distribution of hit timing and integral for Gain" << pixelstr.str();
132  m_TimeIntegralHistogramForFit[iPixel] = new TH2F(hnameForIntegral.str().c_str(), htitleForIntegral.str().c_str(),
133  m_timeHistogramBinning[0], m_timeHistogramBinning[1], m_timeHistogramBinning[2],
134  m_chargeHistogramBinning[3], m_chargeHistogramBinning[4],
135  m_chargeHistogramBinning[5]);
136 
137  std::ostringstream hnameForeff;
138  hnameForeff << "hTimeHeight_efficiency_" << pixelstr.str();
139  std::ostringstream htitleForeff;
140  htitleForeff << "2D distribution of hit timing and pulse height for efficiency" << pixelstr.str();
141  m_TimeHeightHistogramForHitRate[iPixel] = new TH2F(hnameForeff.str().c_str(), htitleForeff.str().c_str(),
142  m_timeHistogramBinning[0], m_timeHistogramBinning[1], m_timeHistogramBinning[2],
143  m_chargeHistogramBinning[0], m_chargeHistogramBinning[1],
144  m_chargeHistogramBinning[2]);
145  }
146 
147  const short nAsic = c_NPixelPerModule / c_NChannelPerAsic * c_NChannelPerPMT;
148  m_nCalPulseHistogram = new TH1F("hNCalPulse", "number of calibration pulses identificed for each asic",
149  nAsic, -0.5, nAsic - 0.5);
150  }
151 
152  void TOPLaserHitSelectorModule::beginRun()
153  {
154  }
155 
156  void TOPLaserHitSelectorModule::event()
157  {
158  StoreArray<TOPDigit> digits;
159 
160  std::map<short, float> refTimingMap;//map of pixel id and time
161  std::map<short, std::vector<hitInfo_t> >
162  calPulsesMap;//map of pixel id and hit information (timing and pulse charge) for cal. pulse candidetes
163 
164  //first, identify cal. pulse
165  for (const auto& digit : digits) {
166 
167  short slotId = digit.getModuleID();
168  short pixelId = digit.getPixelID();
169  short globalPixelId = (slotId - 1) * c_NPixelPerModule + pixelId - 1;
170  if (digit.getHitQuality() == TOPDigit::c_CalPulse) {
171  calPulsesMap[globalPixelId].push_back((hitInfo_t) { (float)digit.getTime(), (float)digit.getPulseHeight() });
172  }
173  }// for digit pair
174 
175 
176  //cal. pulse timing calculation
177  for (const auto& calPulse : calPulsesMap) {
178 
179  short globalPixelId = calPulse.first;
180  short globalAsicId = globalPixelId / c_NChannelPerAsic;
181  std::vector<hitInfo_t> vec = calPulse.second;
182  double calPulseTiming = 9999999;
183  unsigned nCalPulseCandidates = vec.size();
184  if (!m_useDoublePulse) { //try to find the first cal. pulse in case that both of double cal. pulses are not required (choose the largest hit)
185  double maxPulseHeight = -1;
186  double maxHeightTiming = 9999999;
187  for (unsigned iVec = 0 ; iVec < nCalPulseCandidates ; iVec++) {
188  if (maxPulseHeight < vec[iVec].m_height) {
189  maxPulseHeight = vec[iVec].m_height;
190  maxHeightTiming = vec[iVec].m_time;
191  }
192  }
193  if (maxPulseHeight > m_calibrationPulseThreshold1)
194  calPulseTiming = maxHeightTiming;
195  } else { //try to identify both of double cal. pulses when specified by option (default)
196  for (unsigned iVec = 0 ; iVec < nCalPulseCandidates ; iVec++) {
197  for (unsigned jVec = 0 ; jVec < nCalPulseCandidates ; jVec++) {
198 
199  if (iVec == jVec || vec[iVec].m_time > vec[jVec].m_time) continue;
200  if (vec[iVec].m_height > m_calibrationPulseThreshold1
201  && vec[jVec].m_height > m_calibrationPulseThreshold2
202  && TMath::Abs(vec[jVec].m_time - vec[iVec].m_time - m_calibrationPulseInterval) < m_calibrationPulseIntervalRange) {
203 
204  //in case multiple candidates of double cal. pulses are found,
205  //choose a pair with the earliest 1st cal. pulse timing
206  if (refTimingMap.count(globalAsicId) == 0 || refTimingMap[globalAsicId] > vec[iVec].m_time)
207  calPulseTiming = vec[iVec].m_time;
208  }
209  }//for(jVec)
210  }//for(iVec)
211  }//if(m_useDoublePulse)
212 
213  if (calPulseTiming < 9999998) { //when cal. pulse(s) are properly identified
214  refTimingMap[globalAsicId] = calPulseTiming;
215  m_nCalPulseHistogram->Fill(globalAsicId);
216  }
217  }//for(pair)
218 
219  //calculate hit timing with respect to cal. pulse and fill hit info. histogram
220  for (const auto& digit : digits) {
221  short slotId = digit.getModuleID();
222  short pixelId = digit.getPixelID();
223  short globalPixelId = (slotId - 1) * c_NPixelPerModule + pixelId - 1;
224  short globalAsicId = globalPixelId / c_NChannelPerAsic;
225 
226  if (digit.getHitQuality() == TOPDigit::c_Junk
227  || digit.getHitQuality() == TOPDigit::c_CrossTalk) continue;
228 
229  float hitTime = digit.getTime() - refTimingMap[globalAsicId];
230  float pulseHeight = digit.getPulseHeight();
231  float Integral = digit.getIntegral();
232  short windowNumberOfHit = (short)(digit.getFirstWindow()) + (short)(digit.getRawTime() / 64);
233  if (m_windowSelect && windowNumberOfHit % 2 != (m_windowSelect - 1)) continue;
234 
235  if (m_includeAllChargeShare) {
236  m_TimeHeightHistogramForHitRate[globalPixelId]->Fill(hitTime, pulseHeight);
237  m_TimeIntegralHistogramForFit[globalPixelId]->Fill(hitTime, Integral);
238  m_TimeHeightHistogramForFit[globalPixelId]->Fill(hitTime, pulseHeight);
239  continue;
240  }
241 
242  if (!digit.isSecondaryChargeShare()) {
243  m_TimeHeightHistogramForHitRate[globalPixelId]->Fill(hitTime, pulseHeight);
244  if (m_includePrimaryChargeShare) {
245  m_TimeIntegralHistogramForFit[globalPixelId]->Fill(hitTime, Integral);
246  m_TimeHeightHistogramForFit[globalPixelId]->Fill(hitTime, pulseHeight);
247  continue;
248  }
249  }
250 
251  if (digit.isSecondaryChargeShare() || digit.isPrimaryChargeShare()) continue;
252  m_TimeIntegralHistogramForFit[globalPixelId]->Fill(hitTime, Integral);
253  m_TimeHeightHistogramForFit[globalPixelId]->Fill(hitTime, pulseHeight);
254  }
255 
256  }
257 
258  void TOPLaserHitSelectorModule::endRun()
259  {
260  }
261 
262  void TOPLaserHitSelectorModule::terminate()
263  {
264  }
265 
267 } // end Belle2 namespace
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TOPLaserHitSelectorModule::hitInfo_t
structure to hold hit information, used in double cal.
Definition: TOPLaserHitSelectorModule.h:52
Belle2::StoreArray
Accessor to arrays stored in the data store.
Definition: ECLMatchingPerformanceExpertModule.h:33
Belle2::TOPLaserHitSelectorModule
Module for pixel-by-pixel gain/efficiency analysis.
Definition: TOPLaserHitSelectorModule.h:45
Belle2::HistoModule
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
Definition: HistoModule.h:29