Belle II Software  release-08-01-10
TOPAlignmentCollectorModule.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 <top/modules/collectors/TOPAlignmentCollectorModule.h>
10 #include <top/geometry/TOPGeometryPar.h>
11 #include <top/reconstruction_cpp/TOPTrack.h>
12 
13 // framework aux
14 #include <framework/logging/Logger.h>
15 
16 // root
17 #include <TTree.h>
18 #include <TH1F.h>
19 #include <TH2F.h>
20 #include <TRandom.h>
21 
22 using namespace std;
23 
24 namespace Belle2 {
30  using namespace TOP;
31 
32  //-----------------------------------------------------------------
34  //-----------------------------------------------------------------
35 
36  REG_MODULE(TOPAlignmentCollector);
37 
38  //-----------------------------------------------------------------
39  // Implementation
40  //-----------------------------------------------------------------
41 
42  TOPAlignmentCollectorModule::TOPAlignmentCollectorModule()
43  {
44  // set module description and processing properties
45  setDescription("A collector for geometrical alignment of a TOP module with dimuons or Bhabhas. Iterative alignment procedure (NIMA 876 (2017) 260-264) is run here, algorithm just collects the results.");
46  setPropertyFlags(c_ParallelProcessingCertified);
47 
48  // module parameters
49  addParam("targetModule", m_targetMid,
50  "Module to be aligned. Must be 1 <= Mid <= 16.");
51  addParam("maxFails", m_maxFails,
52  "Maximum number of consecutive failed iterations before resetting the procedure", 100);
53  addParam("sample", m_sample,
54  "sample type: one of dimuon or bhabha", std::string("dimuon"));
55  addParam("deltaEcms", m_deltaEcms,
56  "c.m.s energy window (half size) if sample is dimuon or bhabha", 0.1);
57  addParam("dr", m_dr, "cut on POCA in r", 1.0);
58  addParam("dz", m_dz, "cut on POCA in abs(z)", 2.0);
59  addParam("minZ", m_minZ, "minimal local z of extrapolated hit", -130.0);
60  addParam("maxZ", m_maxZ, "maximal local z of extrapolated hit", 130.0);
61  addParam("stepPosition", m_stepPosition, "step size for translations", 1.0);
62  addParam("stepAngle", m_stepAngle, "step size for rotations", 0.01);
63  addParam("stepTime", m_stepTime, "step size for t0", 0.05);
64  std::string names;
65  auto align = ModuleAlignment();
66  for (const auto& parName : align.getParameterNames()) names += parName + ", ";
67  names.pop_back();
68  names.pop_back();
69  addParam("parInit", m_parInit,
70  "initial parameter values in the order [" + names + "]. "
71  "If list is too short, the missing ones are set to 0.", m_parInit);
72  auto parFixed = m_parFixed;
73  addParam("parFixed", m_parFixed, "list of names of parameters to be fixed. "
74  "Valid names are: " + names, parFixed);
75 
76  }
77 
78 
79  void TOPAlignmentCollectorModule::prepare()
80  {
81  // input collections
82 
83  m_digits.isRequired();
84  m_tracks.isRequired();
85  m_extHits.isRequired();
86  m_recBunch.isRequired();
87 
88  // check if target module ID is valid
89 
90  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
91  if (!geo->isModuleIDValid(m_targetMid)) {
92  B2FATAL("Target module ID = " << m_targetMid << " is invalid. Exiting...");
93  }
94 
95  // set track selector
96 
97  if (m_sample == "dimuon" or m_sample == "bhabha") {
98  m_selector = TrackSelector(m_sample);
99  m_selector.setDeltaEcms(m_deltaEcms);
100  m_selector.setCutOnPOCA(m_dr, m_dz);
101  m_selector.setCutOnLocalZ(m_minZ, m_maxZ);
102  } else {
103  B2ERROR("Invalid sample type '" << m_sample << "'");
104  }
105 
106  // set alignment objects
107 
108  for (int set = 0; set < c_numSets; set++) {
109  auto align = ModuleAlignment();
110  align.setModuleID(m_targetMid);
111  align.setSteps(m_stepPosition, m_stepAngle, m_stepTime);
112  align.setParameters(m_parInit);
113  for (const auto& parName : m_parFixed) {
114  align.fixParameter(parName);
115  }
116  m_align.push_back(align);
117  m_countFails.push_back(0);
118  }
119 
120  // create and register output histograms and ntuples
121 
122  int numModules = geo->getNumModules();
123  auto h1 = new TH2F("tracks_per_slot", "Number of tracks per slot and sample",
124  numModules, 0.5, numModules + 0.5, c_numSets, 0, c_numSets);
125  h1->SetXTitle("slot number");
126  h1->SetYTitle("sample number");
127  registerObject<TH2F>("tracks_per_slot", h1);
128 
129  for (int slot = 1; slot <= numModules; slot++) {
130  std::string slotName = "_s" + to_string(slot);
131  std::string slotTitle = "(slot " + to_string(slot) + ")";
132 
133  std::string hname = "local_z" + slotName;
134  std::string title = "Distribution of tracks along bar " + slotTitle;
135  auto h2 = new TH1F(hname.c_str(), title.c_str(), 100, -150.0, 150.0);
136  h2->SetXTitle("local z [cm]");
137  registerObject<TH1F>(hname, h2);
138 
139  hname = "cth_vs_p" + slotName;
140  title = "Track momentum " + slotTitle;
141  auto h3 = new TH2F(hname.c_str(), title.c_str(), 100, 0.0, 7.0, 100, -1.0, 1.0);
142  h3->SetXTitle("p [GeV/c]");
143  h3->SetYTitle("cos #theta");
144  registerObject<TH2F>(hname, h3);
145 
146  hname = "poca_xy" + slotName;
147  title = "Track POCA in x-y " + slotTitle;
148  auto h4 = new TH2F(hname.c_str(), title.c_str(), 100, -m_dr, m_dr, 100, -m_dr, m_dr);
149  h4->SetXTitle("x [cm]");
150  h4->SetYTitle("y [cm]");
151  registerObject<TH2F>(hname, h4);
152 
153  hname = "poca_z" + slotName;
154  title = "Track POCA in z " + slotTitle;
155  auto h5 = new TH1F(hname.c_str(), title.c_str(), 100, -m_dz, m_dz);
156  h5->SetXTitle("z [cm]");
157  registerObject<TH1F>(hname, h5);
158 
159  hname = "Ecms" + slotName;
160  title = "Track c.m.s. energy " + slotTitle;
161  auto h6 = new TH1F(hname.c_str(), title.c_str(), 100, 5.1, 5.4);
162  h6->SetXTitle("E_{cms} [GeV]");
163  registerObject<TH1F>(hname, h6);
164 
165  hname = "charge" + slotName;
166  title = "Charge of track " + slotTitle;
167  auto h7 = new TH1F(hname.c_str(), title.c_str(), 3, -1.5, 1.5);
168  h7->SetXTitle("charge");
169  registerObject<TH1F>(hname, h7);
170 
171  hname = "timeHits" + slotName;
172  title = "Photon time distribution " + slotTitle;
173  auto h8 = new TH2F(hname.c_str(), title.c_str(), 512, 0, 512, 200, 0, 50);
174  h8->SetXTitle("channel number");
175  h8->SetYTitle("time [ns]");
176  registerObject<TH2F>(hname, h8);
177 
178  hname = "numPhot" + slotName;
179  title = "Number of photons " + slotTitle;
180  auto h9 = new TH1F(hname.c_str(), title.c_str(), 100, 0, 100);
181  h9->SetXTitle("photons per track");
182  registerObject<TH1F>(hname, h9);
183  }
184 
185  for (int set = 0; set < c_numSets; set++) {
186  std::string name = "alignTree" + to_string(set);
187  m_treeNames.push_back(name);
188  auto alignTree = new TTree(name.c_str(), "TOP alignment results");
189  alignTree->Branch("ModuleId", &m_targetMid);
190  alignTree->Branch("iter", &m_iter);
191  alignTree->Branch("ntrk", &m_ntrk);
192  alignTree->Branch("errorCode", &m_errorCode);
193  alignTree->Branch("iterPars", &m_vAlignPars);
194  alignTree->Branch("iterParsErr", &m_vAlignParsErr);
195  alignTree->Branch("valid", &m_valid);
196  alignTree->Branch("numPhot", &m_numPhot);
197  alignTree->Branch("x", &m_x);
198  alignTree->Branch("y", &m_y);
199  alignTree->Branch("z", &m_z);
200  alignTree->Branch("p", &m_p);
201  alignTree->Branch("theta", &m_theta);
202  alignTree->Branch("phi", &m_phi);
203  alignTree->Branch("r_poca", &m_pocaR);
204  alignTree->Branch("z_poca", &m_pocaZ);
205  alignTree->Branch("x_poca", &m_pocaX);
206  alignTree->Branch("y_poca", &m_pocaY);
207  alignTree->Branch("Ecms", &m_cmsE);
208  alignTree->Branch("charge", &m_charge);
209  alignTree->Branch("PDG", &m_PDG);
210  registerObject<TTree>(name, alignTree);
211  }
212 
213  }
214 
215 
216  void TOPAlignmentCollectorModule::collect()
217  {
218  // bunch must be reconstructed
219 
220  if (not m_recBunch.isValid()) return;
221  if (not m_recBunch->isReconstructed()) return;
222 
223  // track-by-track iterations
224 
225  for (const auto& track : m_tracks) {
226 
227  // construct TOPTrack from mdst track
228  TOPTrack trk(track);
229  if (not trk.isValid()) continue;
230 
231  // skip if track not hitting target module
232  if (trk.getModuleID() != m_targetMid) continue;
233 
234  // track selection
235  if (not m_selector.isSelected(trk)) continue;
236 
237  // generate sub-sample number
238  int sub = gRandom->Integer(c_numSets);
239  auto& align = m_align[sub];
240  auto& countFails = m_countFails[sub];
241  const auto& name = m_treeNames[sub];
242  auto h1 = getObjectPtr<TH2F>("tracks_per_slot");
243  h1->Fill(trk.getModuleID(), sub);
244 
245  // do an iteration
246  int err = align.iterate(trk, m_selector.getChargedStable());
247  m_iter++;
248 
249  // check number of consecutive failures, and in case reset
250  if (err == 0) {
251  countFails = 0;
252  } else if (countFails <= m_maxFails) {
253  countFails++;
254  } else {
255  B2INFO("Reached maximum allowed number of failed iterations. "
256  "Resetting TOPalign object of set = " << sub << " at iter = " << m_iter);
257  align.reset();
258  countFails = 0;
259  }
260 
261  // get new parameter values and estimated errors
262  m_vAlignPars = align.getParameters();
263  m_vAlignParsErr = align.getErrors();
264  m_ntrk = align.getNumUsedTracks();
265  m_errorCode = err;
266  m_valid = align.isValid();
267  m_numPhot = align.getNumOfPhotons();
268 
269  // set other ntuple variables
270  const auto& localPosition = m_selector.getLocalPosition();
271  m_x = localPosition.X();
272  m_y = localPosition.Y();
273  m_z = localPosition.Z();
274  const auto& localMomentum = m_selector.getLocalMomentum();
275  m_p = localMomentum.R();
276  m_theta = localMomentum.Theta();
277  m_phi = localMomentum.Phi();
278  const auto& pocaPosition = m_selector.getPOCAPosition();
279  m_pocaR = pocaPosition.Rho();
280  m_pocaZ = pocaPosition.Z();
281  m_pocaX = pocaPosition.X();
282  m_pocaY = pocaPosition.Y();
283  m_cmsE = m_selector.getCMSEnergy();
284  m_charge = trk.getCharge();
285  m_PDG = trk.getPDGCode();
286 
287  // fill output tree
288  auto alignTree = getObjectPtr<TTree>(name);
289  alignTree->Fill();
290 
291  // fill control histograms
292  std::string slotName = "_s" + to_string(m_targetMid);
293  auto h2 = getObjectPtr<TH1F>("local_z" + slotName);
294  h2->Fill(m_z);
295  auto h3 = getObjectPtr<TH2F>("cth_vs_p" + slotName);
296  h3->Fill(m_p, cos(m_theta));
297  auto h4 = getObjectPtr<TH2F>("poca_xy" + slotName);
298  h4->Fill(m_pocaX, m_pocaY);
299  auto h5 = getObjectPtr<TH1F>("poca_z" + slotName);
300  h5->Fill(m_pocaZ);
301  auto h6 = getObjectPtr<TH1F>("Ecms" + slotName);
302  h6->Fill(m_cmsE);
303  auto h7 = getObjectPtr<TH1F>("charge" + slotName);
304  h7->Fill(m_charge);
305  auto h8 = getObjectPtr<TH2F>("timeHits" + slotName);
306  for (const auto& digit : m_digits) {
307  if (digit.getHitQuality() != TOPDigit::c_Good) continue;
308  if (digit.getModuleID() != m_targetMid) continue;
309  h8->Fill(digit.getChannel(), digit.getTime());
310  }
311  auto h9 = getObjectPtr<TH1F>("numPhot" + slotName);
312  h9->Fill(m_numPhot);
313 
314  } // tracks
315 
316  }
317 
319 } // Belle2
Alignment of a TOP module.
Reconstructed track at TOP.
Definition: TOPTrack.h:39
int getPDGCode() const
Returns PDG code of associated MCParticle (returns 0 if none)
Definition: TOPTrack.h:228
double getCharge() const
Returns charge.
Definition: TOPTrack.h:161
bool isValid() const
Checks if track is successfully constructed.
Definition: TOPTrack.h:137
int getModuleID() const
Returns slot ID.
Definition: TOPTrack.h:143
Utility for the track selection - used in various calibration modules.
Definition: TrackSelector.h:27
#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.