Belle II Software development
TOPAlignmentAlgorithm.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/calibration/TOPAlignmentAlgorithm.h>
10#include <top/dbobjects/TOPCalModuleAlignment.h>
11
12#include <TFile.h>
13#include <TTree.h>
14#include <TH1F.h>
15#include <TH2F.h>
16
17#include <string>
18#include <algorithm>
19#include <set>
20
21using namespace std;
22
23namespace Belle2 {
28 namespace TOP {
29
31 CalibrationAlgorithm("TOPAlignmentCollector")
32 {
33 setDescription("Calibration algorithm for geometrcal alignment of TOP module");
34 }
35
37 {
38
39 // get basic histogram
40
41 auto h1 = getObjectPtr<TH2F>("tracks_per_slot");
42 if (not h1) {
43 B2ERROR("histogram 'tracks_per_slot' not found");
44 return c_Failure;
45 }
46 unsigned numModules = h1->GetNbinsX();
47 unsigned numSets = h1->GetNbinsY();
48
49 // clear multimap which will hold alignment data from last iterations
50
51 m_inputData.clear();
52
53 // get alignment data of last iterations
54
55 for (unsigned set = 0; set < numSets; set++) {
56
57 // get ntuple of a given subsample
58
59 std::string name = "alignTree" + to_string(set);
60 auto alignTree = getObjectPtr<TTree>(name);
61 if (not alignTree) {
62 B2ERROR("TOPAlignmentAlgorithm: 'alignTree' not found");
63 return c_Failure;
64 }
65
66 alignTree->SetBranchAddress("ModuleId", &m_moduleID);
67 alignTree->SetBranchAddress("iter", &m_iter);
68 alignTree->SetBranchAddress("ntrk", &m_ntrk);
69 alignTree->SetBranchAddress("errorCode", &m_errorCode);
70 alignTree->SetBranchAddress("iterPars", &m_vAlignPars, &m_bAlignPars);
71 alignTree->SetBranchAddress("iterParsErr", &m_vAlignParsErr, &m_bAlignParsErr);
72 alignTree->SetBranchAddress("valid", &m_valid);
73
74 // get last iteration for each module
75
76 std::map<int, int> lastIterations;
77 std::map<int, int> lastIterationEntries;
78 for (int i = 0; i < alignTree->GetEntries(); i++) {
79 alignTree->GetEntry(i);
80 if (m_iter > lastIterations[m_moduleID]) {
81 lastIterations[m_moduleID] = m_iter;
82 lastIterationEntries[m_moduleID] = i;
83 }
84 }
85
86 // store last iteration in a multimap
87
88 for (const auto& lastIterationEntry : lastIterationEntries) {
89 alignTree->GetEntry(lastIterationEntry.second);
90 if (m_vAlignPars->size() != m_vAlignParsErr->size()) {
91 B2ERROR("slot " << m_moduleID << ", set=" << set <<
92 ": sizes of vectors of alignment parameters and errors differ. "
93 "Entry ignored.");
94 continue;
95 }
96 AlignData data;
97 data.iter = m_iter;
98 data.ntrk = m_ntrk;
99 data.alignPars = *m_vAlignPars;
100 data.alignErrs = *m_vAlignParsErr;
101 data.valid = m_valid;
102 m_inputData.emplace(m_moduleID, data);
103 }
104
105 }
106
107 // construct file name, open output root file
108
109 const auto& expRun = getRunList();
110 string expNo = to_string(expRun[0].first);
111 while (expNo.length() < 4) expNo.insert(0, "0");
112 string runNo = to_string(expRun[0].second);
113 while (runNo.length() < 5) runNo.insert(0, "0");
114 string outputFileName = "alignment-e" + expNo + "-r" + runNo + ".root";
115 auto* file = TFile::Open(outputFileName.c_str(), "recreate");
116
117 // write control histograms
118
119 h1->Write();
120 TDirectory* oldDir = gDirectory;
121 for (unsigned slot = 1; slot <= numModules; slot++) {
122 std::string slotName = "_s" + to_string(slot);
123 auto h2 = getObjectPtr<TH1F>("local_z" + slotName);
124 auto h3 = getObjectPtr<TH2F>("cth_vs_p" + slotName);
125 auto h4 = getObjectPtr<TH2F>("poca_xy" + slotName);
126 auto h5 = getObjectPtr<TH1F>("poca_z" + slotName);
127 auto h6 = getObjectPtr<TH1F>("Ecms" + slotName);
128 auto h7 = getObjectPtr<TH1F>("charge" + slotName);
129 auto h8 = getObjectPtr<TH2F>("timeHits" + slotName);
130 auto h9 = getObjectPtr<TH1F>("numPhot" + slotName);
131
132 std::string name = "slot_" + to_string(slot);
133 oldDir->mkdir(name.c_str())->cd();
134 if (h2) h2->Write();
135 if (h3) h3->Write();
136 if (h4) h4->Write();
137 if (h5) h5->Write();
138 if (h6) h6->Write();
139 if (h7) h7->Write();
140 if (h8) h8->Write();
141 if (h9) h9->Write();
142 oldDir->cd();
143 }
144
145 // book output histograms
146
147 auto h_valid = new TH1F("valid", "Valid results",
148 numModules, 0.5, numModules + 0.5);
149 h_valid->SetXTitle("slot number");
150 h_valid->SetYTitle("valid flag");
151
152 auto h_iter = new TH1F("iterations", "Number of iterations",
153 numModules, 0.5, numModules + 0.5);
154 h_iter->SetXTitle("slot number");
155 h_iter->SetYTitle("iterations");
156
157 auto h_ntrk = new TH1F("ntrk", "Number of tracks",
158 numModules, 0.5, numModules + 0.5);
159 h_ntrk->SetXTitle("slot number");
160 h_ntrk->SetYTitle("tracks");
161
162 std::vector<TH1F*> h_params;
163
164 auto h_x = new TH1F("delta_x", "Displacement in x",
165 numModules, 0.5, numModules + 0.5);
166 h_x->SetXTitle("slot number");
167 h_x->SetYTitle("#Deltax [cm]");
168 h_params.push_back(h_x);
169
170 auto h_y = new TH1F("delta_y", "Displacement in y",
171 numModules, 0.5, numModules + 0.5);
172 h_y->SetXTitle("slot number");
173 h_y->SetYTitle("#Deltay [cm]");
174 h_params.push_back(h_y);
175
176 auto h_z = new TH1F("delta_z", "Displacement in z",
177 numModules, 0.5, numModules + 0.5);
178 h_z->SetXTitle("slot number");
179 h_z->SetYTitle("#Deltaz [cm]");
180 h_params.push_back(h_z);
181
182 auto h_alpha = new TH1F("alpha", "Rotation angle around x",
183 numModules, 0.5, numModules + 0.5);
184 h_alpha->SetXTitle("slot number");
185 h_alpha->SetYTitle("#alpha [rad]");
186 h_params.push_back(h_alpha);
187
188 auto h_beta = new TH1F("beta", "Rotation angle around y",
189 numModules, 0.5, numModules + 0.5);
190 h_beta->SetXTitle("slot number");
191 h_beta->SetYTitle("#beta [rad]");
192 h_params.push_back(h_beta);
193
194 auto h_gamma = new TH1F("gamma", "Rotation angle around z",
195 numModules, 0.5, numModules + 0.5);
196 h_gamma->SetXTitle("slot number");
197 h_gamma->SetYTitle("#gamma [rad]");
198 h_params.push_back(h_gamma);
199
200 auto h_t0 = new TH1F("t0", "Module T0",
201 numModules, 0.5, numModules + 0.5);
202 h_t0->SetXTitle("slot number");
203 h_t0->SetYTitle("t_{0} [ns]");
204 h_params.push_back(h_t0);
205
206 auto h_refind = new TH1F("dn_n", "Refractive index scale factor",
207 numModules, 0.5, numModules + 0.5);
208 h_refind->SetXTitle("slot number");
209 h_refind->SetYTitle("#Deltan/n");
210 h_params.push_back(h_refind);
211
212 // create DB object
213
214 auto* alignment = new TOPCalModuleAlignment();
215
216 // merge subsamples
217
218 mergeData();
219
220 // store merged data in histograms and in DB object
221
222 for (const auto& element : m_mergedData) {
223 int moduleID = element.first;
224 const auto& data = element.second;
225 h_valid->SetBinContent(moduleID, data.valid);
226 h_iter->SetBinContent(moduleID, data.iter);
227 h_ntrk->SetBinContent(moduleID, data.ntrk);
228 auto vsize = std::min(data.alignPars.size(), data.alignErrs.size());
229 for (unsigned i = 0; i < std::min(h_params.size(), vsize); i++) {
230 h_params[i]->SetBinContent(moduleID, data.alignPars[i]);
231 h_params[i]->SetBinError(moduleID, data.alignErrs[i]);
232 }
233 if (vsize < 6) {
234 B2ERROR("slot " << moduleID <<
235 ": too few alignment parameters found in ntuple, npar = " << vsize);
236 continue;
237 }
238 alignment->setX(moduleID, data.alignPars[0], data.alignErrs[0]);
239 alignment->setY(moduleID, data.alignPars[1], data.alignErrs[1]);
240 alignment->setZ(moduleID, data.alignPars[2], data.alignErrs[2]);
241 alignment->setAlpha(moduleID, data.alignPars[3], data.alignErrs[3]);
242 alignment->setBeta(moduleID, data.alignPars[4], data.alignErrs[4]);
243 alignment->setGamma(moduleID, data.alignPars[5], data.alignErrs[5]);
244 if (data.valid) {
245 alignment->setCalibrated(moduleID);
246 } else {
247 alignment->setUnusable(moduleID);
248 }
249 }
250
251 // write the results and close the file
252
253 file->Write();
254 file->Close();
255
256 // check the results and return if alignment precision is not satisfied
257
258 if (not alignment->areAllCalibrated()) {
259 B2INFO("Alignment not successful for all slots");
260 delete alignment;
261 return c_NotEnoughData;
262 }
263 if (not alignment->areAllPrecise(m_spatialPrecision, m_angularPrecision)) {
264 B2INFO("Alignment successful but precision worse than required");
265 delete alignment;
266 return c_NotEnoughData;
267 }
268
269 // otherwise import calibration to DB
270
271 saveCalibration(alignment);
272
273 return c_OK;
274 }
275
276
278 {
279 // clear the map
280
281 m_mergedData.clear();
282
283 // make a list of module ID's
284
285 std::set<int> slotIDs;
286 for (const auto& element : m_inputData) {
287 slotIDs.insert(element.first);
288 }
289
290 // book a histogram of pulls
291
292 auto h_pulls = new TH1F("pulls", "Pulls of statistically independent results",
293 200, -20.0, 20.0);
294 h_pulls->SetXTitle("pulls");
295
296 // fill pulls
297
298 for (auto slot : slotIDs) {
299 const auto range = m_inputData.equal_range(slot);
300 std::vector<AlignData> data;
301 for (auto it = range.first; it != range.second; ++it) {
302 data.push_back(it->second);
303 }
304 for (size_t i = 0; i < data.size(); i++) {
305 const auto& pars1 = data[i].alignPars;
306 const auto& errs1 = data[i].alignErrs;
307 for (size_t j = i + 1; j < data.size(); j++) {
308 const auto& pars2 = data[j].alignPars;
309 const auto& errs2 = data[j].alignErrs;
310 for (size_t k = 0; k < std::min(pars1.size(), pars2.size()); k++) {
311 double e1 = errs1[k];
312 double e2 = errs2[k];
313 if (e1 == 0 or e2 == 0) continue;
314 double pull = (pars1[k] - pars2[k]) / sqrt(e1 * e1 + e2 * e2);
315 h_pulls->Fill(pull);
316 }
317 }
318 }
319 }
320
321 // determine scale factor for errors
322
323 double scaleFact = 1;
324 if (h_pulls->GetEntries() > 1) scaleFact = h_pulls->GetRMS();
325
326 // merge data
327
328 for (auto slot : slotIDs) {
329 const auto range = m_inputData.equal_range(slot);
330 if (range.first == range.second) continue;
331 AlignData mergedData;
332 for (auto it = range.first; it != range.second; ++it) {
333 mergedData.add(it->second);
334 }
335 mergedData.finalize(scaleFact);
336 m_mergedData[slot] = mergedData;
337 }
338
339 }
340
341
343 {
344 iter = std::max(iter, data.iter);
345 ntrk += data.ntrk;
346 if (not data.valid) return;
347
348 for (size_t i = alignPars.size(); i < data.alignPars.size(); i++) {
349 alignPars.push_back(0);
350 alignErrs.push_back(0);
351 }
352
353 for (size_t i = 0; i < data.alignPars.size(); i++) {
354 auto e = data.alignErrs[i];
355 if (e == 0) continue;
356 auto wt = 1 / (e * e);
357 alignPars[i] += data.alignPars[i] * wt ;
358 alignErrs[i] += wt ;
359 }
360 valid = true;
361 }
362
363
365 {
366 for (size_t i = 0; i < alignPars.size(); i++) {
367 auto wt = alignErrs[i];
368 if (wt == 0) continue;
369 alignPars[i] /= wt;
370 alignErrs[i] = 1 / sqrt(wt) * scaleFact;
371 }
372 }
373
374
375 } // end namespace TOP
377} // end namespace Belle2
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
EResult
The result of calibration.
@ c_OK
Finished successfully =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
@ c_Failure
Failed =3 in Python.
Alignment constants for all 16 modules.
std::vector< float > * m_vAlignPars
alignment parameters
double m_spatialPrecision
required precision of displacements
TBranch * m_bAlignParsErr
branch of error on alignment parameters
std::multimap< int, AlignData > m_inputData
input from ntuples
virtual EResult calibrate() final
algorithm implementation
double m_angularPrecision
required precision of rotation angles
std::vector< float > * m_vAlignParsErr
error on alignment parameters
TBranch * m_bAlignPars
branch of alignment parameters
bool m_valid
true if alignment parameters are valid
int m_errorCode
error code of the alignment procedure
void mergeData()
merge subsamples and rescale errors
std::map< int, AlignData > m_mergedData
merged subsamples
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.
STL namespace.
void add(const AlignData &data)
Merge another data structure to this one.
bool valid
true if alignment parameters are valid
void finalize(double scaleFact)
Calculate weighted averages and rescale errors.
std::vector< float > alignPars
alignment parameters
std::vector< float > alignErrs
uncertainties on alignment parameters