Newer
Older
/* Copyright (C) 2016-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Sergey Gorbunov, Sergei Zharko [committer] */
/************************************************************************************************************
* @file L1InitManager.cxx
* @bried Input data management class for L1Algo
* @since 19.01.2022
*
***********************************************************************************************************/
#include "L1InitManager.h"
#include <algorithm>
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::AddStation(const L1BaseStationInfo& inStation)
{
// Check if other fields were defined already
// Active detector IDs
if (!fInitFlags[L1InitManager::kEactiveDetectorIDs]) {
LOG(error) << "L1InitManager::AddStation: station initialization called before the active detectors set had been "
"initialized";
assert((fInitFlags[L1InitManager::kEactiveDetectorIDs]));
}
// Number of stations check
if (!fInitFlags[L1InitManager::kEstationsNumberCrosscheck]) {
<< "L1InitManager::AddStation: station initialization called before the numbers of stations for each detector "
<< "had been initialized";
assert((fInitFlags[L1InitManager::kEstationsNumberCrosscheck]));
}
// Field function
if (!fInitFlags[L1InitManager::kEfieldFunction]) {
<< "L1InitManager::AddStation: station initialization called before the magnetic field function was intialized";
assert((fInitFlags[L1InitManager::kEfieldFunction]));
}
// Check activeness of this station type
bool isDetectorActive = fActiveDetectorIDs.find(inStation.GetDetectorID()) != fActiveDetectorIDs.end();
if (isDetectorActive) {
// initialize magnetic field slice
L1BaseStationInfo inStationCopy = L1BaseStationInfo(inStation); // make a copy of station so it can be initialized
inStationCopy.SetFieldSlice(fFieldFunction);
bool isStationInitialized = inStationCopy.IsInitialized();
if (!isStationInitialized) {
LOG(debug) << "L1InitManager::AddStation: station init flags (original)" << inStation.GetInitFlags();
LOG(debug) << "L1InitManager::AddStation: station init flags (copy) " << inStation.GetInitFlags();
LOG(error) << "L1InitManager::AddStation: Trying to add incompletely initialized object with detectorID = "
<< static_cast<int>(inStationCopy.GetDetectorID())
<< " and stationID = " << inStationCopy.GetStationID();
assert((isStationInitialized));
}
// insert the station in a set
auto insertionResult = fStationsInfo.insert(std::move(inStationCopy));
if (!insertionResult.second) {
LOG(error) << "L1InitManager::AddStation: attempt to insert a dublicating L1BaseStationInfo with StationID = "
<< inStation.GetStationID() << " and DetectorID = " << static_cast<int>(inStation.GetDetectorID())
<< ":";
LOG(error) << ">>> Already inserted L1BaseStationInfo object:";
insertionResult.first->Print();
LOG(error) << ">>> A dublicating L1BaseStationInfo object:";
inStation.Print();
assert((insertionResult.second)); // TODO: rewrite the assertion
LOG(debug) << "L1InitManager: adding a station with stationID = " << inStation.GetStationID()
<< " and detectorID = " << static_cast<int>(inStation.GetDetectorID())
<< ". Is active: " << isDetectorActive;
}
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::Init() const
{ // To be implemented
// Plans:
// 1. Must make a final check of the inititalization and turn on a corresponding trigger in L1Algo class to accept
// the incoming data
}
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::PrintStations(int verbosityLevel) const
{
if (verbosityLevel < 1) {
for (auto& station : fStationsInfo) {
LOG(info) << "----------- station: ";
LOG(info) << "\ttype = " << station.GetStationType(); // TMP
LOG(info) << "\tz = " << station.GetZdouble();
}
}
else {
for (auto& station : fStationsInfo) {
station.Print();
}
}
}
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::TransferL1StationArray(std::array<L1Station, L1Parameters::kMaxNstations>& destinationArray)
{
/// First of all, we must check if L1Station was properly initialized
// TODO: actually, false condition will never reached (must thing about it, may be remove assertions from
// CheckStationInfo and leave only warnings and flag)
bool ifStationsInitialized = CheckStationsInfo();
if (!ifStationsInitialized) {
LOG(error) << "L1InitManager::TransferL1StationArray: attempt to pass unitialized L1Station array to L1Algo core";
assert((ifStationsInitialized));
}
/// Check if destinationArraySize is enough for the transfer
int totalStationsNumber = this->GetStationsNumber();
bool ifDestinationArraySizeOk = totalStationsNumber <= static_cast<int>(destinationArray.size());
if (!ifDestinationArraySizeOk) {
LOG(error) << "L1InitManager::TransferL1StationArray: destination array size (" << destinationArray.size()
<< ") is smaller then actual number of active tracking stations (" << totalStationsNumber << ")";
assert((ifDestinationArraySizeOk));
}
auto destinationArrayIterator = destinationArray.begin();
for (const auto& item : fStationsInfo) {
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
*destinationArrayIterator = std::move(item.GetL1Station());
++destinationArrayIterator;
}
LOG(info) << "L1InitManager: L1Station vector was successfully transfered to L1Algo core :)";
}
//
// GETTERS
//
//-----------------------------------------------------------------------------------------------------------------------
//
int L1InitManager::GetStationsNumber(L1DetectorID detectorID) const
{
auto ifDetectorIdDesired = [&detectorID](const L1BaseStationInfo& station) {
return station.GetDetectorID() == detectorID;
};
return std::count_if(fStationsInfo.begin(), fStationsInfo.end(), ifDetectorIdDesired);
}
//
// SETTERS
//
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::SetActiveDetectorIDs(const std::set<L1DetectorID>& detectorIDs)
{
// TODO: To think about redifinition possibilities: should it be allowed or not?
fActiveDetectorIDs = detectorIDs;
fInitFlags[L1InitManager::kEactiveDetectorIDs] = true;
}
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::SetFieldFunction(const std::function<void(const double (&xyz)[3], double (&B)[3])>& fieldFunction)
{
if (!fInitFlags[L1InitManager::kEfieldFunction]) {
fFieldFunction = fieldFunction;
fInitFlags[L1InitManager::kEfieldFunction] = true;
}
else {
LOG(warn) << "L1InitManager::SetFieldFunction: attemt to reinitialize the field function. Ignored";
}
}
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::SetStationsNumberCrosscheck(L1DetectorID detectorID, int nStations)
{
// NOTE: We add and check only those detectors which will be active (?)
// For INACTIVE detectors the initialization code for it inside CbmL1/BmnL1 can (and must) be still in,
// but it will be ignored inside L1InitManager.
if (fActiveDetectorIDs.find(detectorID) != fActiveDetectorIDs.end()) {
fStationsNumberCrosscheck[detectorID] = nStations;
}
// Check if all the station numbers for active detectors are initialized now:
LOG(debug) << "SetStationsNumberCrosscheck called for detectorID = " << static_cast<int>(detectorID);
if (!fInitFlags[L1InitManager::kEstationsNumberCrosscheck]) {
bool ifInitialized = true;
for (auto item : fActiveDetectorIDs) {
if (fStationsNumberCrosscheck.find(item) == fStationsNumberCrosscheck.end()) {
LOG(warn) << "L1InitManager::SetStationsNumberCrosscheck: uninitialized number of stations for detectorID = "
<< static_cast<int>(item);
ifInitialized = false;
break;
}
}
fInitFlags[L1InitManager::kEstationsNumberCrosscheck] = ifInitialized;
}
LOG(debug) << "InitResult: " << fInitFlags[L1InitManager::kEstationsNumberCrosscheck];
}
//-----------------------------------------------------------------------------------------------------------------------
//
void L1InitManager::SetReferencePrimaryVertexPoints(double z0, double z1, double z2)
{
if (fInitFlags[L1InitManager::kEprimaryVertexField]) {
<< "L1InitManager::SetReferencePrimaryVertexPoints: attempt to redefine reference points for field calculation "
<< "near primary vertex. Ignore";
return;
}
// Check for field function
if (!fInitFlags[L1InitManager::kEfieldFunction]) {
<< "L1InitManager::SetReferencePrimaryVertexPoints: attempt to set reference points for field calculation near "
<< "primary vertex before the magnetic field function intialization";
assert((fInitFlags[L1InitManager::kEfieldFunction]));
}
constexpr int numberOfDimensions {3};
constexpr int numberOfReferencePoints {3};
std::array<double, numberOfReferencePoints> inputZ = {z0, z1, z2}; // tmp array to store input assigned with index
std::array<L1FieldValue, numberOfReferencePoints> B = {};
std::array<fvec, numberOfReferencePoints> z = {z0, z1, z2};
for (int idx = 0; idx < numberOfReferencePoints; ++idx) {
double point[numberOfDimensions] = {0., 0., inputZ[idx]};
double field[numberOfDimensions] = {};
fFieldFunction(point, field);
B[idx].x = field[0];
B[idx].y = field[1];
B[idx].z = field[2];
}
fPrimaryVertexFieldRegion.Set(B[0], z[0], B[1], z[1], B[2], z[2]);
fPrimaryVertexFieldValue = B[0];
fInitFlags[L1InitManager::kEprimaryVertexField] = true;
}
//-----------------------------------------------------------------------------------------------------------------------
//
bool L1InitManager::CheckStationsInfo()
{
if (!fInitFlags[L1InitManager::kEstationsInfo]) {
bool ifInitPassed = true;
if (!fInitFlags[L1InitManager::kEifStationNumbersChecked]) {
for (const auto& itemDetector : fActiveDetectorIDs) {
int actualStationsNumber = GetStationsNumber(itemDetector);
int expectedStationsNumber = fStationsNumberCrosscheck.at(itemDetector);
if (actualStationsNumber != expectedStationsNumber) {
LOG(error) << "L1InitManager::CheckStationsInfo: Incorrect number of L1BaseStationInfo objects passed to the "
"L1Manager "
<< "for L1DetectorID = " << static_cast<int>(itemDetector) << ": " << actualStationsNumber
<< " of " << expectedStationsNumber << " expected";
ifInitPassed = false;
}
}
fInitFlags[L1InitManager::kEifStationNumbersChecked] = ifInitPassed;
}
if (!ifInitPassed) {
LOG(error) << "L1InitManager::CheckStationsInfo: initialization failed";
assert((ifInitPassed));
}
// Check for maximum allowed number of stations
int totalStationsNumber = GetStationsNumber();
if (totalStationsNumber > L1Parameters::kMaxNstations) {
LOG(fatal) << "Actual total number of registered stations (" << totalStationsNumber
<< ") is larger then designed one (" << L1Parameters::kMaxNstations
<< "). Please, select another set of active tracking detectors";
// TODO: We have to provide an instruction of how to increase the kMaxNstations number keeping the code consistent
assert((totalStationsNumber <= L1Parameters::kMaxNstations));
}
fInitFlags[L1InitManager::kEstationsInfo] = true;
else {
LOG(warn) << "L1InitManager: L1BaseStationInfo set has already been initialized";
}
// NOTE: we return a flag here to reduce a number of calls outside the funcition. In other hands we keep this flag
// to be consistent with other class fields initialization rules
return fInitFlags[L1InitManager::kEstationsInfo];