diff --git a/macro/alignment/run_BbaAlignment_mcbm.C b/macro/alignment/run_BbaAlignment_mcbm.C new file mode 100644 index 0000000000000000000000000000000000000000..60f8a7cb6b489f6d178b666aa394824c5cb970d3 --- /dev/null +++ b/macro/alignment/run_BbaAlignment_mcbm.C @@ -0,0 +1,281 @@ +/* Copyright (C) 2020 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Dominik Smith [committer] */ + +// -------------------------------------------------------------------------- +// +// Macro for simulation & reconstruction QA +// +// The following naming conventions are assumed: +// Raw data file: [dataset].event.raw.root +// Transport file: [dataset].tra.root +// Parameter file: [dataset].par.root +// Reconstruction file: [dataset].rec.root +// +// S. Gorbunov 28/09/2020 +// +// -------------------------------------------------------------------------- + +// Includes needed for IDE +#if !defined(__CLING__) +#include "CbmDefs.h" +#include "CbmMCDataManager.h" +#include "CbmMuchTransportQa.h" +#include "CbmQaManager.h" +#include "CbmSetup.h" + +#include <FairFileSource.h> +#include <FairMonitor.h> +#include <FairParAsciiFileIo.h> +#include <FairParRootFileIo.h> +#include <FairRootFileSink.h> +#include <FairRunAna.h> +#include <FairRuntimeDb.h> +#include <FairSystemInfo.h> + +#include <TStopwatch.h> +#endif + +void run_BbaAlignment_mcbm(Int_t nEvents = 0, TString dataset = "data/mcbm_beam_2020_03_test", + TString setupName = "mcbm_beam_2020_03", Bool_t bUseMC = kTRUE, const TString& config = "") +{ + + // ======================================================================== + // Adjust this part according to your requirements + + // ----- Logger settings ---------------------------------------------- + FairLogger::GetLogger()->SetLogScreenLevel("INFO"); + FairLogger::GetLogger()->SetLogVerbosityLevel("LOW"); + // ------------------------------------------------------------------------ + + // ----- Environment -------------------------------------------------- + int verbose = 6; // verbose level + TString myName = "mcbm_qa"; // this macro's name for screen output + TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory + TString qaConfig = (config.Length() ? config : srcDir + "/macro/qa/configs/qa_tasks_config_mcbm.yaml"); + // NOTE: SZh 28.07.2024: config can depend from the setup + // ------------------------------------------------------------------------ + + // ----- In- and output file names ------------------------------------ + TString rawFile = dataset + ".event.raw.root"; + TString traFile = dataset + ".tra.root"; + TString parFile = dataset + ".par.root"; + TString recFile = dataset + ".rec.root"; + TString sinkFile = dataset + ".qa.root"; + // ------------------------------------------------------------------------ + + // ----- Load the geometry setup ------------------------------------- + std::cout << '\n'; + TString setupFile = srcDir + "/geometry/setup/setup_" + setupName + ".C"; + TString setupFunct = "setup_"; + setupFunct = setupFunct + setupName + "()"; + std::cout << "-I- " << myName << ": Loading macro " << setupFile << '\n'; + gROOT->LoadMacro(setupFile); + gROOT->ProcessLine(setupFunct); + CbmSetup* setup = CbmSetup::Instance(); + // setup->RemoveModule(ECbmModuleId::kTrd); + // ------------------------------------------------------------------------ + + // ----- Some global switches ----------------------------------------- + //if (setupName == "mcbm_beam_2022_05_23_nickel") { setup->RemoveModule(ECbmModuleId::kMuch); } + + //bool eventBased = !sEvBuildRaw.IsNull(); + bool bUseMvd = setup->IsActive(ECbmModuleId::kMvd); + bool bUseSts = setup->IsActive(ECbmModuleId::kSts); + bool bUseRich = setup->IsActive(ECbmModuleId::kRich); + bool bUseMuch = setup->IsActive(ECbmModuleId::kMuch); + bool bUseTrd = setup->IsActive(ECbmModuleId::kTrd); + bool bUseTof = setup->IsActive(ECbmModuleId::kTof); + bool bUsePsd = setup->IsActive(ECbmModuleId::kPsd); + std::cout << " MVD: " << (bUseMvd ? "ON" : "OFF") << '\n'; + std::cout << " STS: " << (bUseSts ? "ON" : "OFF") << '\n'; + std::cout << " RICH: " << (bUseRich ? "ON" : "OFF") << '\n'; + std::cout << " MUCH: " << (bUseMuch ? "ON" : "OFF") << '\n'; + std::cout << " TRD: " << (bUseTrd ? "ON" : "OFF") << '\n'; + std::cout << " TOF: " << (bUseTof ? "ON" : "OFF") << '\n'; + std::cout << " PSD: " << (bUsePsd ? "ON" : "OFF") << '\n'; + // ------------------------------------------------------------------------ + + // ----- Parameter files as input to the runtime database ------------- + std::cout << '\n'; + std::cout << "-I- " << myName << ": Defining paramete files\n"; + TList* parFileList = new TList(); + TString geoTag; + + // - MUCH digitisation parameters + TString muchParFile {}; + if (setup->GetGeoTag(ECbmModuleId::kMuch, geoTag)) { + bool mcbmFlag = geoTag.Contains("mcbm", TString::kIgnoreCase); + muchParFile = srcDir + "/parameters/much/much_"; + muchParFile += (mcbmFlag) ? geoTag : geoTag(0, 4); + muchParFile += "_digi_sector.root"; + { // init geometry from the file + TFile* f = new TFile(muchParFile, "R"); + TObjArray* stations = f->Get<TObjArray>("stations"); + assert(stations); + CbmMuchGeoScheme::Instance()->Init(stations, mcbmFlag); + } + } + + // - TRD digitisation parameters + if (setup->GetGeoTag(ECbmModuleId::kTrd, geoTag)) { + const Char_t* npar[4] = {"asic", "digi", "gas", "gain"}; + TObjString* trdParFile(NULL); + for (Int_t i(0); i < 4; i++) { + trdParFile = new TObjString(srcDir + "/parameters/trd/trd_" + geoTag + "." + npar[i] + ".par"); + parFileList->Add(trdParFile); + std::cout << "-I- " << myName << ": Using parameter file " << trdParFile->GetString() << std::endl; + } + } + + // - TOF digitisation parameters + if (setup->GetGeoTag(ECbmModuleId::kTof, geoTag)) { + TObjString* tofBdfFile = new TObjString(srcDir + "/parameters/tof/tof_" + geoTag + ".digibdf.par"); + parFileList->Add(tofBdfFile); + std::cout << "-I- " << myName << ": Using parameter file " << tofBdfFile->GetString() << std::endl; + } + // ------------------------------------------------------------------------ + + // In general, the following parts need not be touched + // ======================================================================== + + // ----- Timer -------------------------------------------------------- + TStopwatch timer; + timer.Start(); + // ------------------------------------------------------------------------ + + // ---- Debug option ------------------------------------------------- + gDebug = 0; + // ------------------------------------------------------------------------ + + // ----- FairRunAna --------------------------------------------------- + FairFileSource* inputSource = new FairFileSource(rawFile); + inputSource->AddFriend(traFile); + inputSource->AddFriend(recFile); + + FairRunAna* run = new FairRunAna(); + run->SetSource(inputSource); + run->SetGenerateRunInfo(kFALSE); + + + FairRootFileSink* sink = new FairRootFileSink(sinkFile); + run->SetSink(sink); + + TString monitorFile {sinkFile}; + monitorFile.ReplaceAll("qa", "qa.monitor"); + FairMonitor::GetMonitor()->EnableMonitor(kTRUE, monitorFile); + // ------------------------------------------------------------------------ + + // ----- MCDataManager (legacy mode) ----------------------------------- + if (bUseMC) { + std::cout << "-I- " << myName << ": Adding MC manager and MC to reco matching tasks\n"; + + auto* mcManager = new CbmMCDataManager("MCDataManager", 1); + mcManager->AddFile(traFile); + run->AddTask(mcManager); + + auto* matchRecoToMC = new CbmMatchRecoToMC(); + // NOTE: Matching is suppressed, if there are hit and cluster matches already in the tree. If there + // are no hit matches, they are produced on this stage. + matchRecoToMC->SuppressHitReMatching(); + run->AddTask(matchRecoToMC); + } + // ------------------------------------------------------------------------ + + // ----- Tracking detector interface -------------------------------------- + run->AddTask(new CbmTrackingDetectorInterfaceInit()); + // ------------------------------------------------------------------------ + + + // ----- CA tracking QA --------------------------------------------------- + // Kalman Filter (currently needed to access the magnetic filed, to be + // removed soon) + run->AddTask(new CbmKF()); + + // ------------------------------------------------------------------------ + + // TODO: read tracking parameters from the file like CaOutputQa does + //TODO: instead of initializing the tracker + //TString caParFile = recFile; + //caParFile.ReplaceAll(".root", ".L1Parameters.dat"); + //auto* pCaOutputQa = new cbm::ca::OutputQa(verbose, bUseMC); + //pCaOutputQa->ReadParameters(caParFile.Data()); + + // L1 CA track finder setup + auto l1 = new CbmL1("CA"); + l1->SetMcbmMode(); + l1->DisableTrackingStation(cbm::algo::ca::EDetectorID::kMuch, 0); + l1->DisableTrackingStation(cbm::algo::ca::EDetectorID::kMuch, 1); + l1->DisableTrackingStation(cbm::algo::ca::EDetectorID::kMuch, 2); + + // User configuration example for CA: + //l1->SetConfigUser(srcDir + "/macro/L1/configs/ca_params_user_example.yaml"); + run->AddTask(l1); + + // ----- BBA alignment -------------------------------------------- + CbmBbaAlignmentTask* alignemnt = new CbmBbaAlignmentTask(); + //CbmKFTrackQa* alignemnt = new CbmKFTrackQa(); + run->AddTask(alignemnt); + + + // ----- Parameter database -------------------------------------------- + std::cout << std::endl << std::endl; + std::cout << "-I- " << myName << ": Set runtime DB" << std::endl; + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile.Data(), "in"); + rtdb->setFirstInput(parIo1); + if (!parFileList->IsEmpty()) { + FairParAsciiFileIo* parIo2 = new FairParAsciiFileIo(); + parIo2->open(parFileList, "in"); + rtdb->setSecondInput(parIo2); + } + rtdb->print(); + // ------------------------------------------------------------------------ + + // ----- Run initialisation ------------------------------------------- + std::cout << std::endl; + std::cout << "-I- " << myName << ": Initialise run" << std::endl; + run->Init(); + + // ----- Start run ---------------------------------------------------- + std::cout << std::endl << std::endl; + std::cout << "-I- " << myName << ": Starting run" << std::endl; + run->Run(0, nEvents); + // ------------------------------------------------------------------------ + + // ----- Finish ------------------------------------------------------- + timer.Stop(); + + FairMonitor::GetMonitor()->Print(); + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + std::cout << std::endl << std::endl; + std::cout << "Macro finished successfully." << std::endl; + std::cout << "Output file is " << sinkFile << std::endl; + std::cout << "Parameter file is " << parFile << std::endl; + std::cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl; + std::cout << std::endl; + std::cout << " Test passed" << std::endl; + std::cout << " All ok " << std::endl; + // ------------------------------------------------------------------------ + + // ----- Resource monitoring ------------------------------------------ + // Extract the maximal used memory an add is as Dart measurement + // This line is filtered by CTest and the value send to CDash + FairSystemInfo sysInfo; + Float_t maxMemory = sysInfo.GetMaxMemory(); + std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">"; + std::cout << maxMemory; + std::cout << "</DartMeasurement>" << std::endl; + + Float_t cpuUsage = ctime / rtime; + std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">"; + std::cout << cpuUsage; + std::cout << "</DartMeasurement>" << std::endl; + // ------------------------------------------------------------------------ + + // ----- Function needed for CTest runtime dependency ----------------- + RemoveGeoManager(); + // ------------------------------------------------------------------------ +} diff --git a/reco/alignment/CMakeLists.txt b/reco/alignment/CMakeLists.txt index 136aa977142cff387f1bd9f1a92915a6282f32c7..dcd35b5176fefa4f7f65cf5724b08e2b0214cbab 100644 --- a/reco/alignment/CMakeLists.txt +++ b/reco/alignment/CMakeLists.txt @@ -17,6 +17,12 @@ set(PUBLIC_DEPENDENCIES ) set(PRIVATE_DEPENDENCIES + CbmMvdBase + CbmStsBase + CbmMuchBase + CbmTrdBase + CbmTofBase + L1 KF bba::library CbmStsBase diff --git a/reco/alignment/CbmBbaAlignmentTask.cxx b/reco/alignment/CbmBbaAlignmentTask.cxx index c8d17c92621abe2089f6c310db0bb6233984f9f9..02cb14022a225b3063ad55a3448e1f7e815b7ace 100644 --- a/reco/alignment/CbmBbaAlignmentTask.cxx +++ b/reco/alignment/CbmBbaAlignmentTask.cxx @@ -12,7 +12,6 @@ // Cbm Headers ---------------------- #include "CbmBbaAlignmentTask.h" -#include "CbmL1PFFitter.h" // ROOT headers @@ -24,11 +23,21 @@ #include "TRandom.h" // - +#include "CbmCaTimeSliceReader.h" +#include "CbmGlobalTrack.h" +#include "CbmL1.h" +#include "CbmMuchTrack.h" +#include "CbmMuchTrackingInterface.h" #include "CbmMvdHit.h" +#include "CbmMvdTrackingInterface.h" #include "CbmStsHit.h" #include "CbmStsSetup.h" #include "CbmStsTrack.h" +#include "CbmStsTrackingInterface.h" +#include "CbmTofTrack.h" +#include "CbmTofTrackingInterface.h" +#include "CbmTrdTrack.h" +#include "CbmTrdTrackingInterface.h" #include "bba/BBA.h" @@ -36,6 +45,30 @@ #include <iostream> +namespace +{ + using namespace cbm::algo; +} + +void CbmBbaAlignmentTask::TrackContainer::MakeConsistent() +{ + fNmvdHits = 0; + fNstsHits = 0; + fNmuchHits = 0; + fNtrdHits = 0; + fNtofHits = 0; + for (const auto& n : fUnalignedTrack.fNodes) { + switch (n.fSystemId) { + case ECbmModuleId::kMvd: fNmvdHits++; break; + case ECbmModuleId::kSts: fNstsHits++; break; + case ECbmModuleId::kMuch: fNmuchHits++; break; + case ECbmModuleId::kTrd: fNtrdHits++; break; + case ECbmModuleId::kTof: fNtofHits++; break; + default: break; + } + } +} + CbmBbaAlignmentTask::CbmBbaAlignmentTask(const char* name, Int_t iVerbose, TString histoFileName) : FairTask(name, iVerbose) @@ -66,6 +99,9 @@ CbmBbaAlignmentTask::~CbmBbaAlignmentTask() {} InitStatus CbmBbaAlignmentTask::Init() { + + fFitter.Init(); + //Get ROOT Manager FairRootManager* ioman = FairRootManager::Instance(); @@ -74,35 +110,45 @@ InitStatus CbmBbaAlignmentTask::Init() return kERROR; } - // Get hits + // Get global tracks & matches + + if (TrackingMode::kSts != fTrackingMode) { + + fInputGlobalTracks = static_cast<TClonesArray*>(ioman->GetObject("GlobalTrack")); + if (!fInputGlobalTracks) { + LOG(error) << "CbmBbaAlignmentTask::Init: Global track array not found!"; + return kERROR; + } + + fInputGlobalTrackMatches = static_cast<TClonesArray*>(ioman->GetObject("GlobalTrackMatch")); - fInputMvdHits = static_cast<TClonesArray*>(ioman->GetObject("MvdHit")); - fInputStsHits = static_cast<TClonesArray*>(ioman->GetObject("StsHit")); + if (!fInputGlobalTrackMatches) { + LOG(error) << "CbmBbaAlignmentTask::Init: Global track matches array not found!"; + //return kERROR; + } + } - // Get sts tracks fInputStsTracks = static_cast<TClonesArray*>(ioman->GetObject("StsTrack")); if (!fInputStsTracks) { - LOG(error) << "CbmBbaAlignmentTask::Init: Sts track-array not found!"; + LOG(error) << "CbmBbaAlignmentTask::Init: Sts track array not found!"; return kERROR; } - // MC track match + fInputStsTrackMatches = static_cast<TClonesArray*>(ioman->GetObject("StsTrackMatch")); + + if (!fInputStsTrackMatches) { + LOG(error) << "CbmBbaAlignmentTask::Init: Sts track matches array not found!"; + //return kERROR; + } + + // MC tracks fInputMcTracks = static_cast<TClonesArray*>(ioman->GetObject("MCTrack")); if (!fInputMcTracks) { Warning("CbmBbaAlignmentTask::Init", "mc track array not found!"); return kERROR; } - // Track match - fInputStsTrackMatches = static_cast<TClonesArray*>(ioman->GetObject("StsTrackMatch")); - if (fInputStsTrackMatches == 0) { - LOG(error) << "CbmBbaAlignmentTask::Init: track match array not found!"; - return kERROR; - } - fTracks.clear(); - fMvdHits.clear(); - fStsHits.clear(); return kSUCCESS; } @@ -116,106 +162,110 @@ void CbmBbaAlignmentTask::Exec(Option_t* /*opt*/) if (static_cast<int>(fTracks.size()) >= fMaxNtracks) { return; } - // select STS tracks for alignment and store them - - for (int iTr = 0; iTr < fInputStsTracks->GetEntriesFast(); iTr++) { - - if (static_cast<int>(fTracks.size()) >= fMaxNtracks) { break; } - - CbmStsTrack* stsTrack = static_cast<CbmStsTrack*>(fInputStsTracks->At(iTr)); - - if (stsTrack->GetNofStsHits() < 8) continue; - const auto* par = stsTrack->GetParamFirst(); - if (!std::isfinite(par->GetQp())) continue; - if (fabs(par->GetQp()) > 1.) continue; // select tracks with min 1 GeV momentum - - CbmStsTrack track; - - // copy track parameters - - track.SetParamFirst(stsTrack->GetParamFirst()); - track.SetParamLast(stsTrack->GetParamLast()); - track.SetChiSq(stsTrack->GetChiSq()); - track.SetNDF(stsTrack->GetNDF()); - - // copy hits to the local arrays and set the track hit indices correspondingly - - for (int ih = 0; ih < stsTrack->GetNofMvdHits(); ih++) { - assert(fInputMvdHits); - int hitIndex = stsTrack->GetMvdHitIndex(ih); - CbmMvdHit hit = *dynamic_cast<CbmMvdHit*>(fInputMvdHits->At(hitIndex)); - track.AddMvdHit(fMvdHits.size()); - fMvdHits.push_back(hit); + ca::Framework* l1 = CbmL1::Instance()->fpAlgo; + const ca::Parameters& l1Par = l1->GetParameters(); + + static int statGlobalTracks = 0; + statGlobalTracks += fInputGlobalTracks->GetEntriesFast(); + static int statGlobalTracks1 = 0; + static int statGlobalTracks2 = 0; + // select tracks for alignment and store them + if (fTrackingMode == kSts && fInputStsTracks) { + for (int iTr = 0; iTr < fInputStsTracks->GetEntriesFast(); iTr++) { + if (static_cast<int>(fTracks.size()) >= fMaxNtracks) { break; } + const CbmStsTrack* stsTrack = dynamic_cast<CbmStsTrack*>(fInputStsTracks->At(iTr)); + if (!stsTrack) continue; + TrackContainer t; + if (!fFitter.CreateMvdStsTrack(t.fUnalignedTrack, *stsTrack)) continue; + t.MakeConsistent(); + fFitter.FitTrack(t.fUnalignedTrack); + t.fAlignedTrack = t.fUnalignedTrack; + if (t.fNstsHits < l1Par.GetNstationsActive(ca::EDetectorID::kSts)) continue; + const auto& par = t.fUnalignedTrack.fNodes[t.fUnalignedTrack.fFirstHitNode].fTrack; + if (!std::isfinite(par.GetQp()[0])) continue; + if (fabs(par.GetQp()[0]) > 1.) continue; // select tracks with min 1 GeV momentum + fTracks.push_back(t); } - - for (int ih = 0; ih < stsTrack->GetNofStsHits(); ih++) { - assert(fInputStsHits); - int hitIndex = stsTrack->GetStsHitIndex(ih); - CbmStsHit hit = *dynamic_cast<CbmStsHit*>(fInputStsHits->At(hitIndex)); - track.AddStsHit(fStsHits.size()); - fStsHits.push_back(hit); + } + else if (fTrackingMode == kMcbm && fInputGlobalTracks) { + for (int iTr = 0; iTr < fInputGlobalTracks->GetEntriesFast(); iTr++) { + if (static_cast<int>(fTracks.size()) >= fMaxNtracks) { break; } + const CbmGlobalTrack* globalTrack = dynamic_cast<const CbmGlobalTrack*>(fInputGlobalTracks->At(iTr)); + if (!globalTrack) continue; + statGlobalTracks1++; + TrackContainer t; + if (!fFitter.CreateGlobalTrack(t.fUnalignedTrack, *globalTrack)) { + LOG(error) << "BBA: can not create a global track for the fit! "; + exit(0); + continue; + } + statGlobalTracks2++; + t.MakeConsistent(); + fFitter.FitTrack(t.fUnalignedTrack); + t.fAlignedTrack = t.fUnalignedTrack; + //if (t.fNstsHits < 1) continue; + //if (t.fNtrdHits < 2) continue; + fTracks.push_back(t); } + } - fTracks.push_back(track); - - } // tracks + LOG(info) << "Bba: " << fInputGlobalTracks->GetEntriesFast() << " global tracks in event, " << statGlobalTracks + << " global tracks in total, " << fTracks.size() << " tracks selected for alignment"; } + void CbmBbaAlignmentTask::ApplyAlignment(const std::vector<double>& par) { // apply alignment parameters to the hits - for (unsigned int ih = 0; ih < fStsHits.size(); ih++) { - - const CbmStsHit& hitOrig = fStsHits[ih]; - int iStation = CbmStsSetup::Instance()->GetStationNumber(hitOrig.GetAddress()); + for (TrackContainer& t : fTracks) { - assert(iStation >= 0 && iStation < CbmStsSetup::Instance()->GetNofStations()); + for (unsigned int in = 0; in < t.fUnalignedTrack.fNodes.size(); in++) { + CbmKFTrackFitter::FitNode& node = t.fUnalignedTrack.fNodes[in]; + CbmKFTrackFitter::FitNode& nodeAligned = t.fAlignedTrack.fNodes[in]; + int iAlignmentModule = node.fReference1; + if (iAlignmentModule < 0) continue; + assert(nodeAligned.fReference1 == iAlignmentModule); - double dx = par[3 * iStation + 0]; - double dy = par[3 * iStation + 1]; - double dz = par[3 * iStation + 2]; + double dx = par[3 * iAlignmentModule + 0]; + double dy = par[3 * iAlignmentModule + 1]; + double dz = par[3 * iAlignmentModule + 2]; - CbmStsHit& hitAligned = fStsHitsAligned[ih]; - - hitAligned.SetX(hitOrig.GetX() + dx); - hitAligned.SetY(hitOrig.GetY() + dy); - hitAligned.SetZ(hitOrig.GetZ() + dz); + nodeAligned.fMxy.SetX(node.fMxy.X() + ca::fvec(dx)); + nodeAligned.fMxy.SetY(node.fMxy.Y() + ca::fvec(dy)); + nodeAligned.fZ = node.fZ + dz; + } } } + double CbmBbaAlignmentTask::CostFunction(const std::vector<double>& par) { - // apply new parameters to the hits ApplyAlignment(par); - auto newTracks = fTracks; - - CbmL1PFFitter fitter; - fitter.Fit(newTracks, fMvdHits, fStsHitsAligned, fTrackPdg); - - double chi2Total = 0; - long int ndfTotal = 1; + fChi2Total = 0.; + fNdfTotal = 0; - int nGoodTracks = 0; - for (unsigned int iTr = 0; iTr < newTracks.size(); iTr++) { - if (!std::isfinite(newTracks[iTr].GetChiSq())) continue; - if (newTracks[iTr].GetChiSq() < 0.) continue; - if (newTracks[iTr].GetNDF() < 0.) continue; - - nGoodTracks++; - chi2Total += newTracks[iTr].GetChiSq(); - ndfTotal += newTracks[iTr].GetNDF(); + for (auto& t : fTracks) { + fFitter.FitTrack(t.fAlignedTrack); + double chi2 = t.fAlignedTrack.fNodes[t.fAlignedTrack.fFirstHitNode].fTrack.GetChiSq()[0]; + double ndf = t.fAlignedTrack.fNodes[t.fAlignedTrack.fFirstHitNode].fTrack.GetNdf()[0]; + if (!std::isfinite(chi2) || chi2 <= 0. || ndf <= 0.) { + chi2 = 0.; + ndf = 0.; + } + fChi2Total += chi2; + fNdfTotal += (int) ndf; } - double cost = chi2Total / ndfTotal; - LOG(info) << "BBA: cost function: n tracks " << nGoodTracks << ", cost " << cost + double cost = fChi2Total / (fNdfTotal + 1); + LOG(info) << "BBA: cost function: ndf " << fNdfTotal << ", cost " << cost << ", diff to ideal cost: " << cost - fCostIdeal; + + if (fFixedNdf > 0 && fNdfTotal != fFixedNdf) { cost = 1.e30; } return cost; - if (nGoodTracks == static_cast<int>(fTracks.size())) { return cost; } - return 1.e30; } void CbmBbaAlignmentTask::Finish() @@ -226,15 +276,22 @@ void CbmBbaAlignmentTask::Finish() LOG(info) << "BBA: start the alignment procedure with " << fTracks.size() << " tracks ..."; - // init auxiliary arrays + ca::Framework* l1 = CbmL1::Instance()->fpAlgo; - fStsHitsAligned = fStsHits; - fTrackPdg.resize(fTracks.size(), 211); // pion PDG + const ca::Parameters& l1Param = l1->GetParameters(); // init alignmemt module - int nStsStations = CbmStsSetup::Instance()->GetNofStations(); - int nParameters = 3 * nStsStations; // x,yz + int nStations = l1Param.GetNstationsActive(); + + for (auto& t : fTracks) { + for (auto& n : t.fUnalignedTrack.fNodes) { + n.fReference1 = n.fMaterialLayer; // material layer is currently equal to the active tracking station + } + t.fAlignedTrack = t.fUnalignedTrack; + } + + int nParameters = 3 * nStations; // x, y, z std::vector<bba::Parameter> par(nParameters); @@ -249,48 +306,25 @@ void CbmBbaAlignmentTask::Finish() p.SetStep(10.e-4); } - par[3 * (nStsStations - 1) + 0].SetActive(0); // fix the last station - par[3 * (nStsStations - 1) + 1].SetActive(0); - par[3 * (nStsStations - 1) + 2].SetActive(0); - - //par[3 * 1 + 1].SetActive(1); - - par[3 * 0 + 0].SetActive(1); - par[3 * 0 + 1].SetActive(1); - par[3 * 0 + 2].SetActive(1); - - par[3 * 1 + 0].SetActive(1); - par[3 * 1 + 1].SetActive(1); - par[3 * 1 + 2].SetActive(1); - - par[3 * 2 + 0].SetActive(1); - par[3 * 2 + 1].SetActive(1); - par[3 * 2 + 2].SetActive(1); - - par[3 * 3 + 0].SetActive(1); - par[3 * 3 + 1].SetActive(1); - par[3 * 3 + 2].SetActive(1); + par[0].SetActive(0); // fix the first station + par[1].SetActive(0); + par[2].SetActive(0); - par[3 * 4 + 0].SetActive(1); - par[3 * 4 + 1].SetActive(1); - par[3 * 4 + 2].SetActive(1); + par[3 * (nStations - 1) + 0].SetActive(0); // fix the last station + par[3 * (nStations - 1) + 1].SetActive(0); + par[3 * (nStations - 1) + 2].SetActive(0); - par[3 * 5 + 0].SetActive(1); - par[3 * 5 + 1].SetActive(1); - par[3 * 5 + 2].SetActive(1); - - par[3 * 6 + 0].SetActive(1); - par[3 * 6 + 1].SetActive(1); - par[3 * 6 + 2].SetActive(1); - - par[3 * 7 + 0].SetActive(0); - par[3 * 7 + 1].SetActive(0); - par[3 * 7 + 2].SetActive(0); + // set active parameters for other stations + for (int i = 1; i < nStations - 1; i++) { + par[3 * i + 0].SetActive(1); + par[3 * i + 1].SetActive(1); + par[3 * i + 2].SetActive(1); + } gRandom->SetSeed(1); - for (int is = 0; is < nStsStations; is++) { + for (int is = 0; is < nStations; is++) { bba::Parameter& px = par[3 * is + 0]; bba::Parameter& py = par[3 * is + 1]; bba::Parameter& pz = par[3 * is + 2]; @@ -327,33 +361,19 @@ void CbmBbaAlignmentTask::Finish() } { - ApplyAlignment(parMisaligned); - - CbmL1PFFitter fitter; - auto oldTracks = fTracks; - auto newTracks = fTracks; - fitter.Fit(newTracks, fMvdHits, fStsHitsAligned, fTrackPdg); - - double chi2Total = 0; - long int ndfTotal = 1; - - int nGoodTracks = 0; + fCostInitial = CostFunction(parMisaligned); + auto tmpTracks = fTracks; fTracks.clear(); - for (unsigned int iTr = 0; iTr < newTracks.size(); iTr++) { - if (!std::isfinite(newTracks[iTr].GetChiSq())) continue; - if (newTracks[iTr].GetChiSq() < 0.) continue; - if (newTracks[iTr].GetNDF() < 0.) continue; - fTracks.push_back(oldTracks[iTr]); - nGoodTracks++; - chi2Total += newTracks[iTr].GetChiSq(); - ndfTotal += newTracks[iTr].GetNDF(); + for (auto& t : tmpTracks) { + if (t.fAlignedTrack.fNodes[t.fAlignedTrack.fFirstHitNode].fTrack.GetNdf()[0] > 0) { fTracks.push_back(t); } } - - LOG(info) << "Initial nTracks " << nGoodTracks << " chi2/ndf " << chi2Total / ndfTotal; + fFixedNdf = fNdfTotal; } fCostIdeal = CostFunction(parAligned); + + LOG(info) << "Initial nTracks: " << fTracks.size() << " cost " << fCostInitial; LOG(info) << " cost function for the true parameters: " << fCostIdeal; alignment.align(); @@ -361,14 +381,14 @@ void CbmBbaAlignmentTask::Finish() LOG(info) << " cost function for the true parameters: " << fCostIdeal; LOG(info) << " Misaligned parameters: "; - for (int is = 0; is < nStsStations; is++) { + for (int is = 0; is < nStations; is++) { const std::vector<double>& r = parMisaligned; LOG(info) << "Sts station " << is << ": x " << r[3 * is + 0] << " y " << r[3 * is + 1] << " z " << r[3 * is + 2]; } LOG(info) << " Alignment results: "; - for (int is = 0; is < nStsStations; is++) { + for (int is = 0; is < nStations; is++) { const std::vector<double>& r = alignment.getResult(); LOG(info) << "Sts station " << is << ": x " << r[3 * is + 0] << " y " << r[3 * is + 1] << " z " << r[3 * is + 2]; } diff --git a/reco/alignment/CbmBbaAlignmentTask.h b/reco/alignment/CbmBbaAlignmentTask.h index fee87f52dac7da2e4569b341c08803bea9b0217d..02bcc1cab78093c150527a0e01e4db538a1b49f3 100644 --- a/reco/alignment/CbmBbaAlignmentTask.h +++ b/reco/alignment/CbmBbaAlignmentTask.h @@ -12,13 +12,12 @@ #ifndef CbmBbaAlignmentTask_H #define CbmBbaAlignmentTask_H -#include "CbmMvdHit.h" -#include "CbmStsHit.h" -#include "CbmStsTrack.h" + +#include "CbmKFTrackFitter.h" #include "FairTask.h" -#include <TString.h> +#include "TString.h" #include <vector> @@ -29,6 +28,7 @@ class TFile; class TDirectory; class TH1F; + /// /// an example of alignment using BBA package /// @@ -50,35 +50,57 @@ public: void Exec(Option_t* opt); void Finish(); + void SetMcbmTrackingMode() { fTrackingMode = TrackingMode::kMcbm; } + void SetStsTrackingMode() { fTrackingMode = TrackingMode::kSts; } + +public: + enum TrackingMode + { + kSts, + kMcbm + }; + + /// information about a track + /// aligned and unaligned hits are stored in the corresponding CbmKFTrackFitter::Track objects + struct TrackContainer { + + CbmKFTrackFitter::Track fUnalignedTrack; // track before alignment + CbmKFTrackFitter::Track fAlignedTrack; // track after alignment + + int fNmvdHits {0}; // number of MVD hits + int fNstsHits {0}; // number of STS hits + int fNmuchHits {0}; // number of MUCH hits + int fNtrdHits {0}; // number of TRD hits + int fNtofHits {0}; // number of TOF hits + + void MakeConsistent(); + }; + private: const CbmBbaAlignmentTask& operator=(const CbmBbaAlignmentTask&); CbmBbaAlignmentTask(const CbmBbaAlignmentTask&); void WriteHistosCurFile(TObject* obj); - int GetHistoIndex(int pdg); void ApplyAlignment(const std::vector<double>& par); double CostFunction(const std::vector<double>& par); - //input data arrays - TClonesArray* fInputMvdHits {nullptr}; - TClonesArray* fInputStsHits {nullptr}; - TClonesArray* fInputStsTracks {nullptr}; + TrackingMode fTrackingMode = TrackingMode::kMcbm; - TClonesArray* fInputMcTracks {nullptr}; // Mc info for debugging - TClonesArray* fInputStsTrackMatches {nullptr}; // Mc info for debugging + // input data arrays - // collection of selected tracks and hits - std::vector<CbmStsTrack> fTracks; - std::vector<CbmMvdHit> fMvdHits; - std::vector<CbmStsHit> fStsHits; + TClonesArray* fInputGlobalTracks {nullptr}; + TClonesArray* fInputStsTracks {nullptr}; - // temporary array with aligned hits - std::vector<CbmStsHit> fStsHitsAligned; + TClonesArray* fInputMcTracks {nullptr}; // Mc info for debugging + TClonesArray* fInputGlobalTrackMatches {nullptr}; // Mc info for debugging + TClonesArray* fInputStsTrackMatches {nullptr}; // Mc info for debugging - // array with pdg hypothesis for tracks - std::vector<int> fTrackPdg; + CbmKFTrackFitter fFitter; + + // collection of selected tracks and hits + std::vector<TrackContainer> fTracks; //output file with histograms TString fHistoFileName {"CbmBbaAlignmentHisto.root"}; @@ -90,6 +112,11 @@ private: Int_t fMaxNtracks {10000}; double fCostIdeal {1.e10}; + double fCostInitial {0.}; + + double fChi2Total {0.}; + long fNdfTotal {0}; + long fFixedNdf {-1}; //histograms TH1F* hTestHisto {nullptr};