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