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