12 #include <top/modules/TOPAligner/TOPAlignerModule.h>
13 #include <top/geometry/TOPGeometryPar.h>
14 #include <top/reconstruction/TOPalign.h>
15 #include <top/reconstruction/TOPtrack.h>
16 #include <top/reconstruction/TOPconfigure.h>
19 #include <framework/datastore/StoreArray.h>
20 #include <framework/datastore/StoreObjPtr.h>
23 #include <framework/gearbox/Const.h>
24 #include <framework/logging/Logger.h>
27 #include <analysis/utility/PCmsLabTransform.h>
58 setDescription(
"Alignment of TOP");
62 addParam(
"minBkgPerBar", m_minBkgPerBar,
63 "Minimal number of background photons per module", 0.0);
64 addParam(
"scaleN0", m_scaleN0,
65 "Scale factor for figure-of-merit N0", 1.0);
66 addParam(
"targetModule", m_targetMid,
67 "Module to be aligned. Must be 1 <= Mid <= 16.", 1);
68 addParam(
"maxFails", m_maxFails,
69 "Maximum number of consecutive failed iterations before resetting the procedure", 100);
70 addParam(
"sample", m_sample,
71 "sample type: one of dimuon, bhabha or cosmics", std::string(
"dimuon"));
72 addParam(
"minMomentum", m_minMomentum,
73 "minimal track momentum if sample is cosmics", 1.0);
74 addParam(
"deltaEcms", m_deltaEcms,
75 "c.m.s energy window (half size) if sample is dimuon or bhabha", 0.1);
76 addParam(
"dr", m_dr,
"cut on POCA in r", 2.0);
77 addParam(
"dz", m_dz,
"cut on POCA in abs(z)", 4.0);
78 addParam(
"minZ", m_minZ,
79 "minimal local z of extrapolated hit", -130.0);
80 addParam(
"maxZ", m_maxZ,
81 "maximal local z of extrapolated hit", 130.0);
82 addParam(
"outFileName", m_outFileName,
83 "Root output file name containing alignment results",
84 std::string(
"TopAlignPars.root"));
85 addParam(
"stepPosition", m_stepPosition,
"step size for translations", 1.0);
86 addParam(
"stepAngle", m_stepAngle,
"step size for rotations", 0.01);
87 addParam(
"stepTime", m_stepTime,
"step size for t0", 0.05);
88 addParam(
"stepRefind", m_stepRefind,
89 "step size for scaling of refractive index (dn/n)", 0.005);
90 addParam(
"gridSize", m_gridSize,
91 "size of a 2D grid for time-of-propagation averaging in analytic PDF: "
92 "[number of emission points along track, number of Cerenkov angles]. "
93 "No grid used if list is empty.", m_gridSize);
95 for (
const auto& parName : m_align.getParameterNames()) names += parName +
", ";
98 addParam(
"parInit", m_parInit,
99 "initial parameter values in the order [" + names +
"]. "
100 "If list is too short, the missing ones are set to 0.", m_parInit);
101 auto parFixed = m_parFixed;
102 addParam(
"parFixed", m_parFixed,
"list of names of parameters to be fixed. "
103 "Valid names are: " + names, parFixed);
107 TOPAlignerModule::~TOPAlignerModule()
111 void TOPAlignerModule::initialize()
116 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
117 if (!geo->isModuleIDValid(m_targetMid))
118 B2FATAL(
"Target module ID = " << m_targetMid <<
" is invalid. Exiting...");
122 if (!(m_sample ==
"dimuon" or m_sample ==
"bhabha" or m_sample ==
"cosmics")) {
123 B2FATAL(
"Invalid sample type " << m_sample <<
". Exiting...");
125 if (m_sample ==
"bhabha") m_chargedStable = Const::electron;
129 m_align.setModuleID(m_targetMid);
130 m_align.setSteps(m_stepPosition, m_stepAngle, m_stepTime, m_stepRefind);
131 if (m_gridSize.size() == 2) {
132 m_align.setGrid(m_gridSize[0], m_gridSize[1]);
133 B2INFO(
"TOPAligner: grid for time-of-propagation averaging is set");
135 m_align.setParameters(m_parInit);
136 for (
const auto& parName : m_parFixed) {
137 m_align.fixParameter(parName);
146 m_digits.isRequired();
147 m_tracks.isRequired();
148 m_extHits.isRequired();
149 m_recBunch.isOptional();
157 m_file =
new TFile(m_outFileName.c_str(),
"RECREATE");
158 if (m_file->IsZombie()) {
159 B2FATAL(
"Couldn't open file '" << m_outFileName <<
"' for writing!");
165 m_alignTree =
new TTree(
"alignTree",
"TOP alignment results");
166 m_alignTree->Branch(
"ModuleId", &m_targetMid);
167 m_alignTree->Branch(
"iter", &m_iter);
168 m_alignTree->Branch(
"ntrk", &m_ntrk);
169 m_alignTree->Branch(
"errorCode", &m_errorCode);
170 m_alignTree->Branch(
"iterPars", &m_vAlignPars);
171 m_alignTree->Branch(
"iterParsErr", &m_vAlignParsErr);
172 m_alignTree->Branch(
"valid", &m_valid);
173 m_alignTree->Branch(
"x", &m_x);
174 m_alignTree->Branch(
"y", &m_y);
175 m_alignTree->Branch(
"z", &m_z);
176 m_alignTree->Branch(
"p", &m_p);
177 m_alignTree->Branch(
"theta", &m_theta);
178 m_alignTree->Branch(
"phi", &m_phi);
179 m_alignTree->Branch(
"r_poca", &m_pocaR);
180 m_alignTree->Branch(
"z_poca", &m_pocaZ);
181 m_alignTree->Branch(
"x_poca", &m_pocaX);
182 m_alignTree->Branch(
"y_poca", &m_pocaY);
183 m_alignTree->Branch(
"Ecms", &m_cmsE);
184 m_alignTree->Branch(
"charge", &m_charge);
185 m_alignTree->Branch(
"PDG", &m_PDG);
189 void TOPAlignerModule::beginRun()
193 void TOPAlignerModule::event()
200 if (m_recBunch.isValid()) {
201 if (!m_recBunch->isReconstructed())
return;
206 TOPalign::clearData();
208 for (
const auto& digit : m_digits) {
209 if (digit.getHitQuality() == TOPDigit::EHitQuality::c_Good)
210 TOPalign::addData(digit.getModuleID(), digit.getPixelID(), digit.getTime(),
211 digit.getTimeError());
214 TOPalign::setPhotonYields(m_minBkgPerBar, m_scaleN0);
218 for (
const auto& track : m_tracks) {
228 if (!selectTrack(trk))
continue;
231 int err = m_align.iterate(trk, m_chargedStable);
237 }
else if (m_countFails <= m_maxFails) {
240 B2INFO(
"Reached maximum allowed number of failed iterations. "
241 "Resetting TOPalign object");
247 m_vAlignPars = m_align.getParameters();
248 m_vAlignParsErr = m_align.getErrors();
249 m_ntrk = m_align.getNumUsedTracks();
251 m_valid = m_align.isValid();
257 TString resMsg =
"M= ";
258 resMsg += m_align.getModuleID();
262 resMsg += m_errorCode;
264 resMsg += m_align.isValid();
265 for (
auto par : m_vAlignPars) {
269 B2DEBUG(100, resMsg);
276 void TOPAlignerModule::endRun()
280 void TOPAlignerModule::terminate()
284 m_alignTree->Write();
286 TH1F valid(
"valid",
"status valid", 16, 0.5, 16.5);
287 valid.SetXTitle(
"slot ID");
288 valid.SetBinContent(m_targetMid, m_valid);
291 TH1F ntrk(
"ntrk",
"number of tracks", 16, 0.5, 16.5);
292 ntrk.SetXTitle(
"slot ID");
293 ntrk.SetBinContent(m_targetMid, m_ntrk);
296 std::string name, title;
297 name =
"results_slot" + to_string(m_targetMid);
298 title =
"alignment parameters, slot " + to_string(m_targetMid);
299 int npar = m_align.getParameters().size();
300 TH1F h0(name.c_str(), title.c_str(), npar, 0, npar);
301 const auto& par = m_align.getParameters();
302 const auto& err = m_align.getErrors();
303 for (
int i = 0; i < npar; i++) {
304 h0.SetBinContent(i + 1, par[i]);
305 h0.SetBinError(i + 1, err[i]);
309 name =
"errMatrix_slot" + to_string(m_targetMid);
310 title =
"error matrix, slot " + to_string(m_targetMid);
311 TH2F h1(name.c_str(), title.c_str(), npar, 0, npar, npar, 0, npar);
312 const auto& errMatrix = m_align.getErrorMatrix();
313 for (
int i = 0; i < npar; i++) {
314 for (
int k = 0; k < npar; k++) {
315 h1.SetBinContent(i + 1, k + 1, errMatrix[i + npar * k]);
320 name =
"corMatrix_slot" + to_string(m_targetMid);
321 title =
"correlation matrix, slot " + to_string(m_targetMid);
322 TH2F h2(name.c_str(), title.c_str(), npar, 0, npar, npar, 0, npar);
323 std::vector<double> diag;
324 for (
int i = 0; i < npar; i++) {
325 double d = errMatrix[i * (1 + npar)];
326 if (d != 0) d = 1.0 / sqrt(d);
329 for (
int i = 0; i < npar; i++) {
330 for (
int k = 0; k < npar; k++) {
331 h2.SetBinContent(i + 1, k + 1, diag[i] * diag[k] * errMatrix[i + npar * k]);
339 B2RESULT(
"TOPAligner: slot = " << m_targetMid <<
", status = successful, "
340 <<
"iterations = " << m_iter <<
", tracks used = " << m_ntrk);
342 B2RESULT(
"TOPAligner: slot = " << m_targetMid <<
", status = failed, "
343 <<
"error code = " << m_errorCode
344 <<
", iterations = " << m_iter <<
", tracks used = " << m_ntrk);
352 auto pocaPosition = fit->getPosition();
353 m_pocaR = pocaPosition.Perp();
354 m_pocaZ = pocaPosition.Z();
355 m_pocaX = pocaPosition.X();
356 m_pocaY = pocaPosition.Y();
357 if (m_pocaR > m_dr)
return false;
358 if (fabs(m_pocaZ) > m_dz)
return false;
360 auto pocaMomentum = fit->getMomentum();
362 if (m_sample ==
"cosmics") {
363 if (pocaMomentum.Mag() < m_minMomentum)
return false;
365 TLorentzVector lorentzLab;
366 lorentzLab.SetXYZM(pocaMomentum.X(), pocaMomentum.Y(), pocaMomentum.Z(),
367 m_chargedStable.getMass());
369 auto lorentzCms = T.
labToCms(lorentzLab);
370 m_cmsE = lorentzCms.Energy();
372 if (fabs(dE) > m_deltaEcms)
return false;
375 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
376 const auto& module = geo->getModule(m_targetMid);
377 auto position = module.pointToLocal(trk.
getPosition());
378 auto momentum = module.momentumToLocal(trk.
getMomentum());
382 m_p = momentum.Mag();
383 m_theta = momentum.Theta();
384 m_phi = momentum.Phi();
388 if (m_z < m_minZ or m_z > m_maxZ)
return false;