CbmRoot
Loading...
Searching...
No Matches
CbmStsSetup.cxx
Go to the documentation of this file.
1/* Copyright (C) 2013-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer], Florian Uhlig */
4
9#include "CbmStsSetup.h"
10
11#include "CbmDefs.h" // for kSts
12#include "CbmStsAddress.h" // for GetElementId, kStsSensor, GetAdd...
13#include "CbmStsModule.h" // for CbmStsModule
14#include "CbmStsParSensorCond.h" // for CbmStsParSensorCond
15#include "CbmStsParSetModule.h" // for CbmStsParSetModule
16#include "CbmStsParSetSensor.h" // for CbmStsParSetSensor
17#include "CbmStsParSetSensorCond.h" // for CbmStsParSetSensorCond
18#include "CbmStsSensor.h" // for CbmStsSensor
19#include "CbmStsStation.h" // for CbmStsStation
20
21#include <FairField.h> // for FairField
22#include <FairRun.h> // for FairRun
23#include <Logger.h> // for FairLogger
24
25#include <TCollection.h> // for TIter
26#include <TDirectory.h> // for TDirectory, gDirectory
27#include <TFile.h> // for TFile
28#include <TGeoManager.h> // for TGeoManager, gGeoManager
29#include <TGeoMatrix.h> // for TGeoHMatrix
30#include <TGeoNode.h> // for TGeoNode
31#include <TGeoPhysicalNode.h> // for TGeoPhysicalNode
32#include <TGeoShapeAssembly.h> // for TGeoShapeAssembly
33#include <TGeoVolume.h> // for TGeoVolume
34#include <TGeoVoxelFinder.h> // for TGeoVoxelFinder
35#include <TKey.h> // for TKey
36#include <TList.h> // for TList
37#include <TString.h> // for TString, operator<<, operator+
38#include <TSystem.h> // for TSystem, gSystem
39
40#include <cassert> // for assert
41#include <cstring> // for strcmp
42#include <iomanip> // for setw, __iom_t6
43#include <iostream> // for fstream, string, char_traits
44
45using namespace std;
46
47// ----- Initialisation of static singleton pointer --------------------
49// -------------------------------------------------------------------------
50
51
52// ----- Constructor ---------------------------------------------------
61// -------------------------------------------------------------------------
62
63
64// ----- Create station objects ----------------------------------------
66{
67
68 // For old geometries: the station corresponds to the unit
69 if (fHasStations) {
70 for (Int_t iUnit = 0; iUnit < GetNofDaughters(); iUnit++) {
71 CbmStsElement* unit = GetDaughter(iUnit);
72 // Create one station for each unit
73 Int_t stationId = unit->GetIndex();
74 TString name = Form("STS_S%02i", stationId + 1);
75 TString title = Form("STS Station %i", stationId + 1);
76 CbmStsStation* station = new CbmStsStation(name, title, unit->GetPnode());
77 // Add all ladders of the unit to the station
78 for (Int_t iLadder = 0; iLadder < unit->GetNofDaughters(); iLadder++)
79 station->AddLadder(unit->GetDaughter(iLadder));
80 // Initialise station parameters
81 station->Init();
82 // Add station to station map
83 assert(fStations.find(stationId) == fStations.end());
84 fStations[stationId] = station;
85 } //# units
86 return fStations.size();
87 } //? is old geometry?
88
89
90 // Loop over all ladders. They are associated to a station.
91 for (Int_t iUnit = 0; iUnit < GetNofDaughters(); iUnit++) {
92 CbmStsElement* unit = GetDaughter(iUnit);
93 for (Int_t iLadder = 0; iLadder < unit->GetNofDaughters(); iLadder++) {
94 CbmStsElement* ladder = unit->GetDaughter(iLadder);
95 // This convention must be followed by the STS geometry
96 Int_t nodeNumber = ladder->GetPnode()->GetNode()->GetNumber();
97 Int_t stationId = nodeNumber / 100 - 1;
98 // Get the station from the map. If not there, create it.
99 CbmStsStation* station = nullptr;
100 if (fStations.find(stationId) == fStations.end()) {
101 TString name = Form("STS_S%02i", stationId + 1);
102 TString title = Form("STS Station %i", stationId + 1);
103 station = new CbmStsStation(name, title);
104 fStations[stationId] = station;
105 } //? station not yet in map
106 else
107 station = fStations[stationId];
108
109 // Add ladder to station
110 station->AddLadder(ladder);
111
112 } //# ladders
113 } //# units
114
115 // Initialise the stations
116 auto it = fStations.begin();
117 while (it != fStations.end()) {
118 it->second->Init();
119 it++;
120 } //# stations
121
122 // Check that the station number is set consecutively and that the
123 // stations are ordered w.r.t. position along the beam
124 Bool_t isOk = kTRUE;
125 Double_t zPrevious = -999999;
126 for (UInt_t iStation = 0; iStation < fStations.size(); iStation++) {
127 if (fStations.find(iStation) == fStations.end()) {
128 LOG(error) << GetName() << ": Number of stations is " << fStations.size() << ", but station " << iStation
129 << "is not present!";
130 isOk = kFALSE;
131 } //? station present?
132 if (fStations[iStation]->GetZ() <= zPrevious) {
133 LOG(error) << GetName() << ": Disordered stations. Station " << iStation
134 << " is at z = " << fStations[iStation]->GetZ() << "cm , previous is at z = " << zPrevious << " cm.";
135 isOk = kFALSE;
136 } //? disordered in z
137 } //# stations
138 if (!isOk) LOG(fatal) << GetName() << ": Error in creation of stations.";
139
140 return fStations.size();
141}
142// -------------------------------------------------------------------------
143
144
145// ----- Get an element from the STS setup -----------------------------
147{
148
149 // --- Check for initialisation
150 if (!fAddress) LOG(fatal) << fName << ": not initialised!";
151
152 // --- Catch non-STS addresses
154 LOG(warn) << fName << ": No STS address " << address;
155 return nullptr;
156 }
157
158 // --- Catch illegal level numbers
159 if (level < 0 || level >= kStsNofLevels) {
160 LOG(warn) << fName << ": Illegal level " << level;
161 return nullptr;
162 }
163
164 CbmStsElement* element = this;
165 for (Int_t iLevel = 1; iLevel <= level; iLevel++) {
166 element = element->GetDaughter(CbmStsAddress::GetElementId(address, iLevel));
167 assert(element);
168 }
169
170 return element;
171}
172// -------------------------------------------------------------------------
173
174
175// ----- Get hierarchy level name ---------------------------------------
176const char* CbmStsSetup::GetLevelName(Int_t level) const
177{
178
179 // --- Catch legacy (setup with stations)
180 if (fHasStations && level == kStsUnit) return "station";
181
182 switch (level) {
183 case kStsSystem: return "sts"; break;
184 case kStsUnit: return "unit"; break;
185 case kStsLadder: return "ladder"; break;
186 case kStsHalfLadder: return "halfladder"; break;
187 case kStsModule: return "module"; break;
188 case kStsSensor: return "sensor"; break;
189 case kStsSide: return "side"; break;
190 default: return ""; break;
191 }
192}
193// -------------------------------------------------------------------------
194
195
196// ----- Get the station number from an address ------------------------
198{
199
200 // In old, station-based geometries, the station equals the unit
202
203 // The station is obtained from the ladder
205 assert(ladder);
206 return ladder->GetPnode()->GetNode()->GetNumber() / 100 - 1;
207}
208// -------------------------------------------------------------------------
209
210
211// ----- Initialisation ------------------------------------------------
212Bool_t CbmStsSetup::Init(const char* geoFile)
213{
214
215 // Prevent duplicate initialisation
216 assert(!fIsInitialised);
217
218 LOG(info);
219 LOG(info) << "==========================================================";
220 LOG(info) << "Initialising STS Setup \n";
221
222 // --- Set system address
224
225 // --- If a geometry file was specified, read the geometry from file
226 if (geoFile) ReadGeometry(geoFile);
227
228 // --- Else, read the geometry from TGeoManager
229 else {
230 assert(gGeoManager);
231 ReadGeometry(gGeoManager);
232 }
233
234 // --- Statistics
235 LOG(info) << fName << ": Elements in setup: ";
236 for (Int_t iLevel = 1; iLevel <= kStsSensor; iLevel++) {
237 TString name = GetLevelName(iLevel);
238 name += "s";
239 LOG(info) << " " << setw(12) << name << setw(5) << right << GetNofElements(iLevel);
240 }
241
242 // --- Build the module and sensor maps
243 for (Int_t iUnit = 0; iUnit < GetNofDaughters(); iUnit++) {
244 CbmStsElement* unit = GetDaughter(iUnit);
245 for (Int_t iLad = 0; iLad < unit->GetNofDaughters(); iLad++) {
246 CbmStsElement* ladd = unit->GetDaughter(iLad);
247 for (Int_t iHla = 0; iHla < ladd->GetNofDaughters(); iHla++) {
248 CbmStsElement* hlad = ladd->GetDaughter(iHla);
249 for (Int_t iMod = 0; iMod < hlad->GetNofDaughters(); iMod++) {
250 CbmStsElement* modu = hlad->GetDaughter(iMod);
251 CbmStsModule* module = dynamic_cast<CbmStsModule*>(modu);
252 assert(module);
253 Int_t moduleAddress = module->GetAddress();
254 assert(!fModules.count(moduleAddress));
255 fModules[moduleAddress] = module;
256 fModuleVector.push_back(module);
257 for (Int_t iSens = 0; iSens < modu->GetNofDaughters(); iSens++) {
258 CbmStsElement* sens = modu->GetDaughter(iSens);
259 CbmStsSensor* sensor = dynamic_cast<CbmStsSensor*>(sens);
260 assert(sensor);
261 Int_t sensorAddress = sensor->GetAddress();
262 fSensors[sensorAddress] = sensor;
263 fSensorVector.push_back(sensor);
264 } //# sensors in module
265 } //# modules in half-ladder
266 } //# half-ladders in ladder
267 } //# ladders in unit
268 } //# units in system
269 LOG(info) << "Sensor in map: " << fSensors.size() << " in vector " << fSensorVector.size();
270 assert(fSensors.size() == fSensorVector.size());
271
272 // --- Create station objects
273 Int_t nStations = CreateStations();
274 LOG(info) << GetName() << ": Setup contains " << nStations << " stations objects.";
275 if (fair::Logger::Logging(fair::Severity::debug)) {
276 auto it = fStations.begin();
277 while (it != fStations.end()) {
278 LOG(debug) << " " << it->second->ToString();
279 it++;
280 } //# stations
281 } //? Debug
282
283 // --- Consistency check
285 LOG(fatal) << GetName() << ": inconsistent number of sensors! " << GetNofElements(kStsSensor) << " "
286 << GetNofSensors();
287 if (Int_t(fModules.size()) != GetNofElements(kStsModule))
288 LOG(fatal) << GetName() << ": inconsistent number of modules! " << GetNofElements(kStsModule) << " "
289 << fModules.size();
290
291 LOG(info) << "=========================================================="
292 << "\n";
293 LOG(info);
294
295 fIsInitialised = kTRUE;
296 return kTRUE;
297}
298// -------------------------------------------------------------------------
299
300
301// ----- Singleton instance --------------------------------------------
307// -------------------------------------------------------------------------
308
309
310// ----- Print list of modules -----------------------------------------
312{
313 for (auto it = fModules.begin(); it != fModules.end(); it++)
314 LOG(info) << it->second->ToString();
315}
316// -------------------------------------------------------------------------
317
318
319// ----- Read geometry from TGeoManager --------------------------------
321{
322
323 // --- Catch non-existence of GeoManager
324 assert(geo);
325 LOG(info) << fName << ": Reading geometry from TGeoManager " << geo->GetName();
326
327 // --- Get cave (top node)
328 geo->CdTop();
329 TGeoNode* cave = geo->GetCurrentNode();
330
331 // --- Get top STS node
332 TGeoNode* sts = nullptr;
333 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
334 TString name = cave->GetDaughter(iNode)->GetName();
335 if (name.Contains("STS", TString::kIgnoreCase)) {
336 sts = cave->GetDaughter(iNode);
337 LOG(info) << fName << ": STS top node is " << sts->GetName();
338 break;
339 }
340 }
341 if (!sts) {
342 LOG(error) << fName << ": No top STS node found in geometry!";
343 return kFALSE;
344 }
345
346 // --- Create physical node for STS
347 TString path = cave->GetName();
348 path = path + "/" + sts->GetName();
349 fNode = new TGeoPhysicalNode(path);
350
351 // --- Force BoundingBox recomputation for AssemblyVolumes as they may have been corrupted by alignment
352 // FIXME: will be fixed in FairRoot and/or Root in near future, temp fix in meantime
354 geo->RefreshPhysicalNodes();
355
356 // --- Check for old geometry (with stations) or new geometry (with units)
357 Bool_t hasStation = kFALSE;
358 Bool_t hasUnit = kFALSE;
359 for (Int_t iDaughter = 0; iDaughter < fNode->GetNode()->GetNdaughters(); iDaughter++) {
360 TString dName = fNode->GetNode()->GetDaughter(iDaughter)->GetName();
361 if (dName.Contains("station", TString::kIgnoreCase)) hasStation = kTRUE;
362 if (dName.Contains("unit", TString::kIgnoreCase)) hasUnit = kTRUE;
363 }
364 if (hasUnit && (!hasStation)) fHasStations = kFALSE;
365 else if ((!hasUnit) && hasStation)
366 fHasStations = kTRUE;
367 else if (hasUnit && hasStation)
368 LOG(fatal) << GetName() << ": geometry contains both units and stations!";
369 else
370 LOG(fatal) << GetName() << ": geometry contains neither units nor stations!";
371
372 if (fHasStations) LOG(warn) << GetName() << ": using old geometry (with stations)";
373
374 // --- Recursively initialise daughter elements
376
377 return kTRUE;
378}
379// -------------------------------------------------------------------------
380
382{
383 TIter nextv(geo->GetListOfVolumes());
384 TGeoVolume* vol;
385 while ((vol = dynamic_cast<TGeoVolume*>(nextv()))) {
386 if (vol->IsAssembly()) vol->GetShape()->ComputeBBox();
387 auto finder = vol->GetVoxels();
388 if (finder && finder->NeedRebuild()) {
389 finder->Voxelize();
390 vol->FindOverlaps();
391 }
392 }
393}
394
395// ----- Read geometry from geometry file ------------------------------
397{
398
399 LOG(info) << fName << ": Reading geometry from file " << fileName;
400
401 // Exit if a TGeoManager is already present
402 assert(!gGeoManager);
403
404 TFile* oldFile = gFile;
405 TDirectory* oldDir = gDirectory;
406
407 // --- Open geometry file
408 TFile geoFile(fileName);
409 if (!geoFile.IsOpen()) {
410 LOG(fatal) << GetName() << ": Could not open geometry file " << fileName;
411 gFile = oldFile;
412 gDirectory = oldDir;
413 return kFALSE;
414 }
415
416 // Create a new TGeoManager
417 TGeoManager* stsGeometry = new TGeoManager("StsGeo", "STS stand-alone geometry");
418
419 // --- Get top volume from file
420 TGeoVolume* topVolume = nullptr;
421 TList* keyList = geoFile.GetListOfKeys();
422 TKey* key = nullptr;
423 TIter keyIter(keyList);
424 while ((key = (TKey*) keyIter())) {
425 if (strcmp(key->GetClassName(), "TGeoVolumeAssembly") == 0) {
426 TGeoVolume* volume = (TGeoVolume*) key->ReadObj();
427 if (strcmp(volume->GetName(), "TOP") == 0) {
428 topVolume = volume;
429 break;
430 } //? volume name is "TOP"
431 } //? object class is TGeoVolumeAssembly
432 }
433 if (!topVolume) {
434 LOG(fatal) << GetName() << ": No TOP volume in file!";
435 gFile = oldFile;
436 gDirectory = oldDir;
437 return kFALSE;
438 }
439 stsGeometry->SetTopVolume(topVolume);
440
441 // --- Get cave (top node)
442 stsGeometry->CdTop();
443 TGeoNode* cave = stsGeometry->GetCurrentNode();
444
445 // --- Get top STS node
446 TGeoNode* sts = nullptr;
447 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
448 TString name = cave->GetDaughter(iNode)->GetName();
449 if (name.Contains("STS", TString::kIgnoreCase)) {
450 sts = cave->GetDaughter(iNode);
451 stsGeometry->CdDown(iNode);
452 LOG(info) << fName << ": STS top node is " << sts->GetName();
453 break;
454 }
455 }
456 if (!sts) {
457 LOG(error) << fName << ": No top STS node found in geometry!";
458 gFile = oldFile;
459 gDirectory = oldDir;
460 return kFALSE;
461 }
462
463 // --- Create physical node for STS
464 TString path = cave->GetName();
465 path = path + "/" + sts->GetName();
466 fNode = new TGeoPhysicalNode(path);
467
468 // --- Check for old geometry (with stations) or new geometry (with units)
469 TString dName = fNode->GetNode()->GetDaughter(0)->GetName();
470 if (dName.Contains("station", TString::kIgnoreCase)) fHasStations = kTRUE;
471 else if (dName.Contains("unit", TString::kIgnoreCase))
472 fHasStations = kFALSE;
473 else
474 LOG(fatal) << GetName() << ": unknown geometry type; first level name is " << dName;
475 if (fHasStations) LOG(warn) << GetName() << ": using old geometry (with stations)";
476
477 // --- Recursively initialise daughter elements
479
480 gFile = oldFile;
481 gDirectory = oldDir;
482 return kTRUE;
483}
484// -------------------------------------------------------------------------
485
486
487// ----- Set module parameters from parameter set ----------------------
489{
490 UInt_t nModules = 0;
491 for (auto& moduleIt : fModules) {
492 UInt_t address = moduleIt.first;
493 moduleIt.second->SetParameters(params->GetParModule(address));
494 nModules++;
495 }
496 LOG(info) << GetName() << ": Set parameters for " << nModules << " modules";
497 fIsModuleParsInit = kTRUE;
498 return nModules;
499}
500// -------------------------------------------------------------------------
501
502
503// ----- Set the sensor conditions from the parameter set --------------
505{
506
507 UInt_t nSensors = 0;
508 for (auto& sensorIt : fSensors) {
509 UInt_t address = sensorIt.first;
510 sensorIt.second->SetConditions(&(conds->GetParSensor(address)));
511 nSensors++;
512 }
513 LOG(info) << GetName() << ": Set conditions for " << nSensors << " sensors";
514 fIsSensorCondInit = kTRUE;
515 return nSensors;
516}
517// -------------------------------------------------------------------------
518
519
520// ----- Set the sensor parameters -------------------------------------
522{
523 UInt_t nSensors = 0;
524 for (auto& sensorIt : fSensors) {
525 UInt_t address = sensorIt.first;
526 sensorIt.second->SetParameters(&(parSet->GetParSensor(address)));
527 nSensors++;
528 }
529 LOG(info) << GetName() << ": Set parameters for " << nSensors << " sensors";
530 fIsSensorParsInit = kTRUE;
531 return nSensors;
532}
533// -------------------------------------------------------------------------
534
535
ClassImp(CbmConverterManager)
XPU_D constexpr auto ToIntegralType(T enumerator) -> typename std::underlying_type< T >::type
Converts an element of enum class to its underlying integral type.
Definition CbmDefs.h:33
ECbmModuleId
Enumerator for module Identifiers.
Definition CbmDefs.h:45
@ kSts
Silicon Tracking System.
Definition CbmDefs.h:48
@ kStsModule
@ kStsLadder
@ kStsSystem
@ kStsSide
@ kStsNofLevels
@ kStsHalfLadder
@ kStsSensor
@ kStsUnit
int Int_t
bool Bool_t
Int_t GetAddress() const
TGeoPhysicalNode * fNode
Pointer to geometry.
TGeoPhysicalNode * GetPnode() const
Int_t fAddress
Unique element address.
Int_t GetNofDaughters() const
Int_t GetNofElements(Int_t level) const
Int_t GetIndex() const
virtual void InitDaughters()
CbmStsElement * GetDaughter(Int_t index) const
Class representing an instance of a readout unit in the CBM-STS.
Parameters container for CbmStsParModule.
const CbmStsParModule & GetParModule(UInt_t address)
Get condition parameters of a sensor.
Parameters container for CbmStsParSensorCond.
const CbmStsParSensorCond & GetParSensor(UInt_t address)
Get condition parameters of a sensor.
Parameters container for CbmStsParSensor.
const CbmStsParSensor & GetParSensor(UInt_t address)
Get condition parameters of a sensor.
Class representing an instance of a sensor in the CBM-STS.
Class representing the top level of the STS setup.
Definition CbmStsSetup.h:43
const char * GetLevelName(Int_t level) const
static CbmStsSetup * fgInstance
Static instance of this class.
CbmStsSetup()
Default constructor.
Int_t GetNofSensors() const
Definition CbmStsSetup.h:90
Bool_t fIsSensorCondInit
Sensor conditions set.
Bool_t ReadGeometry(TGeoManager *geoManager)
Read the geometry from TGeoManager.
Bool_t fHasStations
Legacy with stations instead of units.
Bool_t Init(const char *geometryFile=nullptr)
Initialise the setup.
Bool_t fIsSensorParsInit
Sensor parameters set.
CbmStsElement * GetElement(Int_t address, Int_t level)
UInt_t SetSensorConditions(CbmStsParSetSensorCond *conds)
Set sensor conditions from parameter container.
Int_t CreateStations()
Create station objects.
std::map< Int_t, CbmStsSensor * > fSensors
void RecomputePhysicalAssmbBbox(TGeoManager *geo)
static CbmStsSetup * Instance()
std::vector< CbmStsModule * > fModuleVector
Bool_t fIsModuleParsInit
Module parameters set.
UInt_t SetModuleParameters(CbmStsParSetModule *modulePars)
Set module parameters from parameter container.
UInt_t SetSensorParameters(CbmStsParSetSensor *parSet)
Set sensor parameters from parameter container.
std::vector< CbmStsSensor * > fSensorVector
Int_t GetStationNumber(Int_t address)
std::map< Int_t, CbmStsModule * > fModules
Bool_t fIsInitialised
All parameter containers set.
void ListModules() const
std::map< Int_t, CbmStsStation * > fStations
Class representing a station of the StsSystem.
void Init()
Initialise the station parameters.
void AddLadder(CbmStsElement *ladder)
int32_t GetAddress(uint32_t unit=0, uint32_t ladder=0, uint32_t halfladder=0, uint32_t module=0, uint32_t sensor=0, uint32_t side=0, uint32_t version=kCurrentVersion)
Construct address.
ECbmModuleId GetSystemId(int32_t address)
Get system Id (should be ECbmModuleId::kSts)
uint32_t GetElementId(int32_t address, int32_t level)
Get the index of an element.
Hash for CbmL1LinkKey.