BmnRoot 26.10.0-210-gc52d34b0
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
BmnRun9DM.cxx
Go to the documentation of this file.
1/*
2 BM@N alignment routine
3 BM@N experiment at NICA complex, JINR, 2025
4
5 Department: Math & Soft Group of HEP lab
6 Author: Igor Polev, polev@jinr.int
7
8 BmnRun9DM class implementation (out-of-line vtable anchor and geometry)
9
10 The enumeration itself is inline in the header - only the destructor and the
11 geometry loading are kept here, so that the vtable and RTTI are emitted in
12 this translation unit alone instead of once per includer, and the detector
13 configuration headers are not pulled into every includer of the model.
14*/
15
16#include "BmnRun9DM.h"
17
20#include "BmnVSPStationSet.h"
21#include "TGeoSystemOfUnits.h"
22
23#include <algorithm>
24#include <fstream>
25#include <memory>
26#include <sstream>
27#include <string>
28
29/*
30 * The three XML configurations of Run9 (VSP_Run9, SiliconRun9, GemRun9) are
31 * already parsed by the detector classes, and the same files are used by the
32 * hit makers - see config/bmnconf.json. Only the module envelope (the zone
33 * envelope for GEM) is taken from them: pitch, strip angles and dead zones are
34 * not needed here.
35 *
36 * The target is described apart from them, by a FairRoot ASCII geometry file
37 * (geometry/target_CsI.geo). Reading it through FairGeoSet would pull in a
38 * media table and a TGeoManager the alignment builds nowhere else, while the
39 * format is fixed and only a few of its numbers are wanted, so the few lines
40 * below read them directly.
41 */
42Bool_t BmnRun9DM::LoadGeometry(const char* targetGeoFile)
43{
44 constexpr Int_t PERIOD{9}, SETUP{0};
45
46 // The file names the volume, its mother, the shape and the medium, one per
47 // line, then gives a TUBE as the centre of its lower plane, its rmin and
48 // rmax, and the centre of its upper plane, and finally the translation that
49 // places the volume in its mother. The z span goes to the target layer,
50 // unbounded in xy (see BmnDetectorModel::Layer); the tube's xy extent at
51 // the middle of that span is the plane of the target element. Like every
52 // FairGeo ASCII file it gives lengths in millimetres, while the alignment
53 // works in centimetres. Without a file both stay zero.
54 fTarget = {0.0, 0.0};
55 Plane targetPlane{0.0, 0.0, 0.0, 0.0, 0.0};
56 if (nullptr != targetGeoFile) {
57 std::ifstream geo{targetGeoFile};
58 if (!geo) {
59 LOG(error) << " <!> BmnRun9DM : cannot open target geometry " << targetGeoFile;
60 return kFALSE;
61 }
62 std::vector<std::string> fields;
63 for (std::string line; std::getline(geo, line);) {
64 const size_t first{line.find_first_not_of(" \t\r")};
65 if (std::string::npos == first || '/' == line[first])
66 continue; // blank line or comment
67 fields.push_back(line.substr(first, line.find_last_not_of(" \t\r") - first + 1));
68 }
69 if (fields.size() < 8 || "TUBE" != fields[2]) {
70 LOG(error) << " <!> BmnRun9DM : " << targetGeoFile
71 << " is not a TUBE target in FairRoot ASCII geometry format";
72 return kFALSE;
73 }
74 Double_t x{0.0}, y{0.0}, xUpper{0.0}, yUpper{0.0}, rMin{0.0}, rMax{0.0}, xPlacement{0.0}, yPlacement{0.0},
75 zPlacement{0.0};
76 std::istringstream lower{fields[4]}, radii{fields[5]}, upper{fields[6]}, placement{fields[7]};
77 if (!(lower >> x >> y >> fTarget.zStart) || !(radii >> rMin >> rMax)
78 || !(upper >> xUpper >> yUpper >> fTarget.zEnd) || !(placement >> xPlacement >> yPlacement >> zPlacement))
79 {
80 LOG(error) << " <!> BmnRun9DM : cannot read the target tube from " << targetGeoFile;
81 return kFALSE;
82 }
83 fTarget.zStart += zPlacement;
84 fTarget.zEnd += zPlacement;
85 x += xPlacement;
86 y += yPlacement;
87 // conversion into cm
93 targetPlane = {x - rMax, x + rMax, y - rMax, y + rMax, 0.5 * (fTarget.zStart + fTarget.zEnd)};
94 }
95
96 const std::unique_ptr<BmnVSPStationSet> vsp{BmnVSPStationSet ::Create(PERIOD, SETUP)};
97 const std::unique_ptr<BmnSiliconStationSet> sil{BmnSiliconStationSet ::Create(PERIOD, SETUP)};
98 const std::unique_ptr<BmnGemStripStationSet> gem{BmnGemStripStationSet::Create(PERIOD, SETUP)};
99
100 for (Int_t station = 0; station < ALL_STATION_CNT; station++)
101 LOG_IF(warning, 0 == StationModules(station)) << " ! BmnRun9DM : st " << station + STA_NUM_START
102 << " is left out of the model, its hits, if any, are ignored";
103
104 fPlanes.clear();
105 fPlanes.reserve(Alignables());
106
107 // The three station sets share no base class, but name their geometry
108 // getters alike. Indices are checked here because the sets throw or return
109 // a null pointer on an out of range request. A negative zone takes the
110 // whole module.
111 auto append = [this](auto* set, Int_t station, Int_t module, Int_t zone) {
112 if (station < 0 || station >= set->GetNStations())
113 return kFALSE;
114 auto* sta{set->GetStation(station)};
115 if (nullptr == sta || module < 0 || module >= sta->GetNModules())
116 return kFALSE;
117 auto* mod{sta->GetModule(module)};
118 if (nullptr == mod)
119 return kFALSE;
120 Double_t xMin{mod->GetXMinModule()}, xMax{mod->GetXMaxModule()}, yMin{mod->GetYMinModule()},
121 yMax{mod->GetYMaxModule()};
122 if (zone >= 0) {
123 // zone n is the strip layer pair 2n, 2n+1: the rule by which
124 // BmnToCbmHitConverter gives a hit its sector
125 if (2 * zone + 1 >= mod->GetNStripLayers())
126 return kFALSE;
127 auto& lower{mod->GetStripLayer(2 * zone)};
128 auto& upper{mod->GetStripLayer(2 * zone + 1)};
129 xMin = std::min(lower.GetXMinLayer(), upper.GetXMinLayer());
130 xMax = std::max(lower.GetXMaxLayer(), upper.GetXMaxLayer());
131 yMin = std::min(lower.GetYMinLayer(), upper.GetYMinLayer());
132 yMax = std::max(lower.GetYMaxLayer(), upper.GetYMaxLayer());
133 }
134 if (xMax <= xMin || yMax <= yMin)
135 return kFALSE;
136 // the configurations store x mirrored with respect to the hit
137 // coordinates, therefore the bounds are negated and swapped
138 fPlanes.push_back({-xMax, -xMin, yMin, yMax, mod->GetZStartModulePosition() + 0.5 * mod->GetModuleThickness()});
139 return kTRUE;
140 };
141
142 for (Int_t idx = 0; idx < Alignables(); idx++) {
143 const Int_t ID{EncodedID(idx)}, system{ID >> 24}, station{(ID >> 16) & 0xFF}, module{(ID >> 4) & 0xFFF};
144
145 if (TargetID() == ID) {
146 fPlanes.push_back(targetPlane);
147 continue;
148 }
149
150 // A GEM element is one zone of a configuration module: the
151 // BmnToCbmHitConverter sector is 2 * module + 1 + zone.
152 const Bool_t known{
153 VSP_SYSTEM_ID == system ? append(vsp.get(), station - VSP_STATION_IDX[kFirst], module - MOD_NUM_START, -1)
154 : SIL_SYSTEM_ID == system ? append(sil.get(), station - SIL_STATION_IDX[kFirst], module - MOD_NUM_START, -1)
155 : GEM_SYSTEM_ID == system ? append(gem.get(), station - GEM_STATION_IDX[kFirst],
156 (module - MOD_NUM_START) / 2, (module - MOD_NUM_START) % 2)
157 : kFALSE};
158
159 if (!known) {
160 LOG(error) << " <!> BmnRun9DM : no geometry for element " << idx << " (system " << system << ", station "
161 << station << ", module " << module << ")";
162 return kFALSE;
163 }
164 }
165 return kTRUE;
166}
bool Bool_t
int Int_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
Int_t EncodedID(Int_t idx) const
std::vector< Plane > fPlanes
static unique_ptr< BmnGemStripStationSet > Create(Int_t period, Int_t stp=0)
virtual Int_t TargetID() const noexcept override
Definition BmnRun9DM.h:178
static constexpr const Int_t VSP_SYSTEM_ID
Definition BmnRun9DM.h:64
virtual Bool_t LoadGeometry(const char *targetGeoFile) override
Definition BmnRun9DM.cxx:42
static constexpr const Int_t MOD_NUM_START
Definition BmnRun9DM.h:70
static constexpr const Int_t STA_NUM_START
Definition BmnRun9DM.h:69
static constexpr const Int_t GEM_SYSTEM_ID
Definition BmnRun9DM.h:65
static constexpr const Int_t SIL_SYSTEM_ID
Definition BmnRun9DM.h:64
static constexpr const Int_t ALL_STATION_CNT
Definition BmnRun9DM.h:68
Int_t StationModules(Int_t station) const noexcept
Definition BmnRun9DM.h:83
static constexpr const Int_t VSP_STATION_IDX[2]
Definition BmnRun9DM.h:72
static constexpr const Int_t SIL_STATION_IDX[2]
Definition BmnRun9DM.h:73
static constexpr const Int_t GEM_STATION_IDX[2]
Definition BmnRun9DM.h:74
virtual Int_t Alignables() const noexcept override
Definition BmnRun9DM.h:170
static constexpr double millimeter