Project
Loading...
Searching...
No Matches
Aligner.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12//-----------------------------------------------------------------------------
22//-----------------------------------------------------------------------------
23#include <iostream>
24#include <ctime>
25
30#include "Framework/Logger.h"
31#include "MCHAlign/Aligner.h"
32#include "MathUtils/Cartesian.h"
33#include "MCHTracking/Track.h"
36
37#include <TClonesArray.h>
38#include <TGeoManager.h>
39#include <TGeoGlobalMagField.h>
40#include <TGraphErrors.h>
41#include <TMath.h>
42#include <TMatrixD.h>
43#include <TMatrixDSym.h>
44#include <TObject.h>
45#include <TString.h>
46
47namespace o2
48{
49namespace mch
50{
51
52using namespace std;
53
54//_____________________________________________________________________
55// static variables
56const int Aligner::fgNDetElemCh[Aligner::fgNCh] = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26};
57const int Aligner::fgSNDetElemCh[Aligner::fgNCh + 1] = {0, 4, 8, 12, 16, 34, 52, 78, 104, 130, 156};
58
59// number of detector elements in each half-chamber
60const int Aligner::fgNDetElemHalfCh[Aligner::fgNHalfCh] = {2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 13, 13, 13, 13, 13, 13, 13, 13};
61
62// list of detector elements for each half chamber
64 {
65 {100, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
66 {101, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
67
68 {200, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
69 {201, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
70
71 {300, 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
72 {301, 302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
73
74 {400, 403, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
75 {401, 402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
76
77 {500, 501, 502, 503, 504, 514, 515, 516, 517, 0, 0, 0, 0},
78 {505, 506, 507, 508, 509, 510, 511, 512, 513, 0, 0, 0, 0},
79
80 {600, 601, 602, 603, 604, 614, 615, 616, 617, 0, 0, 0, 0},
81 {605, 606, 607, 608, 609, 610, 611, 612, 613, 0, 0, 0, 0},
82
83 {700, 701, 702, 703, 704, 705, 706, 720, 721, 722, 723, 724, 725},
84 {707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719},
85
86 {800, 801, 802, 803, 804, 805, 806, 820, 821, 822, 823, 824, 825},
87 {807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819},
88
89 {900, 901, 902, 903, 904, 905, 906, 920, 921, 922, 923, 924, 925},
90 {907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919},
91
92 {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1020, 1021, 1022, 1023, 1024, 1025},
93 {1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019}
94
95};
96
97//_____________________________________________________________________
99class Array
100{
101
102 public:
105 {
106 for (int i = 0; i < Aligner::fNGlobal; ++i) {
107 values[i] = 0;
108 }
109 }
110
113
114 private:
116 Array(const Array&);
117
119 Array& operator=(const Array&);
120};
121
122//________________________________________________________________________
123double Square(double x) { return x * x; }
124
125//_____________________________________________________________________
127 : TObject(),
128 fInitialized(false),
129 fRunNumber(0),
130 fBFieldOn(false),
131 fRefitStraightTracks(false),
132 fStartFac(65536),
133 fResCutInitial(1000),
134 fResCut(100),
135 fMillepede(nullptr),
136 fNStdDev(3),
137 fDetElemNumber(0),
138 fGlobalParameterStatus(std::vector<int>(fNGlobal)),
139 fGlobalDerivatives(std::vector<double>(fNGlobal)),
140 fLocalDerivatives(std::vector<double>(fNLocal)),
141 fTrackRecord(),
142 mNEntriesAutoSave(10000),
143 mRecordWriter(new o2::fwdalign::MilleRecordWriter()),
144 mWithConstraintsRecWriter(false),
145 mConstraintsRecWriter(nullptr),
146 mRecordReader(new o2::fwdalign::MilleRecordReader()),
147 mWithConstraintsRecReader(false),
148 mConstraintsRecReader(nullptr),
149 fTransformCreator(),
150 fDoEvaluation(false),
151 fDisableRecordWriter(false),
152 mRead(false),
153 fTrkClRes(nullptr),
154 fTFile(nullptr),
155 fTTree(nullptr)
156{
158 fSigma[0] = 1.5e-1;
159 fSigma[1] = 1.0e-2;
160
161 // default allowed variations
162 fAllowVar[0] = 0.5; // x
163 fAllowVar[1] = 0.5; // y
164 fAllowVar[2] = 0.01; // phi_z
165 fAllowVar[3] = 5; // z
166
167 // initialize millepede
168 fMillepede = new o2::fwdalign::MillePede2();
169
170 // initialize degrees of freedom
171 // by default all parameters are free
172 for (int iPar = 0; iPar < fNGlobal; ++iPar) {
173 fGlobalParameterStatus[iPar] = kFreeParId;
174 }
175
176 // initialize local equations
177 for (int i = 0; i < fNLocal; ++i) {
178 fLocalDerivatives[i] = 0.0;
179 }
180
181 for (int i = 0; i < fNGlobal; ++i) {
182 fGlobalDerivatives[i] = 0.0;
183 }
184}
185
186//________________________________________________________________________
188{
189 delete mRecordWriter;
190 delete mRecordReader;
191 delete fMillepede;
192}
193
194//_____________________________________________________________________
195void Aligner::init(TString DataRecFName, TString ConsRecFName)
196{
197
199
204 if (fInitialized) {
205 LOG(fatal) << "Millepede already initialized";
206 }
207
208 if (!mRead) {
209 if (!fDisableRecordWriter) {
210 mRecordWriter->setCyclicAutoSave(mNEntriesAutoSave);
211 mRecordWriter->setDataFileName(DataRecFName);
212 fMillepede->SetRecordWriter(mRecordWriter);
213
214 if (mWithConstraintsRecWriter) {
215 mConstraintsRecWriter->setCyclicAutoSave(mNEntriesAutoSave);
216 mConstraintsRecWriter->setDataFileName(ConsRecFName);
217 fMillepede->SetConstraintsRecWriter(mConstraintsRecWriter);
218 }
219 } else {
220 fMillepede->SetRecord(&fTrackRecord);
221 }
222
223 } else {
224
225 TChain* ch = new TChain(mRecordReader->getDataTreeName());
226 if (DataRecFName.EndsWith(".root")) {
227 ch->AddFile(DataRecFName);
228 }
229 int nent = ch->GetEntries();
230
231 if (nent < 1) {
232 LOG(fatal) << "Obtained chain is empty, please check your record ROOT file.";
233 }
234
235 mRecordReader->connectToChain(ch);
236 fMillepede->SetRecordReader(mRecordReader);
237
238 if (mConstraintsRecReader) {
239
240 TChain* ch_cons = new TChain(mConstraintsRecReader->getDataTreeName());
241 if (ConsRecFName.EndsWith(".root")) {
242 ch_cons->AddFile(ConsRecFName);
243 }
244 int nent_cons = ch_cons->GetEntries();
245
246 if (nent_cons < 1) {
247 LOG(fatal) << "Obtained chain is empty, please check your record ROOT file.";
248 }
249
250 mConstraintsRecReader->connectToChain(ch_cons);
251 fMillepede->SetConstraintsRecReader(mConstraintsRecReader);
252 }
253 }
254
255 // assign proper groupID to free parameters
256 int nGlobal = 0;
257 for (int iPar = 0; iPar < fNGlobal; ++iPar) {
258
259 if (fGlobalParameterStatus[iPar] == kFixedParId) {
260 // fixed parameters are left unchanged
261 continue;
262
263 } else if (fGlobalParameterStatus[iPar] == kFreeParId || fGlobalParameterStatus[iPar] == kGroupBaseId) {
264
265 // free parameters or first element of group are assigned a new group id
266 fGlobalParameterStatus[iPar] = nGlobal++;
267 continue;
268
269 } else if (fGlobalParameterStatus[iPar] < kGroupBaseId) {
270
271 // get detector element id from status, get chamber parameter id
272 const int iDeBase(kGroupBaseId - 1 - fGlobalParameterStatus[iPar]);
273 const int iParBase = iPar % fgNParCh;
274
275 // check
276 if (iDeBase < 0 || iDeBase >= iPar / fgNParCh) {
277 LOG(fatal) << "Group for parameter index " << iPar << " has wrong base detector element: " << iDeBase;
278 }
279
280 // assign identical group id to current
281 fGlobalParameterStatus[iPar] = fGlobalParameterStatus[iDeBase * fgNParCh + iParBase];
282 LOG(info) << "Parameter " << iPar << " grouped to detector " << iDeBase << " (" << GetParameterMaskString(1 << iParBase).Data() << ")";
283
284 } else {
285 LOG(fatal) << "Unrecognized parameter status for index " << iPar << ": " << fGlobalParameterStatus[iPar];
286 }
287 }
288
289 LOG(info) << "Free Parameters: " << nGlobal << " out of " << fNGlobal;
290
291 // initialize millepedes
292 fMillepede->InitMille(fNGlobal, fNLocal, fNStdDev, fResCut, fResCutInitial, fGlobalParameterStatus);
293
294 if (!mRead) {
295 if (!fDisableRecordWriter) {
296 mRecordWriter->init();
297 } else {
298 fMillepede->DisableRecordWriter();
299 }
300 }
301
302 fInitialized = true;
303
304 // some debug output
305 for (int iPar = 0; iPar < fgNParCh; ++iPar) {
306 LOG(info) << "fAllowVar[" << iPar << "]= " << fAllowVar[iPar];
307 }
308
309 // set allowed variations for all parameters
310 for (int iDet = 0; iDet < fgNDetElem; ++iDet) {
311 for (int iPar = 0; iPar < fgNParCh; ++iPar) {
312 fMillepede->SetParSigma(iDet * fgNParCh + iPar, fAllowVar[iPar]);
313 }
314 }
315
316 // Set iterations
317 if (fStartFac > 1) {
318 fMillepede->SetIterations(fStartFac);
319 }
320 // setup monitoring TFile
321 if (fDoEvaluation) {
322 // if (fDoEvaluation && fRefitStraightTracks) {
323 string Path_file = Form("%s%s", "Residual", ".root");
324
325 fTFile = new TFile(Path_file.c_str(), "RECREATE");
326 fTTree = new TTree("TreeE", "Evaluation");
327
328 const int kSplitlevel = 98;
329 const int kBufsize = 32000;
330
331 fTrkClRes = new o2::mch::LocalTrackClusterResidual();
332 fTTree->Branch("fClDetElem", &(fTrkClRes->fClDetElem), "fClDetElem/I");
333 fTTree->Branch("fClDetElemNumber", &(fTrkClRes->fClDetElemNumber), "fClDetElemNumber/I");
334 fTTree->Branch("fClusterX", &(fTrkClRes->fClusterX), "fClusterX/F");
335 fTTree->Branch("fClusterY", &(fTrkClRes->fClusterY), "fClusterY/F");
336 fTTree->Branch("fTrackX", &(fTrkClRes->fTrackX), "fTrackX/F");
337 fTTree->Branch("fTrackY", &(fTrkClRes->fTrackY), "fTrackY/F");
338 fTTree->Branch("fClusterXloc", &(fTrkClRes->fClusterXloc), "fClusterXloc/F");
339 fTTree->Branch("fClusterYloc", &(fTrkClRes->fClusterYloc), "fClusterYloc/F");
340 fTTree->Branch("fTrackXloc", &(fTrkClRes->fTrackXloc), "fTrackXloc/F");
341 fTTree->Branch("fTrackYloc", &(fTrkClRes->fTrackYloc), "fTrackYloc/F");
342 fTTree->Branch("fTrackSlopeX", &(fTrkClRes->fTrackSlopeX), "fTrackSlopeX/F");
343 fTTree->Branch("fTrackSlopeY", &(fTrkClRes->fTrackSlopeY), "fTrackSlopeY/F");
344 fTTree->Branch("fBendingMomentum", &(fTrkClRes->fBendingMomentum), "fBendingMomentum/F");
345 fTTree->Branch("fResiduXGlobal", &(fTrkClRes->fResiduXGlobal), "fResiduXGlobal/F");
346 fTTree->Branch("fResiduYGlobal", &(fTrkClRes->fResiduYGlobal), "fResiduYGlobal/F");
347 fTTree->Branch("fResiduXLocal", &(fTrkClRes->fResiduXLocal), "fResiduXLocal/F");
348 fTTree->Branch("fResiduYLocal", &(fTrkClRes->fResiduYLocal), "fResiduYLocal/F");
349 fTTree->Branch("fCharge", &(fTrkClRes->fCharge), "fCharge/F");
350 fTTree->Branch("fClusterZ", &(fTrkClRes->fClusterZ), "fClusterZ/F");
351 fTTree->Branch("fTrackZ", &(fTrkClRes->fTrackZ), "fTrackZ/F");
352 fTTree->Branch("fBx", &(fTrkClRes->fBx), "fBx/F");
353 fTTree->Branch("fBy", &(fTrkClRes->fBy), "fBy/F");
354 fTTree->Branch("fBz", &(fTrkClRes->fBz), "fBz/F");
355 }
356}
357
358//_____________________________________________________
360{
361 fInitialized = kFALSE;
362 if (fDoEvaluation) {
363 LOG(info) << "Closing Evaluation TFile";
364 if (fTFile && fTTree) {
365 fTFile->cd();
366 fTTree->Write();
367 fTFile->Close();
368 }
369 }
370 if (!fDisableRecordWriter) {
371 mRecordWriter->terminate();
372 }
373}
374
375//_____________________________________________________
377{
378
380 // reset track records
381
382 if (fMillepede->GetRecord()) {
383 fMillepede->GetRecord()->Reset();
384 }
385
386 // loop over clusters to get starting values
387 bool first(true);
388
389 auto itTrackParam = track.begin();
390 for (; itTrackParam != track.end(); ++itTrackParam) {
391
392 // get cluster
393 const Cluster* cluster = itTrackParam->getClusterPtr();
394 if (!cluster) {
395 continue;
396 }
397 // for first valid cluster, save track position as "starting" values
398 if (first) {
399
400 first = false;
401 FillTrackParamData(&*itTrackParam);
402 fTrackPos0[0] = fTrackPos[0];
403 fTrackPos0[1] = fTrackPos[1];
404 fTrackPos0[2] = fTrackPos[2];
405 fTrackSlope0[0] = fTrackSlope[0];
406 fTrackSlope0[1] = fTrackSlope[1];
407
408 break;
409 }
410 }
411
412 // redo straight track fit
413 if (fRefitStraightTracks) {
414
415 // refit straight track
416 const LocalTrackParam trackParam(RefitStraightTrack(track, fTrackPos0[2]));
417
418 /*
419 copy new parameters to stored ones for derivatives calculation
420 this is done only if BFieldOn is false, for which these parameters are used
421 */
422 if (!fBFieldOn) {
423 fTrackPos0[0] = trackParam.fTrackX;
424 fTrackPos0[1] = trackParam.fTrackY;
425 fTrackPos0[2] = trackParam.fTrackZ;
426 fTrackSlope0[0] = trackParam.fTrackSlopeX;
427 fTrackSlope0[1] = trackParam.fTrackSlopeY;
428 }
429 }
430
431 // second loop to perform alignment
432 itTrackParam = track.begin();
433 for (; itTrackParam != track.end(); ++itTrackParam) {
434
435 // get cluster
436 const Cluster* cluster = itTrackParam->getClusterPtr();
437 if (!cluster) {
438 continue;
439 }
440
441 // fill local variables for this position --> one measurement
442
443 FillDetElemData(cluster); // function to get the transformation matrix
444 FillRecPointData(cluster);
445 FillTrackParamData(&*itTrackParam);
446
447 // 'inverse' (GlobalToLocal) rotation matrix
448 // const double* r(fGeoCombiTransInverse.GetRotationMatrix());
450 // LOG(info) << Form("cluster ID: %i", cluster->getDEId());
451 TMatrixD transMat(3, 4);
452 trans.GetTransformMatrix(transMat);
453 // transMat.Print();
454 double r[12];
455 r[0] = transMat(0, 0);
456 r[1] = transMat(0, 1);
457 r[2] = transMat(0, 2);
458 r[3] = transMat(1, 0);
459 r[4] = transMat(1, 1);
460 r[5] = transMat(1, 2);
461 r[6] = transMat(2, 0);
462 r[7] = transMat(2, 1);
463 r[8] = transMat(2, 2);
464 r[9] = transMat(0, 3);
465 r[10] = transMat(1, 3);
466 r[11] = transMat(2, 3);
467 // calculate measurements
468 if (fBFieldOn) {
469
470 // use residuals (cluster - track) for measurement
471 fMeas[0] = r[0] * (fClustPos[0] - fTrackPos[0]) + r[1] * (fClustPos[1] - fTrackPos[1]);
472 fMeas[1] = r[3] * (fClustPos[0] - fTrackPos[0]) + r[4] * (fClustPos[1] - fTrackPos[1]);
473 } else {
474
475 // use cluster position for measurement
476 fMeas[0] = (r[0] * fClustPos[0] + r[1] * fClustPos[1]);
477 fMeas[1] = (r[3] * fClustPos[0] + r[4] * fClustPos[1]);
478 }
479 // printf("DE %d, X: %f %f ; Y: %f %f ; Z: %f\n", cluster->getDEId(), fClustPos[0], fTrackPos[0], fClustPos[1], fTrackPos[1], fClustPos[2]);
480
481 if (fDoEvaluation) {
482
483 const float InvBendingMom = itTrackParam->getInverseBendingMomentum();
484 const float TrackCharge = itTrackParam->getCharge();
485
486 double B[3] = {0.0, 0.0, 0.0};
487 double x[3] = {fTrackPos[0], fTrackPos[1], fTrackPos[2]};
488 TGeoGlobalMagField::Instance()->Field(x, B);
489 const float Bx = B[0];
490 const float By = B[1];
491 const float Bz = B[2];
492
493 fTrkClRes->fClDetElem = cluster->getDEId();
494 fTrkClRes->fClDetElemNumber = GetDetElemNumber(cluster->getDEId());
495 fTrkClRes->fClusterX = fClustPos[0];
496 fTrkClRes->fClusterY = fClustPos[1];
497 fTrkClRes->fClusterZ = fClustPos[2];
498
499 // fTrkClRes->fTrackX = fTrackPos0[0] + fTrackSlope0[0] * (fTrackPos[2] - fTrackPos0[2]); // fTrackPos[0];
500 // fTrkClRes->fTrackY = fTrackPos0[1] + fTrackSlope0[1] * (fTrackPos[2] - fTrackPos0[2]); // fTrackPos[1];
501 // fTrkClRes->fTrackSlopeX = fTrackSlope0[0];
502 // fTrkClRes->fTrackSlopeY = fTrackSlope0[1];
503
504 fTrkClRes->fTrackX = fTrackPos[0];
505 fTrkClRes->fTrackY = fTrackPos[1];
506 fTrkClRes->fTrackZ = fTrackPos[2];
507
508 fTrkClRes->fClusterXloc = r[0] * fClustPos[0] + r[1] * fClustPos[1];
509 fTrkClRes->fClusterYloc = r[3] * fClustPos[0] + r[4] * fClustPos[1];
510
511 fTrkClRes->fTrackXloc = r[0] * fTrackPos[0] + r[1] * fTrackPos[1];
512 fTrkClRes->fTrackYloc = r[3] * fTrackPos[0] + r[4] * fTrackPos[1];
513
514 fTrkClRes->fTrackSlopeX = fTrackSlope[0];
515 fTrkClRes->fTrackSlopeY = fTrackSlope[1];
516
517 fTrkClRes->fBendingMomentum = TrackCharge / InvBendingMom;
518
519 fTrkClRes->fResiduXGlobal = fClustPos[0] - fTrackPos[0];
520 fTrkClRes->fResiduYGlobal = fClustPos[1] - fTrackPos[1];
521 fTrkClRes->fResiduXLocal = r[0] * (fClustPos[0] - fTrackPos[0]) + r[1] * (fClustPos[1] - fTrackPos[1]);
522 fTrkClRes->fResiduYLocal = r[3] * (fClustPos[0] - fTrackPos[0]) + r[4] * (fClustPos[1] - fTrackPos[1]);
523
524 fTrkClRes->fCharge = TrackCharge;
525
526 fTrkClRes->fBx = Bx;
527 fTrkClRes->fBy = By;
528 fTrkClRes->fBz = Bz;
529
530 if (fTTree) {
531 fTTree->Fill();
532 }
533 }
534 // Set local equations
535 LocalEquationX(r);
536 LocalEquationY(r);
537 }
538
539 // copy track record
540 if (!fDisableRecordWriter) {
541 mRecordWriter->setRecordRun(fRunNumber);
542 mRecordWriter->setRecordWeight(weight);
543 }
544
545 // save record data
546 if (doAlignment) {
547 if (!fDisableRecordWriter) {
548 mRecordWriter->fillRecordTree();
549 }
550 }
551}
552
553//_____________________________________________________________________
554void Aligner::FixAll(unsigned int mask)
555{
557 LOG(info) << "Fixing " << GetParameterMaskString(mask).Data() << " for all detector elements";
558
559 // fix all stations
560 for (int i = 0; i < fgNDetElem; ++i) {
561 if (mask & ParX) {
562 FixParameter(i, 0);
563 }
564 if (mask & ParY) {
565 FixParameter(i, 1);
566 }
567 if (mask & ParTZ) {
568 FixParameter(i, 2);
569 }
570 if (mask & ParZ) {
571 FixParameter(i, 3);
572 }
573 }
574}
575
576//_____________________________________________________________________
577void Aligner::FixChamber(int iCh, unsigned int mask)
578{
580
581 // check boundaries
582 if (iCh < 1 || iCh > 10) {
583 LOG(fatal) << "Invalid chamber index " << iCh;
584 }
585
586 // get first and last element
587 const int iDetElemFirst = fgSNDetElemCh[iCh - 1];
588 const int iDetElemLast = fgSNDetElemCh[iCh];
589 for (int i = iDetElemFirst; i < iDetElemLast; ++i) {
590
591 LOG(info) << "Fixing " << GetParameterMaskString(mask).Data() << " for detector element " << i;
592
593 if (mask & ParX) {
594 FixParameter(i, 0);
595 }
596 if (mask & ParY) {
597 FixParameter(i, 1);
598 }
599 if (mask & ParTZ) {
600 FixParameter(i, 2);
601 }
602 if (mask & ParZ) {
603 FixParameter(i, 3);
604 }
605 }
606}
607
608//_____________________________________________________________________
609void Aligner::FixDetElem(int iDetElemId, unsigned int mask)
610{
612 const int iDet(GetDetElemNumber(iDetElemId));
613 if (mask & ParX) {
614 FixParameter(iDet, 0);
615 }
616 if (mask & ParY) {
617 FixParameter(iDet, 1);
618 }
619 if (mask & ParTZ) {
620 FixParameter(iDet, 2);
621 }
622 if (mask & ParZ) {
623 FixParameter(iDet, 3);
624 }
625}
626
627//_____________________________________________________________________
628void Aligner::FixHalfSpectrometer(const bool* lChOnOff, unsigned int sidesMask, unsigned int mask)
629{
630
632 for (int i = 0; i < fgNDetElem; ++i) {
633
634 // get chamber matching detector
635 const int iCh(GetChamberId(i));
636 if (!lChOnOff[iCh - 1]) {
637 continue;
638 }
639
640 // get detector element in chamber
641 int lDetElemNumber = i - fgSNDetElemCh[iCh - 1];
642
643 // skip detector if its side is off
644 // stations 1 and 2
645 if (iCh >= 1 && iCh <= 4) {
646 if (lDetElemNumber == 0 && !(sidesMask & SideTopRight)) {
647 continue;
648 }
649 if (lDetElemNumber == 1 && !(sidesMask & SideTopLeft)) {
650 continue;
651 }
652 if (lDetElemNumber == 2 && !(sidesMask & SideBottomLeft)) {
653 continue;
654 }
655 if (lDetElemNumber == 3 && !(sidesMask & SideBottomRight)) {
656 continue;
657 }
658 }
659
660 // station 3
661 if (iCh >= 5 && iCh <= 6) {
662 if (lDetElemNumber >= 0 && lDetElemNumber <= 4 && !(sidesMask & SideTopRight)) {
663 continue;
664 }
665 if (lDetElemNumber >= 5 && lDetElemNumber <= 10 && !(sidesMask & SideTopLeft)) {
666 continue;
667 }
668 if (lDetElemNumber >= 11 && lDetElemNumber <= 13 && !(sidesMask & SideBottomLeft)) {
669 continue;
670 }
671 if (lDetElemNumber >= 14 && lDetElemNumber <= 17 && !(sidesMask & SideBottomRight)) {
672 continue;
673 }
674 }
675
676 // stations 4 and 5
677 if (iCh >= 7 && iCh <= 10) {
678 if (lDetElemNumber >= 0 && lDetElemNumber <= 6 && !(sidesMask & SideTopRight)) {
679 continue;
680 }
681 if (lDetElemNumber >= 7 && lDetElemNumber <= 13 && !(sidesMask & SideTopLeft)) {
682 continue;
683 }
684 if (lDetElemNumber >= 14 && lDetElemNumber <= 19 && !(sidesMask & SideBottomLeft)) {
685 continue;
686 }
687 if (lDetElemNumber >= 20 && lDetElemNumber <= 25 && !(sidesMask & SideBottomRight)) {
688 continue;
689 }
690 }
691
692 // detector is accepted, fix it
693 FixDetElem(i, mask);
694 }
695}
696
697//______________________________________________________________________
699{
700
702 if (fInitialized) {
703 LOG(fatal) << "Millepede already initialized";
704 }
705
706 fGlobalParameterStatus[iPar] = kFixedParId;
707}
708
709//_____________________________________________________________________
710void Aligner::ReleaseChamber(int iCh, unsigned int mask)
711{
713
714 // check boundaries
715 if (iCh < 1 || iCh > 10) {
716 LOG(fatal) << "Invalid chamber index " << iCh;
717 }
718
719 // get first and last element
720 const int iDetElemFirst = fgSNDetElemCh[iCh - 1];
721 const int iDetElemLast = fgSNDetElemCh[iCh];
722 for (int i = iDetElemFirst; i < iDetElemLast; ++i) {
723
724 LOG(info) << "Releasing " << GetParameterMaskString(mask).Data() << " for detector element " << i;
725
726 if (mask & ParX) {
728 }
729 if (mask & ParY) {
731 }
732 if (mask & ParTZ) {
734 }
735 if (mask & ParZ) {
737 }
738 }
739}
740
741//_____________________________________________________________________
742void Aligner::ReleaseDetElem(int iDetElemId, unsigned int mask)
743{
745 const int iDet(GetDetElemNumber(iDetElemId));
746 if (mask & ParX) {
747 ReleaseParameter(iDet, 0);
748 }
749 if (mask & ParY) {
750 ReleaseParameter(iDet, 1);
751 }
752 if (mask & ParTZ) {
753 ReleaseParameter(iDet, 2);
754 }
755 if (mask & ParZ) {
756 ReleaseParameter(iDet, 3);
757 }
758}
759
760//______________________________________________________________________
762{
763
765 if (fInitialized) {
766 LOG(fatal) << "Millepede already initialized";
767 }
768
769 fGlobalParameterStatus[iPar] = kFreeParId;
770}
771
772//_____________________________________________________________________
773void Aligner::GroupChamber(int iCh, unsigned int mask)
774{
776 if (iCh < 1 || iCh > fgNCh) {
777 LOG(fatal) << "Invalid chamber index " << iCh;
778 }
779
780 const int detElemMin = 100 * iCh;
781 const int detElemMax = 100 * iCh + fgNDetElemCh[iCh] - 1;
782 GroupDetElems(detElemMin, detElemMax, mask);
783}
784
785//_____________________________________________________________________
786void Aligner::GroupHalfChamber(int iCh, int iHalf, unsigned int mask)
787{
789 if (iCh < 1 || iCh > fgNCh) {
790 LOG(fatal) << "Invalid chamber index " << iCh;
791 }
792
793 if (iHalf < 0 || iHalf > 1) {
794 LOG(fatal) << "Invalid half chamber index " << iHalf;
795 }
796
797 const int iHalfCh = 2 * (iCh - 1) + iHalf;
798 GroupDetElems(&fgDetElemHalfCh[iHalfCh][0], fgNDetElemHalfCh[iHalfCh], mask);
799}
800
801//_____________________________________________________________________
802void Aligner::GroupDetElems(int detElemMin, int detElemMax, unsigned int mask)
803{
805 // check number of detector elements
806 const int nDetElem = detElemMax - detElemMin + 1;
807 if (nDetElem < 2) {
808 LOG(fatal) << "Requested group of DEs " << detElemMin << "-" << detElemMax << " contains less than 2 DE's";
809 }
810
811 // create list
812 int* detElemList = new int[nDetElem];
813 for (int i = 0; i < nDetElem; ++i) {
814 detElemList[i] = detElemMin + i;
815 }
816
817 // group
818 GroupDetElems(detElemList, nDetElem, mask);
819 delete[] detElemList;
820}
821
822//_____________________________________________________________________
823void Aligner::GroupDetElems(const int* detElemList, int nDetElem, unsigned int mask)
824{
826 if (fInitialized) {
827 LOG(fatal) << "Millepede already initialized";
828 }
829
830 const int iDeBase(GetDetElemNumber(detElemList[0]));
831 for (int i = 0; i < nDetElem; ++i) {
832 const int iDeCurrent(GetDetElemNumber(detElemList[i]));
833 if (mask & ParX) {
834 fGlobalParameterStatus[iDeCurrent * fgNParCh + 0] = (i == 0) ? kGroupBaseId : (kGroupBaseId - iDeBase - 1);
835 }
836 if (mask & ParY) {
837 fGlobalParameterStatus[iDeCurrent * fgNParCh + 1] = (i == 0) ? kGroupBaseId : (kGroupBaseId - iDeBase - 1);
838 }
839 if (mask & ParTZ) {
840 fGlobalParameterStatus[iDeCurrent * fgNParCh + 2] = (i == 0) ? kGroupBaseId : (kGroupBaseId - iDeBase - 1);
841 }
842 if (mask & ParZ) {
843 fGlobalParameterStatus[iDeCurrent * fgNParCh + 3] = (i == 0) ? kGroupBaseId : (kGroupBaseId - iDeBase - 1);
844 }
845
846 if (i == 0) {
847 LOG(info) << "Creating new group for detector " << detElemList[i] << " and variable " << GetParameterMaskString(mask).Data();
848 } else {
849 LOG(info) << "Adding detector element " << detElemList[i] << " to current group";
850 }
851 }
852}
853
854//______________________________________________________________________
855void Aligner::SetChamberNonLinear(int iCh, unsigned int mask)
856{
858 const int iDetElemFirst = fgSNDetElemCh[iCh - 1];
859 const int iDetElemLast = fgSNDetElemCh[iCh];
860 for (int i = iDetElemFirst; i < iDetElemLast; ++i) {
861
862 if (mask & ParX) {
864 }
865 if (mask & ParY) {
867 }
868 if (mask & ParTZ) {
870 }
871 if (mask & ParZ) {
873 }
874 }
875}
876
877//_____________________________________________________________________
878void Aligner::SetDetElemNonLinear(int iDetElemId, unsigned int mask)
879{
881 const int iDet(GetDetElemNumber(iDetElemId));
882 if (mask & ParX) {
883 SetParameterNonLinear(iDet, 0);
884 }
885 if (mask & ParY) {
886 SetParameterNonLinear(iDet, 1);
887 }
888 if (mask & ParTZ) {
889 SetParameterNonLinear(iDet, 2);
890 }
891 if (mask & ParZ) {
892 SetParameterNonLinear(iDet, 3);
893 }
894}
895
896//______________________________________________________________________
898{
900 if (!fInitialized) {
901 LOG(fatal) << "Millepede not initialized";
902 }
903
904 fMillepede->SetNonLinear(iPar);
905 LOG(info) << "Parameter " << iPar << " set to non linear ";
906}
907
908//______________________________________________________________________
909void Aligner::AddConstraints(const bool* lChOnOff, unsigned int mask)
910{
912
913 Array fConstraintX;
914 Array fConstraintY;
915 Array fConstraintTZ;
916 Array fConstraintZ;
917
918 for (int i = 0; i < fgNDetElem; ++i) {
919
920 // get chamber matching detector
921 const int iCh(GetChamberId(i));
922 if (lChOnOff[iCh - 1]) {
923
924 if (mask & ParX) {
925 fConstraintX.values[i * fgNParCh + 0] = 1.0;
926 }
927 if (mask & ParY) {
928 fConstraintY.values[i * fgNParCh + 1] = 1.0;
929 }
930 if (mask & ParTZ) {
931 fConstraintTZ.values[i * fgNParCh + 2] = 1.0;
932 }
933 if (mask & ParZ) {
934 fConstraintTZ.values[i * fgNParCh + 3] = 1.0;
935 }
936 }
937 }
938
939 if (mask & ParX) {
940 AddConstraint(fConstraintX.values, 0.0);
941 }
942 if (mask & ParY) {
943 AddConstraint(fConstraintY.values, 0.0);
944 }
945 if (mask & ParTZ) {
946 AddConstraint(fConstraintTZ.values, 0.0);
947 }
948 if (mask & ParZ) {
949 AddConstraint(fConstraintZ.values, 0.0);
950 }
951}
952
953//______________________________________________________________________
954void Aligner::AddConstraints(const bool* lChOnOff, const bool* lVarXYT, unsigned int sidesMask)
955{
956 /*
957 questions:
958 - is there not redundancy/inconsistency between lDetTLBR and lSpecLROnOff ? shouldn't we use only lDetTLBR ?
959 - why is weight ignored for ConstrainT and ConstrainB
960 - why is there no constrain on z
961 */
962
964 double lMeanY = 0.;
965 double lSigmaY = 0.;
966 double lMeanZ = 0.;
967 double lSigmaZ = 0.;
968 int lNDetElem = 0;
969
970 for (int i = 0; i < fgNDetElem; ++i) {
971
972 // get chamber matching detector
973 const int iCh(GetChamberId(i));
974
975 // skip detector if chamber is off
976 if (lChOnOff[iCh - 1]) {
977 continue;
978 }
979
980 // get detector element id from detector element number
981 const int lDetElemNumber = i - fgSNDetElemCh[iCh - 1];
982 const int lDetElemId = iCh * 100 + lDetElemNumber;
983
984 // skip detector if its side is off
985 // stations 1 and 2
986 if (iCh >= 1 && iCh <= 4) {
987 if (lDetElemNumber == 0 && !(sidesMask & SideTopRight)) {
988 continue;
989 }
990 if (lDetElemNumber == 1 && !(sidesMask & SideTopLeft)) {
991 continue;
992 }
993 if (lDetElemNumber == 2 && !(sidesMask & SideBottomLeft)) {
994 continue;
995 }
996 if (lDetElemNumber == 3 && !(sidesMask & SideBottomRight)) {
997 continue;
998 }
999 }
1000
1001 // station 3
1002 if (iCh >= 5 && iCh <= 6) {
1003 if (lDetElemNumber >= 0 && lDetElemNumber <= 4 && !(sidesMask & SideTopRight)) {
1004 continue;
1005 }
1006 if (lDetElemNumber >= 5 && lDetElemNumber <= 10 && !(sidesMask & SideTopLeft)) {
1007 continue;
1008 }
1009 if (lDetElemNumber >= 11 && lDetElemNumber <= 13 && !(sidesMask & SideBottomLeft)) {
1010 continue;
1011 }
1012 if (lDetElemNumber >= 14 && lDetElemNumber <= 17 && !(sidesMask & SideBottomRight)) {
1013 continue;
1014 }
1015 }
1016
1017 // stations 4 and 5
1018 if (iCh >= 7 && iCh <= 10) {
1019 if (lDetElemNumber >= 0 && lDetElemNumber <= 6 && !(sidesMask & SideTopRight)) {
1020 continue;
1021 }
1022 if (lDetElemNumber >= 7 && lDetElemNumber <= 13 && !(sidesMask & SideTopLeft)) {
1023 continue;
1024 }
1025 if (lDetElemNumber >= 14 && lDetElemNumber <= 19 && !(sidesMask & SideBottomLeft)) {
1026 continue;
1027 }
1028 if (lDetElemNumber >= 20 && lDetElemNumber <= 25 && !(sidesMask & SideBottomRight)) {
1029 continue;
1030 }
1031 }
1032
1033 // get global x, y and z position
1034 double lDetElemGloX = 0.;
1035 double lDetElemGloY = 0.;
1036 double lDetElemGloZ = 0.;
1037
1038 auto fTransform = fTransformCreator(lDetElemId);
1039 o2::math_utils::Point3D<double> SlatPos{0.0, 0.0, 0.0};
1041
1042 fTransform.LocalToMaster(SlatPos, GlobalPos);
1043 lDetElemGloX = GlobalPos.x();
1044 lDetElemGloY = GlobalPos.y();
1045 lDetElemGloZ = GlobalPos.z();
1046 // fTransform->Local2Global(lDetElemId, 0, 0, 0, lDetElemGloX, lDetElemGloY, lDetElemGloZ);
1047
1048 // increment mean Y, mean Z, sigmas and number of accepted detectors
1049 lMeanY += lDetElemGloY;
1050 lSigmaY += lDetElemGloY * lDetElemGloY;
1051 lMeanZ += lDetElemGloZ;
1052 lSigmaZ += lDetElemGloZ * lDetElemGloZ;
1053 lNDetElem++;
1054 }
1055
1056 // calculate mean values
1057 lMeanY /= lNDetElem;
1058 lSigmaY /= lNDetElem;
1059 lSigmaY = TMath::Sqrt(lSigmaY - lMeanY * lMeanY);
1060 lMeanZ /= lNDetElem;
1061 lSigmaZ /= lNDetElem;
1062 lSigmaZ = TMath::Sqrt(lSigmaZ - lMeanZ * lMeanZ);
1063 LOG(info) << "Used " << lNDetElem << " DetElem, MeanZ= " << lMeanZ << ", SigmaZ= " << lSigmaZ;
1064
1065 // create all possible arrays
1066 Array fConstraintX[4]; // Array for constraint equation X
1067 Array fConstraintY[4]; // Array for constraint equation Y
1068 Array fConstraintP[4]; // Array for constraint equation P
1069 Array fConstraintXZ[4]; // Array for constraint equation X vs Z
1070 Array fConstraintYZ[4]; // Array for constraint equation Y vs Z
1071 Array fConstraintPZ[4]; // Array for constraint equation P vs Z
1072
1073 // do we really need these ?
1074 Array fConstraintXY[4]; // Array for constraint equation X vs Y
1075 Array fConstraintYY[4]; // Array for constraint equation Y vs Y
1076 Array fConstraintPY[4]; // Array for constraint equation P vs Y
1077
1078 // fill bool sides array based on masks, for convenience
1079 bool lDetTLBR[4];
1080 lDetTLBR[0] = sidesMask & SideTop;
1081 lDetTLBR[1] = sidesMask & SideLeft;
1082 lDetTLBR[2] = sidesMask & SideBottom;
1083 lDetTLBR[3] = sidesMask & SideRight;
1084
1085 for (int i = 0; i < fgNDetElem; ++i) {
1086
1087 // get chamber matching detector
1088 const int iCh(GetChamberId(i));
1089
1090 // skip detector if chamber is off
1091 if (!lChOnOff[iCh - 1]) {
1092 continue;
1093 }
1094
1095 // get detector element id from detector element number
1096 const int lDetElemNumber = i - fgSNDetElemCh[iCh - 1];
1097 const int lDetElemId = iCh * 100 + lDetElemNumber;
1098
1099 // get global x, y and z position
1100 double lDetElemGloX = 0.;
1101 double lDetElemGloY = 0.;
1102 double lDetElemGloZ = 0.;
1103
1104 auto fTransform = fTransformCreator(lDetElemId);
1105 o2::math_utils::Point3D<double> SlatPos{0.0, 0.0, 0.0};
1107
1108 fTransform.LocalToMaster(SlatPos, GlobalPos);
1109 lDetElemGloX = GlobalPos.x();
1110 lDetElemGloY = GlobalPos.y();
1111 lDetElemGloZ = GlobalPos.z();
1112 // fTransform->Local2Global(lDetElemId, 0, 0, 0, lDetElemGloX, lDetElemGloY, lDetElemGloZ);
1113
1114 // loop over sides
1115 for (int iSide = 0; iSide < 4; iSide++) {
1116
1117 // skip if side is not selected
1118 if (!lDetTLBR[iSide]) {
1119 continue;
1120 }
1121
1122 // skip detector if it is not in the selected side
1123 // stations 1 and 2
1124 if (iCh >= 1 && iCh <= 4) {
1125 if (lDetElemNumber == 0 && !(iSide == 0 || iSide == 3)) {
1126 continue; // top-right
1127 }
1128 if (lDetElemNumber == 1 && !(iSide == 0 || iSide == 1)) {
1129 continue; // top-left
1130 }
1131 if (lDetElemNumber == 2 && !(iSide == 2 || iSide == 1)) {
1132 continue; // bottom-left
1133 }
1134 if (lDetElemNumber == 3 && !(iSide == 2 || iSide == 3)) {
1135 continue; // bottom-right
1136 }
1137 }
1138
1139 // station 3
1140 if (iCh >= 5 && iCh <= 6) {
1141 if (lDetElemNumber >= 0 && lDetElemNumber <= 4 && !(iSide == 0 || iSide == 3)) {
1142 continue; // top-right
1143 }
1144 if (lDetElemNumber >= 5 && lDetElemNumber <= 9 && !(iSide == 0 || iSide == 1)) {
1145 continue; // top-left
1146 }
1147 if (lDetElemNumber >= 10 && lDetElemNumber <= 13 && !(iSide == 2 || iSide == 1)) {
1148 continue; // bottom-left
1149 }
1150 if (lDetElemNumber >= 14 && lDetElemNumber <= 17 && !(iSide == 2 || iSide == 3)) {
1151 continue; // bottom-right
1152 }
1153 }
1154
1155 // stations 4 and 5
1156 if (iCh >= 7 && iCh <= 10) {
1157 if (lDetElemNumber >= 0 && lDetElemNumber <= 6 && !(iSide == 0 || iSide == 3)) {
1158 continue; // top-right
1159 }
1160 if (lDetElemNumber >= 7 && lDetElemNumber <= 13 && !(iSide == 0 || iSide == 1)) {
1161 continue; // top-left
1162 }
1163 if (lDetElemNumber >= 14 && lDetElemNumber <= 19 && !(iSide == 2 || iSide == 1)) {
1164 continue; // bottom-left
1165 }
1166 if (lDetElemNumber >= 20 && lDetElemNumber <= 25 && !(iSide == 2 || iSide == 3)) {
1167 continue; // bottom-right
1168 }
1169 }
1170
1171 // constrain x
1172 if (lVarXYT[0]) {
1173 fConstraintX[iSide].values[i * fgNParCh + 0] = 1;
1174 }
1175
1176 // constrain y
1177 if (lVarXYT[1]) {
1178 fConstraintY[iSide].values[i * fgNParCh + 1] = 1;
1179 }
1180
1181 // constrain phi (rotation around z)
1182 if (lVarXYT[2]) {
1183 fConstraintP[iSide].values[i * fgNParCh + 2] = 1;
1184 }
1185
1186 // x-z shearing
1187 if (lVarXYT[3]) {
1188 fConstraintXZ[iSide].values[i * fgNParCh + 0] = (lDetElemGloZ - lMeanZ) / lSigmaZ;
1189 }
1190
1191 // y-z shearing
1192 if (lVarXYT[4]) {
1193 fConstraintYZ[iSide].values[i * fgNParCh + 1] = (lDetElemGloZ - lMeanZ) / lSigmaZ;
1194 }
1195
1196 // phi-z shearing
1197 if (lVarXYT[5]) {
1198 fConstraintPZ[iSide].values[i * fgNParCh + 2] = (lDetElemGloZ - lMeanZ) / lSigmaZ;
1199 }
1200
1201 // x-y shearing
1202 if (lVarXYT[6]) {
1203 fConstraintXY[iSide].values[i * fgNParCh + 0] = (lDetElemGloY - lMeanY) / lSigmaY;
1204 }
1205
1206 // y-y shearing
1207 if (lVarXYT[7]) {
1208 fConstraintYY[iSide].values[i * fgNParCh + 1] = (lDetElemGloY - lMeanY) / lSigmaY;
1209 }
1210
1211 // phi-y shearing
1212 if (lVarXYT[8]) {
1213 fConstraintPY[iSide].values[i * fgNParCh + 2] = (lDetElemGloY - lMeanY) / lSigmaY;
1214 }
1215 }
1216 }
1217
1218 // pass constraints to millepede
1219 for (int iSide = 0; iSide < 4; iSide++) {
1220 // skip if side is not selected
1221 if (!lDetTLBR[iSide]) {
1222 continue;
1223 }
1224
1225 if (lVarXYT[0]) {
1226 AddConstraint(fConstraintX[iSide].values, 0.0);
1227 }
1228 if (lVarXYT[1]) {
1229 AddConstraint(fConstraintY[iSide].values, 0.0);
1230 }
1231 if (lVarXYT[2]) {
1232 AddConstraint(fConstraintP[iSide].values, 0.0);
1233 }
1234 if (lVarXYT[3]) {
1235 AddConstraint(fConstraintXZ[iSide].values, 0.0);
1236 }
1237 if (lVarXYT[4]) {
1238 AddConstraint(fConstraintYZ[iSide].values, 0.0);
1239 }
1240 if (lVarXYT[5]) {
1241 AddConstraint(fConstraintPZ[iSide].values, 0.0);
1242 }
1243 if (lVarXYT[6]) {
1244 AddConstraint(fConstraintXY[iSide].values, 0.0);
1245 }
1246 if (lVarXYT[7]) {
1247 AddConstraint(fConstraintYY[iSide].values, 0.0);
1248 }
1249 if (lVarXYT[8]) {
1250 AddConstraint(fConstraintPY[iSide].values, 0.0);
1251 }
1252 }
1253}
1254
1255//______________________________________________________________________
1257{
1259 if (!fInitialized) {
1260 LOG(fatal) << "Millepede is not initialized";
1261 }
1262
1263 fMillepede->SetGlobalParameters(par);
1264}
1265
1266//______________________________________________________________________
1268{
1270 // check initialization
1271 if (fInitialized) {
1272 LOG(fatal) << "Millepede already initialized";
1273 }
1274
1275 // check initialization
1276 if (!(iPar >= 0 && iPar < fgNParCh)) {
1277 LOG(fatal) << "Invalid index: " << iPar;
1278 }
1279
1280 fAllowVar[iPar] = value;
1281}
1282
1283//______________________________________________________________________
1284void Aligner::SetSigmaXY(double sigmaX, double sigmaY)
1285{
1286
1288 fSigma[0] = sigmaX;
1289 fSigma[1] = sigmaY;
1290
1291 // print
1292 for (int i = 0; i < 2; ++i) {
1293 LOG(info) << "fSigma[" << i << "] =" << fSigma[i];
1294 }
1295}
1296
1297//_____________________________________________________
1298void Aligner::GlobalFit(std::vector<double>& parameters, std::vector<double>& errors, std::vector<double>& pulls)
1299{
1301 fMillepede->GlobalFit(parameters, errors, pulls);
1302
1303 LOG(info) << "Done fitting global parameters";
1304 for (int iDet = 0; iDet < fgNDetElem; ++iDet) {
1305 LOG(info) << iDet << " " << parameters[iDet * fgNParCh + 0] << " " << parameters[iDet * fgNParCh + 1] << " " << parameters[iDet * fgNParCh + 3] << " " << parameters[iDet * fgNParCh + 2];
1306 }
1307}
1308
1309//_____________________________________________________
1311{
1312 fMillepede->PrintGlobalParameters();
1313}
1314
1315//_____________________________________________________
1316double Aligner::GetParError(int iPar) const
1317{
1318 return fMillepede->GetParError(iPar);
1319}
1320
1321//______________________________________________________________________
1323 std::vector<o2::detectors::AlignParam>& params,
1324 std::vector<double>& misAlignments)
1325{
1326
1329
1330 // Takes the internal geometry module transformers, copies them
1331 // and gets the Detection Elements from them.
1332 // Takes misalignment parameters and applies these
1333 // to the local transform of the Detection Element
1334 // Obtains the global transform by multiplying the module transformer
1335 // transformation with the local transformation
1336 // Applies the global transform to a new detection element
1337 // Adds the new detection element to a new module transformer
1338 // Adds the new module transformer to a new geometry transformer
1339 // Returns the new geometry transformer
1340
1341 double lModuleMisAlignment[fgNParCh] = {0};
1342 double lDetElemMisAlignment[fgNParCh] = {0};
1343
1345 for (int hc = 0; hc < 20; hc++) {
1346
1347 TGeoCombiTrans localDeltaTransform;
1348 localDeltaTransform = DeltaTransform(lModuleMisAlignment);
1349
1350 std::string sname = fmt::format("MCH/HC{}", hc);
1351 lAP.setSymName(sname.c_str());
1352
1353 double lPsi, lTheta, lPhi = 0.;
1354 if (!isMatrixConvertedToAngles(localDeltaTransform.GetRotationMatrix(),
1355 lPsi, lTheta, lPhi)) {
1356 LOG(error) << "Problem extracting angles!";
1357 }
1358
1359 lAP.setGlobalParams(localDeltaTransform);
1360
1361 // lAP.print();
1362 lAP.applyToGeometry();
1363 params.emplace_back(lAP);
1364 for (int de = 0; de < fgNDetElemHalfCh[hc]; de++) {
1365
1366 // store detector element id and number
1367 const int iDetElemId = fgDetElemHalfCh[hc][de];
1368 if (DetElemIsValid(iDetElemId)) {
1369
1370 const int iDetElemNumber(GetDetElemNumber(iDetElemId));
1371
1372 for (int i = 0; i < fgNParCh; ++i) {
1373 lDetElemMisAlignment[i] = 0.0;
1374 if (hc < fgNHalfCh) {
1375 lDetElemMisAlignment[i] = misAlignments[iDetElemNumber * fgNParCh + i];
1376 }
1377 }
1378
1379 sname = fmt::format("MCH/HC{}/DE{}", hc, fgDetElemHalfCh[hc][de]);
1380 lAP.setSymName(sname.c_str());
1381 localDeltaTransform = DeltaTransform(lDetElemMisAlignment);
1382
1383 if (!isMatrixConvertedToAngles(localDeltaTransform.GetRotationMatrix(),
1384 lPsi, lTheta, lPhi)) {
1385 LOG(error) << "Problem extracting angles for " << sname.c_str();
1386 }
1387
1388 lAP.setGlobalParams(localDeltaTransform);
1389 lAP.applyToGeometry();
1390 params.emplace_back(lAP);
1391
1392 } else {
1393
1394 // "invalid" detector elements come from MTR and are left unchanged
1395 LOG(info) << fmt::format("Keeping detElement {} unchanged\n", iDetElemId);
1396 }
1397 }
1398 }
1399
1400 // return params;
1401}
1402
1403//______________________________________________________________________
1404void Aligner::SetAlignmentResolution(const TClonesArray* misAlignArray, int rChId, double chResX, double chResY, double deResX, double deResY)
1405{
1406
1409 TMatrixDSym mChCorrMatrix(6);
1410 mChCorrMatrix[0][0] = chResX * chResX;
1411 mChCorrMatrix[1][1] = chResY * chResY;
1412
1413 TMatrixDSym mDECorrMatrix(6);
1414 mDECorrMatrix[0][0] = deResX * deResX;
1415 mDECorrMatrix[1][1] = deResY * deResY;
1416
1417 o2::detectors::AlignParam* alignMat = nullptr;
1418
1419 for (int chId = 0; chId <= 9; ++chId) {
1420
1421 // skip chamber if selection is valid, and does not match
1422 if (rChId > 0 && chId + 1 != rChId) {
1423 continue;
1424 }
1425
1426 TString chName1;
1427 TString chName2;
1428 if (chId < 4) {
1429
1430 chName1 = Form("GM%d", chId);
1431 chName2 = Form("GM%d", chId);
1432
1433 } else {
1434
1435 chName1 = Form("GM%d", 4 + (chId - 4) * 2);
1436 chName2 = Form("GM%d", 4 + (chId - 4) * 2 + 1);
1437 }
1438
1439 for (int i = 0; i < misAlignArray->GetEntries(); ++i) {
1440
1441 alignMat = (o2::detectors::AlignParam*)misAlignArray->At(i);
1442 TString volName(alignMat->getSymName());
1443 if ((volName.Contains(chName1) &&
1444 ((volName.Last('/') == volName.Index(chName1) + chName1.Length()) ||
1445 (volName.Length() == volName.Index(chName1) + chName1.Length()))) ||
1446 (volName.Contains(chName2) &&
1447 ((volName.Last('/') == volName.Index(chName2) + chName2.Length()) ||
1448 (volName.Length() == volName.Index(chName2) + chName2.Length())))) {
1449
1450 volName.Remove(0, volName.Last('/') + 1);
1451 }
1452 }
1453 }
1454}
1455
1456//_____________________________________________________
1457LocalTrackParam Aligner::RefitStraightTrack(Track& track, double z0) const
1458{
1459
1460 // initialize matrices
1461 TMatrixD AtGASum(4, 4);
1462 AtGASum.Zero();
1463
1464 TMatrixD AtGMSum(4, 1);
1465 AtGMSum.Zero();
1466
1467 // loop over clusters
1468 for (auto itTrackParam(track.begin()); itTrackParam != track.end(); ++itTrackParam) {
1469
1470 // get cluster
1471 const Cluster* cluster = itTrackParam->getClusterPtr();
1472 if (!cluster) {
1473 continue;
1474 }
1475
1476 // projection matrix
1477 TMatrixD A(2, 4);
1478 A.Zero();
1479 A(0, 0) = 1;
1480 A(0, 2) = (cluster->getZ() - z0);
1481 A(1, 1) = 1;
1482 A(1, 3) = (cluster->getZ() - z0);
1483
1484 TMatrixD At(TMatrixD::kTransposed, A);
1485
1486 // gain matrix
1487 TMatrixD G(2, 2);
1488 G.Zero();
1489 G(0, 0) = 1.0 / Square(cluster->getEx());
1490 G(1, 1) = 1.0 / Square(cluster->getEy());
1491
1492 const TMatrixD AtG(At, TMatrixD::kMult, G);
1493 const TMatrixD AtGA(AtG, TMatrixD::kMult, A);
1494 AtGASum += AtGA;
1495
1496 // measurement
1497 TMatrixD M(2, 1);
1498 M(0, 0) = cluster->getX();
1499 M(1, 0) = cluster->getY();
1500 const TMatrixD AtGM(AtG, TMatrixD::kMult, M);
1501 AtGMSum += AtGM;
1502 }
1503
1504 // perform inversion
1505 TMatrixD AtGASumInv(TMatrixD::kInverted, AtGASum);
1506 TMatrixD X(AtGASumInv, TMatrixD::kMult, AtGMSum);
1507
1508 // fill output parameters
1509 LocalTrackParam out;
1510 out.fTrackX = X(0, 0);
1511 out.fTrackY = X(1, 0);
1512 out.fTrackZ = z0;
1513 out.fTrackSlopeX = X(2, 0);
1514 out.fTrackSlopeY = X(3, 0);
1515
1516 return out;
1517}
1518
1519//_____________________________________________________
1520void Aligner::FillDetElemData(const Cluster* cluster)
1521{
1522
1524 // get detector element number from Alice ID
1525 const int detElemId = cluster->getDEId();
1526 fDetElemNumber = GetDetElemNumber(detElemId);
1527}
1528
1529//______________________________________________________________________
1530void Aligner::FillRecPointData(const Cluster* cluster)
1531{
1532
1534 fClustPos[0] = cluster->getX();
1535 fClustPos[1] = cluster->getY();
1536 fClustPos[2] = cluster->getZ();
1537}
1538
1539//______________________________________________________________________
1540void Aligner::FillTrackParamData(const TrackParam* trackParam)
1541{
1542
1544 fTrackPos[0] = trackParam->getNonBendingCoor();
1545 fTrackPos[1] = trackParam->getBendingCoor();
1546 fTrackPos[2] = trackParam->getZ();
1547 fTrackSlope[0] = trackParam->getNonBendingSlope();
1548 fTrackSlope[1] = trackParam->getBendingSlope();
1549}
1550
1551//______________________________________________________________________
1552void Aligner::LocalEquationX(const double* r)
1553{
1555
1556 // 'inverse' (GlobalToLocal) rotation matrix
1557 // const double* r(fGeoCombiTransInverse.GetRotationMatrix());
1558
1559 // local derivatives
1560 SetLocalDerivative(0, r[0]);
1561 SetLocalDerivative(1, r[0] * (fTrackPos[2] - fTrackPos0[2]));
1562 // SetLocalDerivative(1, -r[0] * fTrackPos[2]);
1563
1564 SetLocalDerivative(2, r[1]);
1565 SetLocalDerivative(3, r[1] * (fTrackPos[2] - fTrackPos0[2]));
1566 // SetLocalDerivative(3, -r[1] * fTrackPos[2]);
1567
1568 // global derivatives
1569 /*
1570 alignment parameters are
1571 0: delta_x
1572 1: delta_y
1573 2: delta_phiz
1574 3: delta_z
1575 */
1576
1577 SetGlobalDerivative(fDetElemNumber * fgNParCh + 0, -r[0]);
1578 SetGlobalDerivative(fDetElemNumber * fgNParCh + 1, -r[1]);
1579
1580 if (fBFieldOn) {
1581
1582 // use local position for derivatives vs 'delta_phi_z'
1583 SetGlobalDerivative(fDetElemNumber * fgNParCh + 2, -r[1] * fTrackPos[0] + r[0] * fTrackPos[1]);
1584
1585 // use local slopes for derivatives vs 'delta_z'
1586 SetGlobalDerivative(fDetElemNumber * fgNParCh + 3, r[0] * fTrackSlope[0] + r[1] * fTrackSlope[1]);
1587
1588 } else {
1589
1590 // local copy of extrapolated track positions
1591 const double trackPosX = fTrackPos0[0] + fTrackSlope0[0] * (fTrackPos[2] - fTrackPos0[2]);
1592 const double trackPosY = fTrackPos0[1] + fTrackSlope0[1] * (fTrackPos[2] - fTrackPos0[2]);
1593
1594 // use properly extrapolated position for derivatives vs 'delta_phi_z'
1595 SetGlobalDerivative(fDetElemNumber * fgNParCh + 2, -r[1] * trackPosX + r[0] * trackPosY);
1596 // SetGlobalDerivative(fDetElemNumber * fgNParCh + 2, -r[1] * (trackPosX - r[9]) + r[0] * (trackPosY - r[10]));
1597
1598 // use slopes at origin for derivatives vs 'delta_z'
1599 SetGlobalDerivative(fDetElemNumber * fgNParCh + 3, r[0] * fTrackSlope0[0] + r[1] * fTrackSlope0[1]);
1600 }
1601
1602 // store local equation
1603 fMillepede->SetLocalEquation(fGlobalDerivatives, fLocalDerivatives, fMeas[0], fSigma[0]);
1604}
1605
1606//______________________________________________________________________
1607void Aligner::LocalEquationY(const double* r)
1608{
1610
1611 // 'inverse' (GlobalToLocal) rotation matrix
1612 // const double* r(fGeoCombiTransInverse.GetRotationMatrix());
1613
1614 // store local derivatives
1615 SetLocalDerivative(0, r[3]);
1616 SetLocalDerivative(1, r[3] * (fTrackPos[2] - fTrackPos0[2]));
1617 // SetLocalDerivative(1, -r[3] * fTrackPos[2]);
1618
1619 SetLocalDerivative(2, r[4]);
1620 SetLocalDerivative(3, r[4] * (fTrackPos[2] - fTrackPos0[2]));
1621 // SetLocalDerivative(3, -r[4] * fTrackPos[2]);
1622
1623 // set global derivatives
1624 SetGlobalDerivative(fDetElemNumber * fgNParCh + 0, -r[3]);
1625 SetGlobalDerivative(fDetElemNumber * fgNParCh + 1, -r[4]);
1626
1627 if (fBFieldOn) {
1628
1629 // use local position for derivatives vs 'delta_phi'
1630 SetGlobalDerivative(fDetElemNumber * fgNParCh + 2, -r[4] * fTrackPos[0] + r[3] * fTrackPos[1]);
1631
1632 // use local slopes for derivatives vs 'delta_z'
1633 SetGlobalDerivative(fDetElemNumber * fgNParCh + 3, r[3] * fTrackSlope[0] + r[4] * fTrackSlope[1]);
1634
1635 } else {
1636
1637 // local copy of extrapolated track positions
1638 const double trackPosX = fTrackPos0[0] + fTrackSlope0[0] * (fTrackPos[2] - fTrackPos0[2]);
1639 const double trackPosY = fTrackPos0[1] + fTrackSlope0[1] * (fTrackPos[2] - fTrackPos0[2]);
1640
1641 // use properly extrapolated position for derivatives vs 'delta_phi'
1642 SetGlobalDerivative(fDetElemNumber * fgNParCh + 2, -r[4] * trackPosX + r[3] * trackPosY);
1643
1644 // use slopes at origin for derivatives vs 'delta_z'
1645 SetGlobalDerivative(fDetElemNumber * fgNParCh + 3, r[3] * fTrackSlope0[0] + r[4] * fTrackSlope0[1]);
1646 }
1647
1648 // store local equation
1649 fMillepede->SetLocalEquation(fGlobalDerivatives, fLocalDerivatives, fMeas[1], fSigma[1]);
1650}
1651
1652//_________________________________________________________________________
1653TGeoCombiTrans Aligner::DeltaTransform(const double* lMisAlignment) const
1654{
1656
1657 // translation
1658 const TGeoTranslation deltaTrans(lMisAlignment[0], lMisAlignment[1], lMisAlignment[3]);
1659
1660 // rotation
1661 TGeoRotation deltaRot;
1662 deltaRot.RotateZ(lMisAlignment[2] * 180. / TMath::Pi());
1663
1664 // combined rotation and translation.
1665 return TGeoCombiTrans(deltaTrans, deltaRot);
1666}
1667
1668bool Aligner::isMatrixConvertedToAngles(const double* rot, double& psi, double& theta, double& phi) const
1669{
1674 //
1675 if (std::abs(rot[0]) < 1e-7 || std::abs(rot[8]) < 1e-7) {
1676 LOG(error) << "Failed to extract roll-pitch-yall angles!";
1677 return false;
1678 }
1679 psi = std::atan2(-rot[5], rot[8]);
1680 theta = std::asin(rot[2]);
1681 phi = std::atan2(-rot[1], rot[0]);
1682 return true;
1683}
1684
1685//______________________________________________________________________
1686void Aligner::AddConstraint(double* par, double value)
1687{
1689 if (!fInitialized) {
1690 LOG(fatal) << "Millepede is not initialized";
1691 }
1692
1693 std::vector<double> vpar(fNGlobal);
1694 for (int i = 0; i < fNGlobal; i++) {
1695 vpar[i] = par[i];
1696 }
1697
1698 fMillepede->SetGlobalConstraint(vpar, value);
1699}
1700
1701//______________________________________________________________________
1702bool Aligner::DetElemIsValid(int iDetElemId) const
1703{
1705 const int iCh = iDetElemId / 100;
1706 const int iDet = iDetElemId % 100;
1707 return (iCh > 0 && iCh <= fgNCh && iDet < fgNDetElemCh[iCh - 1]);
1708}
1709
1710//______________________________________________________________________
1711int Aligner::GetDetElemNumber(int iDetElemId) const
1712{
1714 // get chamber and element number in chamber
1715 const int iCh = iDetElemId / 100;
1716 const int iDet = iDetElemId % 100;
1717
1718 // make sure detector index is valid
1719 if (!(iCh > 0 && iCh <= fgNCh && iDet < fgNDetElemCh[iCh - 1])) {
1720 LOG(fatal) << "Invalid detector element id: " << iDetElemId;
1721 }
1722
1723 // add number of detectors up to this chamber
1724 return iDet + fgSNDetElemCh[iCh - 1];
1725}
1726
1727//______________________________________________________________________
1728int Aligner::GetChamberId(int iDetElemNumber) const
1729{
1731 int iCh(0);
1732 for (iCh = 0; iCh < fgNCh; iCh++) {
1733 if (iDetElemNumber < fgSNDetElemCh[iCh]) {
1734 break;
1735 }
1736 }
1737
1738 return iCh;
1739}
1740
1741//______________________________________________________________________
1742TString Aligner::GetParameterMaskString(unsigned int mask) const
1743{
1744 TString out;
1745 if (mask & ParX) {
1746 out += "X";
1747 }
1748 if (mask & ParY) {
1749 out += "Y";
1750 }
1751 if (mask & ParZ) {
1752 out += "Z";
1753 }
1754 if (mask & ParTZ) {
1755 out += "T";
1756 }
1757 return out;
1758}
1759
1760//______________________________________________________________________
1761TString Aligner::GetSidesMaskString(unsigned int mask) const
1762{
1763 TString out;
1764 if (mask & SideTop) {
1765 out += "T";
1766 }
1767 if (mask & SideLeft) {
1768 out += "L";
1769 }
1770 if (mask & SideBottom) {
1771 out += "B";
1772 }
1773 if (mask & SideRight) {
1774 out += "R";
1775 }
1776 return out;
1777}
1778
1779} // namespace mch
1780} // namespace o2
Definition of the base alignment parameters class.
Definition of the MCH cluster minimal structure.
Definition of the MCH track for internal use.
int32_t i
General class for alignment with large number of degrees of freedom, adapted from AliROOT.
Class to store the data of single track processing.
Definition of the MCH track parameters for internal use.
Definition A.h:16
Definition B.h:16
void setGlobalParams(double x, double y, double z, double psi, double theta, double phi)
================ methods for direct setting of delta params
void setSymName(const char *m)
set symbolic name of the volume
Definition AlignParam.h:64
const std::string & getSymName() const
return symbolic name of the volume
Definition AlignParam.h:45
bool applyToGeometry() const
apply object to geoemetry
void SetGlobalConstraint(const std::vector< double > &dergb, const double val, const double sigma=0, const bool doPrint=false)
define a constraint equation
void DisableRecordWriter()
Disable record writer for DPL process.
Definition MillePede2.h:290
void SetNonLinear(int index, bool v=true)
Definition MillePede2.h:280
int InitMille(int nGlo, const int nLoc, const int lNStdDev=-1, const double lResCut=-1., const double lResCutInit=-1., const std::vector< int > &regroup={})
init all
void SetParSigma(int i, double par)
Definition MillePede2.h:278
void SetConstraintsRecWriter(o2::fwdalign::MilleRecordWriter *myP)
Definition MillePede2.h:268
void SetConstraintsRecReader(o2::fwdalign::MilleRecordReader *myP)
Definition MillePede2.h:270
double GetParError(int iPar) const
return error for parameter iPar
void SetLocalEquation(std::vector< double > &dergb, std::vector< double > &derlc, const double lMeas, const double lSigma)
assing derivs of loc.eq.
int SetIterations(const double lChi2CutFac)
Number of iterations is calculated from lChi2CutFac.
void SetRecord(o2::fwdalign::MillePedeRecord *aRecord)
Definition MillePede2.h:266
int PrintGlobalParameters() const
print the final results into the logfile
int GlobalFit(std::vector< double > &par, std::vector< double > &error, std::vector< double > &pull)
performs a requested number of global iterations
void SetRecordWriter(o2::fwdalign::MilleRecordWriter *myP)
Definition MillePede2.h:267
o2::fwdalign::MillePedeRecord * GetRecord() const
Definition MillePede2.h:260
void SetRecordReader(o2::fwdalign::MilleRecordReader *myP)
Definition MillePede2.h:269
void SetGlobalParameters(double *par)
Definition MillePede2.h:279
TString getDataTreeName() const
return the name of record data tree
void connectToChain(TChain *ch)
connect to input TChain
void setCyclicAutoSave(const long nEntries)
Set the number of entries to be used by TTree::AutoSave()
void setDataFileName(TString fname)
choose data records filename
void init()
init output file and tree
void setRecordRun(int run)
assign run
void terminate()
write tree and close output file
void setRecordWeight(double wgh)
assign weight
void fillRecordTree(const bool doPrint=false)
fill tree
HMPID cluster implementation.
Definition Cluster.h:27
void ReleaseDetElem(int iDetElemId, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:742
void SetAllowedVariation(int iPar, double value)
Definition Aligner.cxx:1267
void ReAlign(std::vector< o2::detectors::AlignParam > &params, std::vector< double > &misAlignments)
Definition Aligner.cxx:1322
void SetDetElemNonLinear(int iSt, unsigned int parameterMask)
Definition Aligner.cxx:878
static const int fgNDetElemCh[fgNCh]
Number of detection elements per chamber.
Definition Aligner.h:150
void FixParameter(int iPar)
Definition Aligner.cxx:698
void SetAlignmentResolution(const TClonesArray *misAlignArray, int chId, double chResX, double chResY, double deResX, double deResY)
Definition Aligner.cxx:1404
void GlobalFit(std::vector< double > &params, std::vector< double > &errors, std::vector< double > &pulls)
perform global fit
Definition Aligner.cxx:1298
static const int fgDetElemHalfCh[fgNHalfCh][fgNDetHalfChMax]
list of detection elements per tracking module
Definition Aligner.h:159
@ fNGlobal
Number of global parameters.
Definition Aligner.h:146
@ fgNDetHalfChMax
max number of detector elements per half chamber
Definition Aligner.h:133
@ fgNHalfCh
Number of half chambers.
Definition Aligner.h:130
@ fNLocal
Number of local parameters.
Definition Aligner.h:140
@ fgNCh
Number tracking chambers.
Definition Aligner.h:124
@ fgNParCh
Number of degrees of freedom per chamber.
Definition Aligner.h:143
void AddConstraints(const bool *bChOnOff, unsigned int parameterMask)
Definition Aligner.cxx:909
void SetParameterNonLinear(int iPar)
Definition Aligner.cxx:897
void FixHalfSpectrometer(const bool *bChOnOff, unsigned int sidesMask=AllSides, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:628
void SetChamberNonLinear(int iCh, unsigned int parameterMask)
Definition Aligner.cxx:855
void init(TString DataRecFName="millerecords.root", TString ConsRecFName="milleconstraints.root")
Definition Aligner.cxx:195
void FixChamber(int iCh, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:577
void PrintGlobalParameters(void) const
print global parameters
Definition Aligner.cxx:1310
static const int fgSNDetElemCh[fgNCh+1]
Sum of detection elements up to this chamber.
Definition Aligner.h:153
void ProcessTrack(Track &track, const o2::mch::geo::TransformationCreator &transformation, Bool_t doAlignment, Double_t weight=1)
Definition Aligner.cxx:376
double GetParError(int iPar) const
get error on a given parameter
Definition Aligner.cxx:1316
void ReleaseChamber(int iCh, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:710
void GroupDetElems(int detElemMin, int detElemMax, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:802
void InitGlobalParameters(double *par)
initialize global parameters to a give set of values
Definition Aligner.cxx:1256
void FixDetElem(int iDetElemId, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:609
void GroupChamber(int iCh, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:773
void FixAll(unsigned int parameterMask=ParAll)
Definition Aligner.cxx:554
void SetSigmaXY(double sigmaX, double sigmaY)
Definition Aligner.cxx:1284
void ReleaseParameter(int iPar)
Definition Aligner.cxx:761
void GroupHalfChamber(int iCh, int iHalf, unsigned int parameterMask=ParAll)
Definition Aligner.cxx:786
static const int fgNDetElemHalfCh[fgNHalfCh]
Number of detection element per tracking module.
Definition Aligner.h:156
self initialized array, used for adding constraints
Array()
contructor
Definition Aligner.cxx:104
Array(void)
contructor
local track residual, for tempoarary eval
Definition Aligner.h:62
local track parameters, for refit
Definition Aligner.h:45
track for internal use
Definition Track.h:33
auto end()
Return an iterator passing the track parameters at last cluster.
Definition Track.h:58
auto begin()
Return an iterator to the track parameters at clusters (point to the first one)
Definition Track.h:55
GLint GLenum GLint x
Definition glcorearb.h:403
GLint first
Definition glcorearb.h:399
GLuint GLuint GLfloat weight
Definition glcorearb.h:5477
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLenum const GLfloat * params
Definition glcorearb.h:272
GLenum GLsizei GLsizei GLint * values
Definition glcorearb.h:1576
GLboolean r
Definition glcorearb.h:1233
GLint GLuint mask
Definition glcorearb.h:291
int detElemId(Chamber chamber, Side side, int number)
std::function< o2::math_utils::Transform3D(int detElemId)> TransformationCreator
Double_t Square(Double_t x)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
cluster minimal structure
Definition Cluster.h:31
double getEx() const
Return the cluster resolution along x as double.
Definition Cluster.h:48
int getDEId() const
Return the detection element ID, part of the unique ID.
Definition Cluster.h:62
double getY() const
Return the cluster position along y as double.
Definition Cluster.h:44
double getX() const
Return the cluster position along x as double.
Definition Cluster.h:42
double getEy() const
Return the cluster resolution along y as double.
Definition Cluster.h:50
double getZ() const
Return the cluster position along z as double.
Definition Cluster.h:46
auto transformation
uint16_t de
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"