Skip to content
Snippets Groups Projects
L1InitManager.cxx 20.7 KiB
Newer Older
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Sergey Gorbunov, Sergei Zharko [committer] */

/// \brief Input parameters management class for L1Algo
/// \since 19.01.2022

#include "L1InitManager.h"
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <algorithm>
Sergei Zharko's avatar
Sergei Zharko committed
#include <sstream>
#include "L1Algo.h"
#include "L1Assert.h"
#include "L1ConfigRW.h"
using namespace constants;
// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::AddStation(const L1BaseStationInfo& inStation)
{
  // TODO: SZh 15.08.2023: Replace L1MASSERT with throw logic_error
  L1MASSERT(0, fInitController.GetFlag(EInitKey::kActiveDetectorIDs),
            "Attempt to add a station info before the active detectors set had been initialized");
  // Check, if the detector subsystem for this station is active
  if (fActiveDetectorIDs.find(inStation.GetDetectorID()) != fActiveDetectorIDs.end()) {
    fvStationInfo.push_back(inStation);
// ----------------------------------------------------------------------------------------------------------------------
void L1InitManager::CheckInit()
{
  this->CheckCAIterationsInit();
  this->CheckStationsInfoInit();
// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::ClearSetupInfo()
{
  // Clear stations set and a thickness map
  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 = ca::FieldRegion();
  fParameters.fVertexFieldValue  = ca::FieldValue();
  fInitController.SetFlag(EInitKey::kPrimaryVertexField, false);

  // Clear target position
  fParameters.fTargetPos.fill(L1Utils::kNaN);
  fTargetZ = 0.;
  fInitController.SetFlag(EInitKey::kTargetPos, false);

  // Clear field function
  fFieldFunction = L1FieldFunction_t([](const double(&)[3], double(&)[3]) {});
  fInitController.SetFlag(EInitKey::kFieldFunction, false);

  // Clear other flags
  fParameters.fRandomSeed       = 1;
  fInitController.SetFlag(EInitKey::kRandomSeed, false);
  fInitController.SetFlag(EInitKey::kGhostSuppression, false);

  fParameters.fDevIsIgnoreHitSearchAreas     = false;
  fParameters.fDevIsUseOfOriginalField       = false;
  fParameters.fDevIsMatchDoubletsViaMc       = false;
  fParameters.fDevIsMatchTripletsViaMc       = false;
  fParameters.fDevIsExtendTracksViaMc        = false;
  fParameters.fDevIsSuppressOverlapHitsViaMc = false;
// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::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 L1InitManager::FormParametersContainer()
  // Read configuration files
  LOG(info) << "L1InitManager: reading parameter configuration ...";
  try {
    this->ReadInputConfigs();
    LOG(info) << "L1InitManager: reading parameter configuration ... \033[1;32mdone\033[0m";
  }
  catch (const std::runtime_error& err) {
    LOG(error) << "L1InitManager: reading parameter configuration ... \033[1;31mfail\033[0m. Reason: " << err.what();
    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); });

    LOG(error) << "L1InitManager: Attempt to form parameters container before all necessary fields were initialized"
    return false;
  {  // Form array of stations
    auto destIt = fParameters.fStations.begin();
    for (const auto& station : fvStationInfo) {
      if (!station.GetTrackingStatus()) { continue; }
      *destIt = station.GetL1Station();
      ++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;
    }
  // 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) << "L1InitManager: parameters container consistency check failed. Reason: " << err.what();
    return false;
  }

  return true;
// ----------------------------------------------------------------------------------------------------------------------
//
int L1InitManager::GetNstationsActive() const
{
  LOG_IF(fatal, !fInitController.GetFlag(EInitKey::kStationLayoutInitialized))
    << "L1InitManager: number of active stations cannot be accessed until the station layout is initialized";
  return fParameters.GetNstationsActive();
}

// ----------------------------------------------------------------------------------------------------------------------
//
int L1InitManager::GetNstationsActive(L1DetectorID detectorID) const
{
  LOG_IF(fatal, !fInitController.GetFlag(EInitKey::kStationLayoutInitialized))
    << "L1InitManager: number of active stations cannot be accessed until the station layout is initialized";
  return fParameters.GetNstationsActive(detectorID);
}

// ----------------------------------------------------------------------------------------------------------------------
//
int L1InitManager::GetNstationsGeometry() const
{
  LOG_IF(fatal, !fInitController.GetFlag(EInitKey::kStationLayoutInitialized))
    << "L1InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
  return fParameters.GetNstationsGeometry();
}

// ----------------------------------------------------------------------------------------------------------------------
//
int L1InitManager::GetNstationsGeometry(L1DetectorID detectorID) const
{
  LOG_IF(fatal, !fInitController.GetFlag(EInitKey::kStationLayoutInitialized))
    << "L1InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
  return fParameters.GetNstationsGeometry(detectorID);
}

// ----------------------------------------------------------------------------------------------------------------------
//
std::vector<L1BaseStationInfo>& L1InitManager::GetStationInfo()
{
  LOG_IF(fatal, !fInitController.GetFlag(EInitKey::kStationLayoutInitialized))
    << "L1InitManager: station info container cannot be accessed until the station layout is initialized";
  return fvStationInfo;
}


// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::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()); ++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 L1InitManager::InitTargetField(double zStep)
  if (fInitController.GetFlag(EInitKey::kPrimaryVertexField)) {
    LOG(warn) << "L1InitManager::InitTargetField: attempt to reinitialize the field value and field region "
              << "near target. Ignore";
    return;

  // Check for field function
  L1MASSERT(0, fInitController.GetFlag(EInitKey::kFieldFunction),
            "Attempt to initialize the field value and field region near target before initializing field function");

  // Check for target defined
  L1MASSERT(
    0, fInitController.GetFlag(EInitKey::kTargetPos),
    "Attempt to initialize the field value and field region near target before the target position initialization");

  constexpr int nDimensions {3};
  constexpr int nPointsNodal {3};

  std::array<double, nPointsNodal> inputNodalZ {fTargetZ, fTargetZ + zStep, fTargetZ + 2. * zStep};
  std::array<ca::FieldValue, 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].x = field[0];
    B[idx].y = field[1];
    B[idx].z = 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 L1InitManager::PushBackCAIteration(const Iteration& iteration)
Sergei Zharko's avatar
Sergei Zharko committed
  // TODO: probably some checks must be inserted here (S.Zharko)
  bool control = fInitController.GetFlag(EInitKey::kCAIterationsNumberCrosscheck);
  L1MASSERT(0, control,  //fInitController.GetFlag(EInitKey::kCAIterationsNumberCrosscheck),
Sergei Zharko's avatar
Sergei Zharko committed
            "Attempt to push back a CA track finder iteration before the number of iterations was defined");

  fParameters.fCAIterations.push_back(iteration);
// ---------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::ReadInputConfigs()
{
  L1ConfigRW configRW = L1ConfigRW(this, 4);
  configRW.SetMainConfigPath(fsConfigInputMain);
  configRW.SetUserConfigPath(fsConfigInputUser);
  configRW.Read();
}

// ---------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::ReadParametersObject(const std::string& fileName)
  // clrs::CL  - end colored log
  // clrs::GNb - bold green log
  // clrs::RDb - bold red log

  if (!ifs) {
    LOG(fatal) << "L1InitManager: parameters data file \"" << clrs::GNb << fileName << clrs::CL << "\" was not found";
  }
    ia >> fParameters;
  }
  catch (const std::exception&) {
    LOG(fatal) << "L1InitManager: parameters file \"" << clrs::GNb << fileName << clrs::CL
               << "\" has incorrect data format or was corrupted";
// ---------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::ReadSearchWindows(const std::string& fileName)
{
  // Open input binary file
  std::ifstream ifs(fileName);
  if (!ifs) { LOG(fatal) << "L1InitManager: search window file \"" << fileName << "\" was not found"; }

  try {
    boost::archive::text_iarchive ia(ifs);
    int nPars    = -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) {
      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()) {
      LOG(fatal) << "L1InitManager: some errors occurred while reading search windows: " << errMsg.str();
    }
  }
  catch (const std::exception&) {
    LOG(fatal) << "L1InitManager: search windows file \"" << fileName
               << "\" has incorrect data format or was corrupted";
  }

  fInitController.SetFlag(EInitKey::kSearchWindows, true);
}

// ---------------------------------------------------------------------------------------------------------------------
//
bool L1InitManager::SendParameters(L1Algo* pAlgo)
{
  assert(pAlgo);
  pAlgo->ReceiveParameters(std::move(fParameters));
  LOG(info) << "L1InitManager: parameters object was sent to the tracking algorithm";
  return true;
}

// ---------------------------------------------------------------------------------------------------------------------
//
bool L1InitManager::SendParameters(Parameters& destination)
{
  destination = std::move(fParameters);
  LOG(info) << "L1InitManager: parameters object was sent to an external destination";
// ----------------------------------------------------------------------------------------------------------------------
Sergei Zharko's avatar
Sergei Zharko committed
void L1InitManager::SetActiveDetectorIDs(const L1DetectorIDSet_t& detectorIDs)
  // TODO: To think about redefinition possibilities: should it be allowed or not? (S.Zh.)
  fActiveDetectorIDs = detectorIDs;
  fInitController.SetFlag(EInitKey::kActiveDetectorIDs);
// ----------------------------------------------------------------------------------------------------------------------
void L1InitManager::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 L1InitManager::SetFieldFunction(const L1FieldFunction_t& fieldFunction)
  if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
    fFieldFunction = fieldFunction;
    fInitController.SetFlag(EInitKey::kFieldFunction);
    LOG(warn) << "L1InitManager::SetFieldFunction: attempt to reinitialize the field function. Ignored";
// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::SetGhostSuppression(int ghostSuppression)
{
  if (fInitController.GetFlag(EInitKey::kGhostSuppression)) {
    LOG(warn) << "L1InitManager::SetGhostSuppression: attempt of reinitializating the ghost suppresion flag. Ignore";
    return;
  }
  fParameters.fGhostSuppression = ghostSuppression;
  fInitController.SetFlag(EInitKey::kGhostSuppression);
// ----------------------------------------------------------------------------------------------------------------------
void L1InitManager::SetRandomSeed(unsigned int seed)
  if (fInitController.GetFlag(EInitKey::kRandomSeed)) {
    LOG(warn) << "L1InitManager::SetRandomSeed: attempt of reinitializating the random seed. Ignore";
  fParameters.fRandomSeed = seed;
  fInitController.SetFlag(EInitKey::kRandomSeed);
// ----------------------------------------------------------------------------------------------------------------------
void L1InitManager::SetTargetPosition(double x, double y, double z)
  if (fInitController.GetFlag(EInitKey::kTargetPos)) {
    LOG(warn) << "L1InitManager::SetTargetPosition: attempt to reinitialize the target position. Ignore";
    return;
  }

  fParameters.fTargetPos[0] = x;
  fParameters.fTargetPos[1] = y;
  fParameters.fTargetPos[2] = z;
  /// Set additional field for z component in double precision
  fInitController.SetFlag(EInitKey::kTargetPos);
// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::WriteParametersObject(const std::string& fileName) const
{
  // Open output binary file
  std::ofstream ofs(fileName, std::ios::binary);
  if (!ofs) {
    LOG(error) << "L1InitManager: failed opening file \"" << clrs::GNb << fileName << clrs::CL
               << "\" to write parameters object";
  LOG(info) << "L1InitManager: writing CA parameters object to file \"" << clrs::GNb << fileName << '\"' << clrs::CL;
  // Serialize L1Parameters object and write
  boost::archive::binary_oarchive oa(ofs);
  oa << fParameters;
}

// ----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::CheckCAIterationsInit()
{
  bool ifInitPassed = true;
  if (!fInitController.GetFlag(EInitKey::kCAIterations)) {
    int nIterationsActual   = fParameters.fCAIterations.size();
    int nIterationsExpected = fCAIterationsNumberCrosscheck;
    if (nIterationsActual != nIterationsExpected) {
      LOG(warn) << "L1InitManager::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 L1InitManager::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) { LOG(fatal) << "At least one of the L1BaseStationInfo objects is not finalized"; }

    // (2) Check for maximum allowed number of stations
    if (fParameters.GetNstationsGeometry() > constants::size::MaxNstations) {
      LOG(fatal) << "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";
  fInitController.SetFlag(EInitKey::kStationsInfo, ifInitPassed);

// ---------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::ClearStationLayout()
{
  fParameters.fvFirstGeoId.fill(0);
  fParameters.fvLocalToGeoIdMap.fill(0);
  fParameters.fvGeoToLocalIdMap.fill(std::make_pair(static_cast<L1DetectorID>(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);
}