DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Volumes.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Detector.h>
16 #include <DD4hep/Printout.h>
17 #include <DD4hep/InstanceCount.h>
18 #include <DD4hep/MatrixHelpers.h>
20 
21 // ROOT include files
22 #include <TROOT.h>
23 #include <TClass.h>
24 #include <TColor.h>
25 #include <TGeoShape.h>
26 #include <TGeoVolume.h>
27 #include <TGeoNode.h>
28 #include <TGeoMatrix.h>
29 #include <TGeoMedium.h>
30 
31 #include <TGeoVoxelFinder.h>
32 #include <TGeoShapeAssembly.h>
33 #include <TGeoScaledShape.h>
34 #include <TMap.h>
35 
36 // C/C++ include files
37 #include <climits>
38 #include <iostream>
39 #include <stdexcept>
40 #include <sstream>
41 #include <iomanip>
42 
43 using namespace dd4hep;
44 
45 /*
46  * The section below uses the new ROOT features using user extensions to volumes
47  * and placements. Once this is common, the above mechanism should be thrown away....
48  *
49  * M.Frank
50  */
51 
52 typedef TGeoNode geo_node_t;
53 typedef TGeoVolume geo_volume_t;
54 typedef TGeoVolumeAssembly geo_assembly_t;
55 
60 
61 namespace {
62 
63  static constexpr double s_rotation_test_limit = 1e-12;
64  static bool s_verifyCopyNumbers = true;
65 
66  template <typename T> typename T::Object* _userExtension(const T& v) {
67  typedef typename T::Object O;
68  O* o = (O*)(v.ptr()->GetUserExtension());
69  return o;
70  }
71 
72  TGeoVolume* _createTGeoVolume(const std::string& name, TGeoShape* s, TGeoMedium* m) {
73  geo_volume_t* e = new geo_volume_t(name.c_str(),s,m);
74  e->SetUserExtension(new Volume::Object());
75  return e;
76  }
77  TGeoVolume* _createTGeoVolumeAssembly(const std::string& name) {
78  geo_assembly_t* e = new geo_assembly_t(name.c_str()); // It is important to use the correct constructor!!
79  e->SetUserExtension(new Assembly::Object());
80  return e;
81  }
82  TGeoVolumeMulti* _createTGeoVolumeMulti(const std::string& name, TGeoMedium* medium) {
83  TGeoVolumeMulti* e = new TGeoVolumeMulti(name.c_str(), medium);
84  e->SetUserExtension(new VolumeMulti::Object());
85  return e;
86  }
87  PlacedVolume::Object* _data(const PlacedVolume& v) {
88  PlacedVolume::Object* o = _userExtension(v);
89  if (o) return o;
90  except("PlacedVolume::_data", "+++ Attempt to access invalid handle of type: PlacedVolume");
91  return nullptr;
92  }
94  Volume::Object* _data(const Volume& v, bool throw_exception = true) {
95  //if ( v.ptr() && v.ptr()->IsA() == TGeoVolume::Class() ) return v.data<Volume::Object>();
96  Volume::Object* o = _userExtension(v);
97  if (o)
98  return o;
99  else if (!throw_exception)
100  return nullptr;
101  except("Volume::_data", "+++ Attempt to access invalid handle of type: Volume");
102  return nullptr;
103  }
104 
105  class VolumeImport {
106  public:
107  void setShapeTitle(TGeoVolume* vol) {
108  if ( vol ) {
109  TGeoShape* sh = vol->GetShape();
110  std::string tag = get_shape_tag(sh);
111  sh->SetTitle(tag.c_str());
112  }
113  }
114 
115  public:
117  void operator()(TGeoVolume* v) {
118  TClass* c = v->IsA();
119  if ( !v->GetUserExtension() ) {
120  if ( c == geo_volume_t::Class() )
121  v->SetUserExtension(new Volume::Object());
122  else if ( c == geo_assembly_t::Class() )
123  v->SetUserExtension(new Assembly::Object());
124  else if ( c == TGeoVolumeMulti::Class() )
125  v->SetUserExtension(new VolumeMulti::Object());
126  else
127  except("dd4hep","VolumeImport: Unknown TGeoVolume sub-class: %s",v->IsA()->GetName());
128  }
129  if ( c == TGeoVolumeMulti::Class() ) {
130  TGeoVolumeMulti* mv = (TGeoVolumeMulti*)v;
131  for( int i=0, n=mv->GetNvolumes(); i<n; ++i ) {
132  TGeoVolume* vol = mv->GetVolume(i);
133  this->setShapeTitle(vol);
134  (*this)(vol);
135  }
136  }
137  for( Int_t i=0; i<v->GetNdaughters(); ++i ) {
138  geo_node_t* pv = v->GetNode(i);
139  if ( !pv->GetUserExtension() )
140  pv->geo_node_t::SetUserExtension(new PlacedVolume::Object());
141  (*this)(pv->GetVolume());
142  }
143  }
145  void operator()(TGeoVolume* new_v, TGeoVolume* old_v, SensitiveDetector sd, int set_bit) {
146  if ( !new_v || !old_v ) {
147  except("dd4hep","VolumeImport: ERROR: The refected volume is INVALID!");
148  }
149  else if ( !old_v->GetUserExtension() ) {
150  except("dd4hep","VolumeImport: ERROR: Reflection of non-dd4hep volume %s",new_v->IsA()->GetName());
151  }
152  else if ( !new_v->GetUserExtension() ) {
153  TClass* c = new_v->IsA();
154  Volume old_vol(old_v);
155  Volume new_vol(new_v);
156  if ( sd.isValid() && old_vol.isSensitive() ) {
157  new_vol.setSensitiveDetector(sd);
158  }
159  if ( c == geo_volume_t::Class() ) {
160  Volume::Object *new_e, *old_e = (Volume::Object*)_data(old_vol);
161  old_e->reflected = new_v;
162  new_v->SetUserExtension(new_e = new Volume::Object(*old_e));
163  new_e->reflected = old_v;
164  }
165  else if ( c == geo_assembly_t::Class() ) {
166  Assembly::Object *new_e, *old_e = (Assembly::Object*)_data(old_vol);
167  old_e->reflected = new_v;
168  new_v->SetUserExtension(new_e = new Assembly::Object(*old_e));
169  new_e->reflected = old_v;
170  }
171  else if ( c == TGeoVolumeMulti::Class() ) {
172  VolumeMulti::Object *new_e, *old_e = (VolumeMulti::Object*)_data(old_vol);
173  TGeoVolumeMulti* new_mv = (TGeoVolumeMulti*)new_v;
174  TGeoVolumeMulti* old_mv = (TGeoVolumeMulti*)old_v;
175  new_v->SetUserExtension(new_e = new VolumeMulti::Object(*old_e));
176  old_e->reflected = new_v;
177  new_e->reflected = old_v;
178  for(int i=0, n=new_mv->GetNvolumes(); i<n; ++i) {
179  TGeoVolume* vol = new_mv->GetVolume(i);
180  this->setShapeTitle(vol);
181  (*this)(vol, old_mv->GetVolume(i), sd, set_bit);
182  }
183  }
184  else
185  except("dd4hep","VolumeImport: Unknown TGeoVolume sub-class: %s",new_v->IsA()->GetName());
186 
187  new_vol.setSensitiveDetector(old_vol.sensitiveDetector());
188  new_vol.setVisAttributes(old_vol.visAttributes());
189  new_vol.setLimitSet(old_vol.limitSet());
190  new_vol.setRegion(old_vol.region());
191 
192  if ( set_bit >= 0 ) new_vol.setFlagBit(set_bit);
193  for(Int_t i=0; i<new_v->GetNdaughters(); ++i) {
194  geo_node_t* pv = new_v->GetNode(i);
195  geo_node_t* ov = old_v->GetNode(i);
196  if ( !pv->GetUserExtension() ) {
197  auto* e = (PlacedVolume::Object*)ov->geo_node_t::GetUserExtension();
198  pv->geo_node_t::SetUserExtension(new PlacedVolume::Object(*e));
199  }
200  (*this)(pv->GetVolume(), ov->GetVolume(), sd, set_bit);
201  }
202  }
203  }
204  };
205 
206  TGeoVolume* MakeReflection(TGeoVolume* v, const char* newname=0) {
207  static TMap map(100);
208  TGeoVolume* vol = (TGeoVolume*)map.GetValue(v);
209  if ( vol ) {
210  if (newname && newname[0]) v->SetName(newname);
211  return vol;
212  }
213  vol = v->CloneVolume();
214  if (!vol) {
215  printout(ERROR,"MakeReflection", "Cannot clone volume %s\n", v->GetName());
216  return nullptr;
217  }
218  map.Add(v, vol);
219  std::string nam;
220  if (newname && newname[0]) {
221  nam = newname;
222  vol->SetName(newname);
223  }
224  else {
225  nam = v->GetName();
226  vol->SetName((nam+"_refl").c_str());
227  }
228  delete vol->GetNodes();
229  vol->SetNodes(nullptr);
230  vol->SetBit(TGeoVolume::kVolumeImportNodes, kFALSE);
231  v->CloneNodesAndConnect(vol);
232  // The volume is now properly cloned, but with the same shape.
233  // Reflect the shape (if any) and connect it.
234  if (v->GetShape()) {
235  TGeoScale* scale = new TGeoScale( 1., 1.,-1.);
236  TGeoShape* reflected_shape =
237  TGeoScaledShape::MakeScaledShape((nam+"_shape_refl").c_str(), v->GetShape(), scale);
238  vol->SetShape(reflected_shape);
239  //vol->SetShape(v->GetShape());
240  }
241  // Reflect the daughters.
242  Int_t nd = vol->GetNdaughters();
243  if ( !nd ) return vol;
244  TGeoVolume *new_vol;
245  if ( !vol->GetFinder() ) {
246  for (Int_t i=0; i < nd; i++) {
247  TGeoNodeMatrix* node = (TGeoNodeMatrix*)vol->GetNode(i);
248  TGeoMatrix* local = node->GetMatrix();
249  // printf("%s before\n", node->GetName());
250  // local->Print();
251  Bool_t reflected = local->IsReflection();
252  TGeoMatrix* local_cloned = new TGeoCombiTrans(*local);
253  local_cloned->RegisterYourself();
254  node->SetMatrix(local_cloned);
255  if (!reflected) {
256  // We need to reflect only the translation and propagate to daughters.
257  // H' = Sz * H * Sz
258  local_cloned->ReflectZ(kTRUE);
259  local_cloned->ReflectZ(kFALSE);
260  // printf("%s after\n", node->GetName());
261  // node->GetMatrix()->Print();
262  new_vol = MakeReflection(node->GetVolume());
263  node->SetVolume(new_vol);
264  continue;
265  }
266  // The next daughter is already reflected, so reflect on Z everything and stop
267  local_cloned->ReflectZ(kTRUE); // rot + tr
268  // printf("%s already reflected... After:\n", node->GetName());
269  // node->GetMatrix()->Print();
270  }
271  if ( vol->GetVoxels() ) vol->GetVoxels()->Voxelize();
272  return vol;
273  }
274  // Volume is divided, so we have to reflect the division.
275  // printf(" ... divided %s\n", fFinder->ClassName());
276  TGeoPatternFinder *new_finder = v->GetFinder()->MakeCopy(kTRUE);
277  if (!new_finder) {
278  printout(ERROR,"MakeReflection", "Could not copy finder for volume %s", v->GetName());
279  return nullptr;
280  }
281  new_finder->SetVolume(vol);
282  vol->SetFinder(new_finder);
283  TGeoNodeOffset *nodeoff;
284  new_vol = 0;
285  for (Int_t i=0; i<nd; i++) {
286  nodeoff = (TGeoNodeOffset*)vol->GetNode(i);
287  nodeoff->SetFinder(new_finder);
288  new_vol = MakeReflection(nodeoff->GetVolume());
289  nodeoff->SetVolume(new_vol);
290  }
291  return vol;
292  }
293 
294  int get_copy_number(TGeoVolume* par) {
295  TObjArray* a = par ? par->GetNodes() : 0;
296  int copy_nr = (a ? a->GetEntries() : 0);
297  return copy_nr;
298  }
299 
300 }
301 
303 void ReflectionBuilder::execute() const {
304  TGeoIterator next(detector.manager().GetTopVolume());
305  bool print_active = isActivePrintLevel(DEBUG);
306  TGeoNode *node;
307  while ( (node=next()) ) {
308  TGeoMatrix* matrix = node->GetMatrix();
309  if (matrix->IsReflection()) {
310  if ( print_active ) {
311  printout(INFO,"ReflectionBuilder","Reflection matrix:");
312  matrix->Print();
313  }
314  Volume vol(node->GetVolume());
315  TGeoMatrix* mclone = new TGeoCombiTrans(*matrix);
316  mclone->RegisterYourself();
317  // Reflect just the rotation component
318  //mclone->ReflectZ(kFALSE, kTRUE);
319  if ( print_active ) {
320  printout(INFO,"ReflectionBuilder","CLONE matrix:");
321  mclone->Print();
322  }
323  TGeoNodeMatrix* nodematrix = (TGeoNodeMatrix*)node;
324  nodematrix->SetMatrix(mclone);
325  if ( print_active ) {
326  printout(INFO,"ReflectionBuilder","Reflected volume: %s ", vol.name());
327  }
328  Volume refl = vol.reflect(vol.sensitiveDetector());
329  node->SetVolume(refl.ptr());
330  }
331  }
332 }
333 
336 }
337 
340 }
341 
344  ++refCount;
345  return this;
346 }
349  --refCount;
350  if ( 0 == refCount ) delete this;
351 }
352 
355  : TGeoExtension(), volIDs()
356 {
357  magic = magic_word();
359 }
360 
363  : TGeoExtension(c), magic(std::move(c.magic)), refCount(0), volIDs(std::move(c.volIDs)) {
365 }
366 
369  : TGeoExtension(), magic(c.magic), refCount(0), volIDs() {
371  volIDs = c.volIDs;
372 }
373 
376  if ( this->params ) this->params->release();
378 }
379 
382  magic = std::move(copy.magic);
383  params = std::move(copy.params);
384  volIDs = std::move(copy.volIDs);
385  return *this;
386 }
389  magic = copy.magic;
390  params = copy.params;
391  volIDs = copy.volIDs;
392  return *this;
393 }
394 
397  ++this->refCount;
398 #ifdef ___print_vols
399  else cout << "Placement grabbed....." << endl;
400 #endif
401  return this;
402 }
403 
406  PlacedVolumeExtension* ext = const_cast<PlacedVolumeExtension*>(this);
407  --ext->refCount;
408  if ( 0 == ext->refCount ) delete ext;
409 }
410 
412 std::vector<PlacedVolumeExtension::VolID>::const_iterator
413 PlacedVolumeExtension::VolIDs::find(const std::string& name) const {
414  for (Base::const_iterator i = this->Base::begin(); i != this->Base::end(); ++i)
415  if (name == (*i).first)
416  return i;
417  return this->end();
418 }
419 
421 std::pair<std::vector<PlacedVolumeExtension::VolID>::iterator, bool>
422 PlacedVolumeExtension::VolIDs::insert(const std::string& name, int value) {
423  Base::iterator i = this->Base::begin();
424  for (; i != this->Base::end(); ++i)
425  if (name == (*i).first)
426  break;
427  //
428  if (i != this->Base::end()) {
429  return make_pair(i, false);
430  }
431  i = this->Base::emplace(this->Base::end(), name, value);
432  return make_pair(i, true);
433 }
434 
437  std::stringstream str;
438  str << std::hex;
439  for(const auto& i : *this ) {
440  str << i.first << "=" << std::setw(4) << std::right
441  << std::setfill('0') << i.second << std::setfill(' ') << " ";
442  }
443  return str.str();
444 }
445 
448  PlacedVolume::Object* o = _userExtension(*this);
449  return o;
450 }
451 
453 const char* PlacedVolume::type() const {
454  return m_element ? m_element->IsA()->GetName() : "UNKNOWN-PlacedVolume";
455 }
456 
459  return m_element ? m_element->GetNumber() : -1;
460 }
461 
464  return Material(m_element ? m_element->GetMedium() : 0);
465 }
466 
469  return Volume(m_element ? m_element->GetVolume() : 0);
470 }
471 
474  return Volume(m_element ? m_element->GetMotherVolume() : 0);
475 }
476 
478 std::size_t PlacedVolume::num_daughters() const {
479  return m_element ? m_element->GetNdaughters() : 0;
480 }
481 
483 PlacedVolume PlacedVolume::daughter(std::size_t which) const {
484  if ( m_element ) {
485  if ( which < (std::size_t)m_element->GetNdaughters() ) {
486  return m_element->GetDaughter(which);
487  }
488  except("Volume","+++ Access daughter %ld of %s [Has only %d daughters]",
489  which, m_element->GetName(), m_element->GetNdaughters());
490  }
491  except("Volume","+++ Cannot access daughters of a non-existing volume!");
492  return nullptr;
493 }
494 
497  return _data(*this)->volIDs;
498 }
499 
501 PlacedVolume& PlacedVolume::addPhysVolID(const std::string& nam, int value) {
502  auto* o = _data(*this);
503  if ( !o->params ) {
504  o->volIDs.emplace_back(nam, value);
505  return *this;
506  }
507  if ( value > 0 ) {
508  except("PlacedVolume",
509  "+++ addPhysVolID(%s): parameterised volumes only accept '0' is volID."
510  "These automatically get overwritten with the copy number!",
511  ptr()->GetName());
512  }
513  if ( !o->volIDs.empty() ) {
514  except("PlacedVolume",
515  "+++ addPhysVolID(%s): parameterised volumes can only host 1 physical volume ID."
516  " vol id '%s' is already defined!", ptr()->GetName(), o->volIDs[0].first.c_str());
517  }
518  for(PlacedVolume pv : o->params->placements) {
519  auto* p = _data(pv);
520  p->volIDs.emplace_back(nam, pv->GetNumber());
521  }
522  return *this;
523 }
524 
526 const TGeoMatrix& PlacedVolume::matrix() const {
527  if ( !isValid() ) {
528  except("PlacedVolume","+++ matrix: Failed to access invalid PlacedVolume! [Invalid handle]");
529  }
530  return *(m_element->GetMatrix());
531 }
532 
535  const double* ptr = matrix().GetTranslation();
536  return Position(ptr[0],ptr[1],ptr[2]);
537 }
538 
540 std::string PlacedVolume::toString() const {
541  std::stringstream str;
542  Object* obj = _data(*this);
543  str << m_element->GetName() << ": vol='" << m_element->GetVolume()->GetName()
544  << "' mat:'" << m_element->GetMatrix()->GetName()
545  << "' volID[" << obj->volIDs.size() << "] ";
546  for (VolIDs::const_iterator i = obj->volIDs.begin(); i != obj->volIDs.end(); ++i)
547  str << (*i).first << "=" << (*i).second << " ";
548  str << std::ends;
549  return str.str();
550 }
551 
554 : TGeoExtension(), region(), limits(), vis(), sens_det() {
556 }
557 
560  detail::deletePtr(properties);
561  region.clear();
562  limits.clear();
563  vis.clear();
564  sens_det.clear();
566 }
567 
570  this->copy(c);
571 }
572 
575  this->copy(c);
576  return *this;
577 }
578 
581  if ( this != &c ) {
582  magic = c.magic;
583  region = c.region;
584  limits = c.limits;
585  vis = c.vis;
586  sens_det = c.sens_det;
588  detail::deletePtr(properties);
589  if ( c.properties ) {
590  properties = new TList();
591  properties->SetOwner();
592  TIter next(properties);
593  TNamed *property;
594  while ((property = (TNamed*)next())) properties->Add(new TNamed(*property));
595  }
596  }
597 }
598 
601  VolumeExtension* ext = const_cast<VolumeExtension*>(this);
602  ++ext->refCount;
603 #ifdef ___print_vols
604  if ( ext->sens_det.isValid() )
605  cout << "Volume grabbed with valid sensitive detector....." << endl;
606  else
607  cout << "Volume grabbed....." << endl;
608 #endif
609  return ext;
610 }
611 
614  VolumeExtension* ext = const_cast<VolumeExtension*>(this);
615  --ext->refCount;
616  if ( 0 == ext->refCount ) {
617 #ifdef ___print_vols
618  cout << "Volume deleted....." << endl;
619 #endif
620  delete ext;
621  }
622  else {
623 #ifdef ___print_vols
624  cout << "VolumeExtension::Release::refCount:" << ext->refCount << endl;
625 #endif
626  }
627 }
628 
630 Volume::Volume(const std::string& nam) {
631  m_element = _createTGeoVolume(nam,0,0);
632 }
633 
635 Volume::Volume(const std::string& nam, const std::string& title) {
636  m_element = _createTGeoVolume(nam,0,0);
637  m_element->SetTitle(title.c_str());
638 }
639 
641 Volume::Volume(const std::string& nam, const Solid& sol, const Material& mat) {
642  m_element = _createTGeoVolume(nam, sol.ptr(), mat.ptr());
643 }
644 
646 Volume::Volume(const std::string& nam, const std::string& title, const Solid& sol, const Material& mat) {
647  m_element = _createTGeoVolume(nam, sol.ptr(), mat.ptr());
648  m_element->SetTitle(title.c_str());
649 }
650 
653  s_verifyCopyNumbers = value;
654 }
655 
658  Volume::Object* o = _userExtension(*this);
659  return o;
660 }
661 
663 const char* Volume::type() const {
664  return m_element ? m_element->IsA()->GetName() : "UNKNOWN-Volume";
665 }
666 
669  return this->reflect(this->sensitiveDetector());
670 }
671 
674  if ( m_element ) {
675  VolumeImport imp;
676  Object* o = data();
677  if ( !o->reflected.isValid() ) {
678  TGeoVolume* vol = MakeReflection(m_element);
679  imp(vol, m_element, sd, Volume::REFLECTED);
680  o->reflected = vol;
681  }
682  return o->reflected;
683  }
684  except("dd4hep","Volume: Attempt to reflect an invalid Volume handle.");
685  return *this;
686 }
687 
690  if ( m_element ) {
691  VolumeImport imp;
692  imp(m_element);
693  return *this;
694  }
695  except("dd4hep","Volume: Attempt to import an invalid Volume handle.");
696  return *this;
697 }
698 
700 void Volume::setFlagBit(unsigned int bit) {
701  if ( bit <= 31 ) {
702  data()->flags |= 1<<bit;
703  return;
704  }
705  except("Volume","+++ Volume flag bit outsize range [0...31]: %d",bit);
706 }
707 
709 bool Volume::testFlagBit(unsigned int bit) const {
710  if ( bit <= 31 ) {
711  return (data()->flags & 1<<bit) != 0;
712  }
713  except("Volume","+++ Volume flag bit outsize range [0...31]: %d",bit);
714  return false; // Anyhow never called. Only to satisfy the compiler.
715 }
716 
718 bool Volume::isReflected() const {
719  return testFlagBit(REFLECTED);
720 }
721 
723 bool Volume::isAssembly() const {
724  return m_element ? m_element->IsAssembly() : false;
725 }
726 
728 unsigned char Volume::setSmartlessValue(unsigned char new_value) {
729  Object* obj = _data(*this);
730  unsigned char tmp = obj->smartLess;
731  obj->smartLess = new_value;
732  return tmp;
733 }
734 
736 unsigned char Volume::smartlessValue() const {
737  return _data(*this)->smartLess;
738 }
739 
741 Volume Volume::divide(const std::string& divname, int iaxis, int ndiv,
742  double start, double step, int numed, const char* option) {
743  TGeoVolume* p = m_element;
744  if ( p ) {
745  TGeoVolume* mvp = p->Divide(divname.c_str(), iaxis, ndiv, start, step, numed, option);
746  if ( mvp ) {
747  VolumeImport imp;
748  imp(mvp);
749  return VolumeMulti(mvp);
750  }
751  except("dd4hep","Volume: Failed to divide volume %s -> %s [Invalid result]",
752  p->GetName(), divname.c_str());
753  }
754  except("dd4hep","Volume: Attempt to divide an invalid logical volume.");
755  return nullptr;
756 }
757 
758 PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform) {
759  TGeoVolume* parent = par;
760  if ( !parent ) {
761  except("dd4hep","Volume: Attempt to assign daughters to an invalid physical parent volume.");
762  }
763  else if ( !daughter ) {
764  except("dd4hep","Volume: Attempt to assign an invalid physical daughter volume.");
765  }
766  else if ( !transform ) {
767  except("dd4hep","Volume: Attempt to place volume without placement matrix.");
768  }
769  if ( transform != detail::matrix::_identity() ) {
770  std::string nam = std::string(daughter->GetName()) + "_placement";
771  transform->SetName(nam.c_str());
772  }
773  TGeoShape* shape = daughter->GetShape();
774  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
775  if ( shape->IsA() == TGeoShapeAssembly::Class() ) {
776  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
777  as->NeedsBBoxRecompute();
778  as->ComputeBBox();
779  }
780  const Double_t* r = transform->GetRotationMatrix();
781  if ( r ) {
782  Double_t test_rot = r[0] + r[4] + r[8] - 3.0;
783  if ( TMath::Abs(test_rot) < s_rotation_test_limit )
784  transform->ResetBit(TGeoMatrix::kGeoRotation);
785  else
786  transform->SetBit(TGeoMatrix::kGeoRotation);
787 
788  if ( transform->IsRotation() ) {
789  Double_t det =
790  r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] -
791  r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3];
793  if ( det < 0e0 ) {
794  transform->SetBit(TGeoMatrix::kGeoReflection);
795  printout(DEBUG, "PlacedVolume",
796  "REFLECTION: (x.Cross(y)).Dot(z): %8.3g Parent: %s [%s] Daughter: %s [%s]",
797  det, par->GetName(), par->IsA()->GetName(),
798  daughter->GetName(), daughter->IsA()->GetName());
799  }
800  }
801  }
802  geo_node_t* n {nullptr};
803  TString nam_id = TString::Format("%s_%d", daughter->GetName(), id);
804  if ( s_verifyCopyNumbers ) {
805  n = static_cast<geo_node_t*>(parent->GetNode(nam_id));
806  if ( n != 0 ) {
807  printout(ERROR,"PlacedVolume","++ Attempt to place already exiting node %s",(const char*)nam_id);
808  }
809  }
810  /* n = */ parent->AddNode(daughter, id, transform);
811  //n = static_cast<geo_node_t*>(parent->GetNode(nam_id));
812  n = static_cast<geo_node_t*>(parent->GetNodes()->Last());
813  if ( nam_id != n->GetName() ) {
814  printout(ERROR,"PlacedVolume","++ FAILED to place node %s",(const char*)nam_id);
815  }
816  PlacedVolume::Object* extension = new PlacedVolume::Object();
817  n->geo_node_t::SetUserExtension(extension);
818  return PlacedVolume(n);
819 }
820 
821 PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Rotation3D& rot3D) {
822  TGeoRotation r;
823  double elements[9];
824  rot3D.GetComponents(elements);
825  r.SetMatrix(elements);
826  auto matrix = std::make_unique<TGeoCombiTrans>(TGeoTranslation(0,0,0),r);
827  return _addNode(par, daughter, copy_nr, matrix.release());
828 }
829 
830 PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Transform3D& tr) {
831  TGeoRotation r;
832  double elements[9];
833  Position pos3D;
834  Rotation3D rot3D;
835  tr.GetRotation(rot3D);
836  tr.GetTranslation(pos3D);
837  rot3D.GetComponents(elements);
838  r.SetMatrix(elements);
839  auto matrix = std::make_unique<TGeoCombiTrans>(TGeoTranslation(pos3D.x(), pos3D.y(), pos3D.z()),r);
840  return _addNode(par, daughter, copy_nr, matrix.release());
841 }
842 
844 PlacedVolume Volume::placeVolume(const Volume& volume, TGeoMatrix* tr) const {
845  return _addNode(m_element, volume, get_copy_number(m_element), tr);
846 }
847 
849 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_nr, TGeoMatrix* tr) const {
850  return _addNode(m_element, volume, copy_nr, tr);
851 }
852 
854 PlacedVolume Volume::placeVolume(const Volume& volume, const Transform3D& trans) const {
855  return _addNode(m_element, volume, get_copy_number(m_element), trans);
856 }
857 
860  return _addNode(m_element, volume, get_copy_number(m_element), detail::matrix::_identity());
861 }
862 
864 PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos) const {
865  return _addNode(m_element, volume, get_copy_number(m_element), detail::matrix::_translation(pos));
866 }
867 
869 PlacedVolume Volume::placeVolume(const Volume& volume, const RotationZYX& rot) const {
870  return _addNode(m_element, volume, get_copy_number(m_element), detail::matrix::_rotationZYX(rot));
871 }
872 
874 PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation3D& rot) const {
875  return _addNode(m_element, volume, get_copy_number(m_element), rot);
876 }
877 
879 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Transform3D& trans) const {
880  return _addNode(m_element, volume, copy_no, trans);
881 }
882 
884 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no) const {
885  return _addNode(m_element, volume, copy_no, detail::matrix::_identity());
886 }
887 
889 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Position& pos) const {
890  return _addNode(m_element, volume, copy_no, detail::matrix::_translation(pos));
891 }
892 
894 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const RotationZYX& rot) const {
895  return _addNode(m_element, volume, copy_no, detail::matrix::_rotationZYX(rot));
896 }
897 
899 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Rotation3D& rot) const {
900  return _addNode(m_element, volume, copy_no, rot);
901 }
902 
905  size_t count, double inc, double start)
906 {
907  Transform3D offset(1e0, 0e0, 0e0, axis == X_axis ? start : 0e0,
908  0e0, 1e0, 0e0, axis == Y_axis ? start : 0e0,
909  0e0, 0e0, 1e0, axis == Z_axis ? start : 0e0);
910  Transform3D tr(1e0, 0e0, 0e0, axis == X_axis ? inc : 0e0,
911  0e0, 1e0, 0e0, axis == Y_axis ? inc : 0e0,
912  0e0, 0e0, 1e0, axis == Z_axis ? inc : 0e0);
913  PlacedVolume pv = paramVolume1D(offset, entity, count, tr);
914  auto* data = pv.data();
915  data->params->flags = axis | REPLICATED;
916  return pv;
917 }
918 
920 PlacedVolume Volume::paramVolume1D(Volume entity, size_t count, const Position& inc) {
921  return paramVolume1D(Transform3D(), entity, count, Transform3D(inc));
922 }
923 
925 PlacedVolume Volume::paramVolume1D(Volume entity, size_t count, const RotationZYX& inc) {
926  return paramVolume1D(Transform3D(), entity, count, Transform3D(inc));
927 }
928 
930 PlacedVolume Volume::paramVolume1D(Volume entity, size_t count, const Transform3D& inc) {
931  return paramVolume1D(Transform3D(), entity, count, inc);
932 }
933 
936  Volume entity,
937  size_t count,
938  const Transform3D& trafo)
939 {
940  Transform3D tr(start);
941  PlacedVolume pv =
942  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr));
943  auto* data = pv.data();
944  if ( pv->GetNdaughters() > 1 ) {
945  except("Volume","paramVolume1D: Mother %s has too many daughters: %ld "
946  "Parameterized volumes may only have one single daughter!",
947  ptr()->GetName(), pv.volume()->GetNdaughters());
948  }
950  data->params->addref();
951  data->params->flags = PARAMETERIZED;
952  data->params->start = start;
953  data->params->trafo1D.first = trafo;
954  data->params->trafo1D.second = count;
955  data->params->trafo2D.second = 0;
956  data->params->trafo3D.second = 0;
957  data->params->placements.emplace_back(pv);
958  for(size_t i=1; i < count; ++i) {
959  tr *= trafo;
960  PlacedVolume ppv =
961  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr));
962  data->params->placements.emplace_back(ppv);
963  ppv.data()->params = data->params->addref();
964  }
965  return pv;
966 }
967 
970  size_t count_1,
971  const Transform3D& trafo_1,
972  size_t count_2,
973  const Transform3D& trafo_2)
974 {
975  return paramVolume2D(Transform3D(), entity, count_1, trafo_1, count_2, trafo_2);
976 }
977 
980  Volume entity,
981  size_t count_1,
982  const Position& pos_1,
983  size_t count_2,
984  const Position& pos_2)
985 {
986  return paramVolume2D(start, entity, count_1, Transform3D(pos_1), count_2, Transform3D(pos_2));
987 }
988 
991  size_t count_1,
992  const Position& pos_1,
993  size_t count_2,
994  const Position& pos_2)
995 {
996  return paramVolume2D(Transform3D(), entity, count_1, Transform3D(pos_1), count_2, Transform3D(pos_2));
997 }
998 
1001  Volume entity,
1002  size_t count_1,
1003  const Transform3D& trafo_1,
1004  size_t count_2,
1005  const Transform3D& trafo_2)
1006 {
1007  PlacedVolume pv =
1008  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(start));
1009  auto* data = pv.data();
1010  if ( pv->GetNdaughters() > 1 ) {
1011  except("Volume","paramVolume1D: Mother %s has too many daughters: %ld "
1012  "Parameterized volumes may only have one single daughter!",
1013  ptr()->GetName(), pv.volume()->GetNdaughters());
1014  }
1016  data->params->addref();
1017  data->params->flags = PARAMETERIZED;
1018  data->params->start = start;
1019  data->params->trafo1D.first = trafo_1;
1020  data->params->trafo1D.second = count_1;
1021  data->params->trafo2D.first = trafo_2;
1022  data->params->trafo2D.second = count_2;
1023  data->params->trafo3D.second = 0;
1024  data->params->placements.emplace_back(pv);
1025  Transform3D tr2(start);
1026  for(size_t j=0; j < count_2; ++j) {
1027  Transform3D tr1 = tr2;
1028  for(size_t i = 0; i < count_1; ++i) {
1029  if ( !( i == 0 && j == 0 ) ) {
1030  PlacedVolume ppv =
1031  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr1));
1032  data->params->placements.emplace_back(ppv);
1033  ppv.data()->params = data->params->addref();
1034  }
1035  tr1 *= trafo_1;
1036  }
1037  tr2 *= trafo_2;
1038  }
1039  return pv;
1040 }
1041 
1044  Volume entity,
1045  size_t count_1,
1046  const Position& pos_1,
1047  size_t count_2,
1048  const Position& pos_2,
1049  size_t count_3,
1050  const Position& pos_3)
1051 {
1052  return paramVolume3D(start, entity,
1053  count_1, Transform3D(pos_1),
1054  count_2, Transform3D(pos_2),
1055  count_3, Transform3D(pos_3));
1056 }
1057 
1060  size_t count_1,
1061  const Position& pos_1,
1062  size_t count_2,
1063  const Position& pos_2,
1064  size_t count_3,
1065  const Position& pos_3)
1066 {
1067  return paramVolume3D(Transform3D(), entity,
1068  count_1, Transform3D(pos_1),
1069  count_2, Transform3D(pos_2),
1070  count_3, Transform3D(pos_3));
1071 }
1072 
1075  Volume entity,
1076  size_t count_1,
1077  const Transform3D& trafo_1,
1078  size_t count_2,
1079  const Transform3D& trafo_2,
1080  size_t count_3,
1081  const Transform3D& trafo_3)
1082 {
1083  PlacedVolume pv =
1084  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(start));
1085  auto* data = pv.data();
1086  if ( pv->GetNdaughters() > 1 ) {
1087  except("Volume","paramVolume1D: Mother %s has too many daughters: %ld "
1088  "Parameterized volumes may only have one single daughter!",
1089  ptr()->GetName(), pv.volume()->GetNdaughters());
1090  }
1092  data->params->addref();
1093  data->params->flags = PARAMETERIZED;
1094  data->params->start = start;
1095  data->params->trafo1D.first = trafo_1;
1096  data->params->trafo1D.second = count_1;
1097  data->params->trafo2D.first = trafo_2;
1098  data->params->trafo2D.second = count_2;
1099  data->params->trafo3D.first = trafo_3;
1100  data->params->trafo3D.second = count_3;
1101  data->params->placements.emplace_back(pv);
1102  Transform3D tr3(start);
1103  for(size_t k=0; k < count_3; ++k) {
1104  Transform3D tr2 = tr3;
1105  for(size_t j=0; j < count_2; ++j) {
1106  Transform3D tr1 = tr2;
1107  for(size_t i = 0; i < count_1; ++i) {
1108  if ( !( i == 0 && j == 0 && k == 0 ) ) {
1109  PlacedVolume ppv =
1110  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr1));
1111  data->params->placements.emplace_back(ppv);
1112  ppv.data()->params = data->params->addref();
1113  }
1114  tr1 *= trafo_1;
1115  }
1116  tr2 *= trafo_2;
1117  }
1118  tr3 *= trafo_3;
1119  }
1120  return pv;
1121 }
1122 
1124 const Volume& Volume::setOption(const std::string& opt) const {
1125  if ( isValid() ) {
1126  m_element->SetOption(opt.c_str());
1127  return *this;
1128  }
1129  throw std::runtime_error("dd4hep: Attempt to access invalid handle of type: PlacedVolume");
1130 }
1131 
1133 std::string Volume::option() const {
1134  return m_element->GetOption();
1135 }
1136 
1138 const Volume& Volume::setMaterial(const Material& mat) const {
1139  if (mat.isValid()) {
1140  TGeoMedium* medium = mat._ptr<TGeoMedium>();
1141  if (medium) {
1142  m_element->SetMedium(medium);
1143  return *this;
1144  }
1145  throw std::runtime_error("dd4hep: Volume: Medium " + std::string(mat.name()) + " is not registered with geometry manager.");
1146  }
1147  throw std::runtime_error("dd4hep: Volume: Attempt to assign invalid material.");
1148 }
1149 
1152  return Material(m_element->GetMedium());
1153 }
1154 
1156 const Volume& Volume::setVisAttributes(const VisAttr& attr) const {
1157  if ( attr.isValid() ) {
1158  VisAttr::Object* vis = attr.data<VisAttr::Object>();
1159  TColor* col = vis->color;
1160  if ( col ) {
1161  int draw_style = vis->drawingStyle;
1162  int line_style = vis->lineStyle;
1163  int col_num = col->GetNumber();
1164  int col_tr_num = vis->colortr->GetNumber();
1165  m_element->SetVisibility(vis->visible ? kTRUE : kFALSE);
1166  m_element->SetVisContainers(kTRUE);
1167  m_element->SetVisDaughters(vis->showDaughters ? kTRUE : kFALSE);
1168  printout(DEBUG,"setVisAttributes",
1169  "Set color %3d transparent(alpha:%.3f): %3d [%02X,%02X,%02X] DrawingStyle:%9s LineStyle:%6s for volume %s",
1170  col_num, vis->alpha, col_tr_num,
1171  int(255*col->GetRed()),
1172  int(255*col->GetGreen()),
1173  int(255*col->GetBlue()),
1174  draw_style == VisAttr::SOLID ? "Solid" : "Wireframe",
1175  line_style == VisAttr::SOLID ? "Solid" : "Dashed",
1176  name()
1177  );
1178  m_element->SetLineWidth(10);
1179  m_element->SetLineColor(col_num);
1180  m_element->SetFillColor(col_tr_num);
1181  if (draw_style == VisAttr::SOLID) {
1182  m_element->SetFillStyle(1001); // Root: solid
1183 
1184 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,29,0)
1185  // Set directly transparency to the volume, NOT to the material as for ROOT < 6.29
1186  m_element->ResetTransparency(Char_t((1.0-vis->alpha)*100));
1187 #else
1188  // As suggested by Valentin Volkl https://sft.its.cern.ch/jira/browse/DDFORHEP-20
1189  //
1190  // According to https://root.cern.ch/phpBB3/viewtopic.php?t=2309#p66013
1191  // a transparency>50 will make a volume invisible in the normal pad.
1192  // Hence: possibly restrict transparency to a maximum of 50.
1193  // but let's see first how this behaves.
1194  m_element->SetTransparency(Char_t((1.0-vis->alpha)*100));
1195 #endif
1196  }
1197  else {
1198  printout(DEBUG,"setVisAttributes","Set to wireframe vis:%s",name());
1199  m_element->SetLineColor(kBlack);
1200  m_element->SetFillColor(0);
1201  m_element->SetFillStyle(0); // Root: hollow
1202  }
1203  if (line_style == VisAttr::SOLID) // Root line style: 1=solid, 2=dash, 3=dot, 4=dash-dot.
1204  m_element->SetLineStyle(1);
1205  else if (line_style == VisAttr::DASHED)
1206  m_element->SetLineStyle(2);
1207  else
1208  m_element->SetLineStyle(line_style);
1209  }
1210  else {
1211  except("Volume","setVisAttributes: encountered valid, but badly initialized visattr: %s",attr.name());
1212  }
1213  }
1214  Volume::Object* o = _userExtension(*this);
1215  if ( o ) o->vis = attr;
1216  return *this;
1217 }
1218 
1220 const Volume& Volume::setVisAttributes(const Detector& description, const std::string& nam) const {
1221  if (!nam.empty()) {
1222  VisAttr attr = description.visAttributes(nam);
1223  setVisAttributes(attr);
1224  }
1225  return *this;
1226 }
1227 
1229 const Volume& Volume::setAttributes(const Detector& description, const std::string& rg, const std::string& ls, const std::string& vis) const {
1230  if (!rg.empty())
1231  setRegion(description.region(rg));
1232  if (!ls.empty())
1233  setLimitSet(description.limitSet(ls));
1234  setVisAttributes(description, vis);
1235  return *this;
1236 }
1237 
1240  Object* o = _data(*this, false);
1241  if (o) return o->vis;
1242  return VisAttr();
1243 }
1244 
1246 const Volume& Volume::setSolid(const Solid& sol) const {
1247  m_element->SetShape(sol);
1248  return *this;
1249 }
1250 
1253  return Solid((*this)->GetShape());
1254 }
1255 
1258  Box box = this->solid();
1259  if ( box.isValid() ) {
1260  return box;
1261  }
1262  else if ( !isValid() ) {
1263  except("dd4hep","Volume: Cannot access the bounding box of an invalid volume [Invalid Handle]!");
1264  }
1265  except("dd4hep","Volume: Cannot access the bounding box an object of type: %s shape: %s",
1266  this->ptr()->IsA()->GetName(), this->ptr()->GetShape()->IsA()->GetName());
1267  return box;
1268 }
1269 
1271 const Volume& Volume::setRegion(const Detector& description, const std::string& nam) const {
1272  if (!nam.empty()) {
1273  return setRegion(description.region(nam));
1274  }
1275  return *this;
1276 }
1277 
1279 const Volume& Volume::setRegion(const Region& obj) const {
1280  _data(*this)->region = obj;
1281  return *this;
1282 }
1283 
1286  return _data(*this)->region;
1287 }
1288 
1290 const Volume& Volume::setLimitSet(const Detector& description, const std::string& nam) const {
1291  if (!nam.empty()) {
1292  return setLimitSet(description.limitSet(nam));
1293  }
1294  return *this;
1295 }
1296 
1298 const Volume& Volume::setLimitSet(const LimitSet& obj) const {
1299  _data(*this)->limits = obj;
1300  return *this;
1301 }
1302 
1305  return _data(*this)->limits;
1306 }
1307 
1310  //cout << "Setting sensitive detector '" << obj.name() << "' to volume:" << ptr() << " " << name() << endl;
1311  _data(*this)->sens_det = obj;
1312  return *this;
1313 }
1314 
1317  const Object* o = _data(*this);
1318  return o->sens_det;
1319 }
1320 
1322 bool Volume::isSensitive() const {
1323  return _data(*this)->sens_det.isValid();
1324 }
1325 
1328  return _data(*this)->properties != nullptr;
1329 }
1330 
1332 void Volume::addProperty(const std::string& nam, const std::string& val) const {
1333  auto* o = _data(*this);
1334  if ( !o->properties ) {
1335  o->properties = new TList();
1336  o->properties->SetOwner();
1337  }
1338  TNamed *prop = (TNamed*)o->properties->FindObject(nam.c_str());
1339  if ( !prop ) {
1340  o->properties->Add(new TNamed(nam.c_str(), val.c_str()));
1341  return;
1342  }
1343  except("Volume::addProperty", "Volume: '%s' Property '%s' is already set!",
1344  ptr()->GetName(), nam.c_str());
1345 }
1346 
1348 std::string Volume::getProperty(const std::string& nam, const std::string& default_val) const {
1349  const auto* o = _data(*this);
1350  if ( !o->properties ) {
1351  return default_val;
1352  }
1353  TNamed *prop = (TNamed*)o->properties->FindObject(nam.c_str());
1354  if ( prop ) return prop->GetTitle();
1355  return default_val;
1356 }
1357 
1359 Assembly::Assembly(const std::string& nam) {
1360  m_element = _createTGeoVolumeAssembly(nam);
1361 }
1362 
1364 VolumeMulti::VolumeMulti(const std::string& nam, Material mat) {
1365  m_element = _createTGeoVolumeMulti(nam, mat.ptr());
1366 }
1367 
1370  if ( m_element ) {
1371  // This will lead to an exception if the type is not TGeoVolumeMulti
1372  TGeoVolumeMulti* multi = detail::safe_cast<TGeoVolumeMulti>::cast(m_element);
1373  if ( multi ) {
1374  import();
1375  return;
1376  }
1377  // Force a bad cast exception
1379  if ( handle.isValid() ) {}
1380  }
1381 }
1382 
1384 std::string dd4hep::toStringMesh(PlacedVolume place, int prec) {
1385  Volume vol = place->GetVolume();
1386  TGeoMatrix* mat = place->GetMatrix();
1387  Solid sol = vol.solid();
1388  std::stringstream os;
1389  struct _numbering {
1390  double adjust(double value) const {
1391  if ( std::abs(value) < TGeoShape::Tolerance() )
1392  return 0.0;
1393  return value/dd4hep::cm;
1394  }
1395  } _vertex;
1396 
1397  if ( vol->IsA() == TGeoVolumeAssembly::Class() ) {
1398  for(int i=0; i<vol->GetNdaughters(); ++i) {
1399  os << toStringMesh(vol->GetNode(i), prec) << std::endl;
1400  }
1401  return os.str();
1402  }
1403 
1404  // Prints shape parameters
1405  int nvert = 0, nsegs = 0, npols = 0;
1406  sol->GetMeshNumbers(nvert, nsegs, npols);
1407  Double_t* points = new Double_t[3*nvert];
1408  sol->SetPoints(points);
1409 
1410  os << std::setw(16) << std::left << sol->IsA()->GetName()
1411  << " " << nvert << " Mesh-points:" << std::endl;
1412  os << std::setw(16) << std::left << sol->IsA()->GetName() << " " << sol->GetName()
1413  << " N(mesh)=" << sol->GetNmeshVertices()
1414  << " N(vert)=" << nvert << " N(seg)=" << nsegs << " N(pols)=" << npols << std::endl;
1415 
1416  for(int i=0; i<nvert; ++i) {
1417  Double_t* p = points + 3*i;
1418  Double_t global[3], local[3] = {p[0], p[1], p[2]};
1419  mat->LocalToMaster(local, global);
1420  os << std::setw(16) << std::left << sol->IsA()->GetName() << " " << std::setw(3) << std::left << i
1421  << " Local (" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(local[0])
1422  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(local[1])
1423  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(local[2])
1424  << ") Global (" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(global[0])
1425  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(global[1])
1426  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(global[2])
1427  << ")" << std::endl;
1428  }
1429  Box box = sol;
1430  const Double_t* org = box->GetOrigin();
1431  os << std::setw(16) << std::left << sol->IsA()->GetName()
1432  << " Bounding box: "
1433  << " dx=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(box->GetDX())
1434  << " dy=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(box->GetDY())
1435  << " dz=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(box->GetDZ())
1436  << " Origin: x=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(org[0])
1437  << " y=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(org[1])
1438  << " z=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(org[2])
1439  << std::endl;
1440 
1442  delete [] points;
1443  return os.str();
1444 }
1445 
dd4hep::detail::matrix::_translation
TGeoTranslation * _translation(const Position &pos)
Convert a Position object to a TGeoTranslation.
Definition: MatrixHelpers.cpp:55
dd4hep::Detector::manager
virtual TGeoManager & manager() const =0
Access the geometry manager of this instance.
dd4hep::VolumeMulti
Implementation class extending the ROOT mulit-volumes (TGeoVolumeMulti)
Definition: Volumes.h:727
dd4hep::Volume::Z_axis
@ Z_axis
Definition: Volumes.h:386
dd4hep::VolumeExtension::Release
virtual void Release() const override
TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore.
Definition: Volumes.cpp:613
dd4hep::Volume::setLimitSet
const Volume & setLimitSet(const Detector &description, const std::string &name) const
Set the limits to the volume. Note: If the name string is empty, the action is ignored.
Definition: Volumes.cpp:1290
dd4hep::Volume::isAssembly
bool isAssembly() const
Test if this volume is an assembly structure.
Definition: Volumes.cpp:723
dd4hep::VolumeExtension
Implementation class extending the ROOT volume (TGeoVolume)
Definition: Volumes.h:300
dd4hep::Volume::setSmartlessValue
unsigned char setSmartlessValue(unsigned char value)
Set the smartless option for G4 voxelization. Returns previous value.
Definition: Volumes.cpp:728
dd4hep::VisAttrObject::colortr
TColor * colortr
Definition: ObjectsInterna.h:92
dd4hep::Volume::enableCopyNumberCheck
static void enableCopyNumberCheck(bool value)
Set flag to enable copy number checks when inserting new nodes.
Definition: Volumes.cpp:652
dd4hep::Volume::hasProperties
bool hasProperties() const
Check for existence of properties.
Definition: Volumes.cpp:1327
dd4hep::Assembly::Assembly
Assembly()=default
Default constructor.
dd4hep::Volume::ReplicationAxis
ReplicationAxis
Definition: Volumes.h:380
dd4hep::VolumeExtension::region
Region region
Region reference.
Definition: Volumes.h:311
v
View * v
Definition: MultiView.cpp:28
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:44
dd4hep::detail::matrix::_rotationZYX
TGeoRotation * _rotationZYX(const RotationZYX &rot)
Convert a RotationZYX object to a newly created TGeoRotation.
Definition: MatrixHelpers.cpp:59
MatrixHelpers.h
Detector.h
dd4hep::PlacedVolumeExtension
Implementation class extending the ROOT placed volume.
Definition: Volumes.h:79
dd4hep::PlacedVolumeExtension::~PlacedVolumeExtension
virtual ~PlacedVolumeExtension()
Default destructor.
Definition: Volumes.cpp:375
dd4hep::VolumeMulti::VolumeMulti
VolumeMulti()=default
Default constructor.
dd4hep::PlacedVolumeExtension::Release
virtual void Release() const override
TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore.
Definition: Volumes.cpp:405
dd4hep::VolumeExtension::reflected
Handle< TGeoVolume > reflected
Reference to the reflected volume (or to the original volume for reflections)
Definition: Volumes.h:319
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:163
dd4hep::VisAttr
Handle class describing visualization attributes.
Definition: Objects.h:324
dd4hep::Volume::paramVolume2D
PlacedVolume paramVolume2D(Volume entity, size_t count_1, const Transform3D &inc_1, size_t count_2, const Transform3D &inc_2)
2D Parameterised volume implementation
Definition: Volumes.cpp:969
geo_volume_t
TGeoVolume geo_volume_t
Definition: Volumes.cpp:53
dd4hep::NamedObject::GetName
const char * GetName() const
Access name.
Definition: NamedObject.h:58
dd4hep::LimitSet::limits
const std::set< Limit > & limits() const
Accessor to limits container.
Definition: Objects.cpp:464
dd4hep::PlacedVolume::addPhysVolID
PlacedVolume & addPhysVolID(const std::string &name, int value)
Add identifier.
Definition: Volumes.cpp:501
dd4hep::detail::matrix::_identity
TGeoIdentity * _identity()
Access the TGeo identity transformation.
Definition: MatrixHelpers.cpp:27
dd4hep::Volume::setOption
const Volume & setOption(const std::string &opt) const
Set the volume's option value.
Definition: Volumes.cpp:1124
dd4hep::Volume::solid
Solid solid() const
Access to Solid (Shape)
Definition: Volumes.cpp:1252
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:128
dd4hep::Handle< NamedObject >
dd4hep::Detector::region
virtual Region region(const std::string &name) const =0
Retrieve a region object by its name from the detector description.
dd4hep::detail::matrix::_transform
TGeoHMatrix * _transform(const Transform3D &trans)
Convert a Transform3D object to a newly created TGeoHMatrix.
Definition: MatrixHelpers.cpp:140
dd4hep::Volume::setRegion
const Volume & setRegion(const Detector &description, const std::string &name) const
Set the regional attributes to the volume. Note: If the name string is empty, the action is ignored.
Definition: Volumes.cpp:1271
dd4hep::PlacedVolume::Object
PlacedVolumeExtension Object
Definition: Volumes.h:165
dd4hep::Rotation3D
ROOT::Math::Rotation3D Rotation3D
Definition: Objects.h:113
dd4hep::PlacedVolumeExtension::volIDs
VolIDs volIDs
ID container.
Definition: Volumes.h:127
dd4hep::magic_word
unsigned long long int magic_word()
Access to the magic word, which is protecting some objects against memory corruptions.
Definition: Handle.h:53
dd4hep::Solid_type< TGeoShape >
dd4hep::Volume::paramVolume1D
PlacedVolume paramVolume1D(const Transform3D &start, Volume entity, size_t count, const Transform3D &inc)
1D Parameterised volume implementation
Definition: Volumes.cpp:935
dd4hep::Volume::isSensitive
bool isSensitive() const
Accessor if volume is sensitive (ie. is attached to a sensitive detector)
Definition: Volumes.cpp:1322
dd4hep::VolumeExtension::magic
unsigned long magic
Magic word to detect memory corruptions.
Definition: Volumes.h:303
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
dd4hep::VolumeExtension::vis
VisAttr vis
Reference to visualization attributes.
Definition: Volumes.h:315
dd4hep::Volume::placeVolume
PlacedVolume placeVolume(const Volume &volume) const
Place daughter volume. The position and rotation are the identity.
Definition: Volumes.cpp:859
dd4hep::PlacedVolumeExtension::Parameterisation::addref
Parameterisation * addref()
Increase ref count.
Definition: Volumes.cpp:343
dd4hep::Handle::clear
Handle< T > & clear()
Release the object held by the handle.
Definition: Handle.h:136
dd4hep::VolumeExtension::refCount
long refCount
Reference count on object (used to implement Grab/Release)
Definition: Volumes.h:305
dd4hep::Volume::material
Material material() const
Access to the Volume material.
Definition: Volumes.cpp:1151
dd4hep::PlacedVolumeExtension::Parameterisation::release
void release()
Decrease ref count.
Definition: Volumes.cpp:348
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:272
dd4hep::Volume::REFLECTED
@ REFLECTED
Definition: Volumes.h:378
dd4hep::Volume::option
std::string option() const
Access the volume's option value.
Definition: Volumes.cpp:1133
dd4hep::PlacedVolume::daughter
PlacedVolume daughter(std::size_t which) const
Access the daughter by index.
Definition: Volumes.cpp:483
dd4hep::Volume::PARAMETERIZED
@ PARAMETERIZED
Definition: Volumes.h:382
dd4hep::PlacedVolume::Processor::Processor
Processor()
Default constructor.
dd4hep::PlacedVolumeExtension::VolIDs
Volume ID container.
Definition: Volumes.h:88
dd4hep::Utilities::GetName
const char * GetName(T *p)
Definition: Utilities.h:45
dd4hep::Volume::REPLICATED
@ REPLICATED
Definition: Volumes.h:381
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:370
dd4hep::Volume::Y_axis
@ Y_axis
Definition: Volumes.h:385
dd4hep::VisAttrObject::showDaughters
unsigned char showDaughters
Definition: ObjectsInterna.h:96
dd4hep::Volume::setSensitiveDetector
const Volume & setSensitiveDetector(const SensitiveDetector &obj) const
Assign the sensitive detector structure.
Definition: Volumes.cpp:1309
dd4hep::VisAttrObject::lineStyle
unsigned char lineStyle
Definition: ObjectsInterna.h:95
dd4hep::Volume::setSolid
const Volume & setSolid(const Solid &s) const
Set the volume's solid shape.
Definition: Volumes.cpp:1246
dd4hep::VolumeExtension::copy
void copy(const VolumeExtension &c)
Copy the object.
Definition: Volumes.cpp:580
dd4hep::Handle::data
Q * data() const
Access to an unrelated object type.
Definition: Handle.h:161
dd4hep::LimitSet
Handle class describing a set of limits as they are used for simulation.
Definition: Objects.h:425
dd4hep::PlacedVolume::material
Material material() const
Volume material.
Definition: Volumes.cpp:463
dd4hep::Volume::limitSet
LimitSet limitSet() const
Access to the limit set.
Definition: Volumes.cpp:1304
dd4hep::Volume::replicate
PlacedVolume replicate(const Volume entity, ReplicationAxis axis, size_t count, double inc, double start=0e0)
1D volume replication implementation
Definition: Volumes.cpp:904
dd4hep::VisAttr::DASHED
@ DASHED
Definition: Objects.h:327
dd4hep::Volume::region
Region region() const
Access to the handle to the region structure.
Definition: Volumes.cpp:1285
dd4hep::VolumeExtension::sens_det
Handle< NamedObject > sens_det
Reference to the sensitive detector.
Definition: Volumes.h:317
_addNode
PlacedVolume _addNode(TGeoVolume *par, TGeoVolume *daughter, int id, TGeoMatrix *transform)
Definition: Volumes.cpp:758
dd4hep::VisAttrObject::color
TColor * color
Definition: ObjectsInterna.h:91
dd4hep::VolumeExtension::flags
int flags
Bit field to determine the usage. Bit 0...15 reserverd for system usage. 16...31 user space.
Definition: Volumes.h:309
dd4hep::Volume::addProperty
void addProperty(const std::string &nam, const std::string &val) const
Add Volume property (name-value pair)
Definition: Volumes.cpp:1332
dd4hep::Volume::setMaterial
const Volume & setMaterial(const Material &m) const
Set the volume's material.
Definition: Volumes.cpp:1138
dd4hep::VisAttrObject::drawingStyle
unsigned char drawingStyle
Definition: ObjectsInterna.h:94
TNamed
Class of the ROOT toolkit. See http://root.cern.ch/root/htmldoc/ClassIndex.html.
Definition: ROOTClasses.h:37
dd4hep::Volume::paramVolume3D
PlacedVolume paramVolume3D(Volume entity, size_t count_1, const Transform3D &inc_1, size_t count_2, const Transform3D &inc_2, size_t count_3, const Transform3D &inc_3)
3D Parameterised volume implementation
dd4hep::Volume::testFlagBit
bool testFlagBit(unsigned int bit) const
Test the user flag bit.
Definition: Volumes.cpp:709
geo_assembly_t
TGeoVolumeAssembly geo_assembly_t
Definition: Volumes.cpp:54
dd4hep::Region
Handle class describing a region as used in simulation.
Definition: Objects.h:462
dd4hep::Handle< TGeoVolume >::m_element
TGeoVolume * m_element
Single and only data member: Reference to the actual element.
Definition: Handle.h:93
dd4hep::Volume::smartlessValue
unsigned char smartlessValue() const
access the smartless option for G4 voxelization
Definition: Volumes.cpp:736
dd4hep::Handle::_ptr
Q * _ptr() const
Access to an unrelated object type.
Definition: Handle.h:157
dd4hep::Detector::limitSet
virtual LimitSet limitSet(const std::string &name) const =0
Retrieve a limitset by its name from the detector description.
dd4hep::PlacedVolume::matrix
const TGeoMatrix & matrix() const
Access the full transformation matrix to the parent volume.
Definition: Volumes.cpp:526
dd4hep::VolumeExtension::Grab
virtual TGeoExtension * Grab() override
TGeoExtension overload: Method called whenever requiring a pointer to the extension.
Definition: Volumes.cpp:600
dd4hep::ReflectionBuilder::execute
void execute() const
Perform scan.
dd4hep::PlacedVolume::motherVol
Volume motherVol() const
Parent volume (envelope)
Definition: Volumes.cpp:473
dd4hep::PlacedVolume::toString
std::string toString() const
String dump.
Definition: Volumes.cpp:540
dd4hep::PlacedVolumeExtension::PlacedVolumeExtension
PlacedVolumeExtension()
Default constructor.
Definition: Volumes.cpp:354
dd4hep::Volume::Volume
Volume()=default
Default constructor.
dd4hep::Detector::visAttributes
virtual const HandleMap & visAttributes() const =0
Accessor to the map of visualisation attributes.
dd4hep::Transform3D
ROOT::Math::Transform3D Transform3D
Definition: Objects.h:117
dd4hep::PlacedVolume::num_daughters
std::size_t num_daughters() const
Number of daughters placed in this volume.
Definition: Volumes.cpp:478
DECREMENT_COUNTER
#define DECREMENT_COUNTER
Definition: config.h:39
dd4hep::Volume::divide
Volume divide(const std::string &divname, int iaxis, int ndiv, double start, double step, int numed=0, const char *option="")
Divide volume into subsections (See the ROOT manual for details)
Definition: Volumes.cpp:741
dd4hep::VolumeExtension::smartLess
unsigned char smartLess
Geant4 optimization flag: Smartless.
Definition: Volumes.h:323
dd4hep::Position
ROOT::Math::XYZVector Position
Definition: Objects.h:81
dd4hep::VolumeExtension::VolumeExtension
VolumeExtension()
Default constructor.
Definition: Volumes.cpp:553
dd4hep::PlacedVolumeExtension::magic
unsigned long magic
Magic word to detect memory corruptions.
Definition: Volumes.h:121
dd4hep::Volume::isReflected
bool isReflected() const
Test if this volume was reflected.
Definition: Volumes.cpp:718
dd4hep::PlacedVolume::type
const char * type() const
Access the object type from the class information.
Definition: Volumes.cpp:453
dd4hep::Box
Class describing a box shape.
Definition: Shapes.h:294
std
Definition: Plugins.h:30
dd4hep::VisAttr::SOLID
@ SOLID
Definition: Objects.h:327
dd4hep::PlacedVolumeExtension::Grab
virtual TGeoExtension * Grab() override
TGeoExtension overload: Method called whenever requiring a pointer to the extension.
Definition: Volumes.cpp:396
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:153
ObjectsInterna.h
dd4hep::Volume::type
const char * type() const
Access the object type from the class information.
Definition: Volumes.cpp:663
dd4hep::ReflectionBuilder::detector
Detector & detector
Definition: Volumes.h:60
dd4hep::Volume::boundingBox
Box boundingBox() const
Access the bounding box of the volume (if available)
Definition: Volumes.cpp:1257
dd4hep::VolumeExtension::operator=
VolumeExtension & operator=(VolumeExtension &&copy)=delete
No move assignment.
geo_node_t
TGeoNode geo_node_t
Definition: Volumes.cpp:52
dd4hep::VolumeMulti::verifyVolumeMulti
void verifyVolumeMulti()
Import volume from pointer as a result of Solid->Divide()
Definition: Volumes.cpp:1369
dd4hep::Volume::setVisAttributes
const Volume & setVisAttributes(const VisAttr &obj) const
Set Visualization attributes to the volume.
Definition: Volumes.cpp:1156
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::PlacedVolumeExtension::VolIDs::str
std::string str() const
String representation for debugging.
Definition: Volumes.cpp:436
dd4hep::Solid
Solid_type< TGeoShape > Solid
Definition: Shapes.h:197
det
DetElement::Object * det
Definition: AlignmentsCalculator.cpp:66
dd4hep::PlacedVolume::copyNumber
int copyNumber() const
Access the copy number of this placement within its mother.
Definition: Volumes.cpp:458
dd4hep::PlacedVolume::Processor::~Processor
virtual ~Processor()
Default destructor.
Definition: Volumes.cpp:339
dd4hep::PlacedVolume::volume
Volume volume() const
Logical volume of this placement.
Definition: Volumes.cpp:468
dd4hep::PlacedVolumeExtension::VolIDs::insert
std::pair< std::vector< VolID >::iterator, bool > insert(const std::string &name, int value)
Insert new entry.
Definition: Volumes.cpp:422
dd4hep::PlacedVolume::data
Object * data() const
Check if placement is properly instrumented.
Definition: Volumes.cpp:447
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
dd4hep::Volume::getProperty
std::string getProperty(const std::string &nam, const std::string &default_val="") const
Access property value. Returns default_value if the property is not present.
Definition: Volumes.cpp:1348
INCREMENT_COUNTER
#define INCREMENT_COUNTER
Definition: config.h:38
dd4hep::Volume::reflect
Volume reflect() const
Create a reflected volume tree. The reflected volume has left-handed coordinates.
Definition: Volumes.cpp:668
dd4hep::VolumeExtension::~VolumeExtension
virtual ~VolumeExtension()
Default destructor.
Definition: Volumes.cpp:559
dd4hep::Volume::setFlagBit
void setFlagBit(unsigned int bit)
Set user flags in bit-field.
Definition: Volumes.cpp:700
TGeoExtension
Class of the ROOT toolkit. See http://root.cern.ch/root/htmldoc/ClassIndex.html.
Definition: ROOTClasses.h:25
dd4hep::detail::tools::copy
void copy(Alignment from, Alignment to)
Copy alignment object from source object.
Definition: AlignmentTools.cpp:43
dd4hep::PlacedVolumeExtension::refCount
long refCount
Reference count on object (used to implement Grab/Release)
Definition: Volumes.h:123
dd4hep::PlacedVolume::volIDs
const PlacedVolumeExtension::VolIDs & volIDs() const
Access to the volume IDs.
Definition: Volumes.cpp:496
dd4hep::RotationZYX
ROOT::Math::RotationZYX RotationZYX
Definition: Objects.h:105
InstanceCount.h
dd4hep::Volume::setAttributes
const Volume & setAttributes(const Detector &description, const std::string &region, const std::string &limits, const std::string &vis) const
Attach attributes to the volume.
Definition: Volumes.cpp:1229
dd4hep::VolumeExtension::properties
TList * properties
Reference to properties.
Definition: Volumes.h:321
dd4hep::VisAttrObject::alpha
float alpha
Definition: ObjectsInterna.h:93
dd4hep::Volume::visAttributes
VisAttr visAttributes() const
Access the visualisation attributes.
Definition: Volumes.cpp:1239
dd4hep::Volume::Object
VolumeExtension Object
Definition: Volumes.h:372
ClassImp
ClassImp(VolumeExtension) ClassImp(PlacedVolumeExtension) ClassImp(PlacedVolumeExtension
Enable ROOT persistency.
Definition: Volumes.cpp:57
dd4hep::PlacedVolumeExtension::params
Parameterisation * params
Reference to the parameterised transformation.
Definition: Volumes.h:125
dd4hep::PlacedVolume::position
Position position() const
Access the translation vector to the parent volume.
Definition: Volumes.cpp:534
dd4hep::get_shape_tag
std::string get_shape_tag(const TGeoShape *shape)
Retrieve tag name from shape type.
Definition: ShapeUtilities.cpp:185
Printout.h
dd4hep::Volume::X_axis
@ X_axis
Definition: Volumes.h:384
dd4hep::PlacedVolumeExtension::Parameterisation
Optional parameters to implement special features such as parametrization.
Definition: Volumes.h:246
dd4hep::Volume::import
Volume & import()
If we import volumes from external sources, we have to attach the extensions to the tree.
Definition: Volumes.cpp:689
dd4hep::PlacedVolumeExtension::VolIDs::find
std::vector< VolID >::const_iterator find(const std::string &name) const
Find entry.
Definition: Volumes.cpp:413
dd4hep::toStringMesh
std::string toStringMesh(const TGeoShape *shape, int precision=2)
Output mesh vertices to string.
Definition: ShapeUtilities.cpp:1295
handle
void handle(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1105
dd4hep::VolumeExtension::referenced
int referenced
Definition: Volumes.h:307
dd4hep::Volume::data
Object * data() const
Check if placement is properly instrumented.
Definition: Volumes.cpp:657
dd4hep::PlacedVolumeExtension::operator=
PlacedVolumeExtension & operator=(PlacedVolumeExtension &&copy)
Move assignment.
Definition: Volumes.cpp:381
dd4hep::Volume::sensitiveDetector
Handle< NamedObject > sensitiveDetector() const
Access to the handle to the sensitive detector.
Definition: Volumes.cpp:1316
dd4hep::VolumeExtension::limits
LimitSet limits
Limit sets used for simulation.
Definition: Volumes.h:313
dd4hep::VisAttrObject::visible
unsigned char visible
Definition: ObjectsInterna.h:97
dd4hep::VisAttrObject
Concrete object implementation of the VisAttr Handle.
Definition: ObjectsInterna.h:88