18#include "FairRootManager.h"
19#include "FairRunAna.h"
20#include "TClonesArray.h"
22#include "TGeoPhysicalNode.h"
43#include "TGeoPhysicalNode.h"
55std::pair<std::string, TGeoHMatrix>
AlignNode(std::string path,
double shiftX,
double shiftY,
double shiftZ,
56 double rotX,
double rotY,
double rotZ)
71 return std::pair<std::string, TGeoHMatrix>(path, result);
83 switch (n.fHitSystemId) {
102 : FairTask(name, iVerbose)
105 TFile* curFile = gFile;
106 TDirectory* curDirectory = gDirectory;
121 gDirectory = curDirectory;
132 const char* env = std::getenv(
"OMP_NUM_THREADS");
135 LOG(info) <<
"BBA: found environment variable OMP_NUM_THREADS = \"" << env
152 FairRootManager* ioman = FairRootManager::Instance();
155 LOG(error) <<
"CbmBbaAlignmentTask::Init :: RootManager not instantiated!";
165 LOG(error) <<
"CbmBbaAlignmentTask::Init: Global track array not found!";
172 LOG(error) <<
"CbmBbaAlignmentTask::Init: Global track matches array not found!";
177 fInputStsTracks =
static_cast<TClonesArray*
>(ioman->GetObject(
"StsTrack"));
179 LOG(error) <<
"CbmBbaAlignmentTask::Init: Sts track array not found!";
186 LOG(error) <<
"CbmBbaAlignmentTask::Init: Sts track matches array not found!";
191 fInputMcTracks =
static_cast<TClonesArray*
>(ioman->GetObject(
"MCTrack"));
193 Warning(
"CbmBbaAlignmentTask::Init",
"mc track array not found!");
206 TDirectory* curDirectory = gDirectory;
211 const char* n1 = Form(
"Station%d", i);
212 const char* n2 = Form(
", station %d", i);
239 if (i == 0 || i == 1) {
264 new TH1F(Form(
"ResBeforeAli%s_X", n1), Form(
"X-Residuals Before Alignment%s", n2), nBins, -sizeX, sizeX));
266 new TH1F(Form(
"ResBeforeAli%s_Y", n1), Form(
"Y-Residuals Before Alignment%s", n2), nBins, -sizeY, sizeY));
268 new TH1F(Form(
"ResAfterAli%s_X", n1), Form(
"X-Residuals After Alignment%s", n2), nBins, -sizeX, sizeX));
270 new TH1F(Form(
"ResAfterAli%s_Y", n1), Form(
"Y-Residuals After Alignment%s", n2), nBins, -sizeY, sizeY));
273 new TH1F(Form(
"PullBeforeAli%s_X", n1), Form(
"X-Pulls Before Alignment%s", n2), nBins, -sizePX, sizePX));
275 new TH1F(Form(
"PullBeforeAli%s_Y", n1), Form(
"Y-Pulls Before Alignment%s", n2), nBins, -sizePY, sizePY));
277 new TH1F(Form(
"PullAfterAli%s_X", n1), Form(
"X-Pulls After Alignment%s", n2), nBins, -sizePX, sizePX));
279 new TH1F(Form(
"PullAfterAli%s_Y", n1), Form(
"Y-Pulls After Alignment%s", n2), nBins, -sizePY, sizePY));
299 gDirectory = curDirectory;
307 LOG(info) <<
"BBA: exec event N " <<
fNEvents;
321 unsigned num_rejected_fit = 0;
323 int numPosMomentum = 0;
324 int numNegMomentum = 0;
333 if (!stsTrack)
continue;
339 n.fIsTimeSet =
false;
347 LOG(debug) <<
"failed to fit the track! ";
355 if (!std::isfinite(par.GetQp()))
continue;
356 if (fabs(par.GetQp()) > 1.)
continue;
357 if (par.GetQp() > 0.) {
369 LOG(info) <<
"BBA: selected " <<
fTracks.size() <<
" tracks for alignment, " << numPosMomentum <<
" positive and "
370 << numNegMomentum <<
" negative momentum tracks";
383 LOG(fatal) <<
"BBA: null pointer to the global track!";
388 LOG(fatal) <<
"BBA: can not create the global track for the fit! ";
394 n.fIsTimeSet =
false;
396 if (n.fMxy.Dx2() < n.fMxy.Dy2()) {
409 LOG(debug) <<
"failed to fit the track! ";
418 if (num_rejected_fit != 0) {
419 LOG(warn) <<
"failed to fit " << num_rejected_fit <<
" tracks";
424 unsigned num_fix_rad_max = 0;
425 unsigned num_fix_rad_min = 0;
426 unsigned num_rejected_fit2 = 0;
428 if (!t.fIsActive)
continue;
429 for (
unsigned int in = 0; in < t.fUnalignedTrack.fNodes.size(); in++) {
438 LOG(debug) <<
"CbmBbaAlignmentTask: radiation thickness is too large: " << node.
fRadThick;
443 LOG(debug) <<
"CbmBbaAlignmentTask: radiation thickness is too small: " << node.
fRadThick;
449 if (num_fix_rad_max != 0) {
450 LOG(warn) <<
"CbmBbaAlignmentTask: radiation thickness is too large " << num_fix_rad_max <<
" times";
452 if (num_fix_rad_min != 0) {
453 LOG(warn) <<
"CbmBbaAlignmentTask: radiation thickness is too small " << num_fix_rad_min <<
" times";
455 if (num_rejected_fit2 != 0) {
456 LOG(warn) <<
"Rejected fit 2 " << num_rejected_fit2 <<
" tracks";
461 unsigned num_rejected_traj = 0;
463 if (!t.fIsActive)
continue;
464 const double cutX = 8.;
465 const double cutY = 8.;
466 for (
unsigned int in = 0; in < t.fUnalignedTrack.fNodes.size(); in++) {
483 || (node.
fMxy.
NdfY() > 0. && fabs(y_pull) > cutY)) {
490 if (num_rejected_traj != 0) {
491 LOG(warn) <<
"Rejected " << num_rejected_traj <<
" tracks for hits deviating from the trajectory";
494 TClonesArray* inputTracks =
nullptr;
501 static int statTracks = 0;
502 statTracks += inputTracks->GetEntriesFast();
504 unsigned active_tracks = 0;
506 if (t.fIsActive) active_tracks++;
509 LOG(info) <<
"Bba: " << inputTracks->GetEntriesFast() <<
" tracks in event, " << statTracks <<
" tracks in total, "
510 <<
fTracks.size() <<
" tracks selected for alignment, " << active_tracks <<
" tracks active";
523 mean += par[3 * i + ixyz];
531 par[3 * i + ixyz] -= mean;
550 std::vector<double> parConstrained = par;
556 for (
unsigned int in = 0; in < t.fUnalignedTrack.fNodes.size(); in++) {
563 assert(iSensor >= 0 && iSensor < (
int)
fSensors.size());
576 nodeAligned.
fZ = node.
fZ + dz;
581 p.
SetX(p.X() + p.Tx() * dz);
582 p.SetY(p.Y() + p.Ty() * dz);
583 p.SetZ(nodeAligned.
fZ);
587 p.
SetX(p.X() + p.Tx() * dz);
588 p.SetY(p.Y() + p.Ty() * dz);
589 p.SetZ(nodeAligned.
fZ);
594 static int statNCalls = 0;
596 if (statNCalls % 100 == 0) {
597 std::vector<double>& r = parConstrained;
598 LOG(info) <<
"Current parameters: ";
601 LOG(info) <<
"Body " << is <<
" sta " << b.fTrackingStation <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1]
602 <<
" z " << r[3 * is + 2];
613 t.fAlignedTrack = t.fUnalignedTrack;
618 std::vector<double> chi2Thread(
fNthreads, 0.);
619 std::vector<long> ndfThread(
fNthreads, 0);
621 auto fitThread = [&](
int iThread) {
628 if (!t.fIsActive)
continue;
632 for (
unsigned int in = 0; in < t.fAlignedTrack.fNodes.size(); in++) {
635 LOG(fatal) <<
"BBA: Cost function: aligned node is not fitted! ";
639 double chi2 = t.fAlignedTrack.fNodes.back().fParamDn.GetChiSq();
640 double ndf = t.fAlignedTrack.fNodes.back().fParamDn.GetNdf();
641 if (!ok || !std::isfinite(chi2) || chi2 <= 0. || ndf <= 0.) {
643 LOG(fatal) <<
"BBA: fit failed! ";
647 chi2Thread[iThread] += chi2;
648 ndfThread[iThread] += (int) ndf;
652 std::vector<std::thread> threads(
fNthreads);
656 threads[i] = std::thread(fitThread, i);
660 for (
auto& th : threads) {
685 LOG(info) <<
"BBA: start the alignment procedure with " <<
fTracks.size() <<
" tracks ...";
694 std::set<Sensor> sensorSet;
696 for (
auto& n : t.fUnalignedTrack.fNodes) {
714 s.
fNodePath =
"/cave_1/trd_v22h_mcbm_0/layer01_20101/module9_101001001";
717 s.
fNodePath =
"/cave_1/trd_v22h_mcbm_0/layer02_10202/module8_101002001";
720 s.
fNodePath =
"/cave_1/trd_v22h_mcbm_0/layer03_11303/module8_101303001";
732 for (
auto& s : sensorSet) {
738 for (
auto& n : t.fUnalignedTrack.fNodes) {
757 auto iter = std::lower_bound(
761 int iSensor = std::distance(
fSensors.begin(), iter);
762 n.fReference1 = iSensor;
764 t.fAlignedTrack = t.fUnalignedTrack;
775 s.fAlignmentBody = s.fTrackingStation;
782 for (
int unsigned i = 0; i <
fSensors.size(); i++) {
790 LOG(info) <<
"\n Sensors: ";
792 for (
unsigned int is = 0; is <
fSensors.size(); is++) {
794 LOG(info) <<
"Sensor " << is <<
" sys " << s.fSystemId <<
" sta " << s.fTrackingStation <<
" body "
799 LOG(info) <<
"\n Alignment bodies: ";
809 std::vector<bba::Parameter> par(nParameters);
811 for (
int ip = 0; ip < nParameters; ip++) {
812 bba::Parameter& p = par[ip];
815 p.SetBoundaryMin(-2.);
816 p.SetBoundaryMax(2.);
828 par[3 * ib + 0].SetActive(0);
829 par[3 * ib + 1].SetActive(0);
830 par[3 * ib + 2].SetActive(0);
833 par[3 * ib + 0].SetActive(1);
834 par[3 * ib + 1].SetActive(1);
835 par[3 * ib + 2].SetActive(1);
839 par[3 * ib + 0].SetActive(0);
846 int ib = s.fAlignmentBody;
849 for (
int j = 0; j < 3; j++) {
850 bba::Parameter& p = par[ib * 3 + j];
853 p.SetStepMin(10.e-4);
856 p.SetStepMin(10.e-4);
866 bba::Parameter& px = par[3 * is + 0];
867 bba::Parameter& py = par[3 * is + 1];
868 bba::Parameter& pz = par[3 * is + 2];
872 px.SetValue(gRandom->Uniform(2. * d) - d);
875 py.SetValue(gRandom->Uniform(2. * d) - d);
878 pz.SetValue(gRandom->Uniform(2. * d) - d);
883 LOG(info) <<
"STS sensor paths: ";
890 LOG(error) <<
"Element not found: " << s.fSensorId;
896 LOG(info) <<
"Node: ";
904 alignment.setParameters(par);
906 auto lambdaCostFunction = [
this](
const std::vector<double>& p) {
return CostFunction(p); };
908 alignment.setChi2(lambdaCostFunction);
909 alignment.printInfo();
911 std::vector<double> parIdeal;
912 std::vector<double> parMisaligned;
914 const std::vector<double>& r = alignment.getResult();
915 for (
unsigned int i = 0; i < r.size(); i++) {
916 parMisaligned.push_back(r[i]);
917 parIdeal.push_back(0.);
922 std::cout <<
"initial cost function..." << std::endl;
926 unsigned tracks_rejected = 0;
928 double ndf = t.fAlignedTrack.fNodes.back().fParamDn.GetNdf();
929 double chi2 = t.fAlignedTrack.fNodes.back().fParamDn.GetChiSq();
930 if (ndf < 0. || chi2 < 0. || !std::isfinite(ndf) || !std::isfinite(chi2)) {
935 std::cout <<
"reject " << tracks_rejected <<
" bad tracks and recalculate the initial cost function..."
942 for (
const auto& t :
fTracks) {
943 if (!t.fIsActive)
continue;
945 for (
unsigned int in = 0; in < t.fAlignedTrack.fNodes.size(); in++) {
985 std::cout <<
"calculate ideal cost function..." << std::endl;
989 LOG(info) <<
" Cost function for the true parameters: " <<
fCostIdeal;
990 LOG(info) <<
" Cost function for the initial parameters: " <<
fCostInitial;
995 double costResult =
CostFunction(alignment.getResult());
1001 std::vector<double> result = alignment.getResult();
1002 std::map<std::string, TGeoHMatrix> alignmentMatrices;
1005 int i = s.fAlignmentBody;
1007 if (i < 0)
continue;
1014 LOG(error) <<
"Element not found: " << s.fSensorId;
1018 LOG(debug) <<
"Node: ";
1019 LOG(debug) << n->GetName();
1020 alignmentMatrices.insert(
1021 AlignNode(n->GetName(), result[i * 3 + 0], result[i * 3 + 1], result[i * 3 + 2], 0., 0., 0.));
1025 LOG(debug) <<
"Node: ";
1026 LOG(debug) << s.fNodePath;
1027 alignmentMatrices.insert(
1028 AlignNode(s.fNodePath, result[i * 3 + 0], result[i * 3 + 1], result[i * 3 + 2], 0., 0., 0.));
1032 LOG(debug) <<
"Node: ";
1033 LOG(debug) << s.fNodePath;
1034 alignmentMatrices.insert(
1035 AlignNode(s.fNodePath, result[i * 3 + 0], result[i * 3 + 1], result[i * 3 + 2], 0., 0., 0.));
1047 TFile* misalignmentMatrixRootfile =
1048 new TFile(
"AlignmentMatrices_mcbm_beam_2022_05_23_nickel_finetuning.root",
"RECREATE");
1049 if (misalignmentMatrixRootfile->IsOpen()) {
1050 gDirectory->WriteObject(&alignmentMatrices,
"AlignmentMatrices");
1051 misalignmentMatrixRootfile->Write();
1052 misalignmentMatrixRootfile->Close();
1055 LOG(info) <<
"\n Misaligned parameters: ";
1057 const std::vector<double>& r = parMisaligned;
1058 LOG(info) <<
"Body " << is <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1] <<
" z " << r[3 * is + 2];
1061 LOG(info) <<
"\n Alignment results: ";
1063 const std::vector<double>& r = alignment.getResult();
1066 LOG(info) <<
"Body " << is <<
" sta " << b.
fTrackingStation <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1]
1067 <<
" z " << r[3 * is + 2];
1071 LOG(info) <<
"\n Alignment results, constrained: ";
1073 std::vector<double> r = alignment.getResult();
1077 LOG(info) <<
"Body " << is <<
" sta " << b.
fTrackingStation <<
": x " << r[3 * is + 0] <<
" y " << r[3 * is + 1]
1078 <<
" z " << r[3 * is + 2];
1082 unsigned active_tracks = 0;
1084 if (t.fIsActive) active_tracks++;
1089 LOG(info) <<
"Bba: " <<
fTracks.size() <<
" tracks used for alignment\n";
1090 LOG(info) <<
" " << active_tracks <<
" tracks active\n";
1092 LOG(info) <<
" Cost function for the true parameters: " <<
fCostIdeal;
1093 LOG(info) <<
" Cost function for the initial parameters: " <<
fCostInitial;
1094 LOG(info) <<
" Cost function for the aligned parameters: " << costResult;
1097 if (!t.fIsActive)
continue;
1100 for (
unsigned int in = 0; in < t.fAlignedTrack.fNodes.size(); in++) {
1135 TDirectory* curr = gDirectory;
1136 TFile* currentFile = gFile;
1145 gFile = currentFile;
1152 if (!obj->IsFolder())
1155 TDirectory* cur = gDirectory;
1156 TFile* currentFile = gFile;
1158 TDirectory* sub = cur->GetDirectory(obj->GetName());
1160 TList* listSub = (
static_cast<TDirectory*
>(obj))->GetList();
1162 while (TObject* obj1 = it()) {
1166 gFile = currentFile;
ClassImp(CbmBbaAlignmentTask)
std::pair< std::string, TGeoHMatrix > AlignNode(std::string path, double shiftX, double shiftY, double shiftZ, double rotX, double rotY, double rotZ)
Task class for alignment.
Time-slice/event reader for CA tracker in CBM (header)
@ kMvd
Micro-Vertex Detector.
@ kTrd
Transition Radiation Detector.
@ kTof
Time-of-flight Detector.
@ kSts
Silicon Tracking System.
@ kTrd2d
TRD-FASP Detector (FIXME)
@ kMuch
Muon detection system.
Data class for a reconstructed hit in the STS.
Data class for STS tracks.
friend fvec sqrt(const fvec &a)
an example of alignment using BBA package
TClonesArray * fInputGlobalTrackMatches
void WriteHistosCurFile(TObject *obj)
std::vector< TrackContainer > fTracks
TrackingMode fTrackingMode
CbmBbaAlignmentTask(const char *name="CbmBbaAlignmentTask", Int_t iVerbose=0, TString histoFileName="CbmBbaAlignmentHisto.root")
std::vector< TH1F * > hPullsBeforeAlignmentX
TClonesArray * fInputStsTrackMatches
std::vector< TH1F * > hPullsAfterAlignmentX
double fSimulatedMisalignmentRange
TClonesArray * fInputMcTracks
TClonesArray * fInputStsTracks
std::vector< TH1F * > hResidualsAfterAlignmentX
std::vector< AlignmentBody > fAlignmentBodies
std::vector< TH1F * > hPullsBeforeAlignmentY
void ApplyAlignment(const std::vector< double > &par)
void ApplyConstraints(std::vector< double > &par)
TClonesArray * fInputGlobalTracks
std::vector< TH1F * > hResidualsAfterAlignmentY
std::vector< Sensor > fSensors
std::vector< TH1F * > hResidualsBeforeAlignmentX
std::vector< TH1F * > hResidualsBeforeAlignmentY
std::vector< TH1F * > hPullsAfterAlignmentY
double CostFunction(const std::vector< double > &par)
void ConstrainStation(std::vector< double > &par, int iSta, int ixyz)
void SetSkipUnmeasuredCoordinates(bool skip=true)
skip unmeasured coordinates
bool CreateMvdStsTrack(Trajectory &kfTrack, int stsTrackIndex)
set the input data arrays
bool CreateGlobalTrack(Trajectory &kfTrack, int globalTrackIndex)
void FixMomentumForMs(bool fix=true)
fix the inverse momentum for the Multiple Scattering calculation
void SetDefaultMomentumForMs(double p)
set the default inverse momentum for the Multiple Scattering calculation
void SetDoSmooth(bool doSmooth)
do the KF-smoothing to define track pars at all the nodes
bool FitTrajectory(CbmKfTrackFitter::Trajectory &t)
fit the track
void SetNoMultipleScattering()
set the default inverse momentum for the Multiple Scattering calculation
static CbmL1 * Instance()
Pointer to CbmL1 instance.
ca::Framework * fpAlgo
Pointer to the L1 track finder algorithm.
Class representing an element of the STS setup.
TGeoPhysicalNode * GetPnode() const
virtual void Print(Option_t *opt="") const
CbmStsElement * GetElement(Int_t address, Int_t level)
static CbmStsSetup * Instance()
static CbmStsTrackingInterface * Instance()
Gets pointer to the instance of the CbmStsTrackingInterface class.
int GetTrackingStationIndex(const CbmHit *hit) const override
Gets a tracking station of a CbmHit.
static int32_t GetRpcFullId(uint32_t address)
int GetNtrackingStations() const
Gets actual number of stations, provided by the current geometry setup.
const Parameters< fvec > & GetParameters() const
Gets a pointer to the Framework parameters object.
A container for all external parameters of the CA tracking algorithm.
int GetNstationsActive() const
Gets total number of active stations.
T X() const
Gets x position [cm].
T Y() const
Gets y position [cm].
void SetX(T v)
Sets x position [cm].
T GetCovariance(int i, int j) const
Get covariance matrix element.
CbmKfTrackFitter::Trajectory fUnalignedTrack
CbmKfTrackFitter::Trajectory fAlignedTrack
cbm::algo::kf::TrackParamD fParamUp
fitted track parameters upstream the node
double fZ
Z coordinate of the node.
bool fIsFitted
true if the track parameters at the node are fitted
cbm::algo::kf::MeasurementXy< double > fMxy
== Hit information ( if present )
int fReference1
some reference can be set by the user
cbm::algo::kf::TrackParamD fParamDn
fitted track parameters downstream the node
bool fIsXySet
== Flags etc
bool fIsRadThickFixed
true if the radiation thickness is fixed to the fRadThick value
A trajectory to be fitted.
std::vector< TrajectoryNode > fNodes
nodes on the trajectory