-
Sergei Zharko authoredSergei Zharko authored
CaInitManager.cxx 22.06 KiB
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Sergey Gorbunov, Sergei Zharko [committer] */
/// \file CaInitManager.cxx
/// \brief Input data management class for the CA tracking algorithm (implementation)
/// \since 19.01.2022
/// \author Sergei Zharko <s.zharko@gsi.de>
#include "CaInitManager.h"
#include "CaConfigReader.h"
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <algorithm>
#include <fstream>
#include <sstream>
using namespace constants;
using cbm::algo::ca::InitManager;
using cbm::algo::ca::MaterialMap;
using cbm::algo::ca::Station;
using cbm::algo::ca::StationInitializer;
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::AddStation(const StationInitializer& inStation)
{
// TODO: SZh 15.08.2023: Replace L1MASSERT with throw logic_error
if (!fInitController.GetFlag(EInitKey::kActiveDetectorIDs)) {
std::stringstream msg;
msg << "ca::InitManager: Attempt to add a station info before the active detectors set had been initialized";
throw std::runtime_error(msg.str());
}
// Check, if the detector subsystem for this station is active
if (fActiveDetectorIDs.find(inStation.GetDetectorID()) != fActiveDetectorIDs.end()) {
fvStationInfo.push_back(inStation);
}
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::CheckInit()
{
this->CheckCAIterationsInit();
this->CheckStationsInfoInit();
fbConfigIsRead = false;
fbGeometryConfigLock = false;
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::ClearSetupInfo()
{
// Clear stations set and a thickness map
fvStationInfo.clear();
fParameters.fThickMap.fill(ca::MaterialMap());
fInitController.SetFlag(EInitKey::kStationsInfo, false);
// Set number of stations do default values
this->ClearStationLayout();
// Clear active detectors
fActiveDetectorIDs.clear();
fInitController.SetFlag(EInitKey::kActiveDetectorIDs, false);
// Clear field info
fParameters.fVertexFieldRegion = kf::FieldRegion<fvec>();
fParameters.fVertexFieldValue = kf::FieldValue<fvec>();
fInitController.SetFlag(EInitKey::kPrimaryVertexField, false);
// Clear target position
fParameters.fTargetPos.fill(Undef<float>);
fTargetZ = 0.;
fInitController.SetFlag(EInitKey::kTargetPos, false);
// Clear field function
fFieldFunction = FieldFunction_t([](const double(&)[3], double(&)[3]) {});
fInitController.SetFlag(EInitKey::kFieldFunction, false);
// Clear other flags
fParameters.fRandomSeed = 1;
fParameters.fGhostSuppression = 0;
fInitController.SetFlag(EInitKey::kRandomSeed, false);
fInitController.SetFlag(EInitKey::kGhostSuppression, false);
fParameters.fMisalignmentX.fill(0.);
fParameters.fMisalignmentY.fill(0.);
fParameters.fMisalignmentT.fill(0.);
fParameters.fDevIsIgnoreHitSearchAreas = false;
fParameters.fDevIsUseOfOriginalField = false;
fParameters.fDevIsMatchDoubletsViaMc = false;
fParameters.fDevIsMatchTripletsViaMc = false;
fParameters.fDevIsExtendTracksViaMc = false;
fParameters.fDevIsSuppressOverlapHitsViaMc = false;
fParameters.fDevIsParSearchWUsed = false;
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::ClearCAIterations()
{
fParameters.fCAIterations.clear();
fCAIterationsNumberCrosscheck = -1;
fInitController.SetFlag(EInitKey::kCAIterations, false);
fInitController.SetFlag(EInitKey::kCAIterationsNumberCrosscheck, false);
}
// ----------------------------------------------------------------------------------------------------------------------
// NOTE: this function should be called once in the SendParameters
bool InitManager::FormParametersContainer()
{
// Read configuration files
this->ReadInputConfigs();
if (!fbConfigIsRead) { // Check config reading status
return false;
}
if (!fParameters.fDevIsParSearchWUsed) {
fInitController.SetFlag(EInitKey::kSearchWindows, true);
}
// Apply magnetic field to the station info objects
std::for_each(fvStationInfo.begin(), fvStationInfo.end(), [&](auto& st) { st.SetFieldFunction(fFieldFunction); });
// Check initialization
this->CheckInit();
if (!fInitController.IsFinalized()) {
LOG(error) << "ca::InitManager: Attempt to form parameters container before all necessary fields were initialized"
<< fInitController.ToString();
return false;
}
{ // Form array of stations
auto destIt = fParameters.fStations.begin();
for (const auto& station : fvStationInfo) {
if (!station.GetTrackingStatus()) {
continue;
}
*destIt = station.GetStation();
++destIt;
}
}
{ // Form array of material map
auto destIt = fParameters.fThickMap.begin();
for (auto& station : fvStationInfo) {
if (!station.GetTrackingStatus()) {
continue;
}
*destIt = std::move(station.TakeMaterialMap());
++destIt;
}
}
// Create an instance for active setup
{
fParameters.fActiveSetup = fParameters.fGeometrySetup;
for (const auto& station : fvStationInfo) {
fParameters.fActiveSetup.DisableLayer(station.GetDetectorID(), station.GetStationID());
}
}
// Check the consistency of the parameters object. If object inconsistent, it throws std::logic_error
try {
fParameters.CheckConsistency();
}
catch (const std::logic_error& err) {
LOG(error) << "ca::InitManager: parameters container consistency check failed. Reason: " << err.what();
return false;
}
return true;
}
// ----------------------------------------------------------------------------------------------------------------------
//
int InitManager::GetNstationsActive() const
{
if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
std::stringstream msg;
msg << "ca::InitManager: number of active stations cannot be accessed until the station layout is initialized";
throw std::runtime_error(msg.str());
}
return fParameters.GetNstationsActive();
}
// ----------------------------------------------------------------------------------------------------------------------
//
int InitManager::GetNstationsActive(EDetectorID detectorID) const
{
if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
std::stringstream msg;
msg << "ca::InitManager: number of active stations cannot be accessed until the station layout is initialized";
throw std::runtime_error(msg.str());
}
return fParameters.GetNstationsActive(detectorID);
}
// ----------------------------------------------------------------------------------------------------------------------
//
int InitManager::GetNstationsGeometry() const
{
if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
std::stringstream msg;
msg << "ca::InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
throw std::runtime_error(msg.str());
}
return fParameters.GetNstationsGeometry();
}
// ----------------------------------------------------------------------------------------------------------------------
//
int InitManager::GetNstationsGeometry(EDetectorID detectorID) const
{
if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
std::stringstream msg;
msg << "ca::InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
throw std::runtime_error(msg.str());
}
return fParameters.GetNstationsGeometry(detectorID);
}
// ----------------------------------------------------------------------------------------------------------------------
//
std::vector<StationInitializer>& InitManager::GetStationInfo()
{
if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
std::stringstream msg;
msg << "ca::InitManager: station info container cannot be accessed until the station layout is initialized";
throw std::runtime_error(msg.str());
}
return fvStationInfo;
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::InitStationLayout()
{
this->ClearStationLayout();
std::sort(fvStationInfo.begin(), fvStationInfo.end());
for (const auto& aStation : fvStationInfo) {
++fParameters.fvFirstGeoId[static_cast<int>(aStation.GetDetectorID()) + 1];
}
for (int iDet = 1; iDet < static_cast<int>(fParameters.fvFirstGeoId.size()) - 1; ++iDet) {
fParameters.fvFirstGeoId[iDet + 1] += fParameters.fvFirstGeoId[iDet];
}
fParameters.fNstationsActiveTotal = 0;
for (int iStGeo = 0; iStGeo < static_cast<int>(fvStationInfo.size()); ++iStGeo) {
const auto& aStation = fvStationInfo[iStGeo];
int iDet = static_cast<int>(aStation.GetDetectorID());
int iStLocal = aStation.GetStationID();
// Fill local -> geo map
fParameters.fvGeoToLocalIdMap[iStGeo] = std::make_pair(aStation.GetDetectorID(), iStLocal);
// Fill geo -> local map
fParameters.fvLocalToGeoIdMap[fParameters.fvFirstGeoId[iDet] + iStLocal] = iStGeo;
// Fill geo <-> active map
int iStActive = aStation.GetTrackingStatus() ? fParameters.fNstationsActiveTotal++ : -1;
fParameters.fvGeoToActiveMap[iStGeo] = iStActive;
if (iStActive > -1) {
fParameters.fvActiveToGeoMap[iStActive] = iStGeo;
}
}
fInitController.SetFlag(EInitKey::kStationLayoutInitialized, true);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::InitTargetField(double zStep)
{
if (fInitController.GetFlag(EInitKey::kPrimaryVertexField)) {
LOG(warn) << "ca::InitManager::InitTargetField: attempt to reinitialize the field value and field region "
<< "near target. Ignore";
return;
}
// Check for field function
if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
std::stringstream msg;
msg << "Attempt to initialize the field value and field region near target before initializing field function";
throw std::runtime_error(msg.str());
}
// Check for target defined
if (!fInitController.GetFlag(EInitKey::kTargetPos)) {
std::stringstream msg;
msg << "Attempt to initialize the field value and field region near target before the target position"
<< "initialization";
throw std::runtime_error(msg.str());
}
constexpr int nDimensions{3};
constexpr int nPointsNodal{3};
std::array<double, nPointsNodal> inputNodalZ{fTargetZ, fTargetZ + zStep, fTargetZ + 2. * zStep};
std::array<kf::FieldValue<fvec>, nPointsNodal> B{};
std::array<fvec, nPointsNodal> z{};
// loop over nodal points
for (int idx = 0; idx < nPointsNodal; ++idx) {
double point[nDimensions]{0., 0., inputNodalZ[idx]};
double field[nDimensions]{};
fFieldFunction(point, field);
z[idx] = inputNodalZ[idx];
B[idx].Set(field[0], field[1], field[2]);
} // loop over nodal points: end
fParameters.fVertexFieldRegion.Set(B[0], z[0], B[1], z[1], B[2], z[2]);
fParameters.fVertexFieldValue = B[0];
fInitController.SetFlag(EInitKey::kPrimaryVertexField);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::PushBackCAIteration(const Iteration& iteration)
{
// TODO: probably some checks must be inserted here (S.Zharko)
if (!fInitController.GetFlag(EInitKey::kCAIterationsNumberCrosscheck)) {
std::stringstream msg;
msg << "Attempt to push back a CA track finder iteration before the number of iterations was defined";
throw std::runtime_error(msg.str());
}
fParameters.fCAIterations.push_back(iteration);
}
// ---------------------------------------------------------------------------------------------------------------------
//
void InitManager::ReadInputConfigs()
{
if (!fbConfigIsRead) {
LOG(info) << "ca::InitManager: reading parameter configuration ...";
try {
auto configReader = ConfigReader(this, 4);
configReader.SetMainConfigPath(fsConfigInputMain);
configReader.SetUserConfigPath(fsConfigInputUser);
configReader.SetGeometryLock(fbGeometryConfigLock);
configReader.Read();
fbConfigIsRead = true;
LOG(info) << "ca::InitManager: reading parameter configuration ... \033[1;32mdone\033[0m";
}
catch (const std::runtime_error& err) {
LOG(error) << "ca::InitManager: reading parameter configuration ... \033[1;31mfail\033[0m. Reason: "
<< err.what();
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
//
void InitManager::ReadParametersObject(const std::string& fileName)
{
// clrs::CL - end colored log
// clrs::GNb - bold green log
// clrs::RDb - bold red log
// Open input binary file
std::ifstream ifs(fileName, std::ios::binary);
if (!ifs) {
std::stringstream msg;
msg << "ca::InitManager: parameters data file \"" << clrs::GNb << fileName << clrs::CL << "\" was not found";
throw std::runtime_error(msg.str());
}
// Get L1InputData object
try {
boost::archive::binary_iarchive ia(ifs);
ia >> fParameters;
fbGeometryConfigLock = true;
}
catch (const std::exception&) {
std::stringstream msg;
msg << "ca::InitManager: parameters file \"" << clrs::GNb << fileName << clrs::CL
<< "\" has incorrect data format or was corrupted";
throw std::runtime_error(msg.str());
}
}
// ---------------------------------------------------------------------------------------------------------------------
//
void InitManager::ReadSearchWindows(const std::string& fileName)
{
// Open input binary file
std::ifstream ifs(fileName);
if (!ifs) {
std::stringstream msg;
msg << "ca::InitManager: search window file \"" << fileName << "\" was not found";
throw std::runtime_error(msg.str());
}
try {
boost::archive::text_iarchive ia(ifs);
int nPars = -1;
int nWindows = -1;
ia >> nPars;
assert(nPars == 1); // Currently only the constant windows are available
ia >> nWindows;
std::stringstream errMsg;
for (int iW = 0; iW < nWindows; ++iW) {
SearchWindow swBuffer;
ia >> swBuffer;
int iStationID = swBuffer.GetStationID();
int iTrackGrID = swBuffer.GetTrackGroupID();
if (iStationID < 0 || iStationID > constants::size::MaxNstations) {
errMsg << "\t- wrong station id for entry " << iW << ": " << iStationID << " (should be between 0 and "
<< constants::size::MaxNstations << ")\n";
}
if (iTrackGrID < 0 || iTrackGrID > constants::size::MaxNtrackGroups) {
errMsg << "\t- wrong track group id for entry " << iW << ": " << iTrackGrID << " (should be between 0 and "
<< constants::size::MaxNtrackGroups << ")\n";
}
fParameters.fSearchWindows[iTrackGrID * constants::size::MaxNstations + iStationID] = swBuffer;
}
if (errMsg.str().size()) {
std::stringstream msg;
msg << "ca::InitManager: some errors occurred while reading search windows: " << errMsg.str();
throw std::runtime_error(msg.str());
}
}
catch (const std::exception& err) {
std::stringstream msg;
msg << "search windows file \"" << fileName << "\" has incorrect data format or was corrupted. ";
msg << "Exception catched: " << err.what();
throw std::runtime_error(msg.str());
}
fInitController.SetFlag(EInitKey::kSearchWindows, true);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::SetActiveDetectorIDs(const DetectorIDSet_t& detectorIDs)
{
// TODO: To think about redefinition possibilities: should it be allowed or not? (S.Zh.)
fActiveDetectorIDs = detectorIDs;
fInitController.SetFlag(EInitKey::kActiveDetectorIDs);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::SetCAIterationsNumberCrosscheck(int nIterations)
{
fCAIterationsNumberCrosscheck = nIterations;
auto& iterationsContainer = fParameters.fCAIterations;
// NOTE: should be called to prevent multiple copies of objects between the memory reallocations
iterationsContainer.reserve(nIterations);
fInitController.SetFlag(EInitKey::kCAIterationsNumberCrosscheck);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::SetFieldFunction(const FieldFunction_t& fieldFunction)
{
if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
fFieldFunction = fieldFunction;
fInitController.SetFlag(EInitKey::kFieldFunction);
}
else {
LOG(warn) << "ca::InitManager::SetFieldFunction: attempt to reinitialize the field function. Ignored";
}
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::SetGhostSuppression(int ghostSuppression)
{
if (fInitController.GetFlag(EInitKey::kGhostSuppression)) {
LOG(warn) << "ca::InitManager::SetGhostSuppression: attempt of reinitializating the ghost suppresion flag. Ignore";
return;
}
fParameters.fGhostSuppression = ghostSuppression;
fInitController.SetFlag(EInitKey::kGhostSuppression);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::SetRandomSeed(unsigned int seed)
{
if (fInitController.GetFlag(EInitKey::kRandomSeed)) {
LOG(warn) << "ca::InitManager::SetRandomSeed: attempt of reinitializating the random seed. Ignore";
return;
}
fParameters.fRandomSeed = seed;
fInitController.SetFlag(EInitKey::kRandomSeed);
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::SetTargetPosition(double x, double y, double z)
{
if (fInitController.GetFlag(EInitKey::kTargetPos)) {
LOG(warn) << "ca::InitManager::SetTargetPosition: attempt to reinitialize the target position. Ignore";
return;
}
/// Fill fvec target fields
fParameters.fTargetPos[0] = x;
fParameters.fTargetPos[1] = y;
fParameters.fTargetPos[2] = z;
/// Set additional field for z component in double precision
fTargetZ = z;
fInitController.SetFlag(EInitKey::kTargetPos);
}
// ----------------------------------------------------------------------------------------------------------------------
//
Parameters<fvec>&& InitManager::TakeParameters() { return std::move(fParameters); }
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::WriteParametersObject(const std::string& fileName) const
{
using clrs::CL;
using clrs::GNb;
// Open output binary file
std::ofstream ofs(fileName, std::ios::binary);
if (!ofs) {
std::stringstream msg;
msg << "ca::InitManager: failed opening file \"" << GNb << fileName << CL << "\" to write parameters object";
throw std::runtime_error(msg.str());
}
LOG(info) << "ca::InitManager: writing CA parameters object to file \"" << GNb << fileName << '\"' << CL;
// Serialize L1Parameters object and write
boost::archive::binary_oarchive oa(ofs);
oa << fParameters;
}
// ----------------------------------------------------------------------------------------------------------------------
//
void InitManager::CheckCAIterationsInit()
{
bool ifInitPassed = true;
if (!fInitController.GetFlag(EInitKey::kCAIterations)) {
int nIterationsActual = fParameters.fCAIterations.size();
int nIterationsExpected = fCAIterationsNumberCrosscheck;
if (nIterationsActual != nIterationsExpected) {
LOG(warn) << "ca::InitManager::CheckCAIterations: incorrect number of iterations registered: "
<< nIterationsActual << " of " << nIterationsExpected << " expected";
ifInitPassed = false;
}
}
fInitController.SetFlag(EInitKey::kCAIterations, ifInitPassed);
}
// ----------------------------------------------------------------------------------------------------------------------
// TODO: REWRITE! and add const qualifier (S.Zharko)
void InitManager::CheckStationsInfoInit()
{
bool ifInitPassed = true;
if (!fInitController.GetFlag(EInitKey::kStationsInfo)) {
// (1) Check the stations themselves
bool bStationsFinalized = std::all_of(fvStationInfo.begin(), fvStationInfo.end(),
[](const auto& st) { return st.GetInitController().IsFinalized(); });
if (!bStationsFinalized) {
std::stringstream msg;
msg << "ca::InitManager: At least one of the StationInitializer objects is not finalized";
}
// (2) Check for maximum allowed number of stations
if (fParameters.GetNstationsGeometry() > constants::size::MaxNstations) {
std::stringstream msg;
msg << "Actual total number of registered stations in geometry (" << fParameters.GetNstationsGeometry()
<< ") is larger then possible (" << constants::size::MaxNstations
<< "). Please, select another set of active tracking detectors or recompile the code with enlarged"
<< " constants::size::MaxNstations value";
throw std::runtime_error(msg.str());
}
}
fInitController.SetFlag(EInitKey::kStationsInfo, ifInitPassed);
}
// ---------------------------------------------------------------------------------------------------------------------
//
void InitManager::ClearStationLayout()
{
fParameters.fvFirstGeoId.fill(0);
fParameters.fvLocalToGeoIdMap.fill(0);
fParameters.fvGeoToLocalIdMap.fill(std::make_pair(static_cast<EDetectorID>(0), -1));
fParameters.fvGeoToActiveMap.fill(-1); // Note: by default all the stations are inactive
fParameters.fvActiveToGeoMap.fill(0);
fParameters.fNstationsActiveTotal = -1;
fInitController.SetFlag(EInitKey::kStationLayoutInitialized, false);
}