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 <stdlib.h>
8 #include <assert.h>
9 #include <iostream>
10 // This is needed for Mac OS only;
11 #ifdef __APPLE__
12 #include <unistd.h>
13 #include <libgen.h>
14 #endif
15 
16 #include <TRealData.h>
17 #include <TDataMember.h>
18 
19 #include <PndGeoHandling.h>
20 
21 #include <EicGeoParData.h>
22 
23 using std::cout;
24 using std::endl;
25 
26 // =======================================================================================
27 
28 //
29 // Constructor & Co
30 //
31 
33 {
35  mTestGeometryFlag = false;
37 
38  {
39  char user[128], host[128];
40 
41  getlogin_r(user, 128-1);
42  gethostname(host, 128-1);
43  mAuthor = TString(user) + "@" + host;
44  }
45 
46  mTimeStamp = TTimeStamp();
47 
49 
51  mGeoLoad = 0; mGeoFace = 0; mFairMedia = 0; mGeobuild = 0;
52 
54 } // EicGeoParData::ResetVars()
55 
56 // ---------------------------------------------------------------------------------------
57 
58 EicGeoParData::EicGeoParData(const char *detName, int version, int subVersion):
59  mVersion(version), mSubVersion(subVersion)
60 {
61  ResetVars();
62 
63  // Well, default constructor of some detectors (like VST) will call VstGeoParData()
64  // as EicGeoParData("VST"); so can not just check on detName=0 here in order to see
65  // whether I reached this place from EicDetector::ConstructGeometry() when ROOT
66  // streamer imported EicGeoParData block, rather than from geometry-producing script
67  // like vst.C; do not want to change default calls for those constructors; so
68  // conventionally check here on FairRun::Instance() and do not mess up with the running
69  // FairRun if it was instantiated (meaning most likely from under the running simulation);
70  if (FairRun::Instance()) return;
71 
72  // No ExpnandedFileName() tricks here, please;
73  TString mediaFileName = TString(getenv("VMCWORKDIR")) + "/geometry/media.geo";
74 
75  // Create detector name class;
76  mDetName = new EicDetName(detName);
77 
79  new FairGeoLoader("TGeo", "FairGeoLoader");
81 
82  mGeoFace->setMediaFile(mediaFileName);
84 
87 
88  // Initialize Geo manager and create basic geometry volume structure;
89  mRootGeoManager = new TGeoManager();
90 
91  // It looks like 2-level layout (with an extra MASTER volume) is required by FairRoot;
92  mWrapperVolume = new TGeoVolumeAssembly(mDetName->Name() + "GeantGeoWrapper");
93  mTopVolume = new TGeoVolumeAssembly(mDetName->NAME());
94 
95  mRootGeoManager->SetTopVolume(mWrapperVolume);
96 } // EicGeoParData::EicGeoParData()
97 
98 // =======================================================================================
99 
100 //
101 // Mapping file creation part
102 //
103 
105 {
106  EicGeoMap *map = new EicGeoMap();
107  mGeantVolumeMaps.push_back(map);
108  return map;
109 } // EicGeoParData::CreateNewMap()
110 
111 // ---------------------------------------------------------------------------------------
112 
113 int EicGeoParData::AddLogicalVolumeGroup(unsigned dimX, unsigned dimY, unsigned dimZ)
114 {
116  printf("Logical table size is full (%d entries)!\n", (unsigned)_LOGICAL_GROUP_NUM_MAX_);
117  return -1;
118  } //if
119 
120  // Arrange a unified access;
121  unsigned dim[_LOGICAL_VOLUME_GROUP_COORD_NUM_] = {dimX, dimY, dimZ}, max = 0;
122 
123  // NB: there can be 0 dimensions in the middle -> so really want to see what is
124  // the max one before populating the vector;
125  for(unsigned iq=0; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++)
126  if (dim[iq]) max = iq;
127 
128  LogicalVolumeGroup *group = new LogicalVolumeGroup();
129 
130  unsigned accu = 0;
131  for(unsigned iq=0; iq<=max; iq++)
132  if (dim[iq]) {
134 
135  EicBitMask<ULogicalIndex_t> *mask = coord->mBitMask;
136 
137  mask->SetShift(accu);
138  accu += mask->GetBitNum();
139 
140  group->mProjections.push_back(coord);
141  }
142  else
143  group->mProjections.push_back(0);
144 
145  // FIXME: do a better check later;
146  assert(accu <= _LOGICAL_XYZ_BIT_NUM_);
147 
148  mLogicalVolumeGroups.push_back(group);
149 
150  //return 0;
151  return mLogicalVolumeGroups.size() - 1;
152 } // EicGeoParData::AddLogicalVolumeGroup()
153 
154 // ---------------------------------------------------------------------------------------
155 
156 int EicGeoParData::SetCircularCore(unsigned group, unsigned what)
157 {
158  // FIXME: these few lines should be shaped up as a routine!;
159  if (group >= mLogicalVolumeGroups.size()) return -1;
160 
161  const std::vector<LogicalVolumeGroupProjection*> &coords =
162  mLogicalVolumeGroups[group]->mProjections;
163 
164  if (what >= coords.size() || !coords[what]) return -1;
165 
166  coords[what]->mCircular = true;
167 
168  return 0;
169 } // EicGeoParData::SetCircularCore()
170 
171 // ---------------------------------------------------------------------------------------
172 
173 Int_t EicGeoParData::SetMappingTableEntry(EicGeoMap *map, const unsigned geo[],
174  unsigned group, unsigned logical[])
175 {
176  if (!map || !geo || !logical) {
177  printf("-E- EicGeoParData::SetMappingTableEntry(): zero pointer(s) used as arguments!\n");
178  return -1;
179  } //if
180 
181  if (group >= _LOGICAL_GROUP_NUM_MAX_) {
182  printf("-E- EicGeoParData::SetMappingTableEntry(): group index '%d' exceeds '%d'!\n",
183  group, (unsigned)_LOGICAL_GROUP_NUM_MAX_);
184  return -1;
185  } //if
186 
187  // Pack logical[] array into a single ULogicalIndex_t value;
189 
190  if (group >= mLogicalVolumeGroups.size()) {
191  printf("-E- EicGeoParData::SetMappingTableEntry(): group index '%d' exceeds "
192  "configured array size (%d)!\n", group, (unsigned)mLogicalVolumeGroups.size());
193  return -1;
194  } //if
195  const std::vector<LogicalVolumeGroupProjection*> &coords =
196  mLogicalVolumeGroups[group]->mProjections;
197 
198  for(unsigned iq=0; iq<coords.size(); iq++) {
199  // Zero logical[] value will not contribute anyway;
200  if (!logical[iq]) continue;
201 
202  LogicalVolumeGroupProjection *coord = coords[iq];
203 
204  // NB: this check is sufficient to guarantee, that overflow in "value"
205  // can not happen (because overall mask/shift consistency was checked
206  // during mProjectionDescriptors creation);
207  if (!coord) {
208  printf("-E- EicGeoParData::SetMappingTableEntry(): coordinate '%d' was not configured!\n", iq);
209  return -1;
210  } //if
211  if (logical[iq] >= coord->mMaxEntryNum) {
212  printf("-E- EicGeoParData::SetMappingTableEntry(): logical index #%d (%d) exceeds "
213  "max configured entry num (%d)!\n", iq, logical[iq], (unsigned)coord->mMaxEntryNum);
214  return -1;
215  } //if
216 
217  // This is guaranteed no be non-zero by mProjectionDescriptors initialization;
218  EicBitMask<ULogicalIndex_t> *mask = coord->mBitMask;
219 
220  value |= (logical[iq] & mask->GetBitMask()) << mask->GetShift();
221  } //for iq
222 
223  return map->SetMappingTableEntry(geo, value);
224 } // EicGeoParData::SetMappingTableEntry()
225 
226 // ---------------------------------------------------------------------------------------
227 
228 //#include <EicMagneticFieldMap.h>
229 
230 SourceFile::SourceFile(const char *fileName): mFileSize(0), mFileContent(0), mOkFlag(false)
231 {
232  // This will also be the default constructor case;
233  if (!fileName) return;
234 
235  FILE *fin = fopen(fileName, "r");
236  if (!fin) {
237  printf("-E- SourceFile::SourceFile(): file '%s' does not exist!\n", fileName);
238  return;
239  } //if
240 
241  // NB: strip directory name;
242  {
243  // FIXME: unify with EicMagneticFieldMap::BasenameWrapper() at some point;
244  char buffer[1024];
245  snprintf(buffer, 1024-1, "%s", fileName);
246 
247  mFileName = TString(basename(buffer));
248  }
249 
250  // FIXME: there is perhaps a better way to do this?; then change EicStlFile.cxx as well;
251  fseek(fin, 0, SEEK_END);
252  mFileSize = ftell(fin);
253 
254  mFileContent = new UChar_t[mFileSize];
255 
256  rewind(fin);
257  if (fread(mFileContent, 1, mFileSize, fin) == mFileSize)
258  mOkFlag = true;
259  else
260  delete [] mFileContent;
261 
262  fclose(fin);
263 } // SourceFile::SourceFile()
264 
265 // ---------------------------------------------------------------------------------------
266 
268 {
269  if (!IsOk()) return;
270 
271  printf("\n Attached file name: %s\n", mFileName.Data());
272  printf(" --------------------");
273  for(unsigned iq=0; iq<mFileName.Length(); iq++)
274  printf("-");
275 
276  // Do not overcomplicate things -> just dump to output assuming it was a clean ASCII file;
277  printf("\n\n%s\n", mFileContent);
278 } // SourceFile::Print()
279 
280 // ---------------------------------------------------------------------------------------
281 
282 void EicGeoParData::PrintAttachedSourceFile(const char *fileName)
283 {
284  for(unsigned fl=0; fl<mSourceFiles.size(); fl++) {
286 
287  if (file->GetFileName().EqualTo(fileName)) {
288  file->Print();
289  return;
290  } //if
291  } //for fl
292 
293  printf("\n No file '%s' was attached!\n", fileName);
294 } // EicGeoParData::PrintAttachedSourceFile()
295 
296 // ---------------------------------------------------------------------------------------
297 
298 int EicGeoParData::AttachSourceFile(const char *fileName)
299 {
300  SourceFile *file = new SourceFile(fileName);
301 
302  if (file->IsOk()) {
303  mSourceFiles.push_back(file);
304 
305  return 0;
306  }
307  else {
308  //delete file;
309  return -1;
310  } //if
311 } // EicGeoParData::AttachSourceFile()
312 
313 // ---------------------------------------------------------------------------------------
314 
315 const TGeoMedium *EicGeoParData::GetMedium(const char *medium)
316 {
317  if (!mRootGeoManager) return 0;
318 
319  if (!mMediaCache.count(medium))
320  {
321  FairGeoMedium *fmedium = mFairMedia->getMedium(medium);
322  mGeobuild->createMedium(fmedium);
323 
324  mMediaCache.insert(medium);
325  } //if
326 
327  return mRootGeoManager->GetMedium(medium);
328 } // EicGeoParData::GetMedium()
329 
330 // ---------------------------------------------------------------------------------------
331 
332 TString EicGeoParData::GetGeometryFileName(bool root) const
333 {
334  const char *suffix = root ? ".root" : ".gdml";
335  // If file is given, use it;
336  if (!mFileName.IsNull()) return mFileName;
337 
338  // If file name format is given and version is defined, use them;
339  if (!mFileNameFormat.IsNull()/* && GetVersion() >= 0*/) {
340  char fileName[128];
341 
342  if (GetVersion() >= 0)
343  snprintf(fileName, 128-1, mFileNameFormat.Data(), GetVersion(), GetSubVersion());
344  else
345  // At least Clang prefers it this way;
346  snprintf(fileName, 128-1, "%s", mFileNameFormat.Data());
347 
348  return TString(fileName);
349  } //if
350 
351  // Detector name is not known -> can hardly do anything -> return empty string;
352  if (!mDetName) return TString("");
353 
354  // Test geometry -> return non-version file name with 'test' suffix;
355  if (IsTestGeometry()) return mDetName->name() + "-test.root";
356 
357  // Otherwise compose a default name out of detector name, version and subversion;
358  char version[128] = "";
359  if (GetVersion() >= 0)
360  snprintf(version, 128-1, "-v%02d.%d", GetVersion(), GetSubVersion());
361 
362  switch (GetGeometryType()) {
364  return mDetName->name() + version + suffix;//".root";
366  return mDetName->name() + version + "-ns" + suffix;//.root";
368  return mDetName->name() + version + "-ss" + suffix;//.root";
370  return mDetName->name() + version + "-fs" + suffix;// .root";
371  default:
372  {
373  // Make the compiler happy;
374  assert(0); return "";
375  }
376  } //switch
377 } // EicGeoParData::GetGeometryFileName()
378 
379 // ---------------------------------------------------------------------------------------
380 
381 void EicGeoParData::FinalizeOutput(bool root, bool gdml, bool check) //const
382 {
383  if (!mRootGeoManager) return;
384 
385  // Set up colors and transparency values;
386  {
387  TIter next( mRootGeoManager->GetListOfVolumes() );
388 
389  TGeoVolume *volume;
390 
391  while ((volume=(TGeoVolume*)next())) {
392  //TString name = volume->GetName();
393  //cout << volume->GetName() << endl;
394 
395  const std::pair<TString, Color_t> *cpattern = GetColorTable()->AnyMatch(volume->GetName());
396 
397  if (cpattern) {
398  volume->SetLineColor(cpattern->second);
399  volume->SetFillColor(cpattern->second);
400 
401  // And check if transparency value is set;
402  {
403  const std::pair<TString, Char_t> *tpattern = GetTransparencyTable()->AnyMatch(volume->GetName());
404 
405  // FIXME: well, this 4000-based stuff indeed looks like a hack;
406  if (tpattern) volume->SetFillStyle(4000 + tpattern->second);
407  }
408  }
409  else
410  volume->SetVisibility(kFALSE);
411  } //while
412  }
413 
414  // Add configured detector to the top volume, with a proper 3D transformation;
416 
417  // Check overlap (1um accuracy) and export;
418  mRootGeoManager->CloseGeometry();
419  //#if _TODAY_
420  if (check) mRootGeoManager->CheckOverlaps(0.0001);
421  //#endif
422 
423  if (root) {
424  TFile *outputFile = new TFile(GetGeometryFileName(true).Data(), "RECREATE");
425 
426  if (outputFile) {
427  mWrapperVolume->Write();
428 
429  // Save geometry (mapping) parameters in the same file;
430  Write(mDetName->Name() + "GeoParData");
431 
432  outputFile->Close();
433  } //if
434  } //if
435 
436  if (gdml) mRootGeoManager->Export(GetGeometryFileName(false).Data());
437 } // EicGeoParData::FinalizeOutput()
438 
439 // =======================================================================================
440 
441 //
442 // Service routines
443 //
444 
445 // FIXME: unify part of these calls later;
446 
447 unsigned EicGeoParData::GetDimCore(unsigned group, unsigned what) const
448 {
449  if (group >= mLogicalVolumeGroups.size()) return 0;
450 
451  const std::vector<LogicalVolumeGroupProjection*> &coords =
452  mLogicalVolumeGroups[group]->mProjections;
453 
454  return (what < coords.size() && coords[what] ? coords[what]->mMaxEntryNum : 0);
455 } // EicGeoParData::GetDimCore()
456 
457 // ---------------------------------------------------------------------------------------
458 
459 unsigned EicGeoParData::GetLogicalCoordCore(unsigned what, ULogicalIndex_t logicalID) const
460 {
461  unsigned group = GetGroup(logicalID);
462 
463  if (group >= mLogicalVolumeGroups.size()) return 0;
464 
465  const std::vector<LogicalVolumeGroupProjection*> &coords =
466  mLogicalVolumeGroups[group]->mProjections;
467 
468  if (what >= coords.size() || !coords[what]) return 0;
469 
470  EicBitMask<ULogicalIndex_t> *mask = coords[what]->mBitMask;
471 
472  return ((logicalID >> mask->GetShift()) & mask->GetBitMask());
473 } // EicGeoParData::GetLogicalCoordCore()
474 
475 // ---------------------------------------------------------------------------------------
476 
477 bool EicGeoParData::GetCircularCore(unsigned group, unsigned what) const
478 {
479  if (group >= mLogicalVolumeGroups.size()) return false;
480 
481  const std::vector<LogicalVolumeGroupProjection*> &coords =
482  mLogicalVolumeGroups[group]->mProjections;
483 
484  if (what >= coords.size() || !coords[what]) return false;
485 
486  return coords[what]->mCircular;
487 } // EicGeoParData::GetCircularCore()
488 
489 // =======================================================================================
490 //
491 // Part used in simulation.C & Co
492 //
493 
495 {
496  mMaxVolumeLevelNum = 0;
497 
498  // Loop through all the maps, calculate bitwise shifts and identify volumes;
499  for(int iq=0; iq<mGeantVolumeMaps.size(); iq++)
500  {
501  EicGeoMap *fmap = mGeantVolumeMaps[iq];
502 
503  if (fmap->CalculateMappingTableSignature()) return -1;
504 
505  // Also use this same loop to get max number of levels;
508  } //for iq
509 
510  return 0;
511 } // EicGeoParData::CalculateMappingTableSignatures()
512 
513 // =======================================================================================
514 
515 //
516 // Part used in digitization.C & Co
517 //
518 
520 {
521  for(unsigned gr=0; gr<mLogicalVolumeGroups.size(); gr++) {
523 
524  vgroup->mDim3D = 1;
525 
526  for(unsigned iq=0; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++) {
527  vgroup->mRealDim[iq] = GetDim(gr,iq) ? GetDim(gr,iq) : 1;
528  vgroup->mDim3D *= vgroup->mRealDim[iq];
529  } //for iq
530 
531  vgroup->mLookup = new LogicalVolumeLookupTableEntry[vgroup->mDim3D];
532  } //for gr
533 
534  TString returnBackPath = gGeoManager->GetPath();
535 
536  // Loop through all maps, figure out their "cell" levels (like where "femcTower" is),
537  // loop through all map look-up table entries, construct respective geo node pointers,
538  // get shape, etc info and put all this into the 2D (3D) lookup table;
539  for(int iq=0; iq<mGeantVolumeMaps.size(); iq++) {
540  int cellLevel = -1;
541 
542  const EicGeoMap *fmap = GetMapPtrViaMapID(iq);
543 
544  {
545  const TString &containerName = fmap->GetSingleSensorContainerVolumeName();
546 
547  if (containerName.IsNull()) continue;
548 
549  for(int lv=0; lv<fmap->GetGeantVolumeLevelNum(); lv++) {
550  const GeantVolumeLevel *lptr = fmap->GetGeantVolumeLevelPtr(lv);
551 
552  if (lptr->GetVolumeName().EqualTo(containerName)) {
553  cellLevel = lv;
554  break;
555  } //if
556  } //for lv
557 
558  // FIXME: remove later (means map is incorrect);
559  assert(cellLevel != -1);
560 
561  // No matching level name -> map is of no interest;
562  if (cellLevel == -1) continue;
563  }
564 
565  // Well, this basically means there were no hits in sensitive volumes
566  // served by this map (so assignment in EicDetector::GetNodeMultiIndex()
567  // routine has never been reached; in other words, map is useless, skip);
568  if (fmap->GetBaseVolumePath()->IsNull()) continue;
569 
570  // Loop through all map entries;
571  for(UGeantIndex_t ent=0; ent<fmap->GetMappingTableDim(); ent++) {
572  ULogicalIndex_t entry = fmap->GetMappingTable()[ent];
573 
574  if (entry == ~ULogicalIndex_t(0)) continue;
575 
576  TString vPath(*fmap->GetBaseVolumePath());
577  for(int lv=fmap->GetGeantVolumeLevelNum()-1; lv>=cellLevel; lv--) {
578  const GeantVolumeLevel *lptr = fmap->GetGeantVolumeLevelPtr(lv);
579 
580  // Node ID; this should be a method of course; fix later;
581  UGeantIndex_t nID = lptr->GetMaskedBits(ent);
582 
583  char buffer[128];
584  snprintf(buffer, 128-1, "%d", nID);
585  vPath += "/" + lptr->GetVolumeName() + "_" + buffer;
586  } //for lv
587 
588  // This is indeed a CPU-consuming process; may want to do on-the-fly for
589  // the needed cells only;
590  gGeoManager->cd(vPath);
591  TGeoNode *gNode = gGeoManager->GetCurrentNode();
593  assert(node);
594  //node->mLogicalID = entry;
595  node->mGeoNode = gNode;
596  node->mVolumePath = vPath;
597  // Yes, gGeoManager->GetCurrentMatrix() is a pointer to whatever
598  // buffer matrix -> reallocate new instead of copy pointer;
599  node->mGeoMtx = new TGeoHMatrix(*gGeoManager->GetCurrentMatrix());
600 
601  // Add entry to the reversed lookup table;
602  mGeantToLogicalLookupTable[gNode] = node;
603  } //for ent
604  } //for iq
605 
606  gGeoManager->cd(returnBackPath);
607 } // EicGeoParData::InitializeLookupTables()
608 
609 // ---------------------------------------------------------------------------------------
610 
612 {
613  unsigned group = GetGroup(xy);
614 
615  if (group >= mLogicalVolumeGroups.size()) return 0;
616 
617  LogicalVolumeGroup *vgroup = mLogicalVolumeGroups[group];
618 
619  unsigned offset = GetCoord(0, xy);
620 
621  for(unsigned iq=1; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++)
622  offset = offset*vgroup->mRealDim[iq] + GetCoord(iq, xy);
623 
624  return vgroup->mLookup + offset;
625 } // EicGeoParData::GetLookupTableNode()
626 
627 // ---------------------------------------------------------------------------------------
628 
630 {
631  // Sanity check;
632  if (!node) return 0;
633 
634  // No such entry?;
635  if (mGeantToLogicalLookupTable.find(node) == mGeantToLogicalLookupTable.end()) return 0;
636 
637  return mGeantToLogicalLookupTable.at(node);
638 } // EicGeoParData::GetLookupTableNode()
639 
640 // ---------------------------------------------------------------------------------------
641 
643 {
644  unsigned mapId = unsigned((multi >> _GEANT_INDEX_BIT_NUM_) & _SERVICE_BIT_MASK_);
646 
647  return mapId < mGeantVolumeMaps.size() ?
648  mGeantVolumeMaps[mapId]->GeantToLogicalIndex(idL) : ~ULogicalIndex_t(0);
649 } // EicGeoParData::GeantMultiToLogicalIndex()
650 
651 // =======================================================================================
652 
653 //
654 // Part used in reconstruction.C & Co
655 //
656 
657 bool EicGeoParData::AreNeighbours(ULogicalIndex_t g1, ULogicalIndex_t g2, unsigned maxLinearDist,
658  unsigned maxChebyshevDist) const
659 {
660  if (GetGroup(g1) != GetGroup(g2)) return false;
661 
662  int x1 [3] = {GetX(g1), GetY(g1), GetZ(g1)};
663  int x2 [3] = {GetX(g2), GetY(g2), GetZ(g2)};
664  unsigned dim [3] = {GetDimX(), GetDimY(), GetDimZ()}, distChebyshev = 0;
665  bool circ [3] = {GetCircularX(), GetCircularY(), GetCircularZ()};
666 
667  // Loop through all 3 dimensions and drop out as soon as any of the
668  // specified limits are exceeded;
669  for(unsigned iq=0; iq<_LOGICAL_VOLUME_GROUP_COORD_NUM_; iq++)
670  {
671  // This dimension is of no interest; actually dim=1 should also be skipped?;
672  if (!dim[iq]) continue;
673 
674  UInt_t dist = abs(x2[iq] - x1[iq]);
675  // If this dimension is circular, check other option as well
676  // and select smaller one; whould be a range check here?; fix later;
677  if (circ[iq])
678  {
679  UInt_t cdist = dim[iq] - dist;
680  if (cdist < dist) dist = cdist;
681  } //if
682 
683  // Linear distance is too large; NB: in principle it is not necessary to have
684  // maxLinearDist=1; nothing prevents from say searching for low-energy-deposit
685  // clusters "far enough" from the main blob;
686  if (dist > maxLinearDist) return false;
687 
688  // No this check per default;
689  if (maxChebyshevDist)
690  {
691  distChebyshev += dist;
692 
693  // 2D (or 3D) distance is too large; idea is to be able to suppress 2D-diagonal
694  // neighbourships for 2D-maps as well as 3D-diagonal (or even 2D-diagonal) ones
695  // for 3D-maps;
696  if (distChebyshev > maxChebyshevDist) return false;
697  } //if
698  } //for iq
699 
700  // Passed all checks -> they are neighbors;
701  return true;
702 } // EicGeoParData::AreNeighbours()
703 
704 // =======================================================================================
705 
706 void EicGeoParData::Print(const char *option) const
707 {
708  // Figure out class name and version;
709  printf("\nClass name: %s (v.%d); object name: %s\n\n",
710  ClassName(), Class()->GetClassVersion(), GetName());
711 
712  // Author;
713  printf("Created by %s\n\n", mAuthor.Data());
714 
715  // Creation time;
716  mTimeStamp.Print("l");
717 
718  // Version, subversion and comment;
719  if (mVersion != -1) printf("\nVersion: v%02d.%d; comment: %s\n\n", mVersion, mSubVersion,
720  mComment.IsNull() ? "-" : mComment.Data());
721 
722  // Class() method returns EicGeoParData instead of say VstGeoParData; so call
723  // gROOT->GetClass() instead; need to verify that this will work under all circumstances;
724  //TList *dataList = Class()->GetListOfRealData();
725  TList *dataList = gROOT->GetClass(ClassName())->GetListOfRealData();
726  TIter next(dataList);
727 
728  // For now handle POD variables of basic types;
729  printf(" Basic type variables:\n");
730  printf(" ---------------------\n\n");
731 
732  TRealData *data;
733  while ((data=(TRealData*)next())) {
734  TDataMember *member = data->GetDataMember();
735 
736  // These guys are for sure of no interest;
737  if (!member->IsPersistent()) continue;
738 
739  // Deal with basic types only for now;
740  if (!member->IsBasic()) continue;
741 
742  // Not really interested in these guys either;
743  if (!strcmp(data->GetName(), "fUniqueID") || !strcmp(data->GetName(), "fBits")) continue;
744  if (!strcmp(data->GetName(), "mVersion") || !strcmp(data->GetName(), "mSubVersion")) continue;
745  if (!strcmp(data->GetName(), "mTimeStamp.fSec") ||
746  !strcmp(data->GetName(), "mTimeStamp.fNanoSec"))
747  continue;
748 
749  printf("%-30s (%-10s):", data->GetName(), member->GetFullTypeName());
750 
751  Long_t offset = member->GetOffset();
752 
753  if (!strcmp(member->GetFullTypeName(), "Double_t"))
754  printf(" %f\n", *(Double_t*)((char*)this + offset));
755  else if (!strcmp(member->GetFullTypeName(), "Int_t"))
756  printf(" %d\n", *(Int_t*)((char*)this + offset));
757  else if (!strcmp(member->GetFullTypeName(), "UInt_t"))
758  printf(" %u\n", *(UInt_t*)((char*)this + offset));
759  else if (!strcmp(member->GetFullTypeName(), "Bool_t"))
760  printf(" %s\n", *(Bool_t*)((char*)this + offset) ? "true" : "false");
761  } //while
762 } // EicGeoParData::Print()
763 
764 /* ========================================================================== */
765 
766 TVector3 LocalToMaster (const TGeoMatrix *mtx, const TVector3& local)
767 {
768  double xlocal[3] = {local.X(), local.Y(), local.Z()}, xmaster[3];
769 
770  mtx->LocalToMaster(xlocal, xmaster);
771 
772  return TVector3(xmaster[0], xmaster[1], xmaster[2]);
773 } // LocalToMaster()
774 
775 // ---------------------------------------------------------------------------------------
776 
777 TVector3 LocalToMasterVect(const TGeoMatrix *mtx, const TVector3& local)
778 {
779  double xlocal[3] = {local.X(), local.Y(), local.Z()}, xmaster[3];
780 
781  mtx->LocalToMasterVect(xlocal, xmaster);
782 
783  return TVector3(xmaster[0], xmaster[1], xmaster[2]);
784 } // LocalToMasterVect()
785 
786 // ---------------------------------------------------------------------------------------
787 
788 TVector3 MasterToLocal (const TGeoMatrix *mtx, const TVector3& master)
789 {
790  double xmaster[3] = {master.X(), master.Y(), master.Z()}, xlocal[3];
791 
792  mtx->MasterToLocal(xmaster, xlocal);
793 
794  return TVector3(xlocal[0], xlocal[1], xlocal[2]);
795 } // MasterToLocal()
796 
797 // ---------------------------------------------------------------------------------------
798 
799 TVector3 MasterToLocalVect(const TGeoMatrix *mtx, const TVector3& master)
800 {
801  double xmaster[3] = {master.X(), master.Y(), master.Z()}, xlocal[3];
802 
803  mtx->MasterToLocalVect(xmaster, xlocal);
804 
805  return TVector3(xlocal[0], xlocal[1], xlocal[2]);
806 } // MasterToLocalVect()
807 
808 // =======================================================================================
809