EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicGeoParData.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicGeoParData.cxx
1 //
2 // AYK (ayk@bnl.gov), 2013/06/13
3 //
4 // EIC geometry mapping classes;
5 //
6 
7 #include <fstream>
8 
9 #include <stdlib.h>
10 #include <assert.h>
11 #include <iostream>
12 // This is needed for Mac OS only;
13 #ifdef __APPLE__
14 #include <unistd.h>
15 #include <libgen.h>
16 #endif
17 
18 #include <TROOT.h>
19 #include <TClass.h>
20 #include <TColor.h>
21 #include <TRealData.h>
22 #include <TDataMember.h>
23 
24 #ifdef _VGM_
25 #include "BaseVGM/volumes/VFactory.h"
26 #include "VGM/volumes/IPlacement.h"
27 #include "Geant4GM/volumes/Factory.h"
28 #include "RootGM/volumes/Factory.h"
29 #endif
30 
31 #include <EtmOrphans.h>
32 #include <EicGeoMedia.h>
33 #include <EicGeoParData.h>
34 
35 #ifdef _ETM2GEANT_
36 #include "G4Material.hh"
37 #include "G4PVPlacement.hh"
38 #include "G4LogicalVolume.hh"
39 #include "G4ThreeVector.hh"
40 #include "G4VisAttributes.hh"
41 #endif
42 
44 
45 // =======================================================================================
46 
47 //
48 // Constructor & Co
49 //
50 
52 {
54  mTestGeometryFlag = false;
56 
57  {
58  char user[128], host[128];
59 
60  getlogin_r(user, 128-1);
61  gethostname(host, 128-1);
62  mAuthor = TString(user) + "@" + host;
63  }
64 
65  mTimeStamp = TTimeStamp();
66 
68 
70  //@@@mGeoLoad = 0; mGeoFace = 0; mGeobuild = 0;
71  //@@@mEicMedia = 0;
73 
75 
76  mTransparency = 0;
77 
78  // SHould be good enough as a default; in fact may want to eliminate the 'check' variable,
79  // and invoke check if this value is non-zero; but ok;
81 } // EicGeoParData::ResetVars()
82 
83 // ---------------------------------------------------------------------------------------
84 
85 EicGeoParData::EicGeoParData(const char *detName, int version, int subVersion):
86  mVersion(version), mSubVersion(subVersion)
87 {
88  ResetVars();
89 
90  // Create detector name class;
91  mDetName = new EicDetName(detName);
92 
93  // Well, default constructor of some detectors (like VST) will call VstGeoParData()
94  // as EicGeoParData("VST"); so can not just check on detName=0 here in order to see
95  // whether I reached this place from EicDetector::ConstructGeometry() when ROOT
96  // streamer imported EicGeoParData block, rather than from geometry-producing script
97  // like vst.C; do not want to change default calls for those constructors; so
98  // conventionally check here on FairRun::Instance() and do not mess up with the running
99  // FairRun if it was instantiated (meaning most likely from under the running simulation);
100 #if _TODAY_
101  if (FairRun::Instance()) return;
102 
103  // No ExpnandedFileName() tricks here, please;
104  TString mediaFileName = TString(getenv("VMCWORKDIR")) + "/geometry/media.geo";
105 
107  new FairGeoLoader("TGeo", "FairGeoLoader");
108  mGeoFace = mGeoLoad->getGeoInterface();
109 
110  mGeoFace->setMediaFile(mediaFileName);
111  mGeoFace->readMedia();
112 
113  mFairMedia = mGeoFace->getMedia();
114  mGeobuild = mGeoLoad->getGeoBuilder();
115 #endif
116 
117  // FIXME: for EicRoot geometries, which require construction elements in the
118  // .C scripts rather than in a library call, will have to switch/restore by hand;
119  //SwitchGeoManager();
120 #if _MOVED_
121  // Initialize Geo manager and create basic geometry volume structure;
122  mRootGeoManager = new TGeoManager();
123 
124  // It looks like 2-level layout (with an extra MASTER volume) is required by FairRoot;
125  mWrapperVolume = new TGeoVolumeAssembly(mDetName->Name() + "GeantGeoWrapper");
126  mTopVolume = new TGeoVolumeAssembly(mDetName->NAME());
127 
128  mRootGeoManager->SetTopVolume(mWrapperVolume);
129 #endif
130 } // EicGeoParData::EicGeoParData()
131 
132 // =======================================================================================
133 
134 int EicGeoParData::ImportMediaFile(const char *fname)
135 {
136  std::fstream fin(fname, std::fstream::in);
137  if (!fin.is_open()) {
138  printf("Media file '%s' does not exist!\n", fname);
139  return -1;
140  } //if
141 
142  mEicMedia = new EicGeoMedia();
143 
144  mEicMedia->read(fin);
145  //mEicMedia->print();
146 
147  return 0;
148 } // EicGeoParData::ImportMediaFile()
149 
150 // =======================================================================================
151 
153 {
154  // Save the original pointers; this is dumb of course (and assumes that a switch back
155  // happens in the same call (which I kind of control myself); indeed ROOT is an awkward
156  // code in terms of using global variables, etc;
157  mSavedGeoManager = gGeoManager;
158  mSavedGeoIdentity = gGeoIdentity;
159 
160  // Initialize Geo manager and create basic geometry volume structure;
161  mRootGeoManager = new TGeoManager();
162 
163  // It looks like 2-level layout (with an extra MASTER volume) is required by FairRoot;
164  mWrapperVolume = new TGeoVolumeAssembly(mDetName->Name() + "GeantGeoWrapper");
165  mTopVolume = new TGeoVolumeAssembly(mDetName->NAME());
166 
167  mRootGeoManager->SetTopVolume(mWrapperVolume);
168 } // EicGeoParData::SwitchGeoManager()
169 
170 // ---------------------------------------------------------------------------------------
171 
173 {
174  // This will remove the pointer from the list of geometries and the list of browsables,
175  // see TGeoManager::~TGeoManager() code;
176  delete mRootGeoManager;
177 
178  gGeoManager = mSavedGeoManager;
179  gGeoIdentity = mSavedGeoIdentity;
180 } // EicGeoParData::RestoreGeoManager()
181 
182 // ---------------------------------------------------------------------------------------
183 
184 //void EicGeoParData::PlaceG4Volume(G4VPhysicalVolume *mother, bool check,
185 void EicGeoParData::PlaceG4Volume(G4LogicalVolume *mother, bool check,
186  //G4RotationMatrix *pRot, G4ThreeVector *tlate)
187  void *pRot, void *tlate)
188 {
189  // Switch() & Restore() calls are generic;
191 
192  // This one is virtual, detector-specific (populates gGeoManager);
193  // perform TGeo geometry check (optional);
194  ConstructGeometry(false, false, check);
195 
196 #if defined(_ETM2GEANT_) && defined(_VGM_)
197  // Create std::set of the sensitive volume names;
198  mSensitiveVolumeNames.clear();
199  mG4Volumes.clear();
200  mG4SensitiveVolumes.clear();
201  for(int iq=0; iq<GetMapNum(); iq++) {
202  const EicGeoMap *fmap = GetMapPtrViaMapID(iq);
203 
204  //printf("@@@ %s\n", fmap->GetInnermostVolumeName()->Data());
205  //mSensitiveVolumeNames.insert(*fmap->GetInnermostVolumeName());
206  assert(mSensitiveVolumeNames.find(*fmap->GetInnermostVolumeName()) ==
207  mSensitiveVolumeNames.end());
209  } //if..for iq
210 
211  {
212  //auto mtable = G4Material::GetMaterialTable();
213  //printf("mtable: %d\n", mtable->size());
214  }
215 
216  // This is again generic; assumes FairRoor two-layer assembly on top of everything,
217  // and then container volumes with the actual stuff inside it;
218  if (gGeoManager && gGeoManager->GetTopNode() && gGeoManager->GetTopNode()->GetVolume()->GetNode(0)) {
219  auto assembly = gGeoManager->GetTopNode()->GetVolume()->GetNode(0)->GetVolume();
220 
221  for(int iq=0; iq<assembly->GetNdaughters(); iq++) {
222  // FIXME: does one really need to create this pair of factories every time new?;
223  RootGM::Factory rtFactory;
224  Geant4GM::Factory g4Factory;
225 
226  auto node = assembly->GetNode(iq);
227  //printf("@@@ -> %s\n", node->GetName());
228 
229  rtFactory.Import(node);
230  rtFactory.Export(&g4Factory);
231 
232  // FIXME: this is a hack (assumes [mm], which seems to be correct; but also will not work with rotations);
233  auto trans = rtFactory.Top()->Transformation();
234  //for(auto value: trans)
235  //printf("%f\n", value);
236  G4ThreeVector offset(trans[0], trans[1], trans[2]);
237  if (tlate) offset += *(G4ThreeVector*)tlate;
238 
239  // FIXME: this is not good; but 'class G4ThreeVector' followed by '#include "G4ThreeVector.hh"'
240  // fails because of the CLHEP typedef conflict;
241  //printf("@@@ %f\n", g4Factory.World()->GetTranslation()[2]);
242  //auto pvol = new G4PVPlacement(g4Factory.World()->GetRotation(), g4Factory.World()->GetTranslation(),
243  auto pvol = new G4PVPlacement((G4RotationMatrix*)pRot, offset,
244  g4Factory.World()->GetLogicalVolume(),
245  node->GetName(), mother/*->GetLogicalVolume()*/, false, 0);
246  AssignG4Colors(pvol);
247  } //for iq
248  }
249 
250  {
251  //auto mtable = G4Material::GetMaterialTable();
252  //printf("mtable: %d\n", mtable->size());
253 
254  //mtable->clear();
255  }
256 
257  //printf("%d %d\n", GetG4Volumes().size(), GetG4SensitiveVolumes().size());
258 #endif
259 
261 } // EicGeoParData::PlaceG4Volume()
262 
263 // ---------------------------------------------------------------------------------------
264 
265 void EicGeoParData::AssignG4Colors(G4VPhysicalVolume *pvol)
266 {
267 #ifdef _ETM2GEANT_
268  auto lvol = pvol->GetLogicalVolume();
269 
270  // Deal with the volume vectors here as well; FIXME: change the method name;
271  mG4Volumes.push_back(pvol);
272  //if (mSensitiveVolumeNames.find(lvol->GetName()) != mSensitiveVolumeNames.end())
273  //mG4SensitiveVolumes.push_back(pvol);
274  if (mSensitiveVolumeNames.find(lvol->GetName()) != mSensitiveVolumeNames.end())
275  mG4SensitiveVolumes[pvol] = mSensitiveVolumeNames[lvol->GetName()];// + 1;
276 
277  // Follow the logic of EicGeoParData::FinalizeOutput();
278  {
279  // FIXME: memory leak?;
280  G4VisAttributes* visAtt = new G4VisAttributes();
281  // Get volume color; if not defined, volume should be invisible;
282  const std::pair<TString, Color_t> *cpattern = GetColorTable()->AnyMatch(lvol->GetName());
283 
284  if (cpattern) {
285  auto rcolor = gROOT->GetColor(cpattern->second);
286 
287  // Get volume transparency value (8-bit character 0..100 in the ROOT world);
288  const std::pair<TString, Char_t> *tpattern = GetTransparencyTable()->AnyMatch(lvol->GetName());
289  double transparency = tpattern ? (100-tpattern->second)/100. : 1.0;
290  visAtt->SetColor(rcolor->GetRed(), rcolor->GetGreen(), rcolor->GetBlue(), transparency);
291  visAtt->SetVisibility(true);
292  visAtt->SetForceWireframe(false);
293  visAtt->SetForceSolid(true);
294  }
295  else
296  visAtt->SetVisibility(false);
297 
298  lvol->SetVisAttributes(visAtt);
299  }
300 
301  for(int iq=0; iq<lvol->GetNoDaughters(); iq++) {
302  auto daughter = lvol->GetDaughter(iq);
303 
304  //printf("--@@@ %s\n", daughter->GetName().data());
305 
306  // Call recursively;
307  AssignG4Colors(daughter);
308  } //for iq
309 #endif
310 } // EicGeoParData::AssignG4Colors()
311 
312 // ---------------------------------------------------------------------------------------
313 
314 //
315 // Mapping file creation part
316 //
317 
319 {
320  EicGeoMap *map = new EicGeoMap();
321  mGeantVolumeMaps.push_back(map);
322  return map;
323 } // EicGeoParData::CreateNewMap()
324 
325 // ---------------------------------------------------------------------------------------
326 
327 int EicGeoParData::AddLogicalVolumeGroup(unsigned dimX, unsigned dimY, unsigned dimZ)
328 {
330  printf("Logical table size is full (%d entries)!\n", (unsigned)_LOGICAL_GROUP_NUM_MAX_);
331  return -1;
332  } //if
333 
334  // Arrange a unified access;
335  unsigned dim[_LOGICAL_VOLUME_GROUP_COORD_NUM_] = {dimX, dimY, dimZ}, max = 0;
336 
337  // NB: there can be 0 dimensions in the middle -> so really want to see what is
338  // the max one before populating the vector;
339  for(unsigned iq=0; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++)
340  if (dim[iq]) max = iq;
341 
342  LogicalVolumeGroup *group = new LogicalVolumeGroup();
343 
344  unsigned accu = 0;
345  for(unsigned iq=0; iq<=max; iq++)
346  if (dim[iq]) {
348 
349  EicBitMask<ULogicalIndex_t> *mask = coord->mBitMask;
350 
351  mask->SetShift(accu);
352  accu += mask->GetBitNum();
353 
354  group->mProjections.push_back(coord);
355  }
356  else
357  group->mProjections.push_back(0);
358 
359  // FIXME: do a better check later;
360  assert(accu <= _LOGICAL_XYZ_BIT_NUM_);
361 
362  mLogicalVolumeGroups.push_back(group);
363 
364  //return 0;
365  return mLogicalVolumeGroups.size() - 1;
366 } // EicGeoParData::AddLogicalVolumeGroup()
367 
368 // ---------------------------------------------------------------------------------------
369 
370 int EicGeoParData::SetCircularCore(unsigned group, unsigned what)
371 {
372  // FIXME: these few lines should be shaped up as a routine!;
373  if (group >= mLogicalVolumeGroups.size()) return -1;
374 
375  const std::vector<LogicalVolumeGroupProjection*> &coords =
376  mLogicalVolumeGroups[group]->mProjections;
377 
378  if (what >= coords.size() || !coords[what]) return -1;
379 
380  coords[what]->mCircular = true;
381 
382  return 0;
383 } // EicGeoParData::SetCircularCore()
384 
385 // ---------------------------------------------------------------------------------------
386 
387 Int_t EicGeoParData::SetMappingTableEntry(EicGeoMap *map, const unsigned geo[],
388  unsigned group, unsigned logical[])
389 {
390  if (!map || !geo || !logical) {
391  printf("-E- EicGeoParData::SetMappingTableEntry(): zero pointer(s) used as arguments!\n");
392  return -1;
393  } //if
394 
395  if (group >= _LOGICAL_GROUP_NUM_MAX_) {
396  printf("-E- EicGeoParData::SetMappingTableEntry(): group index '%d' exceeds '%d'!\n",
397  group, (unsigned)_LOGICAL_GROUP_NUM_MAX_);
398  return -1;
399  } //if
400 
401  // Pack logical[] array into a single ULogicalIndex_t value;
403 
404  if (group >= mLogicalVolumeGroups.size()) {
405  printf("-E- EicGeoParData::SetMappingTableEntry(): group index '%d' exceeds "
406  "configured array size (%d)!\n", group, (unsigned)mLogicalVolumeGroups.size());
407  return -1;
408  } //if
409  const std::vector<LogicalVolumeGroupProjection*> &coords =
410  mLogicalVolumeGroups[group]->mProjections;
411 
412  for(unsigned iq=0; iq<coords.size(); iq++) {
413  // Zero logical[] value will not contribute anyway;
414  if (!logical[iq]) continue;
415 
416  LogicalVolumeGroupProjection *coord = coords[iq];
417 
418  // NB: this check is sufficient to guarantee, that overflow in "value"
419  // can not happen (because overall mask/shift consistency was checked
420  // during mProjectionDescriptors creation);
421  if (!coord) {
422  printf("-E- EicGeoParData::SetMappingTableEntry(): coordinate '%d' was not configured!\n", iq);
423  return -1;
424  } //if
425  if (logical[iq] >= coord->mMaxEntryNum) {
426  printf("-E- EicGeoParData::SetMappingTableEntry(): logical index #%d (%d) exceeds "
427  "max configured entry num (%d)!\n", iq, logical[iq], (unsigned)coord->mMaxEntryNum);
428  return -1;
429  } //if
430 
431  // This is guaranteed no be non-zero by mProjectionDescriptors initialization;
432  EicBitMask<ULogicalIndex_t> *mask = coord->mBitMask;
433 
434  value |= (logical[iq] & mask->GetBitMask()) << mask->GetShift();
435  } //for iq
436 
437  return map->SetMappingTableEntry(geo, value);
438 } // EicGeoParData::SetMappingTableEntry()
439 
440 // ---------------------------------------------------------------------------------------
441 
442 //#include <EicMagneticFieldMap.h>
443 
444 SourceFile::SourceFile(const char *fileName): mFileSize(0), mFileContent(0), mOkFlag(false)
445 {
446  // This will also be the default constructor case;
447  if (!fileName) return;
448 
449  FILE *fin = fopen(fileName, "r");
450  if (!fin) {
451  printf("-E- SourceFile::SourceFile(): file '%s' does not exist!\n", fileName);
452  return;
453  } //if
454 
455  // NB: strip directory name;
456  {
457  // FIXME: unify with EicMagneticFieldMap::BasenameWrapper() at some point;
458  char buffer[1024];
459  snprintf(buffer, 1024-1, "%s", fileName);
460 
461  mFileName = TString(basename(buffer));
462  }
463 
464  // FIXME: there is perhaps a better way to do this?; then change EicStlFile.cxx as well;
465  fseek(fin, 0, SEEK_END);
466  mFileSize = ftell(fin);
467 
468  mFileContent = new UChar_t[mFileSize];
469 
470  rewind(fin);
471  if (fread(mFileContent, 1, mFileSize, fin) == mFileSize)
472  mOkFlag = true;
473  else
474  delete [] mFileContent;
475 
476  fclose(fin);
477 } // SourceFile::SourceFile()
478 
479 // ---------------------------------------------------------------------------------------
480 
481 void SourceFile::Print()
482 {
483  if (!IsOk()) return;
484 
485  printf("\n Attached file name: %s\n", mFileName.Data());
486  printf(" --------------------");
487  for(unsigned iq=0; iq<mFileName.Length(); iq++)
488  printf("-");
489 
490  // Do not overcomplicate things -> just dump to output assuming it was a clean ASCII file;
491  printf("\n\n%s\n", mFileContent);
492 } // SourceFile::Print()
493 
494 // ---------------------------------------------------------------------------------------
495 
496 void EicGeoParData::PrintAttachedSourceFile(const char *fileName)
497 {
498  for(unsigned fl=0; fl<mSourceFiles.size(); fl++) {
500 
501  if (file->GetFileName().EqualTo(fileName)) {
502  file->Print();
503  return;
504  } //if
505  } //for fl
506 
507  printf("\n No file '%s' was attached!\n", fileName);
508 } // EicGeoParData::PrintAttachedSourceFile()
509 
510 // ---------------------------------------------------------------------------------------
511 
512 int EicGeoParData::AttachSourceFile(const char *fileName)
513 {
514  SourceFile *file = new SourceFile(fileName);
515 
516  if (file->IsOk()) {
517  mSourceFiles.push_back(file);
518 
519  return 0;
520  }
521  else {
522  //delete file;
523  return -1;
524  } //if
525 } // EicGeoParData::AttachSourceFile()
526 
527 // ---------------------------------------------------------------------------------------
528 
529 const TGeoMedium *EicGeoParData::GetMedium(const char *medium)
530 {
531  // FIXME: allow for user-created media;
532  if (!mRootGeoManager || !mEicMedia) return 0;
533 
534  if (!mMediaCache.count(medium)) {
535  EicGeoMedium *fmedium = mEicMedia->getMedium(medium);
536  mEicMedia->createMedium(fmedium);
537 
538  mMediaCache.insert(medium);
539  } //if
540 
541  return mRootGeoManager->GetMedium(medium);
542 } // EicGeoParData::GetMedium()
543 
544 // ---------------------------------------------------------------------------------------
545 
546 TString EicGeoParData::GetGeometryFileName(bool root) const
547 {
548  const char *suffix = root ? ".root" : ".gdml";
549  // If file is given, use it;
550  if (!mFileName.IsNull()) return mFileName;
551 
552  // If file name format is given and version is defined, use them;
553  if (!mFileNameFormat.IsNull()/* && GetVersion() >= 0*/) {
554  char fileName[128];
555 
556  if (GetVersion() >= 0)
557  snprintf(fileName, 128-1, mFileNameFormat.Data(), GetVersion(), GetSubVersion());
558  else
559  // At least Clang prefers it this way;
560  snprintf(fileName, 128-1, "%s", mFileNameFormat.Data());
561 
562  return TString(fileName);
563  } //if
564 
565  // Detector name is not known -> can hardly do anything -> return empty string;
566  if (!mDetName) return TString("");
567 
568  // Test geometry -> return non-version file name with 'test' suffix;
569  if (IsTestGeometry()) return mDetName->name() + "-test.root";
570 
571  // Otherwise compose a default name out of detector name, version and subversion;
572  char version[128] = "";
573  if (GetVersion() >= 0)
574  snprintf(version, 128-1, "-v%02d.%d", GetVersion(), GetSubVersion());
575 
576  switch (GetGeometryType()) {
578  return mDetName->name() + version + suffix;//".root";
580  return mDetName->name() + version + "-ns" + suffix;//.root";
582  return mDetName->name() + version + "-ss" + suffix;//.root";
584  return mDetName->name() + version + "-fs" + suffix;// .root";
585  default:
586  {
587  // Make the compiler happy;
588  assert(0); return "";
589  }
590  } //switch
591 } // EicGeoParData::GetGeometryFileName()
592 
593 // ---------------------------------------------------------------------------------------
594 
595 void EicGeoParData::FinalizeOutput(bool root, bool gdml, bool check) //const
596 {
597  if (!mRootGeoManager) return;
598 
599  // Set up colors and transparency values;
600  {
601  TIter next( mRootGeoManager->GetListOfVolumes() );
602 
603  TGeoVolume *volume;
604 
605  while ((volume=(TGeoVolume*)next())) {
606  //TString name = volume->GetName();
607  //cout << volume->GetName() << endl;
608 
609  const std::pair<TString, Color_t> *cpattern = GetColorTable()->AnyMatch(volume->GetName());
610 
611  if (cpattern) {
612  volume->SetLineColor(cpattern->second);
613  volume->SetFillColor(cpattern->second);
614 
615  // And check if transparency value is set;
616  {
617  const std::pair<TString, Char_t> *tpattern = GetTransparencyTable()->AnyMatch(volume->GetName());
618 
619  // FIXME: well, this 4000-based stuff indeed looks like a hack;
620  if (tpattern) volume->SetFillStyle(4000 + tpattern->second);
621  }
622  }
623  else
624  volume->SetVisibility(kFALSE);
625  } //while
626  }
627 
628  // Add configured detector to the top volume, with a proper 3D transformation;
629  mWrapperVolume->AddNode(mTopVolume, 0, mTopVolumeTransformation);
630 
631  // Check overlap (1um accuracy) and export;
632  mRootGeoManager->CloseGeometry();
634 
635  if (root) {
636  TFile *outputFile = new TFile(GetGeometryFileName(true).Data(), "RECREATE");
637 
638  if (outputFile) {
639  mWrapperVolume->Write();
640 
641  // Save geometry (mapping) parameters in the same file;
642  Write(mDetName->Name() + "GeoParData");
643 
644  outputFile->Close();
645  } //if
646  } //if
647 
648  if (gdml) mRootGeoManager->Export(GetGeometryFileName(false).Data());
649 } // EicGeoParData::FinalizeOutput()
650 
651 // =======================================================================================
652 
653 //
654 // Service routines
655 //
656 
657 // FIXME: unify part of these calls later;
658 
659 unsigned EicGeoParData::GetDimCore(unsigned group, unsigned what) const
660 {
661  if (group >= mLogicalVolumeGroups.size()) return 0;
662 
663  const std::vector<LogicalVolumeGroupProjection*> &coords =
664  mLogicalVolumeGroups[group]->mProjections;
665 
666  return (what < coords.size() && coords[what] ? coords[what]->mMaxEntryNum : 0);
667 } // EicGeoParData::GetDimCore()
668 
669 // ---------------------------------------------------------------------------------------
670 
671 unsigned EicGeoParData::GetLogicalCoordCore(unsigned what, ULogicalIndex_t logicalID) const
672 {
673  unsigned group = GetGroup(logicalID);
674 
675  if (group >= mLogicalVolumeGroups.size()) return 0;
676 
677  const std::vector<LogicalVolumeGroupProjection*> &coords =
678  mLogicalVolumeGroups[group]->mProjections;
679 
680  if (what >= coords.size() || !coords[what]) return 0;
681 
682  EicBitMask<ULogicalIndex_t> *mask = coords[what]->mBitMask;
683 
684  return ((logicalID >> mask->GetShift()) & mask->GetBitMask());
685 } // EicGeoParData::GetLogicalCoordCore()
686 
687 // ---------------------------------------------------------------------------------------
688 
689 bool EicGeoParData::GetCircularCore(unsigned group, unsigned what) const
690 {
691  if (group >= mLogicalVolumeGroups.size()) return false;
692 
693  const std::vector<LogicalVolumeGroupProjection*> &coords =
694  mLogicalVolumeGroups[group]->mProjections;
695 
696  if (what >= coords.size() || !coords[what]) return false;
697 
698  return coords[what]->mCircular;
699 } // EicGeoParData::GetCircularCore()
700 
701 // =======================================================================================
702 //
703 // Part used in simulation.C & Co
704 //
705 
707 {
708  mMaxVolumeLevelNum = 0;
709 
710  // Loop through all the maps, calculate bitwise shifts and identify volumes;
711  for(int iq=0; iq<mGeantVolumeMaps.size(); iq++)
712  {
713  EicGeoMap *fmap = mGeantVolumeMaps[iq];
714 
715  if (fmap->CalculateMappingTableSignature()) return -1;
716 
717  // Also use this same loop to get max number of levels;
720  } //for iq
721 
722  return 0;
723 } // EicGeoParData::CalculateMappingTableSignatures()
724 
725 // =======================================================================================
726 
727 //
728 // Part used in digitization.C & Co
729 //
730 
732 {
733  for(unsigned gr=0; gr<mLogicalVolumeGroups.size(); gr++) {
735 
736  vgroup->mDim3D = 1;
737 
738  for(unsigned iq=0; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++) {
739  vgroup->mRealDim[iq] = GetDim(gr,iq) ? GetDim(gr,iq) : 1;
740  vgroup->mDim3D *= vgroup->mRealDim[iq];
741  } //for iq
742 
743  vgroup->mLookup = new LogicalVolumeLookupTableEntry[vgroup->mDim3D];
744  } //for gr
745 
746  TString returnBackPath = gGeoManager->GetPath();
747 
748  // Loop through all maps, figure out their "cell" levels (like where "femcTower" is),
749  // loop through all map look-up table entries, construct respective geo node pointers,
750  // get shape, etc info and put all this into the 2D (3D) lookup table;
751  for(int iq=0; iq<mGeantVolumeMaps.size(); iq++) {
752  int cellLevel = -1;
753 
754  const EicGeoMap *fmap = GetMapPtrViaMapID(iq);
755 
756  {
757  const TString &containerName = fmap->GetSingleSensorContainerVolumeName();
758 
759  if (containerName.IsNull()) continue;
760 
761  for(int lv=0; lv<fmap->GetGeantVolumeLevelNum(); lv++) {
762  const GeantVolumeLevel *lptr = fmap->GetGeantVolumeLevelPtr(lv);
763 
764  if (lptr->GetVolumeName().EqualTo(containerName)) {
765  cellLevel = lv;
766  break;
767  } //if
768  } //for lv
769 
770  // FIXME: remove later (means map is incorrect);
771  assert(cellLevel != -1);
772 
773  // No matching level name -> map is of no interest;
774  if (cellLevel == -1) continue;
775  }
776 
777  // Well, this basically means there were no hits in sensitive volumes
778  // served by this map (so assignment in EicDetector::GetNodeMultiIndex()
779  // routine has never been reached; in other words, map is useless, skip);
780  if (fmap->GetBaseVolumePath()->IsNull()) continue;
781 
782  // Loop through all map entries;
783  for(UGeantIndex_t ent=0; ent<fmap->GetMappingTableDim(); ent++) {
784  ULogicalIndex_t entry = fmap->GetMappingTable()[ent];
785 
786  if (entry == ~ULogicalIndex_t(0)) continue;
787 
788  TString vPath(*fmap->GetBaseVolumePath());
789  for(int lv=fmap->GetGeantVolumeLevelNum()-1; lv>=cellLevel; lv--) {
790  const GeantVolumeLevel *lptr = fmap->GetGeantVolumeLevelPtr(lv);
791 
792  // Node ID; this should be a method of course; fix later;
793  UGeantIndex_t nID = lptr->GetMaskedBits(ent);
794 
795  char buffer[128];
796  snprintf(buffer, 128-1, "%d", nID);
797  vPath += "/" + lptr->GetVolumeName() + "_" + buffer;
798  } //for lv
799 
800  // This is indeed a CPU-consuming process; may want to do on-the-fly for
801  // the needed cells only;
802  gGeoManager->cd(vPath);
803  TGeoNode *gNode = gGeoManager->GetCurrentNode();
805  assert(node);
806  //node->mLogicalID = entry;
807  node->mGeoNode = gNode;
808  node->mVolumePath = vPath;
809  // Yes, gGeoManager->GetCurrentMatrix() is a pointer to whatever
810  // buffer matrix -> reallocate new instead of copy pointer;
811  node->mGeoMtx = new TGeoHMatrix(*gGeoManager->GetCurrentMatrix());
812 
813  // Add entry to the reversed lookup table;
814  mGeantToLogicalLookupTable[gNode] = node;
815  } //for ent
816  } //for iq
817 
818  gGeoManager->cd(returnBackPath);
819 } // EicGeoParData::InitializeLookupTables()
820 
821 // ---------------------------------------------------------------------------------------
822 
824 {
825  unsigned group = GetGroup(xy);
826 
827  if (group >= mLogicalVolumeGroups.size()) return 0;
828 
829  LogicalVolumeGroup *vgroup = mLogicalVolumeGroups[group];
830 
831  unsigned offset = GetCoord(0, xy);
832 
833  for(unsigned iq=1; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++)
834  offset = offset*vgroup->mRealDim[iq] + GetCoord(iq, xy);
835 
836  return vgroup->mLookup + offset;
837 } // EicGeoParData::GetLookupTableNode()
838 
839 // ---------------------------------------------------------------------------------------
840 
842 {
843  // Sanity check;
844  if (!node) return 0;
845 
846  // No such entry?;
847  if (mGeantToLogicalLookupTable.find(node) == mGeantToLogicalLookupTable.end()) return 0;
848 
849  return mGeantToLogicalLookupTable.at(node);
850 } // EicGeoParData::GetLookupTableNode()
851 
852 // ---------------------------------------------------------------------------------------
853 
855 {
856  unsigned mapId = unsigned((multi >> _GEANT_INDEX_BIT_NUM_) & _SERVICE_BIT_MASK_);
858 
859  return mapId < mGeantVolumeMaps.size() ?
860  mGeantVolumeMaps[mapId]->GeantToLogicalIndex(idL) : ~ULogicalIndex_t(0);
861 } // EicGeoParData::GeantMultiToLogicalIndex()
862 
863 // =======================================================================================
864 
865 //
866 // Part used in reconstruction.C & Co
867 //
868 
869 bool EicGeoParData::AreNeighbours(ULogicalIndex_t g1, ULogicalIndex_t g2, unsigned maxLinearDist,
870  unsigned maxChebyshevDist) const
871 {
872  if (GetGroup(g1) != GetGroup(g2)) return false;
873 
874  int x1 [3] = {GetX(g1), GetY(g1), GetZ(g1)};
875  int x2 [3] = {GetX(g2), GetY(g2), GetZ(g2)};
876  unsigned dim [3] = {GetDimX(), GetDimY(), GetDimZ()}, distChebyshev = 0;
877  bool circ [3] = {GetCircularX(), GetCircularY(), GetCircularZ()};
878 
879  // Loop through all 3 dimensions and drop out as soon as any of the
880  // specified limits are exceeded;
881  for(unsigned iq=0; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++)
882  {
883  // This dimension is of no interest; actually dim=1 should also be skipped?;
884  if (!dim[iq]) continue;
885 
886  UInt_t dist = abs(x2[iq] - x1[iq]);
887  // If this dimension is circular, check other option as well
888  // and select smaller one; whould be a range check here?; fix later;
889  if (circ[iq])
890  {
891  UInt_t cdist = dim[iq] - dist;
892  if (cdist < dist) dist = cdist;
893  } //if
894 
895  // Linear distance is too large; NB: in principle it is not necessary to have
896  // maxLinearDist=1; nothing prevents from say searching for low-energy-deposit
897  // clusters "far enough" from the main blob;
898  if (dist > maxLinearDist) return false;
899 
900  // No this check per default;
901  if (maxChebyshevDist)
902  {
903  distChebyshev += dist;
904 
905  // 2D (or 3D) distance is too large; idea is to be able to suppress 2D-diagonal
906  // neighbourships for 2D-maps as well as 3D-diagonal (or even 2D-diagonal) ones
907  // for 3D-maps;
908  if (distChebyshev > maxChebyshevDist) return false;
909  } //if
910  } //for iq
911 
912  // Passed all checks -> they are neighbors;
913  return true;
914 } // EicGeoParData::AreNeighbours()
915 
916 // =======================================================================================
917 
918 void EicGeoParData::Print(const char *option) const
919 {
920  // Figure out class name and version;
921  printf("\nClass name: %s (v.%d); object name: %s\n\n",
922  ClassName(), Class()->GetClassVersion(), GetName());
923 
924  // Author;
925  printf("Created by %s\n\n", mAuthor.Data());
926 
927  // Creation time;
928  mTimeStamp.Print("l");
929 
930  // Version, subversion and comment;
931  if (mVersion != -1) printf("\nVersion: v%02d.%d; comment: %s\n\n", mVersion, mSubVersion,
932  mComment.IsNull() ? "-" : mComment.Data());
933 
934  // Class() method returns EicGeoParData instead of say VstGeoParData; so call
935  // gROOT->GetClass() instead; need to verify that this will work under all circumstances;
936  //TList *dataList = Class()->GetListOfRealData();
937  TList *dataList = gROOT->GetClass(ClassName())->GetListOfRealData();
938  TIter next(dataList);
939 
940  // For now handle POD variables of basic types;
941  printf(" Basic type variables:\n");
942  printf(" ---------------------\n\n");
943 
944  TRealData *data;
945  while ((data=(TRealData*)next())) {
946  TDataMember *member = data->GetDataMember();
947 
948  // These guys are for sure of no interest;
949  if (!member->IsPersistent()) continue;
950 
951  // Deal with basic types only for now;
952  if (!member->IsBasic()) continue;
953 
954  // Not really interested in these guys either;
955  if (!strcmp(data->GetName(), "fUniqueID") || !strcmp(data->GetName(), "fBits")) continue;
956  if (!strcmp(data->GetName(), "mVersion") || !strcmp(data->GetName(), "mSubVersion")) continue;
957  if (!strcmp(data->GetName(), "mTimeStamp.fSec") ||
958  !strcmp(data->GetName(), "mTimeStamp.fNanoSec"))
959  continue;
960 
961  printf("%-30s (%-10s):", data->GetName(), member->GetFullTypeName());
962 
963  Long_t offset = member->GetOffset();
964 
965  if (!strcmp(member->GetFullTypeName(), "Double_t"))
966  printf(" %f\n", *(Double_t*)((char*)this + offset));
967  else if (!strcmp(member->GetFullTypeName(), "Int_t"))
968  printf(" %d\n", *(Int_t*)((char*)this + offset));
969  else if (!strcmp(member->GetFullTypeName(), "UInt_t"))
970  printf(" %u\n", *(UInt_t*)((char*)this + offset));
971  else if (!strcmp(member->GetFullTypeName(), "Bool_t"))
972  printf(" %s\n", *(Bool_t*)((char*)this + offset) ? "true" : "false");
973  } //while
974 } // EicGeoParData::Print()
975 
976 /* ========================================================================== */
977 
978 TVector3 LocalToMaster (const TGeoMatrix *mtx, const TVector3& local)
979 {
980  double xlocal[3] = {local.X(), local.Y(), local.Z()}, xmaster[3];
981 
982  mtx->LocalToMaster(xlocal, xmaster);
983 
984  return TVector3(xmaster[0], xmaster[1], xmaster[2]);
985 } // LocalToMaster()
986 
987 // ---------------------------------------------------------------------------------------
988 
989 TVector3 LocalToMasterVect(const TGeoMatrix *mtx, const TVector3& local)
990 {
991  double xlocal[3] = {local.X(), local.Y(), local.Z()}, xmaster[3];
992 
993  mtx->LocalToMasterVect(xlocal, xmaster);
994 
995  return TVector3(xmaster[0], xmaster[1], xmaster[2]);
996 } // LocalToMasterVect()
997 
998 // ---------------------------------------------------------------------------------------
999 
1000 TVector3 MasterToLocal (const TGeoMatrix *mtx, const TVector3& master)
1001 {
1002  double xmaster[3] = {master.X(), master.Y(), master.Z()}, xlocal[3];
1003 
1004  mtx->MasterToLocal(xmaster, xlocal);
1005 
1006  return TVector3(xlocal[0], xlocal[1], xlocal[2]);
1007 } // MasterToLocal()
1008 
1009 // ---------------------------------------------------------------------------------------
1010 
1011 TVector3 MasterToLocalVect(const TGeoMatrix *mtx, const TVector3& master)
1012 {
1013  double xmaster[3] = {master.X(), master.Y(), master.Z()}, xlocal[3];
1014 
1015  mtx->MasterToLocalVect(xmaster, xlocal);
1016 
1017  return TVector3(xlocal[0], xlocal[1], xlocal[2]);
1018 } // MasterToLocalVect()
1019 
1020 // =======================================================================================
1021 
1027