9 #include <top/modules/collectors/TOPAlignmentCollectorModule.h>
10 #include <top/geometry/TOPGeometryPar.h>
11 #include <top/reconstruction_cpp/TOPTrack.h>
14 #include <framework/logging/Logger.h>
42 TOPAlignmentCollectorModule::TOPAlignmentCollectorModule()
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);
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);
66 for (
const auto& parName : align.getParameterNames()) names += parName +
", ";
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);
79 void TOPAlignmentCollectorModule::prepare()
83 m_digits.isRequired();
84 m_tracks.isRequired();
85 m_extHits.isRequired();
86 m_recBunch.isRequired();
90 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
91 if (!geo->isModuleIDValid(m_targetMid)) {
92 B2FATAL(
"Target module ID = " << m_targetMid <<
" is invalid. Exiting...");
97 if (m_sample ==
"dimuon" or m_sample ==
"bhabha") {
99 m_selector.setDeltaEcms(m_deltaEcms);
100 m_selector.setCutOnPOCA(m_dr, m_dz);
101 m_selector.setCutOnLocalZ(m_minZ, m_maxZ);
103 B2ERROR(
"Invalid sample type '" << m_sample <<
"'");
108 for (
int set = 0; set < c_numSets; set++) {
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);
116 m_align.push_back(align);
117 m_countFails.push_back(0);
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);
129 for (
int slot = 1; slot <= numModules; slot++) {
130 std::string slotName =
"_s" + to_string(slot);
131 std::string slotTitle =
"(slot " + to_string(slot) +
")";
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);
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);
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);
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);
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);
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);
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);
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);
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);
216 void TOPAlignmentCollectorModule::collect()
220 if (not m_recBunch.isValid())
return;
221 if (not m_recBunch->isReconstructed())
return;
225 for (
const auto& track : m_tracks) {
229 if (not trk.
isValid())
continue;
235 if (not m_selector.isSelected(trk))
continue;
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");
246 int err = align.iterate(trk, m_selector.getChargedStable());
252 }
else if (countFails <= m_maxFails) {
255 B2INFO(
"Reached maximum allowed number of failed iterations. "
256 "Resetting TOPalign object of set = " << sub <<
" at iter = " << m_iter);
262 m_vAlignPars = align.getParameters();
263 m_vAlignParsErr = align.getErrors();
264 m_ntrk = align.getNumUsedTracks();
266 m_valid = align.isValid();
267 m_numPhot = align.getNumOfPhotons();
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();
288 auto alignTree = getObjectPtr<TTree>(name);
292 std::string slotName =
"_s" + to_string(m_targetMid);
293 auto h2 = getObjectPtr<TH1F>(
"local_z" + slotName);
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);
301 auto h6 = getObjectPtr<TH1F>(
"Ecms" + slotName);
303 auto h7 = getObjectPtr<TH1F>(
"charge" + slotName);
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());
311 auto h9 = getObjectPtr<TH1F>(
"numPhot" + slotName);
Alignment of a TOP module.
Reconstructed track at TOP.
int getPDGCode() const
Returns PDG code of associated MCParticle (returns 0 if none)
double getCharge() const
Returns charge.
bool isValid() const
Checks if track is successfully constructed.
int getModuleID() const
Returns slot ID.
Utility for the track selection - used in various calibration modules.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.