-
Sergei Zharko authoredSergei Zharko authored
L1BaseStationInfo.cxx 22.11 KiB
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Sergey Gorbunov, Sergei Zharko [committer] */
/************************************************************************************************************
* @file L1BaseStationInfo.cxx
* @bried Realization of L1BaseStationInfo class large methods
* @since 18.01.2022
*
* The class is implemented to connect concrete experimental setup (CBM or BMN in CbmL1
* or BmnL1) with general L1Tracking algorithm. Each derived class must contain general
* algorithms sutable for the particular station type.
*
***********************************************************************************************************/
// FairRoot
#include <FairLogger.h>
// L1Algo core
#include "L1Assert.h"
#include "L1BaseStationInfo.h"
#include "L1Constants.h"
#include "L1Def.h"
// C++ STL
#include <iomanip>
#include <sstream>
#include <utility>
//
// CONSTRUCTORS AND DESTRUCTOR
//
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo::L1BaseStationInfo() noexcept
{
LOG(debug) << "L1BaseStationInfo: Default constructor called for " << this << '\n'; // Temporary
}
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo::L1BaseStationInfo(L1DetectorID detectorID, int stationID) noexcept
: fDetectorID(detectorID)
, fStationID(stationID)
{
LOG(debug) << "L1BaseStationInfo: Constructor (detectorID, stationID) called for " << this << '\n'; // Temporary
fInitController.SetFlag(EInitKey::kDetectorID);
fInitController.SetFlag(EInitKey::kStationID);
}
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo::~L1BaseStationInfo() noexcept
{
LOG(debug) << "L1BaseStationInfo: Destructor called for " << this << '\n'; // Temporary
}
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo::L1BaseStationInfo(const L1BaseStationInfo& other) noexcept
: fDetectorID(other.fDetectorID)
, fStationID(other.fStationID)
, fTrackingStatus(other.fTrackingStatus)
, fXmax(other.fXmax)
, fYmax(other.fYmax)
, fZPos(other.fZPos)
, fL1Station(other.fL1Station)
, fThicknessMap(other.fThicknessMap)
, fInitController(other.fInitController)
{
LOG(debug) << "L1BaseStationInfo: Copy constructor called: " << &other << " was copied into " << this;
}
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo::L1BaseStationInfo(L1BaseStationInfo&& other) noexcept
{
LOG(debug) << "L1BaseStationInfo: Move constructor called: " << &other << " was moved into " << this;
this->Swap(other);
}
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo& L1BaseStationInfo::operator=(const L1BaseStationInfo& other) noexcept
{
LOG(debug) << "L1BaseStationInfo: Copy operator= called for " << &other << " was copied into" << this;
if (this != &other) { L1BaseStationInfo(other).Swap(*this); }
return *this;
}
//------------------------------------------------------------------------------------------------------------------------
//
L1BaseStationInfo& L1BaseStationInfo::operator=(L1BaseStationInfo&& other) noexcept
{
LOG(debug) << "L1BaseStationInfo: Move operator= called for " << &other << " was copied into" << this;
if (this != &other) {
L1BaseStationInfo tmp(std::move(other));
this->Swap(tmp);
}
return *this;
}
//
// BASIC METHODS
//
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::Print(int verbosity) const
{
if (verbosity == 0) {
LOG(info) << "L1BaseStationInfo object: {stationID, detectorID, address} = {" << fStationID << ", "
<< static_cast<int>(fDetectorID) << ", " << this << '}';
}
else if (verbosity > 0) {
LOG(info) << "L1BaseStationInfo object: at " << this;
LOG(info) << "\tStation ID: " << fStationID;
LOG(info) << "\tDetector ID: " << static_cast<int>(fDetectorID);
LOG(info) << "\tStation z position: " << fZPos;
LOG(info) << "\tTracking status: " << fTrackingStatus;
fL1Station.Print(verbosity - 1);
LOG(info) << "\tAdditional fields:";
LOG(info) << "\t\tXmax: " << fXmax;
LOG(info) << "\t\tYmax: " << fYmax;
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::Reset()
{
L1BaseStationInfo other;
this->Swap(other);
}
//------------------------------------------------------------------------------------------------------------------------
//
const L1Station& L1BaseStationInfo::GetL1Station() const
{
std::stringstream aStream;
aStream << "L1BaseStationInfo::GetL1Station: attempt to get an L1Staion object from uninitialized L1BaseStation with "
<< "stationID = " << fStationID << " and detectorID = " << static_cast<int>(fDetectorID);
L1MASSERT(0, fInitController.IsFinalized(), aStream.str().c_str());
return fL1Station;
}
//------------------------------------------------------------------------------------------------------------------------
//
const L1Material& L1BaseStationInfo::GetMaterialMap() const
{
if (!fInitController.IsFinalized()) {
LOG(fatal) << "L1BaseStationInfo::GetMaterialMap: attempt of getting the material map object from uninitialized "
"L1BaseStation class (detectorID = "
<< static_cast<int>(fDetectorID) << ", stationID = " << fStationID << ")";
}
if (fManagementFlags[static_cast<int>(EManagementFlag::kThicknessMapMoved)]) {
LOG(fatal) << "L1BaseStationInfo::GetMaterialMap: attempt of getting the material map, which has been moved. The "
"thickness map instance have been "
<< "already took from the L1BaseStationInfo object (detectorID = " << static_cast<int>(fDetectorID)
<< ", stationID = " << fStationID << ")";
}
return fThicknessMap;
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetDetectorID(L1DetectorID inID)
{
if (!fInitController.GetFlag(EInitKey::kDetectorID)) {
fDetectorID = inID;
fInitController.SetFlag(EInitKey::kDetectorID);
}
else {
LOG(warn) << "L1BaseStationInfo::SetDetectorID: Attempt of detector ID redifinition";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetRmax(double inRmax)
{
fL1Station.Rmax = inRmax;
fInitController.SetFlag(EInitKey::kRmax);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetRmin(double inRmin)
{
fL1Station.Rmin = inRmin;
fInitController.SetFlag(EInitKey::kRmin);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetFieldFunction(
const std::function<void(const double (&xyz)[3], double (&B)[3])>& getFieldValue)
{
if (fInitController.GetFlag(EInitKey::kFieldSlice)) {
LOG(warn) << "L1BaseStationInfo::SetFieldSlice: Attempt to redifine field slice for station with detectorID = "
<< static_cast<int>(fDetectorID) << " and stationID = " << fStationID << ". Redifinition ignored";
return;
}
L1MASSERT(0, fInitController.GetFlag(EInitKey::kZ),
"Attempt to set magnetic field slice before setting z position of the station");
L1MASSERT(0, fInitController.GetFlag(EInitKey::kXmax),
"Attempt to set magnetic field slice before Xmax size of the station");
L1MASSERT(0, fInitController.GetFlag(EInitKey::kYmax),
"Attempt to set magnetic field slice before Ymax size of the station");
// TODO: Change names of variables according to convention (S.Zh.)
constexpr int M = L1Constants::size::kMaxFieldApproxPolynomialOrder;
constexpr int N = L1Constants::size::kMaxNFieldApproxCoefficients;
constexpr int D = 3; ///> number of dimensions
// SLE initialization
double A[N][N + D] = {}; // augmented matrix
double dx = (fXmax / N / 2 < 1.) ? fXmax / N / 4. : 1.;
double dy = (fYmax / N / 2 < 1.) ? fYmax / N / 4. : 1.;
for (double x = -fXmax; x <= fXmax; x += dx) {
for (double y = -fYmax; y <= fYmax; y += dy) {
double r = sqrt(fabs(x * x / fXmax / fXmax + y / fYmax * y / fYmax));
if (r > 1.) { continue; }
double p[D] = {x, y, fZPos};
double B[D] = {};
getFieldValue(p, B);
double m[N] = {1};
m[0] = 1;
for (int i = 1; i <= M; ++i) {
int k = (i - 1) * i / 2;
int l = i * (i + 1) / 2;
for (int j = 0; j < i; ++j) {
m[l + j] = x * m[k + j];
}
m[l + i] = y * m[k + i - 1];
}
double w = 1. / (r * r + 1);
for (int i = 0; i < N; ++i) {
// fill the left part of the matrix
for (int j = 0; j < N; ++j) {
A[i][j] += w * m[i] * m[j];
}
// fill the right part of the matrix
for (int j = 0; j < D; ++j) {
A[i][N + j] += w * B[j] * m[i];
}
}
}
}
// SLE solution (Gaussian elimination)
//
for (int kCol = 0; kCol < N - 1; ++kCol) {
for (int jRow = kCol + 1; jRow < N; ++jRow) {
double factor = A[jRow][kCol] / A[kCol][kCol];
for (int iCol = kCol; iCol < N + D; ++iCol) {
A[jRow][iCol] -= factor * A[kCol][iCol];
}
}
}
for (int kCol = N - 1; kCol > 0; --kCol) {
for (int jRow = kCol - 1; jRow >= 0; --jRow) {
double factor = A[jRow][kCol] / A[kCol][kCol];
for (int iCol = kCol; iCol < N + D; ++iCol) {
A[jRow][iCol] -= factor * A[kCol][iCol];
}
}
}
for (int j = 0; j < N; ++j) {
fL1Station.fieldSlice.cx[j] = A[j][N + 0] / A[j][j];
fL1Station.fieldSlice.cy[j] = A[j][N + 1] / A[j][j];
fL1Station.fieldSlice.cz[j] = A[j][N + 2] / A[j][j];
}
fInitController.SetFlag(EInitKey::kFieldSlice);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetFieldStatus(int fieldStatus)
{
fL1Station.fieldStatus = fieldStatus;
fInitController.SetFlag(EInitKey::kFieldStatus);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetFrontBackStripsGeometry(double frontPhi, double frontSigma, double backPhi, double backSigma)
{
//----- Original code from L1Algo -----------------------------------------------------------------------
double cFront = cos(frontPhi);
double sFront = sin(frontPhi);
double cBack = cos(backPhi);
double sBack = sin(backPhi);
// NOTE: Here additional double variables are used to save the precission
fL1Station.frontInfo.cos_phi = cFront;
fL1Station.frontInfo.sin_phi = sFront;
fL1Station.frontInfo.sigma2 = frontSigma * frontSigma;
fL1Station.backInfo.cos_phi = cBack;
fL1Station.backInfo.sin_phi = sBack;
fL1Station.backInfo.sigma2 = backSigma * backSigma;
double det = (fabs(backPhi - frontPhi) < 0.1) ? cos(backPhi - frontPhi) : (cFront * sBack - sFront * cBack);
det *= det;
fL1Station.XYInfo.C00 = (sBack * sBack * frontSigma * frontSigma + sFront * sFront * backSigma * backSigma) / det;
fL1Station.XYInfo.C10 = -(sBack * cBack * frontSigma * frontSigma + sFront * cFront * backSigma * backSigma) / det;
fL1Station.XYInfo.C11 = (cBack * cBack * frontSigma * frontSigma + cFront * cFront * backSigma * backSigma) / det;
fL1Station.xInfo.cos_phi = -sFront / (cFront * sBack - cBack * sFront);
fL1Station.xInfo.sin_phi = sBack / (cFront * sBack - cBack * sFront);
fL1Station.xInfo.sigma2 = fL1Station.XYInfo.C00;
fL1Station.yInfo.cos_phi = cBack / (cBack * sFront - cFront * sBack);
fL1Station.yInfo.sin_phi = -cFront / (cBack * sFront - cFront * sBack);
fL1Station.yInfo.sigma2 = fL1Station.XYInfo.C11;
//-------------------------------------------------------------------------------------------------------
fInitController.SetFlag(EInitKey::kStripsFrontPhi);
fInitController.SetFlag(EInitKey::kStripsFrontSigma);
fInitController.SetFlag(EInitKey::kStripsBackPhi);
fInitController.SetFlag(EInitKey::kStripsBackSigma);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetMaterialSimple(double inThickness, double inRL)
{
//L1MASSERT(0, inRL, "Attempt of entering zero inRL (radiational length) value");
fL1Station.materialInfo.thick = inThickness;
fL1Station.materialInfo.RL = inRL;
fL1Station.materialInfo.RadThick = fL1Station.materialInfo.thick / fL1Station.materialInfo.RL;
fL1Station.materialInfo.logRadThick = log(fL1Station.materialInfo.RadThick);
fInitController.SetFlag(EInitKey::kMaterialInfo);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetMaterialMap(const L1Material& thicknessMap,
const std::function<void(L1Material& thicknessMap)>& correction)
{
if (!fInitController.GetFlag(EInitKey::kThicknessMap)) {
fThicknessMap = thicknessMap;
if (correction) { correction(fThicknessMap); }
fInitController.SetFlag(EInitKey::kThicknessMap);
}
else {
LOG(warn) << "L1BaseStationInfo::SetMaterialMap: attempt to reinitialize the material map";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetMaterialMap(
const L1Material& thicknessMap,
const std::function<void(L1Material& thicknessMap, const L1MaterialInfo& homogenious)>& correction)
{
if (!fInitController.GetFlag(EInitKey::kMaterialInfo)) {
LOG(fatal)
<< "L1BaseStationInfo::SetMaterialMap: It is impossible to setup the station material thickness map with a "
<< "correction, which utilizes information on the average station thickness and radiation length. Please, insure "
"to "
<< "set material info with the L1BaseStationInfo::SetMaterialSimple method before setting the thickness map or "
<< "use correction without the information on average station thickness and radiation length.";
}
if (!fInitController.GetFlag(EInitKey::kThicknessMap)) {
fThicknessMap = thicknessMap;
correction(fThicknessMap, fL1Station.materialInfo);
fInitController.SetFlag(EInitKey::kThicknessMap);
}
else {
LOG(warn) << "L1BaseStationInfo::SetMaterialMap: attempt to reinitialize the material map";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetMaterialMap(L1Material&& thicknessMap,
const std::function<void(L1Material& thicknessMap)>& correction) noexcept
{
if (!fInitController.GetFlag(EInitKey::kThicknessMap)) {
fThicknessMap = std::move(thicknessMap);
if (correction) { correction(fThicknessMap); }
fInitController.SetFlag(EInitKey::kThicknessMap);
}
else {
LOG(warn) << "L1BaseStationInfo::SetMaterialMap: attempt to reinitialize the material map";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetMaterialMap(
L1Material&& thicknessMap,
const std::function<void(L1Material& thicknessMap, const L1MaterialInfo& homogenious)>& correction) noexcept
{
if (!fInitController.GetFlag(EInitKey::kMaterialInfo)) {
LOG(fatal)
<< "L1BaseStationInfo::SetMaterialMap: It is impossible to setup the station material thickness map with a "
<< "correction, which utilizes information on the average station thickness and radiation length. Please, insure "
"to "
<< "set material info with the L1BaseStationInfo::SetMaterialSimple method before setting the thickness map or "
<< "use correction without the information on average station thickness and radiation length.";
}
if (!fInitController.GetFlag(EInitKey::kThicknessMap)) {
fThicknessMap = std::move(thicknessMap);
correction(fThicknessMap, fL1Station.materialInfo);
fInitController.SetFlag(EInitKey::kThicknessMap);
}
else {
LOG(warn) << "L1BaseStationInfo::SetMaterialMap: attempt to reinitialize the material map";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetStationID(int inID)
{
if (!fInitController.GetFlag(EInitKey::kStationID)) {
fStationID = inID;
fInitController.SetFlag(EInitKey::kStationID);
}
else {
LOG(warn) << "L1BaseStationInfo::SetStationID: Attempt of station ID redifinition";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetStationType(int inType)
{
if (!fInitController.GetFlag(EInitKey::kType)) {
fL1Station.type = inType;
fInitController.SetFlag(EInitKey::kType);
}
else {
LOG(warn) << "L1BaseStationInfo::SetStationType: Attempt of station type redifinition";
}
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetXmax(double aSize)
{
fXmax = aSize;
fInitController.SetFlag(EInitKey::kXmax);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetYmax(double aSize)
{
fYmax = aSize;
fInitController.SetFlag(EInitKey::kYmax);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetTimeInfo(int inTimeInfo)
{
fL1Station.timeInfo = inTimeInfo;
fInitController.SetFlag(EInitKey::kTimeInfo);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetTimeResolution(double dt)
{
fL1Station.dt = dt;
fInitController.SetFlag(EInitKey::kTimeResolution);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetTrackingStatus(bool flag)
{
fTrackingStatus = flag;
fInitController.SetFlag(EInitKey::kTrackingStatus);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::SetZ(double inZ)
{
fL1Station.z = inZ; // setting simd vector of single-precision floats, which is passed to high performanced L1Algo
fZPos = inZ; // setting precised value to use in field approximation etc
fInitController.SetFlag(EInitKey::kZ);
}
//------------------------------------------------------------------------------------------------------------------------
//
void L1BaseStationInfo::Swap(L1BaseStationInfo& other) noexcept
{
std::swap(fDetectorID, other.fDetectorID);
std::swap(fStationID, other.fStationID);
std::swap(fTrackingStatus, other.fTrackingStatus);
std::swap(fXmax, other.fXmax);
std::swap(fYmax, other.fYmax);
std::swap(fZPos, other.fZPos);
std::swap(fL1Station, other.fL1Station);
std::swap(fThicknessMap, other.fThicknessMap);
std::swap(fInitController, other.fInitController);
}
//------------------------------------------------------------------------------------------------------------------------
//
L1Material&& L1BaseStationInfo::TakeMaterialMap()
{
if (!fInitController.IsFinalized()) {
LOG(fatal) << "L1BaseStationInfo::GetMaterialMap: attempt of getting the material map object from uninitialized "
"L1BaseStation class (detectorID = "
<< static_cast<int>(fDetectorID) << ", stationID = " << fStationID << ")";
}
if (fManagementFlags[static_cast<int>(EManagementFlag::kThicknessMapMoved)]) {
LOG(fatal) << "L1BaseStationInfo::GetMaterialMap: attempt of taking the material map, which has been moved. The "
"thickness map instance have been "
<< "already took from the L1BaseStationInfo object (detectorID = " << static_cast<int>(fDetectorID)
<< ", stationID = " << fStationID << ")";
}
else {
fManagementFlags[static_cast<int>(EManagementFlag::kThicknessMapMoved)] = true;
}
return std::move(fThicknessMap);
}
//------------------------------------------------------------------------------------------------------------------------
//
std::string L1BaseStationInfo::ToString(int verbosityLevel, int indentLevel) const
{
std::stringstream aStream {};
constexpr char indentChar = '\t';
std::string indent(indentLevel, indentChar);
if (verbosityLevel == 0) {
aStream << indent << "L1BaseStationInfo object: {stationID, detectorID, z, address} = {" << fStationID << ", "
<< static_cast<int>(fDetectorID) << ", " << fZPos << ", " << this << '}';
}
else if (verbosityLevel > 0) {
aStream << indent << "L1BaseStationInfo object: at " << this << '\n';
aStream << indent << indentChar << "Station ID: " << fStationID << '\n';
aStream << indent << indentChar << "Detector ID: " << static_cast<int>(fDetectorID) << '\n';
aStream << indent << indentChar << "L1Station object:" << '\n';
aStream << fL1Station.ToString(verbosityLevel - 1, indentLevel + 1) << '\n';
aStream << indent << indentChar << "Additional fields:\n";
aStream << indent << indentChar << indentChar << "Xmax: " << fXmax << '\n';
aStream << indent << indentChar << indentChar << "Ymax: " << fYmax << '\n';
}
return aStream.str();
}