CbmRoot
Loading...
Searching...
No Matches
CaParameters.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022-2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergey Gorbunov, Sergei Zharko [committer] */
4
9
10#include "CaParameters.h"
11
13
14#include <iomanip>
15
19using cbm::algo::ca::kfutils::CheckSimdVectorEquality;
20
21// ---------------------------------------------------------------------------------------------------------------------
22//
23template<typename DataT>
25{
26 fvGeoToActiveMap.fill(-1); // by default, all stations are inactive, thus all the IDs must be -1
27}
28
29// ---------------------------------------------------------------------------------------------------------------------
30//
31template<typename DataT>
33{
34 LOG(info) << "Consistency test for L1 parameters object... ";
35 /*
36 * Array of active station IDs
37 *
38 * In the array of active station IDs,
39 * (i) sum of elements, which are not equal -1, must be equal the number of stations,
40 * (ii) subsequence of all the elements, which are not equal -1, must be a gapless subset of integer numbers starting with 0
41 */
42
43 auto filterInactiveStationIDs = [](int x) { return x != -1; };
44 int nStationsCheck = std::count_if(fvGeoToActiveMap.cbegin(), fvGeoToActiveMap.cend(), filterInactiveStationIDs);
45 if (nStationsCheck != fNstationsActiveTotal) {
46 std::stringstream msg;
47 msg << "ca::Parameters: invalid object condition: array of active station IDs is not consistent "
48 << "with the total number of stations (" << nStationsCheck << " vs. " << fNstationsActiveTotal << ' '
49 << "expected)";
50 throw std::logic_error(msg.str());
51 }
52
53 // Check, if the subsequence of all the elements, which are not equal -1, must be a gapless subset of integer numbers
54 // starting from 0. If it is, the testValue in the end must be equal the number of non -1 elements
55
56 std::vector<int> idsCheck(
57 nStationsCheck); // temporary vector containing a sequence of active station IDs without -1 elements
58 std::copy_if(fvGeoToActiveMap.cbegin(), fvGeoToActiveMap.cend(), idsCheck.begin(), filterInactiveStationIDs);
59 bool isStationIDsOk = true;
60 for (int id = 0; id < nStationsCheck; ++id) {
61 isStationIDsOk = isStationIDsOk && idsCheck[id] == id;
62 }
63 if (!isStationIDsOk) {
64 std::stringstream msg;
65 msg << "ca::Parameters: invalid object condition: array of active station IDs is not a gapless subset "
66 << "of integer numbers starting from 0:\n\t";
67 for (auto id : fvGeoToActiveMap) {
68 msg << std::setw(3) << std::setfill(' ') << id << ' ';
69 }
70 throw std::logic_error(msg.str());
71 }
72
73 /*
74 * Check magnetic field flags of the stations
75 *
76 * In a current version of tracking there are three configurations possible to be proceeded:
77 * A. All the stations are inside magnetic field
78 * B. There is no magnetic field in a setup
79 * C. All the first stations are inside magnetic field, all the last stations are outside the field
80 * In all the cases the fieldStatus flags should be sorted containing all non-zero elements in the beginning
81 * (representing stations placed into magnetic field) and all zero elements in the end of z-axis.
82 */
83 bool ifFieldStatusFlagsOk = std::is_sorted(fStations.cbegin(), fStations.cbegin() + fNstationsActiveTotal,
84 [&](const ca::Station<DataT>& lhs, const ca::Station<DataT>& rhs) {
85 return bool(lhs.fieldStatus) > bool(rhs.fieldStatus);
86 });
87
88 if (!ifFieldStatusFlagsOk) {
89 std::stringstream msg;
90 msg << "ca::Parameters: invalid object condition: L1 tracking is impossible for a given field configuration:\n";
91 for (int iSt = 0; iSt < fNstationsActiveTotal; ++iSt) {
92 msg << "- station ID: " << iSt << ", field status: " << fStations[iSt].fieldStatus << '\n';
93 }
94 throw std::logic_error(msg.str());
95 }
96
97 /*
98 * Check target position SIMD vector
99 */
100
101 kfutils::CheckSimdVectorEquality(fTargetPos[0], "L1Parameters: target position x");
102 kfutils::CheckSimdVectorEquality(fTargetPos[1], "L1Parameters: target position y");
103 kfutils::CheckSimdVectorEquality(fTargetPos[2], "L1Parameters: target position z");
104
105 /*
106 * Check vertex field region and value objects at primary vertex
107 */
108
109 fVertexFieldValue.CheckConsistency();
110 fVertexFieldRegion.CheckConsistency();
111
112
113 /*
114 * Check if each station object is consistent itself, and if all of them are placed after the target
115 * NOTE: If a station was not set up, it is accounted inconsistent (uninitialized). In the array of stations there are uninitialized
116 * stations possible (with id > NstationsActiveTotal), thus one should NOT run the loop above over all the stations in array
117 * but only until *(fNstationsActive.cend() - 1) (== NstationsActiveTotal).
118 * TODO: Probably, we should introduce methods, which check the consistency of fully initialized objects such as ca::Station,
119 * L1MaterialInfo, etc. (S.Zharko)
120 */
122 for (int iSt = 0; iSt < fNstationsActiveTotal; ++iSt) {
123 fStations[iSt].CheckConsistency();
124 if (kfutils::simd::Cast<DataT, float>(fStations[iSt].fZ, 0) < kfutils::simd::Cast<DataT, float>(fTargetPos[2], 0)) {
125 std::stringstream msg;
126 msg << "ca::Parameters: station with global ID = " << iSt << " is placed before target "
127 << "(z_st = " << kfutils::simd::Cast<DataT, float>(fStations[iSt].fZ, 0)
128 << " [cm] < z_targ = " << kfutils::simd::Cast<DataT, float>(fTargetPos[2], 0) << " [cm])";
129 throw std::logic_error(msg.str());
130 }
131 }
132
133 /*
134 * Check thickness maps
135 * NOTE: If a ca::MaterialMap map was not set up, it is accounted inconsistent (uninitialized). In the array of thickness maps for each
136 * there are uninitialized elements possible (with id > NstationsActiveTotal), thus one should NOT run the loop above over
137 * all the stations in array but only until *(fNstationsActive.cend() - 1) (== NstationsActiveTotal).
138 */
139 // TODO: Provide these checks in the kf::Setup
140 //for (int iSt = 0; iSt < fNstationsActiveTotal; ++iSt) {
141 // fThickMap[iSt].CheckConsistency();
142 //}
143
144 /*
145 * Check equality of station indices in setups:
146 */
147 {
148 if (fActiveSetup.GetNofLayers() != this->GetNstationsActive()) {
149 std::stringstream msg;
150 msg << "ca::Parameters: number of stations in active kf setup (" << fActiveSetup.GetNofLayers()
151 << ") differes from the actual number of active tracking stations (" << GetNstationsActive() << ')';
152 throw std::logic_error(msg.str());
153 }
154
155 if (fGeometrySetup.GetNofLayers() != this->GetNstationsGeometry()) {
156 std::stringstream msg;
157 msg << "ca::Parameters: number of stations in geometry kf setup (" << fGeometrySetup.GetNofLayers()
158 << ") differes from the actual number of geometry tracking stations (" << GetNstationsGeometry() << ')';
159 throw std::logic_error(msg.str());
160 }
161
162 {
163 std::stringstream msg;
164 msg << "ca::Parameters: inconsistency in geometry station indexing in kf-setup and old init:";
165 bool bConsistent = true;
166 for (int iStGeo = 0; iStGeo < GetNstationsGeometry(); ++iStGeo) {
167 auto [detId, locId] = GetStationIndexLocal(iStGeo);
168 auto [detIdSetup, locIdSetup] = fGeometrySetup.GetIndexMap().template GlobalToLocal<EDetectorID>(iStGeo);
169 if (detId != detIdSetup || locId != locIdSetup) {
170 bConsistent = false;
171 }
172 msg << "\n- (old) detId = " << static_cast<int>(detId) << ", locId = " << locId
173 << " ---- (kf) detId = " << static_cast<int>(detIdSetup) << ", locId = " << locIdSetup;
174 }
175 if (!bConsistent) {
176 throw std::logic_error(msg.str());
177 }
178 }
179
180 {
181 std::stringstream msg;
182 msg << "ca::Parameters: inconsistency in active station indexing in kf-setup and old init:";
183 bool bConsistent = true;
184 for (int iStGeo = 0; iStGeo < GetNstationsGeometry(); ++iStGeo) {
185 auto [detId, locId] = GetStationIndexLocal(iStGeo);
186 int iStActive = GetStationIndexActive(locId, detId);
187 if (iStActive < 0) {
188 continue;
189 }
190 auto [detIdSetup, locIdSetup] = fActiveSetup.GetIndexMap().template GlobalToLocal<EDetectorID>(iStActive);
191 if (detId != detIdSetup || locId != locIdSetup) {
192 bConsistent = false;
193 }
194 msg << "\n- (old) detId = " << static_cast<int>(detId) << ", locId = " << locId
195 << " ---- (kf) detId = " << static_cast<int>(detIdSetup) << ", locId = " << locIdSetup;
196 }
197 if (!bConsistent) {
198 throw std::logic_error(msg.str());
199 }
200 }
201 }
202
203
204 /*
205 * Check iterations sequence
206 * 1. Number of iterations should be larger then zero
207 * 2. Each iteration should contain values within predefined limits
208 * 3. Number of iterations with TrackFromTriplets flag turned on no more then 1
209 * 4. If the TrackFromTriplets iteration exists, it should be the last one in the sequence
210 */
211 {
212 int nIterations = fCAIterations.size();
213 if (!nIterations) {
214 std::stringstream msg;
215 msg << "L1Parameters: 0 track finder iterations were found. Please, define at least one iteration";
216 throw std::logic_error(msg.str());
217 }
218
219 std::string names = "";
220 for (const auto& iter : fCAIterations) {
221 if (!iter.Check()) {
222 names += iter.GetName() + " ";
223 }
224 }
225 if (names.size()) {
226 std::stringstream msg;
227 msg << "L1Parameters: some parameters are out of range for the following iterations: " << names;
228 throw std::logic_error(msg.str());
229 }
230
231 nIterations = std::count_if(fCAIterations.begin(), fCAIterations.end(),
232 [=](const Iteration& it) { return it.GetTrackFromTripletsFlag(); });
233 if (nIterations > 1) {
234 std::stringstream msg;
235 msg << "L1Parameters: found " << nIterations << " iterations with GetTrackFromTripletsFlag() == true:\n";
236 for (const auto& iter : fCAIterations) {
237 if (iter.GetTrackFromTripletsFlag()) {
238 msg << '\t' << "- " << iter.GetName() << '\n';
239 }
240 }
241 msg << "Only the one iteration can have GetTrackFromTripletsFlag() == true, and this iteration should be ";
242 msg << "the last one";
243 throw std::logic_error(msg.str());
244 }
245
246 if (nIterations == 1 && !(fCAIterations.end() - 1)->GetTrackFromTripletsFlag()) {
247 std::stringstream msg;
248 msg << "L1Parameters: iteration with GetTrackFromTripletsFlag() == true is not the last in a sequence. ";
249 msg << "The GetTrackFromTripletsFlag() value in the iterations sequence: \n";
250 for (const auto& iter : fCAIterations) {
251 msg << '\t' << "- " << std::setw(15) << std::setfill(' ') << iter.GetName() << ' ';
252 msg << std::setw(6) << std::setfill(' ') << iter.GetTrackFromTripletsFlag() << '\n';
253 }
254 throw std::logic_error(msg.str());
255 }
256 }
257
258 LOG(info) << "Consistency test for L1 parameters object... \033[1;32mpassed\033[0m";
259}
260
261// ---------------------------------------------------------------------------------------------------------------------
262//
263template<typename DataT>
265{
266 int nStations = 0;
267 for (int iStLoc = 0; iStLoc < this->GetNstationsGeometry(detectorID); ++iStLoc) {
268 int iStActive = this->GetStationIndexActive(iStLoc, detectorID);
269 if (iStActive > -1) {
270 ++nStations;
271 }
272 }
273 return nStations;
274}
275
276// ---------------------------------------------------------------------------------------------------------------------
277//
278template<typename DataT>
279void Parameters<DataT>::Print(int /*verbosityLevel*/) const
280{
281 LOG(info) << ToString();
282}
283
284// ---------------------------------------------------------------------------------------------------------------------
285//
286template<typename DataT>
287std::string Parameters<DataT>::ToString(int verbosity, int indentLevel) const
288{
289 using namespace constants;
290 using std::setfill;
291 using std::setw;
292 std::stringstream msg{};
293 if (verbosity < 1) {
294 return msg.str();
295 }
296
297 constexpr char indentCh = '\t';
298 std::string indent(indentLevel, indentCh);
299
301 auto ClrFlg = [&](bool flag) { return (flag ? clrs::GN : clrs::RD); };
302
303 msg << " ----- CA parameters list -----\n";
304 msg << indent << clrs::CLb << "COMPILE TIME CONSTANTS:\n" << clrs::CL;
305 msg << indent << indentCh << "Bits to code one station: " << constants::size::StationBits << '\n';
306 msg << indent << indentCh << "Bits to code one triplet: " << constants::size::TripletBits << '\n';
307 msg << indent << indentCh << "Max number of detectors: " << constants::size::MaxNdetectors << '\n';
308 msg << indent << indentCh << "Max number of stations: " << constants::size::MaxNstations << '\n';
309 msg << indent << indentCh << "Max number of triplets: " << constants::size::MaxNtriplets << '\n';
310 msg << indent << clrs::CLb << "RUNTIME CONSTANTS:\n" << clrs::CL;
311 msg << indent << indentCh << "Random seed: " << fRandomSeed << '\n';
312 msg << indent << indentCh << "Max number of doublets per singlet: " << fMaxDoubletsPerSinglet << '\n';
313 msg << indent << indentCh << "Max number of triplets per doublet: " << fMaxTripletPerDoublets << '\n';
314 msg << indent << indentCh << "Ghost suppression: " << fGhostSuppression << '\n';
315 msg << indent << clrs::CLb << "CA TRACK FINDER ITERATIONS:\n" << clrs::CL;
316 msg << Iteration::ToTableFromVector(fCAIterations);
317 msg << indent << clrs::CLb << "GEOMETRY:\n" << clrs::CL;
318 msg << indent << indentCh << clrs::CLb << "TARGET:\n" << clrs::CL;
319 msg << indent << indentCh << indentCh << "Position:\n";
320 for (int dim = 0; dim < 3 /*nDimensions*/; ++dim) {
321 msg << indent << indentCh << indentCh << indentCh << char(120 + dim) << " = "
322 << kfutils::simd::Cast<DataT, float>(fTargetPos[dim], 0) << " cm\n";
323 }
324 msg << indent << indentCh << clrs::CLb << "FIELD:\n" << clrs::CL;
325 msg << indent << indentCh << indentCh << "Target field:\n";
326 msg << indent << indentCh << indentCh << indentCh
327 << "Bx = " << kfutils::simd::Cast<DataT, float>(fVertexFieldValue.GetBx(), 0) << " Kg\n";
328 msg << indent << indentCh << indentCh << indentCh
329 << "By = " << kfutils::simd::Cast<DataT, float>(fVertexFieldValue.GetBy(), 0) << " Kg\n";
330 msg << indent << indentCh << indentCh << indentCh
331 << "Bz = " << kfutils::simd::Cast<DataT, float>(fVertexFieldValue.GetBz(), 0) << " Kg\n";
332
333
334 msg << indent << indentCh << clrs::CLb << "NUMBER OF STATIONS:\n" << clrs::CL;
335 msg << indent << indentCh << indentCh << "Number of stations (Geometry): ";
336 for (int iDet = 0; iDet < constants::size::MaxNdetectors; ++iDet) {
337 msg << setw(2) << this->GetNstationsGeometry(static_cast<EDetectorID>(iDet)) << ' ';
338 }
339 msg << " | total = " << setw(2) << this->GetNstationsGeometry();
340 msg << '\n';
341 msg << indent << indentCh << indentCh << "Number of stations (Active): ";
342 for (int iDet = 0; iDet < constants::size::MaxNdetectors; ++iDet) {
343 msg << setw(2) << setfill(' ') << this->GetNstationsActive(static_cast<EDetectorID>(iDet)) << ' ';
344 }
345 msg << " | total = " << setw(2) << this->GetNstationsActive();
346 msg << '\n' << indent << indentCh << indentCh << clrs::CL << "Geometry station indices: ";
347 for (int iStGeo = 0; iStGeo < this->GetNstationsGeometry(); ++iStGeo) {
348 bool isActive = fvGeoToActiveMap[iStGeo] != -1;
349 msg << ClrFlg(isActive) << setw(3) << setfill(' ') << iStGeo << ' ';
350 }
351 msg << '\n' << indent << indentCh << indentCh << clrs::CL << "Local station indices: ";
352 for (int iStGeo = 0; iStGeo < this->GetNstationsGeometry(); ++iStGeo) {
353 bool isActive = fvGeoToActiveMap[iStGeo] != -1;
354 msg << ClrFlg(isActive) << setw(3) << setfill(' ') << static_cast<int>(fvGeoToLocalIdMap[iStGeo].second) << ' ';
355 }
356 msg << '\n' << indent << indentCh << indentCh << clrs::CL << "Detector indices: ";
357 for (int iStGeo = 0; iStGeo < this->GetNstationsGeometry(); ++iStGeo) {
358 bool isActive = fvGeoToActiveMap[iStGeo] != -1;
359 msg << ClrFlg(isActive) << setw(3) << setfill(' ') << static_cast<int>(fvGeoToLocalIdMap[iStGeo].first) << ' ';
360 }
361 msg << '\n' << indent << indentCh << indentCh << clrs::CL << "Active station indices: ";
362 for (int iStGeo = 0; iStGeo < this->GetNstationsGeometry(); ++iStGeo) {
363 bool isActive = fvGeoToActiveMap[iStGeo] != -1;
364 msg << ClrFlg(isActive) << setw(3) << setfill(' ') << fvGeoToActiveMap[iStGeo] << ' ';
365 }
366 msg << clrs::CL << '\n';
367
368 msg << indent << indentCh << clrs::CLb << "STATIONS:\n" << clrs::CL;
369 msg << indent << indentCh << setw(9) << "Active ID" << ' ';
370 msg << fStations[0].ToString(1, 0, true) << '\n';
371 for (int iStAct = 0; iStAct < this->GetNstationsActive(); ++iStAct) {
372 msg << indent << indentCh << setw(9) << iStAct << ' ';
373 msg << fStations[iStAct].ToString(verbosity, 0) << '\n';
374 }
375
376 msg << indent << indentCh << clrs::CLb << "MISALIGNMENT TOLERANCES:\n" << clrs::CL;
377 msg << indent << indentCh;
378 msg << setw(9) << "Active ID";
379 msg << setw(9) << "dx[cm]";
380 msg << setw(9) << "dy[cm]";
381 msg << setw(9) << "dt[ns]" << '\n';
382
383 for (int iDet = 0; iDet < constants::size::MaxNdetectors; ++iDet) {
384 for (int iStLocal = 0; iStLocal < this->GetNstationsGeometry(static_cast<EDetectorID>(iDet)); ++iStLocal) {
385 int iStActive = this->GetStationIndexActive(iStLocal, static_cast<EDetectorID>(iDet));
386 if (iStActive < 0) {
387 continue;
388 }
389 msg << indent << indentCh;
390 msg << setw(9) << iStActive;
391 msg << setw(9) << fMisalignmentX[iDet];
392 msg << setw(9) << fMisalignmentY[iDet];
393 msg << setw(9) << fMisalignmentT[iDet] << '\n';
394 }
395 }
396
397 msg << indent << clrs::CLb << "DEV FLAGS:" << clrs::CL << " (for debug only)\n";
398 msg << indent << indentCh << "Hits search area is ignored: " << fDevIsIgnoreHitSearchAreas << '\n';
399 msg << indent << indentCh << "Non-approx. field is used: " << fDevIsMatchDoubletsViaMc << '\n';
400 msg << indent << indentCh << "Doublets matching via MC: " << fDevIsMatchDoubletsViaMc << '\n';
401 msg << indent << indentCh << "Triplets matching via MC: " << fDevIsMatchTripletsViaMc << '\n';
402 msg << indent << indentCh << "Extend tracks with MC matching: " << fDevIsExtendTracksViaMc << '\n';
403 msg << indent << indentCh << "Overlap hits matching via MC: " << fDevIsSuppressOverlapHitsViaMc << '\n';
404 msg << indent << indentCh << "Use hit search windows: " << fDevIsParSearchWUsed << '\n';
405
406 if (fDevIsParSearchWUsed) {
407 msg << indent << "SEARCH WINDOWS:\n";
408 for (int iSt = 1; iSt < fNstationsActiveTotal; ++iSt) {
409 for (int iIter = 0; iIter < (int) fCAIterations.size(); ++iIter) {
410 msg << indent << "- station: " << iSt << ", iteration: " << iIter << '\n';
411 msg << GetSearchWindow(iSt, iIter).ToString() << '\n';
412 }
413 }
414 }
415
416 msg << '\n';
417 return msg.str();
418}
419
420namespace cbm::algo::ca
421{
422 template class Parameters<fvec>;
423 template class Parameters<float>;
424 template class Parameters<double>;
425} // namespace cbm::algo::ca
std::string ToString(ECbmModuleId modId)
Definition CbmDefs.cxx:70
bool first
A set of parameters for the CA Track finder iteration.
static std::string ToTableFromVector(const Vector< Iteration > &vIterations)
Forms a string, representing a table of iterations from the vector of iterations.
A container for all external parameters of the CA tracking algorithm.
std::string ToString(int verbosity=0, int indentLevel=0) const
String representation of the class contents.
int GetNstationsActive() const
Gets total number of active stations.
void Print(int verbosityLevel=0) const
Prints configuration.
void CheckConsistency() const
Class invariant checker.
Parameters()
Default constructor.
constexpr char RD[]
normal red
Definition CaDefs.h:143
constexpr char GN[]
normal green
Definition CaDefs.h:144
constexpr char CLb[]
clear bold
Definition CaDefs.h:133
constexpr char CL[]
clear
Definition CaDefs.h:132
TODO: SZh 8.11.2022: add selection of parameterisation.
Definition CaBranch.h:14
EDetectorID
Enumeration for the tracking detector subsystems in CBM-CA.
Definition CbmDefs.h:176
void CheckSimdVectorEquality(fvec v, const char *name)
Checks, if a SIMD vector horizontally equal TODO: Find this method in the VC!
Definition KfUtils.cxx:29