Belle II Software  release-05-01-25
TOPCommonT0LLCollectorModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2019 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Marko Staric *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <top/modules/collectors/TOPCommonT0LLCollectorModule.h>
12 #include <top/geometry/TOPGeometryPar.h>
13 #include <top/reconstruction/TOPreco.h>
14 #include <top/reconstruction/TOPtrack.h>
15 #include <top/reconstruction/TOPconfigure.h>
16 
17 // framework aux
18 #include <framework/gearbox/Const.h>
19 #include <framework/logging/Logger.h>
20 
21 // root
22 #include <TRandom.h>
23 #include <TH1F.h>
24 #include <TH1D.h>
25 #include <TH2F.h>
26 
27 using namespace std;
28 
29 namespace Belle2 {
35  using namespace TOP;
36 
37  //-----------------------------------------------------------------
38  // Register module
39  //-----------------------------------------------------------------
40 
41  REG_MODULE(TOPCommonT0LLCollector)
42 
43  //-----------------------------------------------------------------
44  // Implementation
45  //-----------------------------------------------------------------
46 
48  {
49  // set module description and processing properties
50  setDescription("A collector for common T0 calibration with dimuons or Bhabha's using "
51  "neg. log likelihood minimization (method LL)");
52  setPropertyFlags(c_ParallelProcessingCertified);
53 
54  // module parameters
55  addParam("bunchesPerSSTclk", m_bunchesPerSSTclk,
56  "number of bunches per SST clock period", 24);
57  addParam("numBins", m_numBins, "number of bins of the search region", 200);
58  addParam("timeRange", m_timeRange,
59  "time range in which to search for the minimum [ns]", 10.0);
60  addParam("minBkgPerBar", m_minBkgPerBar,
61  "minimal number of background photons per module", 0.0);
62  addParam("scaleN0", m_scaleN0,
63  "Scale factor for figure-of-merit N0", 1.0);
64  addParam("sigmaSmear", m_sigmaSmear,
65  "sigma in [ns] for additional smearing of PDF", 0.0);
66  addParam("sample", m_sample,
67  "sample type: one of dimuon or bhabha", std::string("dimuon"));
68  addParam("deltaEcms", m_deltaEcms,
69  "c.m.s energy window (half size) if sample is dimuon or bhabha", 0.1);
70  addParam("dr", m_dr, "cut on POCA in r", 2.0);
71  addParam("dz", m_dz, "cut on POCA in abs(z)", 4.0);
72  addParam("minZ", m_minZ,
73  "minimal local z of extrapolated hit", -130.0);
74  addParam("maxZ", m_maxZ,
75  "maximal local z of extrapolated hit", 130.0);
76  addParam("pdfOption", m_pdfOption,
77  "PDF option, one of 'rough', 'fine', 'optimal'", std::string("rough"));
78  }
79 
80 
81  void TOPCommonT0LLCollectorModule::prepare()
82  {
83  // input collections
84 
85  m_digits.isRequired();
86  m_tracks.isRequired();
87  m_extHits.isRequired();
88  m_recBunch.isRequired();
89 
90  // bunch time separation
91 
92  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
93  m_bunchTimeSep = geo->getNominalTDC().getSyncTimeBase() / m_bunchesPerSSTclk;
94 
95  // Configure TOP detector for reconstruction
96 
97  TOPconfigure config;
98 
99  // Parse PDF option
100 
101  if (m_pdfOption == "rough") {
102  m_PDFOption = TOPreco::c_Rough;
103  } else if (m_pdfOption == "fine") {
104  m_PDFOption = TOPreco::c_Fine;
105  } else if (m_pdfOption == "optimal") {
106  m_PDFOption = TOPreco::c_Optimal;
107  } else {
108  B2ERROR("Unknown PDF option '" << m_pdfOption << "'");
109  }
110 
111  // set track selector
112 
113  if (m_sample == "dimuon" or m_sample == "bhabha") {
114  m_selector = TrackSelector(m_sample);
115  m_selector.setDeltaEcms(m_deltaEcms);
116  m_selector.setCutOnPOCA(m_dr, m_dz);
117  m_selector.setCutOnLocalZ(m_minZ, m_maxZ);
118  } else {
119  B2ERROR("Invalid sample type '" << m_sample << "'");
120  }
121 
122  // create and register histograms
123 
124  double tmin = -m_timeRange / 2;
125  double tmax = m_timeRange / 2;
126  for (unsigned i = 0; i < c_numSets; i++) {
127  string name = "chi2_set" + to_string(i);
128  auto h = new TH1D(name.c_str(), "chi2 scan; t0 [ns]; chi2", m_numBins, tmin, tmax);
129  registerObject<TH1D>(name, h);
130  m_names.push_back(name);
131  }
132 
133  auto h1 = new TH1F("tracks_per_set", "tracks per sample; sample number; num tracks",
134  c_numSets, 0, c_numSets);
135  registerObject<TH1F>("tracks_per_set", h1);
136 
137  auto h2 = new TH1F("numHits", "Number of photons per slot",
138  c_numModules, 0.5, c_numModules + 0.5);
139  h2->SetXTitle("slot number");
140  h2->SetYTitle("hits per slot");
141  registerObject<TH1F>("numHits", h2);
142 
143  auto h3 = new TH2F("timeHits", "Photon times vs. boardstacks",
144  c_numModules * 4, 0.5, c_numModules + 0.5, 200, 0.0, 20.0);
145  h3->SetXTitle("slot number");
146  h3->SetYTitle("time [ns]");
147  registerObject<TH2F>("timeHits", h3);
148 
149  // this one is needed primarely to pass bunch time separation to the algorithm,
150  // since DB interface doesn't work there
151  auto h4 = new TH1F("offset", "current offset from input files; offset [ns]",
152  200, -m_bunchTimeSep / 2, m_bunchTimeSep / 2);
153  registerObject<TH1F>("offset", h4);
154 
155  }
156 
157 
158  void TOPCommonT0LLCollectorModule::collect()
159  {
160  // bunch must be reconstructed
161 
162  if (not m_recBunch.isValid()) return;
163  if (not m_recBunch->isReconstructed()) return;
164 
165  // create reconstruction object and set various options
166 
167  int Nhyp = 1;
168  double mass = m_selector.getChargedStable().getMass();
169  int pdg = m_selector.getChargedStable().getPDGCode();
170  TOPreco reco(Nhyp, &mass, &pdg, m_minBkgPerBar, m_scaleN0);
171  reco.setPDFoption(m_PDFOption);
172  const auto& tdc = TOPGeometryPar::Instance()->getGeometry()->getNominalTDC();
173  double timeMin = tdc.getTimeMin();
174  double timeMax = tdc.getTimeMax();
175 
176  // add photon hits to reconstruction object with time corrected-back for common T0
177 
178  double T0 = 0;
179  if (m_commonT0->isCalibrated()) T0 = m_commonT0->getT0();
180  for (const auto& digit : m_digits) {
181  if (digit.getHitQuality() == TOPDigit::c_Good) {
182  double t = digit.getTime();
183  if (digit.isCommonT0Calibrated()) t += T0;
184  if (digit.hasStatus(TOPDigit::c_BunchOffsetSubtracted)) {
185  t += m_recBunch->getAverageOffset();
186  }
187  reco.addData(digit.getModuleID(), digit.getPixelID(), t, digit.getTimeError());
188  }
189  }
190 
191  // loop over reconstructed tracks, make a selection and accumulate log likelihoods
192 
193  int ntra = 0;
194  for (const auto& track : m_tracks) {
195 
196  // track selection
197  TOPtrack trk(&track);
198  if (not trk.isValid()) continue;
199 
200  if (not m_selector.isSelected(trk)) continue;
201 
202  // run reconstruction
203  reco.reconstruct(trk);
204  if (reco.getFlag() != 1) continue; // track is not in the acceptance of TOP
205 
206  // minimization procedure: accumulate
207  int sub = gRandom->Integer(c_numSets); // generate sub-sample number
208  auto h = getObjectPtr<TH1D>(m_names[sub]);
209  for (int ibin = 0; ibin < h->GetNbinsX(); ibin++) {
210  double t0 = h->GetBinCenter(ibin + 1);
211  double chi = h->GetBinContent(ibin + 1);
212  chi += -2 * reco.getLogL(t0, timeMin, timeMax, m_sigmaSmear);
213  h->SetBinContent(ibin + 1, chi);
214  }
215  auto h1 = getObjectPtr<TH1F>("tracks_per_set");
216  h1->Fill(sub);
217 
218  // fill histograms of hits
219  auto h2 = getObjectPtr<TH1F>("numHits");
220  auto h3 = getObjectPtr<TH2F>("timeHits");
221  for (const auto& digit : m_digits) {
222  if (digit.getHitQuality() != TOPDigit::c_Good) continue;
223  if (digit.getModuleID() != trk.getModuleID()) continue;
224  if (digit.getTime() < timeMin) continue;
225  if (digit.getTime() > timeMax) continue;
226  h2->Fill(digit.getModuleID());
227  int bs = digit.getBoardstackNumber();
228  h3->Fill((digit.getModuleID() * 4 + bs - 1.5) / 4.0 , digit.getTime());
229  }
230  ntra++;
231  }
232 
233  // fill just another control histogram
234 
235  if (ntra > 0) {
236  auto h4 = getObjectPtr<TH1F>("offset");
237  h4->Fill(m_recBunch->getCurrentOffset());
238  }
239 
240  }
241 
243 }
Belle2::TOP::TOPreco::getFlag
int getFlag()
Return status.
Definition: TOPreco.cc:278
Belle2::TOP::TOPreco::reconstruct
void reconstruct(const TOPtrack &trk, int pdg=0)
Run reconstruction for a given track.
Definition: TOPreco.cc:268
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::TOP::TOPtrack
Class to hold reconstructed track, interface to fortran.
Definition: TOPtrack.h:42
Belle2::TOP::TOPtrack::isValid
bool isValid() const
Check if track is properly defined.
Definition: TOPtrack.h:87
Belle2::TOP::TOPreco::addData
int addData(int moduleID, int pixelID, double time, double timeError)
Add data.
Definition: TOPreco.cc:214
Belle2::TOP::TOPtrack::getModuleID
int getModuleID() const
Return module ID.
Definition: TOPtrack.h:217
Belle2::TOP::TOPreco
TOP reconstruction: this class provides interface to fortran code.
Definition: TOPreco.h:36
Belle2::TOP::TOPreco::getLogL
double getLogL(int i=0)
Return log likelihood for i-th mass hypothesis.
Definition: TOPreco.cc:303
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TOP::TOPconfigure
Configure TOP geometry for reconstruction: provides interface to fortran code.
Definition: TOPconfigure.h:36
Belle2::TOP::TrackSelector
Utility for the track selection - used in various calibration modules.
Definition: TrackSelector.h:37
Belle2::TOPCommonT0LLCollectorModule
Collector for common T0 calibration with neg.
Definition: TOPCommonT0LLCollectorModule.h:47
Belle2::TOP::TOPreco::setPDFoption
void setPDFoption(PDFoption opt, int NP=0, int NC=0)
Sets PDF option.
Definition: TOPreco.cc:196