50std::pair<std::string, TGeoHMatrix>
CreateAlignmentNode(std::string path,
double shiftX,
double shiftY,
double shiftZ,
51 double rotX,
double rotY,
double rotZ)
55 LOG(fatal) <<
"Alignment node path is empty!";
60 <<
"Alignment node path provided by the Cbm***TrackingInterface is not global. It must start with \"/\" ";
63 Bool_t ok = gGeoManager->cd(path.c_str());
65 LOG(fatal) <<
"Failed to cd to path " << path;
68 const TGeoNode* node = gGeoManager->GetCurrentNode();
71 LOG(fatal) <<
"Failed to find TGeoNode at path " << path;
85 TGeoHMatrix currG = *(gGeoManager->GetCurrentMatrix());
86 TGeoHMatrix newG = aliG * currG;
89 TGeoHMatrix motherG = *(gGeoManager->GetCurrentMatrix());
93 TGeoHMatrix newL = motherG.Inverse() * newG;
96 TGeoHMatrix origL = *node->GetMatrix();
101 TObjArray* pNodes = gGeoManager->GetListOfPhysicalNodes();
102 for (
int i = 0; i < pNodes->GetEntriesFast(); i++) {
103 const TGeoPhysicalNode* pnode =
dynamic_cast<const TGeoPhysicalNode*
>(pNodes->At(i));
104 if (pnode->GetNode() == node) {
107 origL = *pnode->GetOriginalMatrix();
112 LOG(info) <<
"Failed to find physical node for node " << path;
115 LOG(info) <<
"Found physical node for node " << path;
121 TGeoHMatrix aliL = origL.Inverse() * newL;
122 aliL.SetName(
"aligned with bba");
124 LOG(info) <<
"Write alignment matrix for the node " << path <<
":";
125 LOG(info) <<
" delta alignment global: ";
127 LOG(info) <<
" original alignment local: ";
129 LOG(info) <<
" full alignment local: ";
193 const char* env = std::getenv(
"OMP_NUM_THREADS");
196 LOG(info) <<
"BBA: found environment variable OMP_NUM_THREADS = \"" << env
210 fFitter.SetIgnorePoorCoordinates();
213 FairRootManager* ioman = FairRootManager::Instance();
216 LOG(error) <<
"CbmBbaAlignmentMcbmTask::Init :: RootManager not instantiated!";
224 if (!pRecoSetupManager->IsInitialized())
return kFATAL;
227 if (!pRecoSetupManager->HasGeoNodeMaps()) {
237 LOG(error) <<
"CbmBbaAlignmentMcbmTask::Init: Global track array not found!";
244 LOG(error) <<
"CbmBbaAlignmentMcbmTask::Init: Global track matches array not found!";
249 fInputStsTracks =
static_cast<TClonesArray*
>(ioman->GetObject(
"StsTrack"));
251 LOG(error) <<
"CbmBbaAlignmentMcbmTask::Init: Sts track array not found!";
258 LOG(error) <<
"CbmBbaAlignmentMcbmTask::Init: Sts track matches array not found!";
263 fInputMcTracks =
static_cast<TClonesArray*
>(ioman->GetObject(
"MCTrack"));
265 Warning(
"CbmBbaAlignmentMcbmTask::Init",
"mc track array not found!");
278 TDirectory* curDirectory = gDirectory;
283 const char* n1 = Form(
"Station%d", i);
284 const char* n2 = Form(
", station %d", i);
311 if (i == 0 || i == 1) {
336 new TH1F(Form(
"ResBeforeAli%s_X", n1), Form(
"X-Residuals Before Alignment%s", n2), nBins, -sizeX, sizeX));
338 new TH1F(Form(
"ResBeforeAli%s_Y", n1), Form(
"Y-Residuals Before Alignment%s", n2), nBins, -sizeY, sizeY));
340 new TH1F(Form(
"ResAfterAli%s_X", n1), Form(
"X-Residuals After Alignment%s", n2), nBins, -sizeX, sizeX));
342 new TH1F(Form(
"ResAfterAli%s_Y", n1), Form(
"Y-Residuals After Alignment%s", n2), nBins, -sizeY, sizeY));
345 new TH1F(Form(
"PullBeforeAli%s_X", n1), Form(
"X-Pulls Before Alignment%s", n2), nBins, -sizePX, sizePX));
347 new TH1F(Form(
"PullBeforeAli%s_Y", n1), Form(
"Y-Pulls Before Alignment%s", n2), nBins, -sizePY, sizePY));
349 new TH1F(Form(
"PullAfterAli%s_X", n1), Form(
"X-Pulls After Alignment%s", n2), nBins, -sizePX, sizePX));
351 new TH1F(Form(
"PullAfterAli%s_Y", n1), Form(
"Y-Pulls After Alignment%s", n2), nBins, -sizePY, sizePY));
371 gDirectory = curDirectory;
379 LOG(info) <<
"BBA: exec event N " <<
fNEvents;
384 LOG(info) <<
"BBA: max number of tracks already reached, skip the event";
394 unsigned num_rejected_fit = 0;
396 int numPosMomentum = 0;
397 int numNegMomentum = 0;
399 fFitter.SetDefaultMomentumForMs(0.1);
406 if (!stsTrack)
continue;
412 LOG(debug) <<
"failed to fit the track! ";
420 if (!std::isfinite(par.GetQp()))
continue;
421 if (fabs(par.GetQp()) > 1.)
continue;
422 if (par.GetQp() > 0.) {
434 LOG(info) <<
"BBA: selected " <<
fTracks.size() <<
" tracks for alignment, " << numPosMomentum <<
" positive and "
435 << numNegMomentum <<
" negative momentum tracks";
439 fFitter.SetDefaultMomentumForMs(0.5);
440 fFitter.SetEnforceDefaultMomentumForMs();
441 int statNselected = 0;
448 LOG(fatal) <<
"BBA: null pointer to the global track!";
453 LOG(fatal) <<
"BBA: can not create the global track for the fit! ";
461 if (n.measurementXY.Dx2() < n.measurementXY.Dy2()) {
462 n.measurementXY.SetNdfY(0);
465 n.measurementXY.SetNdfX(0);
475 LOG(debug) <<
"failed to fit the track! ";
483 LOG(warning) <<
"BBA: input " <<
fInputGlobalTracks->GetEntriesFast() <<
" global tracks." << statNselected
484 <<
" tracks selected for alignment";
488 if (num_rejected_fit != 0) {
489 LOG(warn) <<
"failed to fit " << num_rejected_fit <<
" tracks";
496 unsigned num_fix_rad_max = 0;
497 unsigned num_fix_rad_min = 0;
498 unsigned num_rejected_fit2 = 0;
500 if (!t.fIsActive)
continue;
501 for (
unsigned int in = 0; in < t.fUnalignedTrack.GetNofNodes(); in++) {
502 auto& node = t.fUnalignedTrack.fNodes[in];
503 if (!node.isFitted) {
508 if (node.radThick > 0.01) {
509 LOG(debug) <<
"CbmBbaAlignmentMcbmTask: radiation thickness is too large: " << node.radThick;
511 node.radThick = 0.01;
513 if (node.radThick < 0.001) {
514 LOG(debug) <<
"CbmBbaAlignmentMcbmTask: radiation thickness is too small: " << node.radThick;
516 node.radThick = 0.001;
522 if (num_fix_rad_max != 0) {
523 LOG(warn) <<
"CbmBbaAlignmentMcbmTask: radiation thickness is too large " << num_fix_rad_max <<
" times";
525 if (num_fix_rad_min != 0) {
526 LOG(warn) <<
"CbmBbaAlignmentMcbmTask: radiation thickness is too small " << num_fix_rad_min <<
" times";
528 if (num_rejected_fit2 != 0) {
529 LOG(warn) <<
"Rejected fit 2 " << num_rejected_fit2 <<
" tracks";
534 unsigned num_rejected_traj = 0;
536 if (!t.fIsActive)
continue;
537 const double cutX = 8.;
538 const double cutY = 8.;
539 for (
unsigned int in = 0; in < t.fUnalignedTrack.GetNofNodes(); in++) {
540 auto tr = t.fUnalignedTrack;
541 const auto& node = tr.GetNode(in);
545 tr.DisableMeasurementAtNode(in);
546 if (!
fFitter.FitTrajectory(tr)) {
551 double x_residual = node.measurementXY.X() - node.paramDn.X();
552 double y_residual = node.measurementXY.Y() - node.paramDn.Y();
553 double x_pull = x_residual /
sqrt(node.measurementXY.Dx2() + node.paramDn.GetCovariance(0, 0));
554 double y_pull = y_residual /
sqrt(node.measurementXY.Dy2() + node.paramDn.GetCovariance(1, 1));
555 if (!node.isFitted || (node.measurementXY.NdfX() > 0. && fabs(x_pull) > cutX)
556 || (node.measurementXY.NdfY() > 0. && fabs(y_pull) > cutY)) {
563 if (num_rejected_traj != 0) {
564 LOG(warn) <<
"Rejected " << num_rejected_traj <<
" tracks for hits deviating from the trajectory";
567 TClonesArray* inputTracks =
nullptr;
574 static int statTracks = 0;
575 statTracks += inputTracks->GetEntriesFast();
577 unsigned active_tracks = 0;
579 if (t.fIsActive) active_tracks++;
582 LOG(info) <<
"Bba: " << inputTracks->GetEntriesFast() <<
" tracks in event, " << statTracks <<
" tracks in total, "
583 <<
fTracks.size() <<
" tracks selected for alignment, " << active_tracks <<
" tracks active";
623 std::vector<double> parConstrained = par;
629 for (
unsigned int in = 0; in < t.fUnalignedTrack.GetNofNodes(); in++) {
630 const auto& node = t.fUnalignedTrack.GetNode(in);
634 auto& nodeAligned = t.fAlignedTrack.fNodes[in];
636 assert(iSensor >= 0 && iSensor < (
int)
fSensors.size());
647 nodeAligned.measurementXY.SetX(node.measurementXY.X() + dx);
648 nodeAligned.measurementXY.SetY(node.measurementXY.Y() + dy);
649 nodeAligned.z = node.z + dz;
653 auto& p = nodeAligned.paramDn;
654 p.SetX(p.X() + p.Tx() * dz);
655 p.SetY(p.Y() + p.Ty() * dz);
656 p.SetZ(nodeAligned.z);
659 auto& p = nodeAligned.paramUp;
660 p.SetX(p.X() + p.Tx() * dz);
661 p.SetY(p.Y() + p.Ty() * dz);
662 p.SetZ(nodeAligned.z);
667 static int statNCalls = 0;
669 if (statNCalls % 100 == 0) {
670 std::vector<double>& r = parConstrained;
671 LOG(info) <<
"Current parameters: ";
674 LOG(info) <<
"Body " << is <<
" sta " << b.fTrackingStation <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1]
675 <<
" z " << r[3 * is + 2];
758 LOG(info) <<
"BBA: start the alignment procedure with " <<
fTracks.size() <<
" tracks ...";
770 std::set<Sensor> sensorSet;
772 for (
auto& n : t.fUnalignedTrack.GetNodes()) {
786 for (
auto& s : sensorSet) {
793 LOG(info) <<
"BBA: found " <<
fSensors.size() <<
" sensors used by selected tracks:";
795 LOG(info) <<
"Sensor sys " << s.fSystemId <<
" sta " << s.fTrackingStation <<
"path " << s.fNodePath;
799 for (
unsigned int in = 0; in < t.fUnalignedTrack.GetNofNodes(); in++) {
800 const auto& n = t.fUnalignedTrack.GetNode(in);
809 auto iter = std::lower_bound(
813 int iSensor = std::distance(
fSensors.begin(), iter);
814 t.fUnalignedTrack.SetSensorId(in, iSensor);
816 t.fAlignedTrack = t.fUnalignedTrack;
827 s.fAlignmentBody = s.fTrackingStation;
834 for (
int unsigned i = 0; i <
fSensors.size(); i++) {
842 LOG(info) <<
"\n Sensors: ";
844 for (
unsigned int is = 0; is <
fSensors.size(); is++) {
846 LOG(info) <<
"Sensor " << is <<
" sys " << s.fSystemId <<
" sta " << s.fTrackingStation <<
" body "
851 LOG(info) <<
"\n Alignment bodies: ";
861 std::vector<bba::Parameter> par(nParameters);
863 for (
int ip = 0; ip < nParameters; ip++) {
864 bba::Parameter& p = par[ip];
867 p.SetBoundaryMin(-2.);
868 p.SetBoundaryMax(2.);
885 par[3 * ib + 0].SetActive(0);
886 par[3 * ib + 1].SetActive(0);
887 par[3 * ib + 2].SetActive(0);
890 par[3 * ib + 0].SetActive(1);
891 par[3 * ib + 1].SetActive(1);
892 par[3 * ib + 2].SetActive(0);
896 par[3 * ib + 0].SetActive(0);
903 int ib = s.fAlignmentBody;
906 for (
int j = 0; j < 3; j++) {
907 bba::Parameter& p = par[ib * 3 + j];
910 p.SetStepMin(10.e-4);
913 p.SetStepMin(10.e-4);
923 bba::Parameter& px = par[3 * is + 0];
924 bba::Parameter& py = par[3 * is + 1];
925 bba::Parameter& pz = par[3 * is + 2];
929 px.SetValue(gRandom->Uniform(2. * d) - d);
932 py.SetValue(gRandom->Uniform(2. * d) - d);
935 pz.SetValue(gRandom->Uniform(2. * d) - d);
941 alignment.setParameters(par);
943 auto lambdaCostFunction = [
this](
const std::vector<double>& p) {
return CostFunction(p); };
945 alignment.setChi2(lambdaCostFunction);
946 alignment.printInfo();
948 std::vector<double> parIdeal;
949 std::vector<double> parMisaligned;
951 const std::vector<double>& r = alignment.getResult();
952 for (
unsigned int i = 0; i < r.size(); i++) {
953 parMisaligned.push_back(r[i]);
954 parIdeal.push_back(0.);
959 std::cout <<
"initial cost function..." << std::endl;
963 unsigned tracks_rejected = 0;
965 double ndf = t.fFittedAlignedTrackParam.GetNdf();
966 double chi2 = t.fFittedAlignedTrackParam.GetChiSq();
967 if (ndf < 0. || chi2 < 0. || !std::isfinite(ndf) || !std::isfinite(chi2)) {
972 std::cout <<
"reject " << tracks_rejected <<
" bad tracks and recalculate the initial cost function..."
979 for (
const auto& t :
fTracks) {
980 if (!t.fIsActive)
continue;
982 for (
unsigned int in = 0; in < t.fAlignedTrack.GetNofNodes(); in++) {
983 auto tr = t.fAlignedTrack;
984 const auto& node = tr.GetNode(in);
989 tr.DisableMeasurementAtNode(in);
990 if (!
fFitter.FitTrajectory(tr) || !node.isFitted) {
996 double x_residual = node.measurementXY.X() - node.paramDn.X();
997 double y_residual = node.measurementXY.Y() - node.paramDn.Y();
998 double x_pull = x_residual /
sqrt(node.measurementXY.Dx2() + node.paramDn.GetCovariance(0, 0));
999 double y_pull = y_residual /
sqrt(node.measurementXY.Dy2() + node.paramDn.GetCovariance(1, 1));
1001 if (node.measurementXY.NdfX() > 0) {
1005 if (node.measurementXY.NdfY() > 0) {
1019 std::cout <<
"calculate ideal cost function..." << std::endl;
1023 LOG(info) <<
" Cost function for the true parameters: " <<
fCostIdeal;
1024 LOG(info) <<
" Cost function for the initial parameters: " <<
fCostInitial;
1028 bool doManualAlignment =
false;
1030 if (!doManualAlignment) {
1037 par[3 * ib + 0].SetValue(0.1);
1038 par[3 * ib + 1].SetValue(0.1);
1039 par[3 * ib + 2].SetValue(0.);
1042 par[3 * ib + 0].SetValue(0.);
1043 par[3 * ib + 1].SetValue(0.);
1044 par[3 * ib + 2].SetValue(0.);
1047 alignment.setParameters(par);
1050 double costResult =
CostFunction(alignment.getResult());
1056 std::vector<double> result = alignment.getResult();
1057 std::map<std::string, TGeoHMatrix> alignmentMatrices;
1059 if (doManualAlignment) {
1060 for (
unsigned int i = 0; i < result.size(); i++) {
1061 result[i] = par[i].GetValue();
1065 LOG(info) <<
"Alignment matrices: ";
1068 int i = s.fAlignmentBody;
1070 if (i < 0)
continue;
1071 if (s.fNodePath.empty())
continue;
1072 LOG(info) <<
"Write alignment matrix for the node " << s.fNodePath <<
" x " << result[i * 3 + 0] <<
" y "
1073 << result[i * 3 + 1] <<
" z " << result[i * 3 + 2];
1074 if (s.fNodePath.empty())
continue;
1075 alignmentMatrices.insert(
1076 CreateAlignmentNode(s.fNodePath, result[i * 3 + 0], result[i * 3 + 1], result[i * 3 + 2], 0., 0., 0.));
1081 if (misalignmentMatrixRootfile->IsOpen()) {
1082 gDirectory->WriteObject(&alignmentMatrices,
"MisalignMatrices");
1083 misalignmentMatrixRootfile->Write();
1084 misalignmentMatrixRootfile->Close();
1087 LOG(info) <<
"\n Misaligned parameters: ";
1089 const std::vector<double>& r = parMisaligned;
1090 LOG(info) <<
"Body " << is <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1] <<
" z " << r[3 * is + 2];
1093 LOG(info) <<
"\n Alignment results: ";
1095 const std::vector<double>& r = alignment.getResult();
1098 LOG(info) <<
"Body " << is <<
" sta " << b.
fTrackingStation <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1]
1099 <<
" z " << r[3 * is + 2];
1103 LOG(info) <<
"\n Alignment results, constrained: ";
1105 std::vector<double> r = alignment.getResult();
1109 LOG(info) <<
"Body " << is <<
" sta " << b.
fTrackingStation <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1]
1110 <<
" z " << r[3 * is + 2];
1114 unsigned active_tracks = 0;
1116 if (t.fIsActive) active_tracks++;
1121 LOG(info) <<
"Bba: " <<
fTracks.size() <<
" tracks used for alignment\n";
1122 LOG(info) <<
" " << active_tracks <<
" tracks active\n";
1124 LOG(info) <<
" Cost function for the true parameters: " <<
fCostIdeal;
1125 LOG(info) <<
" Cost function for the initial parameters: " <<
fCostInitial;
1126 LOG(info) <<
" Cost function for the aligned parameters: " << costResult;
1129 if (!t.fIsActive)
continue;
1132 for (
unsigned int in = 0; in < t.fAlignedTrack.GetNofNodes(); in++) {
1133 auto tr = t.fAlignedTrack;
1134 const auto& node = tr.GetNode(in);
1135 if (!node.isXySet) {
1138 tr.DisableMeasurementAtNode(in);
1139 if (!
fFitter.FitTrajectory(tr) || !node.isFitted) {
1145 double x_residual = node.measurementXY.X() - node.paramDn.X();
1146 double y_residual = node.measurementXY.Y() - node.paramDn.Y();
1147 double x_pull = x_residual /
sqrt(node.measurementXY.Dx2() + node.paramDn.GetCovariance(0, 0));
1148 double y_pull = y_residual /
sqrt(node.measurementXY.Dy2() + node.paramDn.GetCovariance(1, 1));
1150 if (node.measurementXY.NdfX() > 0) {
1154 if (node.measurementXY.NdfY() > 0) {
1169 TDirectory* curr = gDirectory;
1170 TFile* currentFile = gFile;
1179 gFile = currentFile;