Project
Loading...
Searching...
No Matches
Controller.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
16
17#include "Align/Controller.h"
18#include "Align/AlignConfig.h"
19#include "Framework/Logger.h"
20#include "Align/utils.h"
28#include "Align/EventVertex.h"
36#include "MathUtils/Utils.h"
37
38#include <TMath.h>
39#include <TString.h>
40
41#include <TROOT.h>
42#include <TSystem.h>
43#include <TRandom.h>
44#include <TH1F.h>
45#include <TList.h>
46#include <cstdio>
47#include "GPUO2Interface.h"
49#include <TGeoGlobalMagField.h>
53#include "GPUParam.h"
54
58#include <unordered_map>
59
60using namespace TMath;
61using namespace o2::align::utils;
62using namespace o2::dataformats;
63using namespace o2::globaltracking;
64
65namespace o2
66{
67namespace align
68{
72
74{
75 const auto& stat0 = data[kInput];
76 LOGP(info, "StatSeen: Vtx: {:10} Tracks: {:10} TracksWVtx: {:10}", stat0[kVertices], stat0[kTracks], stat0[kTracksWithVertex]);
77 const auto& stat1 = data[kAccepted];
78 LOGP(info, "StatAcc : Vtx: {:10} Tracks: {:10} TracksWVtx: {:10}", stat1[kVertices], stat1[kTracks], stat1[kTracksWithVertex]);
79}
80
81const Char_t* Controller::sMPDataExt = ".mille";
82const Char_t* Controller::sMPDataTxtExt = ".mille_txt";
83
84const Char_t* Controller::sDetectorName[Controller::kNDetectors] = {"ITS", "TPC", "TRD", "TOF", "HMPID"}; //RSREM
85
86//const int Controller::mgkSkipLayers[Controller::kNLrSkip] = {AliGeomManager::kPHOS1, AliGeomManager::kPHOS2,
87// AliGeomManager::kMUON, AliGeomManager::kEMCAL}; TODO(milettri, shahoian): needs detector IDs previously stored in AliGeomManager
88const int Controller::sSkipLayers[Controller::kNLrSkip] = {0, 0, 0, 0}; // TODO(milettri, shahoian): needs AliGeomManager - remove this line after fix.
89
90//________________________________________________________________
91Controller::Controller(DetID::mask_t detmask, GTrackID::mask_t trcmask, bool cosmic, bool useMC, int instID)
92 : mDetMask(detmask), mMPsrc(trcmask), mUseMC(useMC), mInstanceID(instID)
93{
94 setCosmic(cosmic);
95 init();
96}
97
98//________________________________________________________________
100{
101 // d-tor
105 //
106}
107
108//________________________________________________________________
110{
111 if (mDetMask[DetID::ITS]) {
113 }
114 if (mDetMask[DetID::TRD]) {
116 }
117 if (mDetMask[DetID::TPC]) {
119 }
120 if (mDetMask[DetID::TOF]) {
122 }
123 for (int src = GIndex::NSources; src--;) {
124 if (mMPsrc[src]) {
125 mTrackSources.push_back(src);
126 }
127 }
128 mVtxSens = std::make_unique<EventVertex>(this);
129 mVtxSens->setInternalID(1);
130 const auto& algConf = AlignConfig::Instance();
131 if (algConf.MPRecOutFraction > 0. || mInstanceID == 0) {
132 mMPRecOutFraction = std::abs(algConf.MPRecOutFraction);
133 }
134 if (algConf.controlFraction > 0. || mInstanceID == 0) {
135 mControlFraction = std::abs(algConf.controlFraction);
136 }
137}
138
139//________________________________________________________________
141{
143 if (mUseMC) {
144 if (!mcReader.initFromDigitContext("collisioncontext.root")) {
145 throw std::invalid_argument("initialization of MCKinematicsReader failed");
146 }
147 }
148 auto timerStart = std::chrono::system_clock::now();
149 int nVtx = 0, nVtxAcc = 0, nTrc = 0, nTrcAcc = 0;
150 for (auto id = DetID::First; id <= DetID::Last; id++) {
151 auto* det = getDetector(id);
152 if (det) {
153 det->prepareDetectorData(); // in case the detector needs to preprocess the RecoContainer data
154 }
155 }
156 auto primVertices = mRecoData->getPrimaryVertices();
157 auto primVer2TRefs = mRecoData->getPrimaryVertexMatchedTrackRefs();
158 auto primVerGIs = mRecoData->getPrimaryVertexMatchedTracks();
159 const auto& algConf = AlignConfig::Instance();
160 // process vertices with contributor tracks
161 std::unordered_map<GIndex, bool> ambigTable;
162 int nvRefs = primVer2TRefs.size();
163 bool fieldON = std::abs(PropagatorD::Instance()->getNominalBz()) > 0.1;
164
165 for (int ivref = 0; ivref < nvRefs; ivref++) {
166 const o2::dataformats::PrimaryVertex* vtx = (ivref < nvRefs - 1) ? &primVertices[ivref] : nullptr;
167 bool useVertexConstrain = false;
168 if (vtx) {
169 auto nContrib = vtx->getNContributors();
170 // check cov matrix since data reconstructed with < 6797a257f5ab8ffaec32d56dddb0a321939bdf1c may have negative errors
171 if (vtx->getSigmaX2() < 0. || vtx->getSigmaY2() < 0. || vtx->getSigmaZ2() < 0.) {
172 continue;
173 }
174 useVertexConstrain = nContrib >= algConf.vtxMinCont && nContrib <= algConf.vtxMaxCont;
176 }
177 auto& trackRef = primVer2TRefs[ivref];
178 if (algConf.verbose > 1) {
179 LOGP(info, "processing vtref {} of {} with {} tracks, {}", ivref, nvRefs, trackRef.getEntries(), vtx ? vtx->asString() : std::string{});
180 }
181 nVtx++;
182 bool newVtx = true;
183 for (int src : mTrackSources) {
184 if ((GIndex::getSourceDetectorsMask(src) & mDetMask).none()) { // do we need this source?
185 continue;
186 }
187 int start = trackRef.getFirstEntryOfSource(src), end = start + trackRef.getEntriesOfSource(src);
188 for (int ti = start; ti < end; ti++) {
189 auto trackIndex = primVerGIs[ti];
190 mAlgTrack->setCurrentTrackID(trackIndex);
191 bool tpcIn = false;
192 if (trackIndex.isAmbiguous()) {
193 auto& ambSeen = ambigTable[trackIndex];
194 if (ambSeen) { // processed
195 continue;
196 }
197 ambSeen = true;
198 }
200 if (vtx) {
202 }
203 int npnt = 0;
204 auto contributorsGID = mRecoData->getSingleDetectorRefs(trackIndex);
205
206 std::string trComb;
207 for (int ig = 0; ig < GIndex::NSources; ig++) {
208 if (contributorsGID[ig].isIndexSet()) {
209 trComb += " " + contributorsGID[ig].asString();
210 }
211 }
212 if (algConf.verbose > 1) {
213 LOG(info) << "processing track " << trackIndex.asString() << " contributors: " << trComb;
214 }
216 nTrc++;
217 // RS const auto& trcOut = mRecoData->getTrackParamOut(trackIndex);
218 auto trcOut = mRecoData->getTrackParamOut(trackIndex);
219 const auto& trcIn = mRecoData->getTrackParam(trackIndex);
220 // check detectors contributions
221 AlignableDetector* det = nullptr;
222 int ndet = 0, npntDet = 0;
223
224 if ((det = getDetector(DetID::ITS))) {
225 if (contributorsGID[GIndex::ITS].isIndexSet() && (npntDet = det->processPoints(contributorsGID[GIndex::ITS], algConf.minITSClusters, false)) > 0) {
226 npnt += npntDet;
227 ndet++;
228 } else if (mAllowAfterburnerTracks && contributorsGID[GIndex::ITSAB].isIndexSet() && (npntDet = det->processPoints(contributorsGID[GIndex::ITSAB], 2, false)) > 0) {
229 npnt += npntDet;
230 ndet++;
231 } else {
232 continue;
233 }
234 }
235 if ((det = getDetector(DetID::TPC)) && contributorsGID[GIndex::TPC].isIndexSet()) {
236 float t0 = 0, t0err = 0;
237 mRecoData->getTrackTime(trackIndex, t0, t0err);
238 ((AlignableDetectorTPC*)det)->setTrackTimeStamp(t0);
239 npntDet = det->processPoints(contributorsGID[GIndex::TPC], algConf.minTPCClusters, false);
240 if (npntDet > 0) {
241 npnt += npntDet;
242 ndet++;
243 tpcIn = true;
244 }
245 }
246
247 if ((det = getDetector(DetID::TRD)) && contributorsGID[GIndex::TRD].isIndexSet() && (npntDet = det->processPoints(contributorsGID[GIndex::TRD], algConf.minTRDTracklets, false)) > 0) {
248 npnt += npntDet;
249 ndet++;
250 }
251 if ((det = getDetector(DetID::TOF)) && contributorsGID[GIndex::TOF].isIndexSet() && (npntDet = det->processPoints(contributorsGID[GIndex::TOF], algConf.minTOFClusters, false)) > 0) {
252 npnt += npntDet;
253 ndet++;
254 }
255 // other detectors
256 if (algConf.verbose > 1) {
257 LOGP(info, "processing track {} {} of vtref {}, Ndets:{}, Npoints: {}, use vertex: {} | Kin: {} Kout: {}", ti, trackIndex.asString(), ivref, ndet, npnt, useVertexConstrain && trackIndex.isPVContributor(), trcIn.asString(), trcOut.asString());
258 }
259 if (ndet < algConf.minDetectors || (tpcIn && ndet == 1)) { // we don't want TPC only track
260 continue;
261 }
262 if (npnt < algConf.minPointTotal) {
263 if (algConf.verbose > 0) {
264 LOGP(info, "too few points {} < {}", npnt, algConf.minPointTotal);
265 }
266 continue;
267 }
268 bool vtxCont = false;
269 if (trackIndex.isPVContributor() && useVertexConstrain) {
270 mAlgTrack->copyFrom(trcIn); // copy kinematices of inner track just for propagation to the vertex
271 if (addVertexConstraint(*vtx)) {
272 mAlgTrack->setRefPoint(mRefPoint.get()); // set vertex as a reference point
273 vtxCont = true;
274 }
275 }
276 mAlgTrack->copyFrom(trcOut); // copy kinematices of outer track as the refit will be done inward
277 mAlgTrack->setFieldON(fieldON);
278 mAlgTrack->sortPoints();
279
280 int pntMeas = mAlgTrack->getInnerPointID() - 1;
281 if (pntMeas < 0) { // this should not happen
282 mAlgTrack->Print("p meas");
283 LOG(error) << "AliAlgTrack->GetInnerPointID() cannot be 0";
284 }
285 if (!mAlgTrack->iniFit()) {
286 if (algConf.verbose > 0) {
287 LOGP(warn, "iniFit failed");
288 }
289 continue;
290 }
291 // compare refitted and original track
292 if (mDebugOutputLevel) {
293 trackParam_t trcAlgRef(*mAlgTrack.get());
294 std::array<double, 5> dpar{};
295 std::array<double, 15> dcov{};
296 for (int i = 0; i < 5; i++) {
297 dpar[i] = trcIn.getParam(i);
298 }
299 for (int i = 0; i < 15; i++) {
300 dcov[i] = trcIn.getCov()[i];
301 }
302 trackParam_t trcOrig(trcIn.getX(), trcIn.getAlpha(), dpar, dcov, trcIn.getCharge());
303 if (PropagatorD::Instance()->propagateToAlphaX(trcOrig, trcAlgRef.getAlpha(), trcAlgRef.getX(), true)) {
304 (*mDBGOut) << "trcomp"
305 << "orig=" << trcOrig << "fit=" << trcAlgRef << "\n";
306 }
307 }
308 // RS: this is to substitute the refitter track by MC truth, just for debugging
309 /*
310 if (mUseMC) {
311 auto lbl = mRecoData->getTrackMCLabel(trackIndex);
312 if (lbl.isValid()) {
313 o2::MCTrack mcTrack = *mcReader.getTrack(lbl);
314 std::array<float,3> xyz{(float)mcTrack.GetStartVertexCoordinatesX(),(float)mcTrack.GetStartVertexCoordinatesY(),(float)mcTrack.GetStartVertexCoordinatesZ()},
315 pxyz{(float)mcTrack.GetStartVertexMomentumX(),(float)mcTrack.GetStartVertexMomentumY(),(float)mcTrack.GetStartVertexMomentumZ()};
316 std::array<float,21> cv21{10., 0.,10., 0.,0.,10., 0.,0.,0.,1., 0.,0.,0.,0.,1., 0.,0.,0.,0.,0.,1.};
317 trcOut.set(xyz, pxyz, cv21, trcOut.getSign(), false);
318 mAlgTrack->copyFrom(trcOut);
319 }
320 }
321 */
322 if (!mAlgTrack->processMaterials()) {
323 if (algConf.verbose > 0) {
324 LOGP(warn, "processMaterials failed");
325 }
326 continue;
327 }
328 mAlgTrack->defineDOFs();
329 if (!mAlgTrack->calcResidDeriv()) {
330 if (algConf.verbose > 0) {
331 LOGP(warn, "calcResidDeriv failed");
332 }
333 continue;
334 }
336 mAlgTrackDbg.mGID = trackIndex;
337 (*mDBGOut) << "algtrack"
338 << "runNumber=" << mTimingInfo.runNumber
339 << "tfID=" << mTimingInfo.tfCounter
340 << "orbit=" << mTimingInfo.firstTForbit
341 << "bz=" << PropagatorD::Instance()->getNominalBz()
342 << "t=" << mAlgTrackDbg << "\n";
343 }
344 if (mUseMC && mDebugOutputLevel > 1) {
345 auto lbl = mRecoData->getTrackMCLabel(trackIndex);
346 if (lbl.isValid()) {
347 std::vector<float> pntX, pntY, pntZ, trcX, trcY, trcZ, prpX, prpY, prpZ, alpha, xsens, pntXTF, pntYTF, pntZTF, resY, resZ;
348 std::vector<int> detid, volid;
349
350 o2::MCTrack mcTrack = *mcReader.getTrack(lbl);
351 trackParam_t recTrack{*mAlgTrack};
352 for (int ip = 0; ip < mAlgTrack->getNPoints(); ip++) {
353 double tmp[3], tmpg[3];
354 auto* pnt = mAlgTrack->getPoint(ip);
355 auto* sens = pnt->getSensor();
356 detid.emplace_back(pnt->getDetID());
357 volid.emplace_back(pnt->getVolID());
358 TGeoHMatrix t2g;
359 sens->getMatrixT2G(t2g);
360 t2g.LocalToMaster(pnt->getXYZTracking(), tmpg);
361 pntX.emplace_back(tmpg[0]);
362 pntY.emplace_back(tmpg[1]);
363 pntZ.emplace_back(tmpg[2]);
364 double xyz[3]{pnt->getXTracking(), pnt->getYTracking(), pnt->getZTracking()};
365 xyz[1] += mAlgTrack->getResidual(0, ip);
366 xyz[2] += mAlgTrack->getResidual(1, ip);
367 t2g.LocalToMaster(xyz, tmpg);
368 trcX.emplace_back(tmpg[0]);
369 trcY.emplace_back(tmpg[1]);
370 trcZ.emplace_back(tmpg[2]);
371
372 pntXTF.emplace_back(pnt->getXTracking());
373 pntYTF.emplace_back(pnt->getYTracking());
374 pntZTF.emplace_back(pnt->getZTracking());
375 resY.emplace_back(mAlgTrack->getResidual(0, ip));
376 resZ.emplace_back(mAlgTrack->getResidual(1, ip));
377
378 alpha.emplace_back(pnt->getAlphaSens());
379 xsens.emplace_back(pnt->getXSens());
380 }
381 (*mDBGOut) << "mccomp"
382 << "mcTr=" << mcTrack << "recTr=" << recTrack << "gid=" << trackIndex << "lbl=" << lbl << "vtxConst=" << vtxCont
383 << "pntX=" << pntX << "pntY=" << pntY << "pntZ=" << pntZ
384 << "trcX=" << trcX << "trcY=" << trcY << "trcZ=" << trcZ
385 << "alp=" << alpha << "xsens=" << xsens
386 << "pntXTF=" << pntXTF << "pntYTF=" << pntYTF << "pntZTF=" << pntZTF
387 << "resY=" << resY << "resZ=" << resZ
388 << "detid=" << detid << "volid=" << volid << "\n";
389 }
390 }
392 if (vtxCont) {
394 }
395 nTrcAcc++;
396 if (newVtx) {
397 newVtx = false;
399 nVtxAcc++;
400 }
401 storeProcessedTrack(trackIndex);
402 }
403 }
404 }
405 auto timerEnd = std::chrono::system_clock::now();
406 std::chrono::duration<float, std::milli> duration = timerEnd - timerStart;
407 LOGP(info, "Processed TF {}: {} vertices ({} used), {} tracks ({} used) in {} ms", mNTF, nVtx, nVtxAcc, nTrc, nTrcAcc, duration.count());
408 mNTF++;
409}
410
411//________________________________________________________________
413{
414 auto timerStart = std::chrono::system_clock::now();
415 const auto tracks = mRecoData->getCosmicTracks();
416 if (!tracks.size()) {
417 LOGP(info, "Skipping TF {}: No cosmic tracks", mNTF);
418 mNTF++;
419 return;
420 }
421 int nTrc = 0, nTrcAcc = 0;
422 for (auto id = DetID::First; id <= DetID::Last; id++) {
423 auto* det = getDetector(id);
424 if (det) {
425 det->prepareDetectorData(); // in case the detector needs to preprocess the RecoContainer data
426 }
427 }
428 const auto& algConf = AlignConfig::Instance();
429 bool fieldON = std::abs(PropagatorD::Instance()->getNominalBz()) > 0.1;
430 for (const auto& track : tracks) {
432 nTrc++;
434 std::array<GTrackID, GTrackID::NSources> contributorsGID[2] = {mRecoData->getSingleDetectorRefs(track.getRefBottom()), mRecoData->getSingleDetectorRefs(track.getRefTop())};
435 bool hasTRD = false, hasITS = false, hasTPC = false, hasTOF = false;
436 if (contributorsGID[0][GTrackID::TRD].isIndexSet() || contributorsGID[1][GTrackID::TRD].isIndexSet()) {
437 hasTRD = true;
438 }
439 if (contributorsGID[0][GTrackID::TOF].isIndexSet() || contributorsGID[1][GTrackID::TOF].isIndexSet()) {
440 hasTOF = true;
441 }
442 if (contributorsGID[0][GTrackID::TPC].isIndexSet() || contributorsGID[1][GTrackID::TPC].isIndexSet()) {
443 hasTPC = true;
444 }
445 if (contributorsGID[0][GTrackID::ITS].isIndexSet() || contributorsGID[1][GTrackID::ITS].isIndexSet()) {
446 hasITS = true;
447 }
448 // check detectors contributions
449 AlignableDetector* det = nullptr;
450 int ndet = 0, npnt = 0;
451 bool accTrack = true;
452 bool tpcIn = false;
453 if ((det = getDetector(DetID::ITS))) {
454 int npntDet = 0;
455 for (int ibt = 0; ibt < 2; ibt++) {
456 int npntDetBT = 0;
457 mAlgTrack->setCurrentTrackID(ibt ? track.getRefBottom() : track.getRefTop());
458 if (contributorsGID[ibt][GIndex::ITS].isIndexSet() && (npntDetBT = det->processPoints(contributorsGID[ibt][GIndex::ITS], algConf.minITSClustersCosmLeg, ibt)) < 0) {
459 accTrack = false;
460 break;
461 }
462 npntDet += npntDetBT;
463 }
464 if (!accTrack || npntDet < algConf.minITSClustersCosm) {
465 continue;
466 }
467 if (npntDet) {
468 ndet++;
469 npnt += npntDet;
470 }
471 }
472
473 if ((det = getDetector(DetID::TPC))) {
474 int npntDet = 0;
475 ((AlignableDetectorTPC*)det)->setTrackTimeStamp(track.getTimeMUS().getTimeStamp());
476 for (int ibt = 0; ibt < 2; ibt++) {
477 int npntDetBT = 0;
478 mAlgTrack->setCurrentTrackID(ibt ? track.getRefBottom() : track.getRefTop());
479 if (contributorsGID[ibt][GIndex::TPC].isIndexSet() && (npntDetBT = det->processPoints(contributorsGID[ibt][GIndex::TPC], algConf.minTPCClustersCosmLeg, ibt)) < 0) {
480 accTrack = false;
481 break;
482 }
483 npntDet += npntDetBT;
484 }
485 if (!accTrack || npntDet < algConf.minTPCClustersCosm) {
486 continue;
487 }
488 if (npntDet) {
489 ndet++;
490 npnt += npntDet;
491 tpcIn = true;
492 }
493 }
494
495 if ((det = getDetector(DetID::TRD))) {
496 int npntDet = 0;
497 for (int ibt = 0; ibt < 2; ibt++) {
498 int npntDetBT = 0;
499 mAlgTrack->setCurrentTrackID(ibt ? track.getRefBottom() : track.getRefTop());
500 if (contributorsGID[ibt][GIndex::TRD].isIndexSet() && (npntDetBT = det->processPoints(contributorsGID[ibt][GIndex::TRD], algConf.minTRDTrackletsCosmLeg, ibt)) < 0) {
501 accTrack = false;
502 break;
503 }
504 npntDet += npntDetBT;
505 }
506 if (!accTrack || npntDet < algConf.minTRDTrackletsCosm) {
507 continue;
508 }
509 if (npntDet) {
510 ndet++;
511 npnt += npntDet;
512 }
513 }
514
515 if ((det = getDetector(DetID::TOF))) {
516 int npntDet = 0;
517 for (int ibt = 0; ibt < 2; ibt++) {
518 int npntDetBT = 0;
519 mAlgTrack->setCurrentTrackID(ibt ? track.getRefBottom() : track.getRefTop());
520 if (contributorsGID[ibt][GIndex::TOF].isIndexSet() && (npntDetBT = det->processPoints(contributorsGID[ibt][GIndex::TOF], algConf.minTOFClustersCosmLeg, ibt)) < 0) {
521 accTrack = false;
522 break;
523 }
524 npntDet += npntDetBT;
525 }
526 if (!accTrack || npntDet < algConf.minTOFClustersCosm) {
527 continue;
528 }
529 if (npntDet) {
530 ndet++;
531 npnt += npntDet;
532 }
533 }
534 if (algConf.verbose > 1) {
535 LOGP(info, "processing cosmic track B-Leg:{} T-Leg:{}, Ndets:{}, Npoints: {}", track.getRefBottom().asString(), track.getRefTop().asString(), ndet, npnt);
536 }
537 if (ndet < algConf.minDetectorsCosm /* || (tpcIn && ndet == 1)*/) {
538 continue;
539 }
540 if (npnt < algConf.minPointTotalCosm) {
541 if (algConf.verbose > 0) {
542 LOGP(info, "too few points {} < {}", npnt, algConf.minPointTotalCosm);
543 }
544 continue;
545 }
546 mAlgTrack->setCosmic(true);
547 mAlgTrack->copyFrom(mRecoData->getTrackParamOut(track.getRefBottom())); // copy kinematices of outer track as the refit will be done inward
548 mAlgTrack->setFieldON(fieldON);
549 mAlgTrack->sortPoints();
550 if (!mAlgTrack->iniFit()) {
551 if (algConf.verbose > 0) {
552 LOGP(warn, "iniFit failed");
553 }
554 continue;
555 }
556 if (!mAlgTrack->processMaterials()) {
557 if (algConf.verbose > 0) {
558 LOGP(warn, "processMaterials failed");
559 }
560 continue;
561 }
562 mAlgTrack->defineDOFs();
563 if (!mAlgTrack->calcResidDeriv()) {
564 if (algConf.verbose > 0) {
565 LOGP(warn, "calcResidDeriv failed");
566 }
567 continue;
568 }
570 mAlgTrackDbg.mGID = track.getRefBottom();
571 mAlgTrackDbg.mGIDCosmUp = track.getRefTop();
572 (*mDBGOut) << "algtrack"
573 << "runNumber=" << mTimingInfo.runNumber
574 << "tfID=" << mTimingInfo.tfCounter
575 << "orbit=" << mTimingInfo.firstTForbit
576 << "bz=" << PropagatorD::Instance()->getNominalBz()
577 << "t=" << mAlgTrackDbg << "\n";
578 }
581 nTrcAcc++;
582 }
583 auto timerEnd = std::chrono::system_clock::now();
584 std::chrono::duration<float, std::milli> duration = timerEnd - timerStart;
585 LOGP(info, "Processed cosmic TF {}: {} tracks ({} used) in {} ms", mNTF, nTrc, nTrcAcc, duration.count());
586 mNTF++;
587}
588
589//________________________________________________________________
591{
592 // init all detectors geometry
593 //
594 if (getInitGeomDone()) {
595 return;
596 }
597 //
598 mAlgTrack = std::make_unique<AlignmentTrack>();
599 mRefPoint = std::make_unique<AlignmentPoint>();
600 //
601 int dofCnt = 0;
602 // special fake sensor for vertex constraint point
603 // it has special T2L matrix adjusted for each track, no need to init it here
604 mVtxSens->prepareMatrixL2G();
605 mVtxSens->prepareMatrixL2GIdeal();
606 dofCnt += mVtxSens->getNDOFs();
607 //
608 for (auto id = DetID::First; id <= DetID::Last; id++) {
609 auto* det = getDetector(id);
610 if (det) {
611 dofCnt += det->initGeom();
612 }
613 }
614 if (!dofCnt) {
615 LOG(fatal) << "No DOFs found";
616 }
617 //
618 //
619 for (auto id = DetID::First; id <= DetID::Last; id++) {
620 auto* det = getDetector(id);
621 if (!det || det->isDisabled()) {
622 continue;
623 }
624 det->cacheReferenceCCDB();
625 }
626 //
627 assignDOFs();
628 LOG(info) << "Booked " << dofCnt << " global parameters";
629 //
631 //
632}
633
634//________________________________________________________________
636{
637 // scan all free global parameters, link detectors to array of params
638 //
639 if (getInitDOFsDone()) {
640 LOG(info) << "initDOFs was already done, just reassigning " << getNDOFs() << "DOFs arrays/labels";
641 assignDOFs();
642 return;
643 }
644 const auto& conf = AlignConfig::Instance();
645
646 mNDOFs = 0;
647 int ndfAct = 0;
648 assignDOFs();
649 int nact = 0;
650 mVtxSens->initDOFs();
651 for (auto id = DetID::First; id <= DetID::Last; id++) {
653 if (det && !det->isDisabled()) {
654 det->initDOFs();
655 nact++;
656 ndfAct += det->getNDOFs();
657 }
658 }
659 for (int i = 0; i < NTrackTypes; i++) {
660 if (nact < conf.minDetAcc[i]) {
661 LOG(fatal) << nact << " detectors are active, while " << conf.minDetAcc[i] << " in track are asked";
662 }
663 }
664 LOG(info) << mNDOFs << " global parameters " << mNDet << " detectors, " << ndfAct << " in " << nact << " active detectors";
667}
668
669//________________________________________________________________
671{
672 // add parameters/labels arrays to volumes. If the Controller is read from the file, this method need
673 // to be called (of initDOFs should be called)
674 //
675 int ndfOld = -1;
676 if (mNDOFs > 0) {
677 ndfOld = mNDOFs;
678 }
679 mNDOFs = 0;
680 //
681 // reserve
682 int ndofTOT = mVtxSens->getNDOFs();
683 for (auto id = DetID::First; id <= DetID::Last; id++) {
685 if (!det) {
686 continue;
687 }
688 ndofTOT += det->getNDOFs();
689 }
690 mGloParVal.clear();
691 mGloParErr.clear();
692 mGloParLab.clear();
693 mLbl2ID.clear();
694 mGloParVal.reserve(ndofTOT);
695 mGloParErr.reserve(ndofTOT);
696 mGloParLab.reserve(ndofTOT);
697
698 mVtxSens->assignDOFs();
699
700 for (auto id = DetID::First; id <= DetID::Last; id++) {
702 if (!det) {
703 continue;
704 }
705 det->assignDOFs();
706 }
707 LOG(info) << "Assigned parameters/labels arrays for " << mNDOFs << " DOFs";
708 if (ndfOld > 0 && ndfOld != mNDOFs) {
709 LOG(error) << "Recalculated NDOFs=" << mNDOFs << " not equal to saved NDOFs=" << ndfOld;
710 }
711 // build Lbl -> parID table
712 for (int i = 0; i < ndofTOT; i++) {
713 int& id = mLbl2ID[mGloParLab[i]];
714 if (id != 0) {
715 LOGP(fatal, "parameters {} and {} share the same label {}", id - 1, i, mGloParLab[i]);
716 }
717 id = i + 1;
718 }
719 //
720}
721
722//_________________________________________________________
724{
725 // add detector constructed externally to alignment framework
726 mDetectors[det->getDetID()].reset(det);
727 mNDet++;
728}
729
730//_________________________________________________________
732{
733 //validate detector pattern
735 patt.count() >= AlignConfig::Instance().minDetAcc[mTracksType];
736}
737
738//_________________________________________________________
739bool Controller::checkDetectorPoints(const int* npsel) const
740{
741 //validate detectors pattern according to number of selected points
742 int ndOK = 0;
743 for (auto id = DetID::First; id <= DetID::Last; id++) {
745 if (!det || det->isDisabled(mTracksType)) {
746 continue;
747 }
748 if (npsel[id] < det->getNPointsSel(mTracksType)) {
749 if (det->isObligatory(mTracksType)) {
750 return false;
751 }
752 continue;
753 }
754 ndOK++;
755 }
756 return ndOK >= AlignConfig::Instance().minDetAcc[mTracksType];
757}
758
759//_________________________________________________________
761{
762 // write alignment track
763 bool res = true;
764 const auto& conf = AlignConfig::Instance();
765 if (conf.MilleOut) {
766 res &= fillMilleData();
767 }
768 float rnd = gRandom->Rndm();
769 if (mMPRecOutFraction > rnd) {
770 res &= fillMPRecData(tid);
771 }
772 if ((mControlFraction > rnd) && mAlgTrack->testLocalSolution()) {
773 res &= fillControlData(tid);
774 }
775 //
776 if (!res) {
777 LOGP(error, "storeProcessedTrack failed");
778 }
779 return res;
780}
781
782//_________________________________________________________
784{
785 // store MP2 data in Mille format
786 if (!mMille) {
787 const auto& conf = AlignConfig::Instance();
788 mMilleFileName = fmt::format("{}_{:08d}_{:010d}{}", AlignConfig::Instance().mpDatFileName, mTimingInfo.runNumber, mTimingInfo.tfCounter, conf.MilleOutBin ? sMPDataExt : sMPDataTxtExt);
789 mMille = std::make_unique<Mille>(mMilleFileName.c_str(), conf.MilleOutBin);
790 }
791 if (!mAlgTrack->getDerivDone()) {
792 LOG(error) << "Track derivatives are not yet evaluated";
793 return false;
794 }
795 int np = mAlgTrack->getNPoints(), nDGloTot = 0; // total number global derivatives stored
796 int nParETP = mAlgTrack->getNLocExtPar(); // numnber of local parameters for reference track param
797 int nVarLoc = mAlgTrack->getNLocPar(); // number of local degrees of freedom in the track
798 //
799 const int* gloParID = mAlgTrack->getGloParID(); // IDs of global DOFs this track depends on
800 for (int ip = 0; ip < np; ip++) {
801 AlignmentPoint* pnt = mAlgTrack->getPoint(ip);
802 if (pnt->containsMeasurement()) {
803 int gloOffs = pnt->getDGloOffs(); // 1st entry of global derivatives for this point
804 int nDGlo = pnt->getNGloDOFs(); // number of global derivatives (number of DOFs it depends on)
805 if (!pnt->isStatOK()) {
806 pnt->incrementStat();
807 }
808 int milleIBufferG[nDGlo];
809 float milleDBufferG[nDGlo];
810 float milleDBufferL[nVarLoc];
811 std::memset(milleIBufferG, 0, sizeof(int) * nDGlo);
812 std::memset(milleDBufferG, 0, sizeof(float) * nDGlo);
813 std::memset(milleDBufferL, 0, sizeof(float) * nVarLoc);
814 // local der. array cannot be 0-suppressed by Mille construction, need to reset all to 0
815 for (int idim = 0; idim < 2; idim++) { // 2 dimensional orthogonal measurement
816 const double* deriv = mAlgTrack->getDResDLoc(idim, ip); // array of Dresidual/Dparams_loc
817 // derivatives over reference track parameters
818 for (int j = 0; j < nParETP; j++) {
819 milleDBufferL[j] = isZeroAbs(deriv[j]) ? 0. : deriv[j];
820 }
821 //
822 // point may depend on material variables within these limits
823 for (int j = pnt->getMinLocVarID(); j < pnt->getMaxLocVarID(); j++) {
824 milleDBufferL[j] = isZeroAbs(deriv[j]) ? 0. : deriv[j];
825 }
826 // derivatives over global params: this array can be 0-suppressed, no need to reset
827 int nGlo = 0;
828 deriv = mAlgTrack->getDResDGlo(idim, gloOffs);
829 const int* gloIDP(gloParID + gloOffs);
830 for (int j = 0; j < nDGlo; j++) {
831 milleDBufferG[nGlo] = isZeroAbs(deriv[j]) ? 0. : deriv[j]; // value of derivative
832 milleIBufferG[nGlo++] = getGloParLab(gloIDP[j]); // global DOF ID + 1 (Millepede needs positive labels)
833 }
834 mMille->mille(nVarLoc, milleDBufferL, nGlo, milleDBufferG, milleIBufferG, mAlgTrack->getResidual(idim, ip), Sqrt(pnt->getErrDiag(idim)));
835 nDGloTot += nGlo;
836 }
837 }
838 if (pnt->containsMaterial()) { // material point can add 4 or 5 otrhogonal pseudo-measurements
839 int nmatpar = pnt->getNMatPar(); // residuals (correction expectation value)
840 // const float* expMatCorr = pnt->getMatCorrExp(); // expected corrections (diagonalized)
841 const float* expMatCov = pnt->getMatCorrCov(); // their diagonalized error matrix
842 int offs = pnt->getMaxLocVarID() - nmatpar; // start of material variables
843 // here all derivatives are 1 = dx/dx
844 float milleDBufferL[nVarLoc];
845 std::memset(milleDBufferL, 0, sizeof(float) * nVarLoc);
846 for (int j = 0; j < nmatpar; j++) { // mat. "measurements" don't depend on global params
847 int j1 = j + offs;
848 milleDBufferL[j1] = 1.0; // only 1 non-0 derivative
849 // mMille->mille(nVarLoc,milleDBufferL,0, nullptr, nullptr, expMatCorr[j], Sqrt(expMatCov[j]));
850 // expectation for MS effect is 0
851 mMille->mille(nVarLoc, milleDBufferL, 0, nullptr, nullptr, 0, Sqrt(expMatCov[j]));
852 milleDBufferL[j1] = 0.0; // reset buffer
853 }
854 } // material "measurement"
855 } // loop over points
856 //
857 if (!nDGloTot) {
858 LOG(info) << "Track does not depend on free global parameters, discard";
859 mMille->clear();
860 return false;
861 }
862 mMille->finalise(); // store the record
863 return true;
864}
865
866//_________________________________________________________
868{
869 // store MP2 in MPRecord format
870 if (!mMPRecFile) {
872 }
874 if (!mMPRecord.fillTrack(*mAlgTrack.get(), mGloParLab)) {
875 return false;
876 }
880 mMPRecTree->Fill();
881 return true;
882}
883
884//_________________________________________________________
886{
887 // store control residuals
888 if (!mResidFile) {
890 }
891 int nps, np = mAlgTrack->getNPoints();
892 nps = (!mRefPoint->containsMeasurement()) ? np - 1 : np; // ref point is dummy?
893 if (nps < 0) {
894 return true;
895 }
896 mCResid.clear();
897 if (!mCResid.fillTrack(*mAlgTrack.get(), AlignConfig::Instance().KalmanResid)) {
898 return false;
899 }
903 mCResid.setTrackID(tid);
904 // if (isCosmic()) {
905 // mCResid.setInvTrackID(tid);
906 // }
907 mResidTree->Fill();
908 return true;
909}
910
911//_________________________________________________________
913{
914 mTimingInfo = ti;
915 LOGP(info, "TIMING {} {}", ti.runNumber, ti.creation);
916 if (ti.runNumber != mRunNumber) {
918 }
919}
920
921//____________________________________________
922void Controller::Print(const Option_t* opt) const
923{
924 // print info
925 TString opts = opt;
926 opts.ToLower();
927 printf("%5d DOFs in %d detectors\n", mNDOFs, mNDet);
928 if (getMPAlignDone()) {
929 printf("ALIGNMENT FROM MILLEPEDE SOLUTION IS APPLIED\n");
930 }
931 //
932 for (auto id = DetID::First; id <= DetID::Last; id++) {
934 if (!det) {
935 continue;
936 }
937 det->Print(opt);
938 }
939 if (!opts.IsNull()) {
940 printf("\nSpecial sensor for Vertex Constraint\n");
941 mVtxSens->Print(opt);
942 }
943 //
944 if (mRefRunNumber >= 0) {
945 printf("(%d)", mRefRunNumber);
946 }
947 AlignConfig::Instance().printKeyValues();
948 //
949 if (opts.Contains("stat")) {
951 }
952}
953
954//________________________________________________________
956{
957 // print processing stat
958 mStat.print();
959}
960
961//________________________________________________________
963{
964 // reset detectors for next track
965 mRefPoint->clear();
966 mAlgTrack->Clear();
967 for (auto id = DetID::First; id <= DetID::Last; id++) {
969 if (det) {
970 det->reset();
971 }
972 }
973}
974
975//____________________________________________
977{
978 // test track local solution
979 int npnt = mAlgTrack->getNPoints(), nlocpar = mAlgTrack->getNLocPar();
980 double mat[nlocpar][nlocpar], rhs[nlocpar];
981 std::memset(mat, 0, sizeof(double) * nlocpar * nlocpar);
982 std::memset(rhs, 0, sizeof(double) * nlocpar);
983 for (int ip = npnt; ip--;) {
984 AlignmentPoint* pnt = mAlgTrack->getPoint(ip);
985 if (pnt->containsMeasurement()) {
986 for (int idim = 2; idim--;) { // each point has 2 position residuals
987 double resid = mAlgTrack->getResidual(idim, ip), sg2inv = 1. / pnt->getErrDiag(idim); // residual and its inv. error
988 auto deriv = mAlgTrack->getDResDLoc(idim, ip); // array of Dresidual/Dparams
989 for (int parI = 0; parI < nlocpar; parI++) {
990 rhs[parI] -= deriv[parI] * resid * sg2inv;
991 for (int parJ = parI; parJ < nlocpar; parJ++) {
992 mat[parI][parJ] += deriv[parI] * deriv[parJ] * sg2inv;
993 }
994 }
995 } // loop over 2 orthogonal measurements at the point
996 } // derivarives at measured points
997 // if the point contains material, consider its expected kinks, eloss as measurements
998 if (pnt->containsMaterial()) { // at least 4 parameters: 2 spatial + 2 angular kinks with 0 expectaction
999 int npm = pnt->getNMatPar();
1000 // const float* expMatCorr = pnt->getMatCorrExp(); // expected correction (diagonalized) // RS??
1001 const float* expMatCov = pnt->getMatCorrCov(); // its error
1002 int offs = pnt->getMaxLocVarID() - npm;
1003 for (int ipar = 0; ipar < npm; ipar++) {
1004 int parI = offs + ipar;
1005 // expected
1006 // rhs[parI] -= expMatCorr[ipar]/expMatCov[ipar]; // consider expectation as measurement // RS??
1007 mat[parI][parI] += 1. / expMatCov[ipar]; // this measurement is orthogonal to all others
1008 }
1009 } // material effect descripotion params
1010 //
1011 }
1012 o2::math_utils::SymMatrixSolver solver(nlocpar, 1);
1013 for (int i = 0; i < nlocpar; i++) {
1014 for (int j = i; j < nlocpar; j++) {
1015 solver.A(i, j) = mat[i][j];
1016 }
1017 solver.B(i, 0) = rhs[i];
1018 }
1019 solver.solve();
1020 // increment current params by new solution
1021 auto& pars = mAlgTrack->getLocParsV();
1022 for (int i = 0; i < nlocpar; i++) {
1023 pars[i] += solver.B(i, 0);
1024 }
1025 mAlgTrack->calcResiduals();
1026 return true;
1027}
1028
1029//____________________________________________
1031{
1032 // prepare MP record output
1033 mMPRecFile.reset(TFile::Open(fmt::format("{}_{:08d}_{:010d}{}", AlignConfig::Instance().mpDatFileName, mTimingInfo.runNumber, mTimingInfo.tfCounter, ".root").c_str(), "recreate"));
1034 mMPRecTree = std::make_unique<TTree>("mpTree", "MPrecord Tree");
1035 mMPRecTree->Branch("mprec", "o2::align::Millepede2Record", &mMPRecordPtr);
1036}
1037
1038//____________________________________________
1040{
1041 // prepare residual output
1042 mResidFile.reset(TFile::Open(fmt::format("{}_{:08d}_{:010d}{}", AlignConfig::Instance().residFileName, mTimingInfo.runNumber, mTimingInfo.tfCounter, ".root").c_str(), "recreate"));
1043 mResidTree = std::make_unique<TTree>("res", "Control Residuals");
1044 mResidTree->Branch("t", "o2::align::ResidualsController", &mCResidPtr);
1045}
1046
1047//____________________________________________
1049{
1050 // close output
1051 if (!mMPRecFile) {
1052 return;
1053 }
1054 LOGP(info, "Writing tree {} with {} entries to {}", mMPRecTree->GetName(), mMPRecTree->GetEntries(), mMPRecFile->GetName());
1055 mMPRecFile->cd();
1056 mMPRecTree->Write();
1057 mMPRecTree.reset();
1058 mMPRecFile->Close();
1059 mMPRecFile.reset();
1060}
1061
1062//____________________________________________
1064{
1065 // close output
1066 if (!mResidFile) {
1067 return;
1068 }
1069 LOG(info) << "Closing " << mResidFile->GetName();
1070 mResidFile->cd();
1071 mResidTree->Write();
1072 mResidTree.reset();
1073 mResidFile->Close();
1074 mResidFile.reset();
1075 mCResid.clear();
1076}
1077
1078//____________________________________________
1080{
1081 // close output
1082 bool compress = false;
1083 if (mMille) {
1084 LOG(info) << "Closing " << mMilleFileName;
1085 compress = AlignConfig::Instance().GZipMilleOut;
1086 } else {
1087 return;
1088 }
1089 mMille.reset();
1090 if (compress) {
1091 std::string cmd = fmt::format("sh -c \"gzip {}\"", mMilleFileName);
1092 LOG(info) << "Compressing: " << cmd;
1093 const auto sysRet = gSystem->Exec(cmd.c_str());
1094 if (sysRet != 0) {
1095 LOGP(alarm, "non-zero exit code {} for cmd={}", sysRet, cmd);
1096 }
1097 }
1098}
1099
1100//____________________________________________
1101void Controller::setObligatoryDetector(DetID detID, int trtype, bool v)
1102{
1103 // mark detector presence obligatory in the track of given type
1104 AlignableDetector* det = getDetector(detID);
1105 if (!det) {
1106 LOG(error) << "Detector " << detID << " is not defined";
1107 }
1108 if (v) {
1109 mObligatoryDetPattern[trtype] |= detID.getMask();
1110 } else {
1111 mObligatoryDetPattern[trtype] &= ~detID.getMask();
1112 }
1113 if (det->isObligatory(trtype) != v) {
1114 det->setObligatory(trtype, v);
1115 }
1116 //
1117}
1118
1119//____________________________________________
1121{
1122 auto* prop = PropagatorD::Instance();
1123 const auto& conf = AlignConfig::Instance();
1124 o2::dataformats::DCA dcaInfo;
1126 if (!prop->propagateToDCABxByBz(vtx, trcDCA, conf.maxStep, MatCorrType(conf.matCorType), &dcaInfo)) {
1127 return false;
1128 }
1129 // RS FIXME do selections if needed
1130 mVtxSens->setAlpha(trcDCA.getAlpha());
1131 const auto* addErr = mVtxSens->getAddError();
1132 double xyz[3] = {vtx.getX(), vtx.getY(), vtx.getZ()}, xyzT[3];
1133 double c[3] = {0.5 * (vtx.getSigmaX2() + vtx.getSigmaY2()) + addErr[0] * addErr[0], 0., vtx.getSigmaZ2() + addErr[1] * addErr[1]};
1134
1135 mVtxSens->applyCorrection(xyz);
1136 mVtxSens->getMatrixT2L().MasterToLocal(xyz, xyzT);
1137
1138 mRefPoint->setSensor(mVtxSens.get());
1139 // RS FIXME the Xsensor is 0 ?
1140 mRefPoint->setXYZTracking(xyzT);
1141 mRefPoint->setYZErrTracking(c);
1142 mRefPoint->setAlphaSens(mVtxSens->getAlpTracking()); // RS FIXME Cannot this be done in setSensor?
1143 mRefPoint->setContainsMeasurement(true);
1144 mRefPoint->init();
1145 return true;
1146}
1147
1148//______________________________________________________
1150{
1151 // writes output calibration
1152 AlignableDetector* det;
1153 for (auto id = DetID::First; id <= DetID::Last; id++) {
1154 if (!(det = getDetector(id)) || det->isDisabled()) {
1155 continue;
1156 }
1158 }
1159}
1160
1161//________________________________________________________
1163{
1164 // return detector owning DOF with this ID
1165 for (auto idet = DetID::First; idet <= DetID::Last; idet++) {
1166 AlignableDetector* det = getDetector(id);
1167 if (det && det->ownsDOFID(id)) {
1168 return det;
1169 }
1170 }
1171 return nullptr;
1172}
1173
1174//________________________________________________________
1176{
1177 // return volume owning DOF with this ID
1178 for (auto idet = DetID::First; idet <= DetID::Last; idet++) {
1179 AlignableDetector* det = getDetector(idet);
1180 if (det && det->ownsDOFID(id)) {
1181 return det->getVolOfDOFID(id);
1182 }
1183 }
1184 if (mVtxSens && mVtxSens->ownsDOFID(id)) {
1185 return mVtxSens.get();
1186 }
1187 return nullptr;
1188}
1189
1190//________________________________________________________
1192{
1193 // return volume owning DOF with this label
1194 const auto& ent = mLbl2ID.find(lbl);
1195 return ent == mLbl2ID.end() ? nullptr : getVolOfDOFID(ent->second);
1196}
1197
1198//________________________________________________________
1200{
1201 // finalize processing
1202 //
1203 for (auto id = DetID::First; id <= DetID::Last; id++) {
1204 if (getDetector(id)) {
1205 getDetector(id)->terminate();
1206 }
1207 }
1211 // Print("stat");
1212 //
1213}
1214
1215//________________________________________________________
1216Char_t* Controller::getDOFLabelTxt(int idf) const
1217{
1218 // get DOF full label
1219 AlignableVolume* vol = getVolOfDOFID(idf);
1220 if (vol) {
1221 return Form("%d_%s_%s", getGloParLab(idf), vol->getSymName(),
1222 vol->getDOFName(idf - vol->getFirstParGloID()));
1223 }
1224 //
1225 // this might be detector-specific calibration dof
1226 AlignableDetector* det = getDetOfDOFID(idf);
1227 if (det) {
1228 return Form("%d_%s_%s", getGloParLab(idf), det->GetName(),
1229 det->getCalibDOFName(idf - det->getFirstParGloID()));
1230 }
1231 return nullptr;
1232}
1233
1234//********************* interaction with PEDE **********************
1235
1236//______________________________________________________
1238{
1239 // attach labels to millepede.res-like file
1240 FILE* parFl = fopen(AlignConfig::Instance().mpLabFileName.c_str(), "w+");
1241 fprintf(parFl, "parameters\n");
1242 if (mVtxSens) {
1243 mVtxSens->writeLabeledPedeResults(parFl);
1244 }
1245
1246 for (auto id = DetID::First; id <= DetID::Last; id++) {
1247 AlignableDetector* det = getDetector(id);
1248 if (!det || det->isDisabled()) {
1249 continue;
1250 }
1251 det->writeLabeledPedeResults(parFl);
1252 //
1253 }
1254 fclose(parFl);
1255}
1256
1257//______________________________________________________
1258void Controller::genPedeSteerFile(const Option_t* opt) const
1259{
1260 // produce steering file template for PEDE + params and constraints
1261 //
1262 enum { kOff,
1263 kOn,
1264 kOnOn };
1265 const char* cmt[3] = {" ", "! ", "!!"};
1266 const char* kSolMeth[] = {"inversion", "diagonalization", "fullGMRES", "sparseMINRES", "cholesky", "HIP"};
1267 const int kDefNIter = 3; // default number of iterations to ask
1268 const float kDefDelta = 0.1; // def. delta to exit
1269 TString opts = opt;
1270 opts.ToLower();
1271 LOG(info) << "Generating MP2 templates:\n "
1272 << "Steering :\t" << AlignConfig::Instance().mpSteerFileName << "\n"
1273 << "Parameters :\t" << AlignConfig::Instance().mpParFileName << "\n"
1274 << "Constraints:\t" << AlignConfig::Instance().mpConFileName << "\n";
1275 //
1276 FILE* parFl = fopen(AlignConfig::Instance().mpParFileName.c_str(), "w+");
1277 FILE* strFl = fopen(AlignConfig::Instance().mpSteerFileName.c_str(), "w+");
1278 //
1279 // --- template of steering file
1280 fprintf(strFl, "%-20s%s %s\n", AlignConfig::Instance().mpParFileName.c_str(), cmt[kOnOn], "parameters template");
1281 fprintf(strFl, "%-20s%s %s\n", AlignConfig::Instance().mpConFileName.c_str(), cmt[kOnOn], "constraints template");
1282 //
1283 fprintf(strFl, "\n\n%s %s\n", cmt[kOnOn], "MUST uncomment 1 solving methods and tune it");
1284 //
1285 int nm = sizeof(kSolMeth) / sizeof(char*);
1286 for (int i = 0; i < nm; i++) {
1287 fprintf(strFl, "%s%s %-20s %2d %.2f %s\n", cmt[kOn], "method", kSolMeth[i], kDefNIter, kDefDelta, cmt[kOnOn]);
1288 }
1289 fprintf(strFl, "\n%sskipemptycons\n", cmt[kOff]);
1290 fprintf(strFl, "\n%sthreads 20 1\n", cmt[kOff]);
1291 //
1292 const float kDefChi2F0 = 10., kDefChi2F = 3.; // chi2 factors for 1st and following iterations
1293 const float kDefDWFrac = 0.1; // cut outliers with downweighting above this factor
1294 const int kDefOutlierDW = 4; // start Cauchy function downweighting from iteration
1295 const int kDefEntries = 25; // min entries per DOF to allow its variation
1296 //
1297 fprintf(strFl, "\n\n%s %s\n", cmt[kOnOn], "Optional settings");
1298 fprintf(strFl, "\n%s%-20s %.2f %.2f %s %s\n", cmt[kOff], "chisqcut", kDefChi2F0, kDefChi2F,
1299 cmt[kOnOn], "chi2 cut factors for 1st and next iterations");
1300 fprintf(strFl, "%s%-20s %2d %s %s\n", cmt[kOff], "outlierdownweighting", kDefOutlierDW,
1301 cmt[kOnOn], "iteration for outliers downweighting with Cauchi factor");
1302 fprintf(strFl, "%s%-20s %.3f %s %s\n", cmt[kOff], "dwfractioncut", kDefDWFrac,
1303 cmt[kOnOn], "cut outliers with downweighting above this factor");
1304 fprintf(strFl, "%s%-20s %2d %s %s\n", cmt[kOff], "entries", kDefEntries,
1305 cmt[kOnOn], "min entries per DOF to allow its variation");
1306 //
1307 fprintf(strFl, "\n\n\n%s%-20s %s %s\n\n\n", cmt[kOff], "CFiles", cmt[kOnOn], "put below *.mille files list");
1308 //
1309 if (mVtxSens) {
1310 mVtxSens->writePedeInfo(parFl, opt);
1311 }
1312 //
1313 for (auto id = DetID::First; id <= DetID::Last; id++) {
1314 AlignableDetector* det = getDetector(id);
1315 if (!det || det->isDisabled()) {
1316 continue;
1317 }
1318 det->writePedeInfo(parFl, opt);
1319 //
1320 }
1321 //
1323 //
1324 fclose(strFl);
1325 fclose(parFl);
1326 //
1327}
1328
1329//___________________________________________________________
1330bool Controller::readParameters(const std::string& parfile, bool useErrors)
1331{
1332 // read parameters file (millepede output)
1333 if (mNDOFs < 1) {
1334 LOG(error) << "Something is wrong in init, no DOFs found: mNDOFs=" << mNDOFs << " N GloParVal=" << mGloParVal.size() << " N GloParErr=" << mGloParErr.size();
1335 }
1336 std::ifstream inpf(parfile);
1337 if (!inpf.good()) {
1338 LOGP(fatal, "Failed on input filename {}", parfile);
1339 }
1340 mGloParVal.resize(mNDOFs);
1341 if (useErrors) {
1342 mGloParErr.resize(mNDOFs);
1343 }
1344 int cnt = 0;
1345 TString fline;
1346 while (fline.ReadLine(inpf)) {
1347 fline = fline.Strip(TString::kBoth, ' ');
1348 fline.ToLower();
1349 if (fline.Length() == 0 || fline.BeginsWith("!") || fline.BeginsWith("*")) {
1350 continue;
1351 }
1352 if (!fline.BeginsWith("parameter")) {
1353 LOGP(fatal, "First line of {} is not parameter keyword: {}", parfile, fline.Data());
1354 }
1355 break;
1356 }
1357 double v0, v1, v2;
1358 int lab, asg = 0, asg0 = 0;
1359 while (fline.ReadLine(inpf)) {
1360 cnt++;
1361 fline = fline.Strip(TString::kBoth, ' ');
1362 if (fline.BeginsWith("!") || fline.BeginsWith("*") || fline.BeginsWith("parameter")) { // parameter keyword may repeat
1363 continue;
1364 } // ignore comment
1365 int nr = sscanf(fline.Data(), "%d%lf%lf%lf", &lab, &v0, &v1, &v2);
1366 if (nr < 3) {
1367 LOG(error) << "Expected to read at least 3 numbers, got " << nr << ", this is NOT milleped output";
1368 LOG(fatal) << "line (" << cnt << ") was: " << fline.Data();
1369 }
1370 if (nr == 3) {
1371 asg0++;
1372 }
1373 int parID = label2ParID(lab);
1374 if (parID < 0 || parID >= mNDOFs) {
1375 LOG(fatal) << "Invalid label " << lab << " at line " << cnt << " -> ParID=" << parID;
1376 }
1377 mGloParVal[parID] = -v0;
1378 if (useErrors) {
1379 mGloParErr[parID] = v1;
1380 }
1381 asg++;
1382 //
1383 };
1384 LOG(info) << "Read " << cnt << " lines, assigned " << asg << " values, " << asg0 << " dummy";
1385 //
1386 return true;
1387}
1388
1389//______________________________________________________
1391{
1392 // check how the constraints are satisfied with already uploaded or provided params
1393 //
1394 if (params && !readParameters(params)) {
1395 LOG(error) << "Failed to load parameters from " << params;
1396 return;
1397 }
1398 //
1399 int ncon = getNConstraints();
1400 for (int icon = 0; icon < ncon; icon++) {
1402 }
1403 //
1404}
1405
1406//___________________________________________________________
1407void Controller::MPRec2Mille(const std::string& mprecfile, const std::string& millefile, bool bindata)
1408{
1409 // converts MPRecord tree to millepede binary format
1410 TFile* flmpr = TFile::Open(mprecfile.c_str());
1411 if (!flmpr) {
1412 LOG(fatal) << "Failed to open MPRecord file " << mprecfile;
1413 return;
1414 }
1415 TTree* mprTree = (TTree*)flmpr->Get("mpTree");
1416 if (!mprTree) {
1417 LOG(fatal) << "No mpTree in xMPRecord file " << mprecfile;
1418 return;
1419 }
1420 MPRec2Mille(mprTree, millefile, bindata);
1421 delete mprTree;
1422 flmpr->Close();
1423 delete flmpr;
1424}
1425
1426//___________________________________________________________
1427void Controller::MPRec2Mille(TTree* mprTree, const std::string& millefile, bool bindata)
1428{
1429 // converts MPRecord tree to millepede binary format
1430 //
1431 TBranch* br = mprTree->GetBranch("mprec");
1432 if (!br) {
1433 LOG(error) << "provided tree does not contain branch mprec";
1434 return;
1435 }
1436 Millepede2Record mrec, *rec = &mrec;
1437 br->SetAddress(&rec);
1438 int nent = mprTree->GetEntries();
1439 std::string mlname = millefile;
1440 if (mlname.empty()) {
1441 mlname = "mpRec2mpData";
1442 }
1443 if (!o2::utils::Str::endsWith(mlname, sMPDataExt)) {
1444 mlname += sMPDataExt;
1445 }
1446 Mille mille(mlname, bindata);
1447 std::vector<float> buffLoc;
1448 for (int i = 0; i < nent; i++) {
1449 br->GetEntry(i);
1450 int nr = rec->getNResid(); // number of residual records
1451 int nloc = rec->getNVarLoc();
1452 auto recDGlo = rec->getArrGlo();
1453 auto recDLoc = rec->getArrLoc();
1454 auto recLabLoc = rec->getArrLabLoc();
1455 auto recLabGlo = rec->getArrLabGlo();
1456 //
1457 for (int ir = 0; ir < nr; ir++) {
1458 buffLoc.clear();
1459 buffLoc.resize(nloc);
1460 int ndglo = rec->getNDGlo(ir);
1461 int ndloc = rec->getNDLoc(ir);
1462 // fill 0-suppressed array from MPRecord to non-0-suppressed array of Mille
1463 for (int l = ndloc; l--;) {
1464 buffLoc[recLabLoc[l]] = recDLoc[l];
1465 }
1466 //
1467 mille.mille(nloc, buffLoc.data(), ndglo, recDGlo, recLabGlo, rec->getResid(ir), rec->getResErr(ir));
1468 //
1469 recLabGlo += ndglo; // next record
1470 recDGlo += ndglo;
1471 recLabLoc += ndloc;
1472 recDLoc += ndloc;
1473 }
1474 mille.finalise();
1475 }
1476 br->SetAddress(nullptr);
1477}
1478
1479//____________________________________________________________
1481{
1482 // print global IDs and Labels
1483 for (int i = 0; i < mNDOFs; i++) {
1484 printf("%5d %s\n", i, getDOFLabelTxt(i));
1485 }
1486}
1487
1488//____________________________________________________________
1489int Controller::label2ParID(int lab) const
1490{
1491 // convert Mille label to ParID (slow)
1492 auto it = mLbl2ID.find(lab);
1493 if (it == mLbl2ID.end()) {
1494 LOGP(fatal, "Label {} is not mapped to any parameter", lab);
1495 }
1496 return it->second - 1;
1497}
1498
1499//____________________________________________________________
1501{
1502 // add default constraints on children cumulative corrections within the volumes
1503 for (auto id = DetID::First; id <= DetID::Last; id++) {
1504 AlignableDetector* det = getDetector(id);
1505 if (!det || det->isDisabled()) {
1506 continue;
1507 }
1508 det->addAutoConstraints();
1509 }
1510 LOG(info) << "Added " << getNConstraints() << " automatic constraints";
1511}
1512
1513//____________________________________________________________
1515{
1516 // write constraints file
1517 FILE* conFl = fopen(AlignConfig::Instance().mpConFileName.c_str(), "w+");
1518 //
1519 int nconstr = getNConstraints();
1520 for (int icon = 0; icon < nconstr; icon++) {
1522 }
1523 //
1524 fclose(conFl);
1525}
1526
1527//______________________________________________
1528void Controller::checkSol(TTree* mpRecTree, bool store,
1529 bool verbose, bool loc, const char* outName)
1530{
1531 // do fast check of pede solution with MPRecord tree
1532 ResidualsControllerFast* rLG = store ? new ResidualsControllerFast() : nullptr;
1533 ResidualsControllerFast* rL = store && loc ? new ResidualsControllerFast() : nullptr;
1534 TTree *trLG = nullptr, *trL = nullptr;
1535 TFile* outFile = nullptr;
1536 if (store) {
1537 TString outNS = outName;
1538 if (outNS.IsNull()) {
1539 outNS = "resFast";
1540 }
1541 if (!outNS.EndsWith(".root")) {
1542 outNS += ".root";
1543 }
1544 outFile = TFile::Open(outNS.Data(), "recreate");
1545 trLG = new TTree("resFLG", "Fast residuals with LG correction");
1546 trLG->Branch("rLG", "ResidualsControllerFast", &rLG);
1547 //
1548 if (rL) {
1549 trL = new TTree("resFL", "Fast residuals with L correction");
1550 trL->Branch("rL", "ResidualsControllerFast", &rL);
1551 }
1552 }
1553 //
1555 mpRecTree->SetBranchAddress("mprec", &rec);
1556 int nrec = mpRecTree->GetEntriesFast();
1557 for (int irec = 0; irec < nrec; irec++) {
1558 mpRecTree->GetEntry(irec);
1559 checkSol(rec, rLG, rL, verbose, loc);
1560 // store even in case of failure, to have the trees aligned with controlRes
1561 if (trLG) {
1562 trLG->Fill();
1563 }
1564 if (trL) {
1565 trL->Fill();
1566 }
1567 }
1568 //
1569 // save
1570 if (trLG) {
1571 outFile->cd();
1572 trLG->Write();
1573 delete trLG;
1574 if (trL) {
1575 trL->Write();
1576 delete trL;
1577 }
1578 outFile->Close();
1579 delete outFile;
1580 }
1581 delete rLG;
1582 delete rL;
1583 //
1584}
1585
1586//______________________________________________
1589 bool verbose, bool loc)
1590{
1591 LOG(fatal) << __PRETTY_FUNCTION__ << " is disabled";
1592 //FIXME(milettri): needs AliSymMatrix
1593 // // Check pede solution using derivates, rather than updated geometry
1594 // // If loc==true, also produces residuals for current geometry,
1595 // // neglecting global corrections
1596 // //
1597 // if (rL){
1598 // loc = true;} // if local sol. tree asked, always evaluate it
1599 // //
1600 // int nres = rec->getNResid();
1601 // //
1602 // const float* recDGlo = rec->getArrGlo();
1603 // const float* recDLoc = rec->getArrLoc();
1604 // const short* recLabLoc = rec->getArrLabLoc();
1605 // const int* recLabGlo = rec->getArrLabGlo();
1606 // int nvloc = rec->getNVarLoc();
1607 // //
1608 // // count number of real measurement duplets and material correction fake 4-plets
1609 // int nPoints = 0;
1610 // int nMatCorr = 0;
1611 // for (int irs = 0; irs < nres; irs++) {
1612 // if (rec->getNDGlo(irs) > 0) {
1613 // if (irs == nres - 1 || rec->getNDGlo(irs + 1) == 0){
1614 // LOG(fatal) << ("Real coordinate measurements must come in pairs");}
1615 // nPoints++;
1616 // irs++; // skip 2nd
1617 // continue;
1618 // } else if (rec->getResid(irs) == 0 && rec->getVolID(irs) == -1) { // material corrections have 0 residual
1619 // nMatCorr++;
1620 // } else { // might be fixed parameter, global derivs are skept
1621 // nPoints++;
1622 // irs++; // skip 2nd
1623 // continue;
1624 // }
1625 // }
1626 // //
1627 // if (nMatCorr % 4){
1628 // LOG(warning) << "Error? NMatCorr=" << nMatCorr << " is not multiple of 4";}
1629 // //
1630 // if (rLG) {
1631 // rLG->Clear();
1632 // rLG->setNPoints(nPoints);
1633 // rLG->setNMatSol(nMatCorr);
1634 // rLG->setCosmic(rec->isCosmic());
1635 // }
1636 // if (rL) {
1637 // rL->Clear();
1638 // rL->setNPoints(nPoints);
1639 // rL->setNMatSol(nMatCorr);
1640 // rL->setCosmic(rec->isCosmic());
1641 // }
1642 // //
1643 // AliSymMatrix* matpG = new AliSymMatrix(nvloc);
1644 // TVectorD *vecp = 0, *vecpG = new TVectorD(nvloc);
1645 // //
1646 // if (loc){
1647 // vecp = new TVectorD(nvloc);}
1648 // //
1649 // float chi2Ini = 0, chi2L = 0, chi2LG = 0;
1650 // //
1651 // // residuals, accounting for global solution
1652 // double* resid = new double[nres];
1653 // int* volID = new int[nres];
1654 // for (int irs = 0; irs < nres; irs++) {
1655 // double resOr = rec->getResid(irs);
1656 // resid[irs] = resOr;
1657 // //
1658 // int ndglo = rec->getNDGlo(irs);
1659 // int ndloc = rec->getNDLoc(irs);
1660 // volID[irs] = 0;
1661 // for (int ig = 0; ig < ndglo; ig++) {
1662 // int lbI = recLabGlo[ig];
1663 // int idP = label2ParID(lbI);
1664 // if (idP < 0){
1665 // LOG(fatal) << "Did not find parameted for label " << lbI;}
1666 // double parVal = getGloParVal()[idP];
1667 // // resid[irs] -= parVal*recDGlo[ig];
1668 // resid[irs] += parVal * recDGlo[ig];
1669 // if (!ig) {
1670 // AlignableVolume* vol = getVolOfDOFID(idP);
1671 // if (vol){
1672 // volID[irs] = vol->getVolID();}
1673 // else
1674 // volID[irs] = -2; // calibration DOF !!! TODO
1675 // }
1676 // }
1677 // //
1678 // double sg2inv = rec->getResErr(irs);
1679 // sg2inv = 1. / (sg2inv * sg2inv);
1680 // //
1681 // chi2Ini += resid[irs] * resid[irs] * sg2inv; // chi accounting for global solution only
1682 // //
1683 // // Build matrix to solve local parameters
1684 // for (int il = 0; il < ndloc; il++) {
1685 // int lbLI = recLabLoc[il]; // id of local variable
1686 // (*vecpG)[lbLI] -= recDLoc[il] * resid[irs] * sg2inv;
1687 // if (loc){
1688 // (*vecp)[lbLI] -= recDLoc[il] * resOr * sg2inv;}
1689 // for (int jl = il + 1; jl--;) {
1690 // int lbLJ = recLabLoc[jl]; // id of local variable
1691 // (*matpG)(lbLI, lbLJ) += recDLoc[il] * recDLoc[jl] * sg2inv;
1692 // }
1693 // }
1694 // //
1695 // recLabGlo += ndglo; // prepare for next record
1696 // recDGlo += ndglo;
1697 // recLabLoc += ndloc;
1698 // recDLoc += ndloc;
1699 // //
1700 // }
1701 // //
1702 // if (rL){
1703 // rL->setChi2Ini(chi2Ini);}
1704 // if (rLG){
1705 // rLG->setChi2Ini(chi2Ini);}
1706 // //
1707 // TVectorD vecSol(nvloc);
1708 // TVectorD vecSolG(nvloc);
1709 // //
1710 // if (!matpG->SolveChol(*vecpG, vecSolG, false)) {
1711 // LOG(info) << "Failed to solve track corrected for globals";
1712 // delete matpG;
1713 // matpG = 0;
1714 // } else if (loc) { // solution with local correction only
1715 // if (!matpG->SolveChol(*vecp, vecSol, false)) {
1716 // LOG(info) << "Failed to solve track corrected for globals";
1717 // delete matpG;
1718 // matpG = 0;
1719 // }
1720 // }
1721 // delete vecpG;
1722 // delete vecp;
1723 // if (!matpG) { // failed
1724 // delete[] resid;
1725 // delete[] volID;
1726 // if (rLG){
1727 // rLG->Clear();}
1728 // if (rL){
1729 // rL->Clear();}
1730 // return false;
1731 // }
1732 // // check
1733 // recDGlo = rec->getArrGlo();
1734 // recDLoc = rec->getArrLoc();
1735 // recLabLoc = rec->getArrLabLoc();
1736 // recLabGlo = rec->getArrLabGlo();
1737 // //
1738 // if (verbose) {
1739 // printf(loc ? "Sol L/LG:\n" : "Sol LG:\n");
1740 // int nExtP = (nvloc % 4) ? 5 : 4;
1741 // for (int i = 0; i < nExtP; i++){
1742 // loc ? printf("%+.3e/%+.3e ", vecSol[i], vecSolG[i]) : printf("%+.3e ", vecSolG[i]);}
1743 // printf("\n");
1744 // bool nln = true;
1745 // int cntL = 0;
1746 // for (int i = nExtP; i < nvloc; i++) {
1747 // nln = true;
1748 // loc ? printf("%+.3e/%+.3e ", vecSol[i], vecSolG[i]) : printf("%+.3e ", vecSolG[i]);
1749 // if (((++cntL) % 4) == 0) {
1750 // printf("\n");
1751 // nln = false;
1752 // }
1753 // }
1754 // if (!nln){
1755 // printf("\n");}
1756 // if (loc){
1757 // printf("%3s (%9s) %6s | [ %7s:%7s ] [ %7s:%7s ]\n", "Pnt", "Label",
1758 // "Sigma", "resid", "pull/L ", "resid", "pull/LG");}
1759 // else{
1760 // printf("%3s (%9s) %6s | [ %7s:%7s ]\n", "Pnt", "Label",
1761 // "Sigma", "resid", "pull/LG");}
1762 // }
1763 // int idMeas = -1, pntID = -1, matID = -1;
1764 // for (int irs = 0; irs < nres; irs++) {
1765 // double resOr = rec->getResid(irs);
1766 // double resL = resOr;
1767 // double resLG = resid[irs];
1768 // double sg = rec->getResErr(irs);
1769 // double sg2Inv = 1 / (sg * sg);
1770 // //
1771 // int ndglo = rec->getNDGlo(irs);
1772 // int ndloc = rec->getNDLoc(irs);
1773 // //
1774 // for (int il = 0; il < ndloc; il++) {
1775 // int lbLI = recLabLoc[il]; // id of local variable
1776 // resL += recDLoc[il] * vecSol[lbLI];
1777 // resLG += recDLoc[il] * vecSolG[lbLI];
1778 // }
1779 // //
1780 // chi2L += resL * resL * sg2Inv; // chi accounting for global solution only
1781 // chi2LG += resLG * resLG * sg2Inv; // chi accounting for global solution only
1782 // //
1783 // if (ndglo || resOr != 0) { // real measurement
1784 // idMeas++;
1785 // if (idMeas > 1){
1786 // idMeas = 0;}
1787 // if (idMeas == 0){
1788 // pntID++;} // measurements come in pairs
1789 // int lbl = rec->getVolID(irs);
1790 // lbl = ndglo ? recLabGlo[0] : 0; // TMP, until VolID is filled // RS!!!!
1791 // if (rLG) {
1792 // rLG->setResSigMeas(pntID, idMeas, resLG, sg);
1793 // if (idMeas == 0){
1794 // rLG->setLabel(pntID, lbl, volID[irs]);}
1795 // }
1796 // if (rL) {
1797 // rL->setResSigMeas(pntID, idMeas, resL, sg);
1798 // if (idMeas == 0){
1799 // rL->setLabel(pntID, lbl, volID[irs]);}
1800 // }
1801 // } else {
1802 // matID++; // mat.correcitons come in 4-plets, but we fill each separately
1803 // //
1804 // if (rLG){
1805 // rLG->setMatCorr(matID, resLG, sg);}
1806 // if (rL){
1807 // rL->setMatCorr(matID, resL, sg);}
1808 // }
1809 // //
1810 // if (verbose) {
1811 // int lbl = rec->getVolID(irs);
1812 // lbl = ndglo ? recLabGlo[0] : (resOr == 0 ? -1 : 0); // TMP, until VolID is filled // RS!!!!
1813 // if (loc){
1814 // printf("%3d (%9d) %6.4f | [%+.2e:%+7.2f] [%+.2e:%+7.2f]\n",
1815 // irs, lbl, sg, resL, resL / sg, resLG, resLG / sg);}
1816 // else
1817 // printf("%3d (%9d) %6.4f | [%+.2e:%+7.2f]\n",
1818 // irs, lbl, sg, resLG, resLG / sg);
1819 // }
1820 // //
1821 // recLabGlo += ndglo; // prepare for next record
1822 // recDGlo += ndglo;
1823 // recLabLoc += ndloc;
1824 // recDLoc += ndloc;
1825 // }
1826 // if (rL){
1827 // rL->setChi2(chi2L);}
1828 // if (rLG){
1829 // rLG->setChi2(chi2LG);}
1830 // //
1831 // if (verbose) {
1832 // printf("Chi: G = %e | LG = %e", chi2Ini, chi2LG);
1833 // if (loc){
1834 // printf(" | L = %e", chi2L);}
1835 // printf("\n");
1836 // }
1837 // // store track corrections
1838 // int nTrCor = nvloc - matID - 1;
1839 // for (int i = 0; i < nTrCor; i++) {
1840 // if (rLG){
1841 // rLG->getTrCor()[i] = vecSolG[i];}
1842 // if (rL){
1843 // rL->getTrCor()[i] = vecSol[i];}
1844 // }
1845 // //
1846 // delete[] resid;
1847 // delete[] volID;
1848 return true;
1849}
1850
1851//______________________________________________
1853{
1854 // apply alignment from millepede solution array to reference alignment level
1855 LOG(info) << "Applying alignment from Millepede solution";
1856 for (auto id = DetID::First; id <= DetID::Last; id++) {
1857 AlignableDetector* det = getDetector(id);
1858 if (!det || det->isDisabled()) {
1859 continue;
1860 }
1862 }
1864 //
1865}
1866
1867//______________________________________________
1869{
1870 // expand global param contaiers by n
1871 int snew = n + mGloParVal.size();
1872 mGloParVal.resize(snew);
1873 mGloParErr.resize(snew);
1874 mGloParLab.resize(snew);
1875 mNDOFs += n;
1876}
1877
1878//______________________________________________
1883
1884//______________________________________________
1889
1890} // namespace align
1891} // namespace o2
Configuration file for global alignment.
ITS detector wrapper.
Wrapper for TOF detector.
TPC detector wrapper.
TRD detector wrapper.
Base class for detector: wrapper for set of volumes.
Base class of alignable volume.
Meausered point in the sensor.
Definition of SymMatrixSolver class.
General auxilliary methods.
Steering class for the global alignment.
Wrapper container for different reconstructed object types.
Collection of auxillary methods.
Special fake "sensor" for event vertex.
int32_t i
Header of the General Run Parameters object.
Descriptor of geometrical constraint.
Utility functions for MC particles.
Definition of the Names Generator class.
uint32_t j
Definition RawData.h:0
uint32_t res
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Container for control fast residuals evaluated via derivatives.
Extention of GlobalTrackID by flags relevant for verter-track association.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
Helper class to obtain TPC clusters / digits / labels from DPL.
virtual int processPoints(GIndex gid, int npntCut=0, bool inv=false)
virtual void writeLabeledPedeResults(FILE *parOut) const
void setObligatory(int tp, bool v=true)
AlignableVolume * getVolOfDOFID(int id) const
virtual void writePedeInfo(FILE *parOut, const Option_t *opt="") const
void Print(const Option_t *opt="") const override
virtual void writeCalibrationResults() const
virtual const char * getCalibDOFName(int) const
const char * getSymName() const
virtual const char * getDOFName(int i) const
float * getMatCorrCov() const
double getErrDiag(int i) const
static const int sSkipLayers[kNLrSkip]
Definition Controller.h:365
const GeometricalConstraint & getConstraint(int i) const
Definition Controller.h:159
o2::tpc::VDriftCorrFact mTPCDrift
Definition Controller.h:361
o2::gpu::CorrectionMapsHelper * mTPCCorrMapsHelper
Definition Controller.h:362
void writeCalibrationResults() const
std::unique_ptr< TTree > mMPRecTree
control residuals
Definition Controller.h:350
bool readParameters(const std::string &parfile="millepede.res", bool useErrors=true)
ResidualsController mCResid
MP record.
Definition Controller.h:347
AlignableDetector * getDetector(DetID id) const
Definition Controller.h:205
bool fillControlData(o2::dataformats::GlobalTrackID tid)
void setObligatoryDetector(DetID id, int tp, bool v=true)
AlignableDetector * getDetOfDOFID(int id) const
void setTimingInfo(const o2::framework::TimingInfo &ti)
std::string mMilleFileName
file to store control residuals tree
Definition Controller.h:354
bool checkDetectorPattern(DetID::mask_t patt) const
Char_t * getDOFLabelTxt(int idf) const
void expandGlobalsBy(int n)
std::unique_ptr< Mille > mMille
Definition Controller.h:344
void checkSol(TTree *mpRecTree, bool store=true, bool verbose=false, bool loc=true, const char *outName="resFast")
void addDetector(AlignableDetector *det)
bool storeProcessedTrack(o2::dataformats::GlobalTrackID tid={})
static const Char_t * sDetectorName[kNDetectors]
Definition Controller.h:366
std::array< DetID::mask_t, utils::NTrackTypes > mObligatoryDetPattern
Definition Controller.h:326
void checkConstraints(const char *params=nullptr)
std::vector< float > mGloParErr
Definition Controller.h:329
bool getInitDOFsDone() const
Definition Controller.h:147
void writeLabeledPedeResults() const
std::unique_ptr< AlignmentPoint > mRefPoint
Definition Controller.h:333
std::vector< int > mTrackSources
Definition Controller.h:300
int label2ParID(int lab) const
bool getMPAlignDone() const
Definition Controller.h:150
void genPedeSteerFile(const Option_t *opt="") const
Millepede2Record * mMPRecordPtr
MP record.
Definition Controller.h:346
bool getInitGeomDone() const
Definition Controller.h:144
GTrackID::mask_t mMPsrc
Definition Controller.h:299
void writePedeConstraints() const
const o2::globaltracking::RecoContainer * mRecoData
Definition Controller.h:313
std::unique_ptr< AlignmentTrack > mAlgTrack
Definition Controller.h:311
static const Char_t * sMPDataTxtExt
Definition Controller.h:368
bool fillMPRecData(o2::dataformats::GlobalTrackID tid)
std::vector< float > mGloParVal
Definition Controller.h:328
ResidualsController * mCResidPtr
control residuals
Definition Controller.h:348
static const Char_t * sMPDataExt
Definition Controller.h:367
int mDebugOutputLevel
reference point for track definition
Definition Controller.h:335
void Print(const Option_t *opt="") const final
std::unique_ptr< EventVertex > mVtxSens
Definition Controller.h:322
void setCosmic(bool v=true)
Definition Controller.h:170
int getNConstraints() const
Definition Controller.h:156
std::unique_ptr< TFile > mMPRecFile
tree to store control residuals
Definition Controller.h:352
AlignableVolume * getVolOfLabel(int label) const
std::unique_ptr< TFile > mResidFile
file to store MP record tree
Definition Controller.h:353
std::array< std::unique_ptr< AlignableDetector >, DetID::nDetectors > mDetectors
Definition Controller.h:320
DetID::mask_t mDetMask
Definition Controller.h:298
void printStatistics() const
bool addVertexConstraint(const o2::dataformats::PrimaryVertex &vtx)
static void MPRec2Mille(const std::string &mprecfile, const std::string &millefile="mpData.mille", bool bindata=true)
std::unique_ptr< TTree > mResidTree
tree to store MP record
Definition Controller.h:351
std::unordered_map< int, int > mLbl2ID
Definition Controller.h:331
AlignableVolume * getVolOfDOFID(int id) const
Millepede2Record mMPRecord
Mille interface.
Definition Controller.h:345
o2::framework::TimingInfo mTimingInfo
Definition Controller.h:301
void setTPCCorrMaps(o2::gpu::CorrectionMapsHelper *maph)
void setTPCVDrift(const o2::tpc::VDriftCorrFact &v)
bool checkDetectorPoints(const int *npsel) const
std::vector< int > mGloParLab
Definition Controller.h:330
int getFirstParGloID() const
Definition DOFSet.h:48
int getNDOFs() const
Definition DOFSet.h:44
void writeChildrenConstraints(FILE *conOut) const
void mille(int NLC, const float *derLc, int NGL, const float *derGl, const int *label, float rMeas, float sigma)
Add measurement to buffer.
Definition Mille.cxx:55
int finalise()
Write buffer (set of derivatives with same local parameters) to file.
Definition Mille.cxx:129
bool fillTrack(AlignmentTrack &trc, const std::vector< int > &id2Lab)
void setTrackID(o2::dataformats::GlobalTrackID t)
void setTrackID(o2::dataformats::GlobalTrackID t)
bool fillTrack(AlignmentTrack &trc, bool doKalman=kTRUE)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID First
Definition DetID.h:94
static constexpr ID TRD
Definition DetID.h:65
static constexpr ID Last
if extra detectors added, update this !!!
Definition DetID.h:92
static constexpr ID TPC
Definition DetID.h:64
static mask_t getMask(const std::string_view detList)
detector masks from any non-alpha-num delimiter-separated list (empty if NONE is supplied)
Definition DetID.cxx:42
static constexpr ID TOF
Definition DetID.h:66
double & A(int i, int j)
access to A elements
double & B(int i, int j)
access to B elements
bool initFromDigitContext(std::string_view filename)
MCTrack const * getTrack(o2::MCCompLabel const &) const
GLdouble n
Definition glcorearb.h:1982
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLenum src
Definition glcorearb.h:1767
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLenum const GLfloat * params
Definition glcorearb.h:272
GLboolean * data
Definition glcorearb.h:298
GLfloat v0
Definition glcorearb.h:811
GLfloat GLfloat v1
Definition glcorearb.h:812
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
GLuint start
Definition glcorearb.h:469
GLfloat GLfloat GLfloat v2
Definition glcorearb.h:813
constexpr bool isZeroAbs(double d) noexcept
Definition utils.h:63
typename track::TrackParametrizationWithError< double > trackParam_t
Definition utils.h:29
PropagatorImpl< double > PropagatorD
Definition Propagator.h:181
Definition of a container to keep/associate and arbitrary number of labels associated to an index wit...
void align(gsl::span< ElinkEncoder< BareFormat, CHARGESUM > > elinks)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
GPUReconstruction * rec
bool setTrackParam(const AlignmentTrack *trc)
Definition AlgTrcDbg.h:35
o2::dataformats::GlobalTrackID mGID
Definition AlgTrcDbg.h:82
o2::dataformats::GlobalTrackID mGIDCosmUp
Definition AlgTrcDbg.h:83
std::array< std::array< size_t, kMaxStat >, kNStatCl > data
Definition Controller.h:106
uint32_t tfCounter
the orbit the TF begins
Definition TimingInfo.h:32
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
o2::MCCompLabel getTrackMCLabel(GTrackID id) const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
const o2::track::TrackParCov & getTrackParamOut(GTrackID gidx) const
void getTrackTime(GTrackID gid, float &t, float &tErr) const
static bool endsWith(const std::string &s, const std::string &ending)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)