CbmRoot
Loading...
Searching...
No Matches
CbmGeometryUtils.cxx
Go to the documentation of this file.
1/* Copyright (C) 2018-2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Florian Uhlig [committer], Eoin Clerkin */
4
5#include "CbmGeometryUtils.h"
6
7#include <FairGeoBuilder.h> // for FairGeoBuilder
8#include <FairGeoInterface.h> // for FairGeoInterface
9#include <FairGeoLoader.h> // for FairGeoLoader
10#include <FairGeoMedia.h> // for FairGeoMedia
11#include <FairModule.h> // for FairModule
12#include <Logger.h> // for LOG, Logger, Severity, Severity::debug
13
14#include <RtypesCore.h> // for Bool_t, Int_t, kTRUE, kFALSE
15#include <TCollection.h> // for TIter
16#include <TDirectory.h> // for gDirectory, TDirectory (ptr only)
17#include <TFile.h> // for TFile, gFile
18#include <TGeoManager.h> // for TGeoManager, gGeoManager
19#include <TGeoMaterial.h> // for TGeoMaterial
20#include <TGeoMatrix.h> // for TGeoMatrix
21#include <TGeoMedium.h> // for TGeoMedium
22#include <TGeoNode.h> // for TGeoNode
23#include <TGeoVolume.h> // for TGeoVolume
24#include <TKey.h> // for TKey
25#include <TList.h> // for TList
26#include <TObjArray.h> // for TObjArray
27#include <TObject.h> // for TObject
28#include <TString.h> // for TString, operator<, operator<<
29#include <TSystem.h> // for gSystem
30
31#include <climits>
32#include <cstring> // for strcmp
33#include <map> // for map
34
35namespace Cbm
36{
37 namespace GeometryUtils
38 {
40 {
41 TList* media = gGeoManager->GetListOfMedia();
42 TIter next1(media);
43 TGeoMedium* med;
44 while ((med = static_cast<TGeoMedium*>(next1()))) {
45 LOG(info) << "Medium " << med->GetName() << " with ID " << med->GetId();
46 }
47 LOG(info) << "****";
48 }
49
51 {
52 TList* material = gGeoManager->GetListOfMaterials();
53 TIter next1(material);
54 TGeoMaterial* mat;
55 while ((mat = static_cast<TGeoMaterial*>(next1()))) {
56 LOG(info) << "Material " << mat->GetName() << " with ID " << mat->GetIndex();
57 }
58 LOG(info) << "****";
59 }
60
61
62 void UniqueId()
63 {
64 /* Uniqueness is not strictly true but should be in practice.
65 The names are converted to Int_t with 2 billion positives followed by same negative
66 after overflow. If each ascii character were uniquely converted guarantee uniqueness to the
67 first 4 characters (256^4). I account for all characters in the name, allow overflow,
68 uppercase and lowercase treated same. I treat all special characters the same.
69
70 Very unlikely names like "Rich_C02_gas+" would have same id as "rich-CO3-Gas-" which
71 could throw up errors in future.
72 */
73
74 TList* media = gGeoManager->GetListOfMedia();
75
76 TGeoMedium* med;
77 TGeoMaterial* mat;
78
79 Int_t base = 27; // 26 alphabet plus 1 for all special characters
80 Int_t j = 0;
81 while (j < media->GetSize()) { // cycle through med but mat name sets id
82
83 med = (TGeoMedium*) media->At(j);
84 mat = med->GetMaterial();
85
86 Int_t UniqueID = 0; // INT_MAX 2147483647 overflow to negative ID not so undesireable.
87
88 for (size_t i = 0; i < strlen(mat->GetName()); ++i) {
89 if (mat->GetName()[i] >= 'A' && mat->GetName()[i] <= 'Z') {
90 UniqueID +=
91 ((Int_t) pow((double) base, (double) i) % INT_MAX) * ((Int_t) mat->GetName()[i] - 'B'); // So A=1
92 }
93 else if (med->GetMaterial()->GetName()[i] >= 'a' && mat->GetName()[i] <= 'z') {
94 UniqueID +=
95 ((Int_t) pow((double) base, (double) i) % INT_MAX) * ((Int_t) mat->GetName()[i] - 'b'); // so a=1
96 }
97 else {
98 UniqueID +=
99 ((Int_t) pow((double) base, (double) i + 1) % INT_MAX) * ((Int_t) mat->GetName()[i]); // i+1 equiv +base
100 };
101 }
102
103 med->SetId((UniqueID > 0) ? UniqueID : -1 * UniqueID);
104 mat->SetIndex((UniqueID > 0) ? UniqueID : -1 * UniqueID); // ? negative number caused issue for mat but not med
105
106 LOG(debug) << "Reset ID number of Medium " << med->GetName() << " to " << med->GetId();
107 LOG(debug) << "Reset ID number of Material " << mat->GetName() << " to " << mat->GetIndex();
108
109 j++;
110 }
111 }
112
113
115 {
116 // Revove duplicate materials
117 TList* materials = gGeoManager->GetListOfMaterials();
118 TIter next(materials);
119 // map for existing materials
120 std::map<TString, Bool_t> mapMatName;
121 TGeoMaterial* mat;
122 while ((mat = static_cast<TGeoMaterial*>(next()))) {
123 // If material exist - delete dublicated. If not - set the flag
124 if (mapMatName[mat->GetName()]) {
125 LOG(debug) << "Removing duplicate material " << mat->GetName();
126 materials->Remove(mat);
127 }
128 else {
129 mapMatName[mat->GetName()] = kTRUE;
130 }
131 }
132 }
133
135 {
136 // Revove duplicate media
137 TList* media = gGeoManager->GetListOfMedia();
138 TIter next(media);
139 // map for existing materials
140 std::map<TString, Bool_t> mapMedName;
141 TGeoMedium* med;
142 while ((med = static_cast<TGeoMedium*>(next()))) {
143 // If medium exist - delete duplicated. If not - set the flag
144 if (mapMedName[med->GetName()]) {
145 LOG(debug) << "Removing duplicate medium " << med->GetName();
146 media->Remove(med);
147 }
148 else {
149 mapMedName[med->GetName()] = kTRUE;
150 }
151 }
152 }
153
155 {
156 // Initialise pointer to GeoBuilder
157 FairGeoBuilder* geoBuilder = FairGeoLoader::Instance()->getGeoBuilder();
158 // Get list of TGeo media
159 TList* media = gGeoManager->GetListOfMedia();
160
161 gGeoManager->GetListOfMedia()->Print();
162
163 // Loop over new media which are not in GeoBase and shift the ID
164 TGeoMedium* med;
165 for (Int_t i = geoBuilder->GetNMedia(); i < media->GetEntries(); i++) {
166 med = static_cast<TGeoMedium*>(media->At(i));
167 med->SetId(i + 1);
168 }
169 // Change GeoBase medium index
170 geoBuilder->SetNMedia(media->GetEntries());
171
174
175 media = gGeoManager->GetListOfMedia();
176 TIter next3(media);
177 while ((med = static_cast<TGeoMedium*>(next3()))) {
178 TGeoMaterial* mat = med->GetMaterial();
179 if (mat) {
180 // mat->Print();
181 }
182 else {
183 LOG(info) << "No Material found for medium " << med->GetName();
184 }
185 }
186 gGeoManager->SetAllIndex();
187 }
188
189 Bool_t IsNewGeometryFile(TString& filename)
190 {
191 TString tempString {""};
192 TGeoMatrix* tempMatrix {nullptr};
193 return IsNewGeometryFile(filename, tempString, &tempMatrix);
194 }
195
196 void ImportRootGeometry(TString& filename, FairModule* mod, TGeoMatrix* mat)
197 {
198
199 TString fVolumeName {""};
200 TGeoMatrix* tempMatrix {nullptr};
201
202 IsNewGeometryFile(filename, fVolumeName, &tempMatrix);
203
204 TGeoVolume* module1 = TGeoVolume::Import(filename, fVolumeName.Data());
205
206 if (fair::Logger::Logging(fair::Severity::debug)) {
207 LOG(debug) << "Information about imported volume:";
208 module1->Print();
209 LOG(debug);
210 LOG(debug) << "Information about imported transformation matrix:";
211 tempMatrix->Print();
212 if (mat) {
213 LOG(debug) << "There is a transformation matrix passed "
214 << "from the module class which overwrites "
215 << "the imported matrix.";
216 LOG(debug);
217 LOG(debug) << "Information about passed transformation matrix:";
218 mat->Print();
219 }
220 }
221
222
226
227
228 if (mat) { gGeoManager->GetTopVolume()->AddNode(module1, 0, mat); }
229 else {
230 gGeoManager->GetTopVolume()->AddNode(module1, 0, tempMatrix);
231 }
232
234 gGeoManager->SetAllIndex();
235 }
236
237 Bool_t IsNewGeometryFile(TString& filename, TString& volumeName, TGeoMatrix** matrix)
238 {
239 // Save current gFile and gDirectory information
240 TFile* oldFile = gFile;
241 TDirectory* oldDirectory = gDirectory;
242
243 TFile* f = new TFile(filename);
244 TList* l = f->GetListOfKeys();
245 Int_t numKeys = l->GetSize();
246
247 if (2 != numKeys) {
248 LOG(debug) << "Not exactly two keys in the file. File is not of new type.";
249 return kFALSE;
250 }
251
252 TKey* key;
253 TIter next(l);
254
255 Bool_t foundGeoVolume = kFALSE;
256 Bool_t foundGeoMatrix = kFALSE;
257
258 while ((key = (TKey*) next())) {
259 if (key->ReadObj()->InheritsFrom("TGeoVolume")) {
260 volumeName = key->GetName();
261 foundGeoVolume = kTRUE;
262 LOG(debug) << "Found TGeoVolume with name " << volumeName;
263 continue;
264 }
265 if (key->ReadObj()->InheritsFrom("TGeoMatrix")) {
266 *matrix = dynamic_cast<TGeoMatrix*>(key->ReadObj());
267 foundGeoMatrix = kTRUE;
268 LOG(debug) << "Found TGeoMatrix derrived object.";
269 continue;
270 }
271 }
272
273 // Restore previous gFile and gDirectory information
274 f->Close();
275 delete f;
276 gFile = oldFile;
277 gDirectory = oldDirectory;
278
279 if (foundGeoVolume && foundGeoMatrix) {
280 LOG(debug) << "Geometry file is of new type.";
281 return kTRUE;
282 }
283 else {
284 if (!foundGeoVolume) { LOG(fatal) << "No TGeoVolume found in geometry file. File is of unknown type."; }
285 if (!foundGeoMatrix) {
286 LOG(fatal) << "No TGeoMatrix derived object found in geometry file. "
287 "File is of unknown type.";
288 }
289 return kFALSE;
290 }
291 }
292
293
294 void AssignMediumAtImport(TGeoVolume* v)
295 {
302 FairGeoMedia* Media = FairGeoLoader::Instance()->getGeoInterface()->getMedia();
303 FairGeoBuilder* geobuild = FairGeoLoader::Instance()->getGeoBuilder();
304
305 TGeoMedium* med1 = v->GetMedium();
306
307 if (med1) {
308 // In newer ROOT version also a TGeoVolumeAssembly has a material and medium.
309 // This medium is called dummy and is automatically set when the geometry is constructed.
310 // Since this material and medium is neither in the TGeoManager (at this point) nor in our
311 // ASCII file we have to create it the same way it is done in TGeoVolume::CreateDummyMedium()
312 // In the end the new medium and material has to be added to the TGeomanager, because this is
313 // not done automatically when using the default constructor. For all other constructors the
314 // newly created medium or material is added to the TGeomanger.
315 // Create the medium and material only the first time.
316 TString medName = static_cast<TString>(med1->GetName());
317 if ((medName.EqualTo("dummy")) && (nullptr == gGeoManager->GetMedium(medName))) {
318 TGeoMaterial* dummyMaterial = new TGeoMaterial();
319 dummyMaterial->SetName("dummy");
320
321 TGeoMedium* dummyMedium = new TGeoMedium();
322 dummyMedium->SetName("dummy");
323 dummyMedium->SetMaterial(dummyMaterial);
324
325 gGeoManager->GetListOfMedia()->Add(dummyMedium);
326 gGeoManager->AddMaterial(dummyMaterial);
327 }
328
329 TGeoMaterial* mat1 = v->GetMaterial();
330 TGeoMaterial* newMat = gGeoManager->GetMaterial(mat1->GetName());
331 if (nullptr == newMat) {
335 LOG(info) << "Create new material " << mat1->GetName();
336 FairGeoMedium* FairMedium = Media->getMedium(mat1->GetName());
337 if (!FairMedium) {
338 LOG(fatal) << "Material " << mat1->GetName() << "is neither defined in ASCII file nor in Root file.";
339 }
340 else {
341 Int_t nmed = geobuild->createMedium(FairMedium);
342 v->SetMedium(gGeoManager->GetMedium(nmed));
343 gGeoManager->SetAllIndex();
344 }
345 }
346 else {
348 TGeoMedium* med2 = gGeoManager->GetMedium(mat1->GetName());
349 v->SetMedium(med2);
350 }
351 }
352 else {
353 if (strcmp(v->ClassName(), "TGeoVolumeAssembly") != 0) {
354 LOG(fatal) << "The volume " << v->GetName()
355 << "has no medium information and is not an Assembly so "
356 "we have to quit";
357 }
358 }
359 }
360
361 void ExpandNodes(TGeoVolume* vol, FairModule* mod)
362 {
363
365 TObjArray* NodeList = vol->GetNodes();
366 for (Int_t Nod = 0; Nod < NodeList->GetEntriesFast(); Nod++) {
367 TGeoNode* fNode = (TGeoNode*) NodeList->At(Nod);
368
369 TGeoVolume* v = fNode->GetVolume();
370 if (fNode->GetNdaughters() > 0) { Cbm::GeometryUtils::ExpandNodes(v, mod); }
372
373 if ((mod->InheritsFrom("FairDetector")) && mod->IsSensitive(v->GetName())) {
374 LOG(debug) << "Module " << v->GetName() << " of detector " << mod->GetName() << " is sensitive";
375 mod->AddSensitiveVolume(v);
376 }
377 }
378 }
379
380
381 void LocalToMasterCovarianceMatrix(const TGeoMatrix& m, Double_t& covXX, Double_t& covXY, Double_t& covYY)
382 {
383 // Fast calculation with skipping zeros
384
385 // 3x3 covariance matrix. c01==c11, other elements are 0.
386 double c00 = covXX;
387 double c10 = covXY;
388 double c11 = covYY;
389
390 // 3x3 transformation matrix. other elements will not be needed
391 double r00 = m.GetRotationMatrix()[0];
392 double r01 = m.GetRotationMatrix()[1];
393 double r10 = m.GetRotationMatrix()[3];
394 double r11 = m.GetRotationMatrix()[4];
395
396 // rc == r * c
397 double rc00 = r00 * c00 + r01 * c10;
398 double rc01 = r00 * c10 + r01 * c11;
399 double rc10 = r10 * c00 + r11 * c10;
400 double rc11 = r10 * c10 + r11 * c11;
401
402 // transformed c = rc * r^t
403 covXX = rc00 * r00 + rc01 * r01;
404 covXY = rc10 * r00 + rc11 * r01;
405 covYY = rc10 * r10 + rc11 * r11;
406 }
407
408
409 /* Populate a GeoManager with the full media and materials defined to return */
410 TGeoManager* pop_TGeoManager(const char* name)
411 {
412
413 // Use the FairRoot geometry interface to load the media which are already defined
414 FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
415 FairGeoInterface* geoFace = geoLoad->getGeoInterface();
416 TString geoPath = gSystem->Getenv("VMCWORKDIR");
417 TString geoFile = geoPath + "/geometry/media.geo";
418 geoFace->setMediaFile(geoFile);
419 geoFace->readMedia();
420
421 // Read the required media and create them in the GeoManager
422 FairGeoMedia* geoMedia = geoFace->getMedia();
423 FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
424
425 int num = geoMedia->getListOfMedia()->GetSize();
426 FairGeoMedium* med = new FairGeoMedium();
427
428 for (int i = 0; i < num; i++) {
429 med = geoMedia->getMedium(geoMedia->getListOfMedia()->At(i)->GetName());
430 geoBuild->createMedium(med);
431 };
432
433 gGeoManager->SetTitle(name);
434
435 return gGeoManager;
436 }
437
438 /* Open root file geometry and add it to parent */
439 bool add_binary(const char rootFile[], TGeoVolume* top, TGeoMedium* med, Int_t inum, TGeoMatrix* mat)
440 {
441
442 TFile* file = TFile::Open(rootFile, "OPEN");
443 if (file == NULL) {
444 LOG(info) << "Error file " << rootFile << " not opened";
445 return false;
446 }
447 else {
448 ((TGeoVolume*) file->Get(file->GetListOfKeys()->First()->GetName()))->SetMedium(med);
449 top->AddNode((TGeoVolume*) (file->Get(file->GetListOfKeys()->First()->GetName()))->Clone(), inum, mat);
450 };
451
452 (top->GetNode(top->GetNodes()->Last()->GetName()))->GetVolume()->SetMedium(med);
453 file->Close();
454 return true;
455 }
456
457 /* Take in the positional matrix and return it in TGeo format */
458 TGeoMatrix* cad_matrix(double XX, double XY, double XZ, double YX, double YY, double YZ, double ZX, double ZY,
459 double ZZ, double TX, double TY, double TZ)
460 {
461
462 TGeoHMatrix* hmat = new TGeoHMatrix();
463 (hmat->GetRotationMatrix())[0] = XX;
464 (hmat->GetRotationMatrix())[3] = XY;
465 (hmat->GetRotationMatrix())[6] = XZ;
466
467 (hmat->GetRotationMatrix())[1] = YX;
468 (hmat->GetRotationMatrix())[4] = YY;
469 (hmat->GetRotationMatrix())[7] = YZ;
470
471 (hmat->GetRotationMatrix())[2] = ZX;
472 (hmat->GetRotationMatrix())[5] = ZY;
473 (hmat->GetRotationMatrix())[8] = ZZ;
474
475 TGeoRotation* rot = new TGeoRotation();
476 rot->SetRotation(*hmat);
477
478 TGeoCombiTrans* mat = new TGeoCombiTrans(TX / 1, TY / 1, TZ / 1, rot);
479 return mat;
480 };
481
482
483 } // namespace GeometryUtils
484} // namespace Cbm
fscal v[fmask::Size]
Definition KfSimdPseudo.h:4
int Int_t
bool Bool_t
TGeoMatrix * cad_matrix(double XX, double XY, double XZ, double YX, double YY, double YZ, double ZX, double ZY, double ZZ, double TX, double TY, double TZ)
void AssignMediumAtImport(TGeoVolume *v)
Bool_t IsNewGeometryFile(TString &filename)
void ExpandNodes(TGeoVolume *vol, FairModule *mod)
void ImportRootGeometry(TString &filename, FairModule *mod, TGeoMatrix *mat)
void LocalToMasterCovarianceMatrix(const TGeoMatrix &m, Double_t &covXX, Double_t &covXY, Double_t &covYY)
Convert the local X/Y covariance matrix to global coordinates.
TGeoManager * pop_TGeoManager(const char *name)
bool add_binary(const char rootFile[], TGeoVolume *top, TGeoMedium *med, Int_t inum, TGeoMatrix *mat)