DD4hep  1.38.0
Detector Description Toolkit for High Energy Physics
DetectorStructure.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // ALEPH software suite
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see OnlineSys/LICENSE.
8 //
9 //--------------------------------------------------------------------------
10 //
11 // Author : Markus Frank
12 //==========================================================================
13 
15 #include <XML/DetectorStructure.h>
16 
18 #include <iomanip>
19 #include <memory>
20 #include <regex>
21 
22 namespace {
24  void _reset_cache(dd4hep::DetElement de) {
25  de->path = "";
26  de->placementPath = "";
27  for( const auto& c : de->children )
28  _reset_cache( c.second );
29  }
30 }
31 
33 namespace dd4hep {
34 
36  namespace tools {
37 
38  static std::regex_constants::syntax_option_type regex_flags() {
39  return std::regex_constants::icase | std::regex_constants::ECMAScript;
40  }
41 
42  struct placement_scan {
43  const std::string& _place;
45  placement_scan(const std::string& pl) : _place(pl) {
46  }
47  std::pair<std::string, PlacedVolume>
48  scan( std::string p, PlacedVolume node ) const {
49  std::string path = std::move(p) + "/" + node.name();
50  if( path == this->_place ) return { path, node };
51  for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) {
52  auto ret = this->scan( path, node->GetDaughter(idau) );
53  if( ret.second.isValid() ) return ret;
54  }
55  return { {}, {} };
56  }
57  };
58 
59  struct volume_scan {
60  std::regex _regex;
62  volume_scan(const std::string& v) : _regex(v.c_str(), regex_flags()) { }
63  std::pair<std::string, PlacedVolume>
64  scan( std::string p, PlacedVolume node ) const {
65  std::string path = std::move(p) + "/" + node.name();
66  std::string voln = node.volume().name();
67  std::smatch sm;
68  bool stat = std::regex_match( voln, sm, this->_regex );
69  if( stat ) {
70  return { path, node };
71  }
72  for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) {
73  auto ret = this->scan( path, node->GetDaughter(idau) );
74  if( ret.second.isValid() ) return ret;
75  }
76  return { {}, {} };
77  }
78  };
79 
80  struct volume_collect {
81  std::regex _regex;
82  std::map<std::string, PlacedVolume> placements;
83 
85  volume_collect(const std::string& v) : _regex(v.c_str(), regex_flags()) { }
86  void collect( std::string p, PlacedVolume node ) {
87  std::string path = std::move(p) + "/" + node.name();
88  std::string voln = node.volume().name();
89  std::smatch sm;
90  bool stat = std::regex_match( voln, sm, this->_regex );
91  if( stat ) {
92  this->placements.insert( { path, node } );
93  }
94  for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau )
95  this->collect( path, { node->GetDaughter(idau) } );
96  }
97  };
98  }
99 }
100 
103  : description(dsc), sensitive(sd), xd(e) {
104  if( xd.hasAttr(_U(debug)) ) {
105  int value = xd.attr<int>(_U(debug));
106  this->print = PrintLevel(value);
107  }
108 }
109 
111 void dd4hep::DetectorStructure::_set_volid( PlacedVolume pv, const std::string& volid, int value ) {
112  const auto& vids = pv.volIDs();
113  for( const auto& vid : vids ) {
114  if( vid.first == volid ) {
115  if( value == vid.second ) {
116  return;
117  }
118  printout(ERROR, this->name,
119  "+++ Invalid VOLID: %s: %s %d <> %d",
120  name.c_str(), volid.c_str(), vid.second, value);
121  }
122  }
123  pv.addPhysVolID( volid, value );
124 }
125 
128  if( e.hasAttr(_U(vis)) ) {
129  auto vis = e.attr<std::string>(_U(vis));
130  volume.setVisAttributes( this->description, vis );
131  }
132  if( e.hasAttr(_U(limits)) ) {
133  auto lim = e.attr<std::string>(_U(limits));
134  volume.setLimitSet( this->description, lim );
135  }
136  if( e.hasAttr(_U(region)) ) {
137  auto reg = e.attr<std::string>(_U(region));
138  volume.setRegion( this->description, reg );
139  }
140  if( this->sensitive.isValid() && xd.ptr() != e.ptr() && e.hasAttr(_U(sensitive)) ) {
141  volume.setSensitiveDetector( this->sensitive );
142  }
143 }
144 
147  std::pair<std::string, PlacedVolume> ret;
148 
149  this->id = this->xd.id();
150  this->name = this->xd.nameStr();
151 
152  if( this->xd.hasAttr(_U(placement)) ) {
153  auto place = this->xd.attr<std::string>(_U(placement));
154  ret = tools::placement_scan(place).scan( {}, this->description.world().placement() );
155  if( !ret.second.isValid() ) {
156  except( this->name, "+++ [id:%d] %s: Failed to find top level placement: '%s'",
157  this->id, this->name.c_str(), place.c_str() );
158  }
159  }
160  else if( this->xd.hasAttr(_U(volume)) ) {
161  auto vol = this->xd.attr<std::string>(_U(volume));
162  ret = tools::volume_scan(vol).scan( {}, this->description.world().placement() );
163  if( !ret.second.isValid() ) {
164  except( this->name, "+++ [id:%d] %s: Failed to find top level volume: '%s'",
165  this->id, this->name.c_str(), vol.c_str() );
166  }
167  }
168  else {
169  except( this->name, "+++ [id:%d] %s Unknown DetElement selector.",
170  this->id, this->name.c_str() );
171  }
172 
173  if( xd.hasAttr(_U(sensitive)) ) {
174  auto sens = xd.attr<std::string>(_U(sensitive));
175  if( !this->sensitive.isValid() ) {
176  this->sensitive = this->description.sensitiveDetector( this->name );
177  }
178  if( !this->sensitive.isValid() ) {
179  except( this->name, "+++ [id:%d] %s No suitable sensitive detector available",
180  this->id, this->name.c_str() );
181  }
182  this->sensitive.setType( sens );
183  }
184 
185  DetElement detector( this->name, this->id );
186  auto pv = ret.second;
187  auto vol = pv.volume();
188  detector->volumeID = this->id;
189  detector.setPlacement( pv );
190  _set_attr( vol, xd );
191 
192  printout( this->print, this->name,
193  "+++ [id:%d] %-40s Creating detector element path:%s",
194  detector.id(), detector.path().c_str(), detector.placementPath().c_str());
195  if( xd.hasAttr(_U(sensitive)) ) {
196  std::string readout_name = "----";
197 
198  pv.addPhysVolID( "system", this->id );
199  if( xd.hasAttr(_U(readout)) ) {
200  readout_name = xd.readoutStr();
201  Readout rdout = this->description.readout( readout_name );
202  if( !rdout.isValid() ) {
203  except(this->name, "+++ [id:%d] %s Invalid readout object: %s.",
204  this->id, this->name.c_str(), readout_name.c_str() );
205  }
206  this->sensitive.setReadout( rdout );
207  }
208  printout( this->print, this->name,
209  "+++ [id:%d] %-40s Assign readout '%s' to sensitive detector: '%s' [%s]",
210  this->id, this->name.c_str(), readout_name.c_str(),
211  this->sensitive.name(), this->sensitive.type().c_str() );
212  }
213  if( pv.num_daughters() > 0 ) {
214  for( xml_coll_t coll(this->xd, _U(daughter)); coll; ++coll ) {
215  this->add_children( detector, coll );
216  }
217  }
218  // We printed the detelement pathes. Need to reset them before returning.
219  _reset_cache( detector );
220  return detector;
221 }
222 
225  auto pv = parent.placement();
226  auto vol = e.attr<std::string>(_U(volume));
227  tools::volume_collect helper(vol);
228 
229  helper.collect( {}, pv );
230  if( helper.placements.empty() ) {
231  return;
232  }
233  for( auto& place : helper.placements ) {
234  PlacedVolume& dpv = place.second;
235  int vid = e.hasAttr(_U(id)) ? e.id() : parent.children().size();
236  VisAttr vis = dpv.volume().visAttributes();
237  std::string nam = e.nameStr() + _toString(vid, "_%d");
238  DetElement de( parent, nam, parent.id() );
239  Volume volume = dpv.volume();
240 
241  _set_attr( volume, e );
242  if( !this->sensitive.isValid() ) {
243  if( e.hasAttr(_U(sensitive)) ) {
244  volume.setSensitiveDetector( this->sensitive );
245  }
246  }
247  if( e.hasAttr(_U(physvolid)) ) {
248  auto volid = e.attr<std::string>( _U(physvolid) );
249  this->_set_volid( dpv, volid, vid );
250  }
251  de->volumeID = vid;
252  de.setPlacement( dpv );
253 
254  printout( this->print, this->name,
255  "+++ [id:%d] %-40s sub-element %-8s [id:%d] vis:%-10s %3d --> place %s",
256  parent.id(), de.path().c_str(), de.name(), de.id(),
257  vis.isValid() ? vis.name() : "---", dpv.copyNumber(), place.first.c_str() );
258  if( dpv.num_daughters() > 0 ) {
259  for( xml_coll_t coll(e, _U(daughter)); coll; ++coll ) {
260  this->add_children( de, coll );
261  }
262  }
263  }
264 }
dd4hep::DetElement::children
const Children & children() const
Access to the list of children.
Definition: DetElement.cpp:207
dd4hep::DetElement::path
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
Definition: DetElement.cpp:158
dd4hep::tools::placement_scan::_place
const std::string & _place
Definition: DetectorStructure.cpp:43
dd4hep::xml::Collection_t
Class to support the access to collections of XmlNodes (or XmlElements)
Definition: XMLElements.h:636
dd4hep::tools::placement_scan::placement_scan
placement_scan(const std::string &pl)
Default constructor.
Definition: DetectorStructure.cpp:45
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:1306
dd4hep::tools::volume_collect
Definition: DetectorStructure.cpp:80
v
View * v
Definition: MultiView.cpp:28
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:43
dd4hep::DetectorStructure::construct
DetElement construct()
Construct subdetector from Geant3 geometry.
Definition: DetectorStructure.cpp:146
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:164
dd4hep::VisAttr
Handle class describing visualization attributes.
Definition: Objects.h:331
dd4hep::DetElement::placement
PlacedVolume placement() const
Access to the physical volume of this detector element.
Definition: DetElement.cpp:321
dd4hep::PlacedVolume::addPhysVolID
PlacedVolume & addPhysVolID(const std::string &name, int value)
Add identifier.
Definition: Volumes.cpp:505
dd4hep::DetectorStructure::DetectorStructure
DetectorStructure(Detector &dsc, xml_h e, SensitiveDetector sd)
Default constructor.
Definition: DetectorStructure.cpp:102
dd4hep::debug
std::size_t debug(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:64
dd4hep::DetectorStructure::_set_attr
void _set_attr(Volume volume, xml_det_t e) const
Set properties for all volumes.
Definition: DetectorStructure.cpp:127
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:126
dd4hep::DetectorStructure::xd
xml_det_t xd
Definition: DetectorStructure.h:31
dd4hep::_toString
std::string _toString(bool value)
String conversions: boolean value to string.
Definition: Handle.cpp:332
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:1287
dd4hep::xml::Handle_t
Class to easily access the properties of single XmlElements.
Definition: XMLElements.h:380
dd4hep::DetectorStructure::print
PrintLevel print
Definition: DetectorStructure.h:29
dd4hep::DetElement::volumeID
VolumeID volumeID() const
The cached VolumeID of this subdetector element.
Definition: DetElement.cpp:344
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
DetectorStructure.h
dd4hep::tools::placement_scan::scan
std::pair< std::string, PlacedVolume > scan(std::string p, PlacedVolume node) const
Definition: DetectorStructure.cpp:48
dd4hep::tools::volume_scan
Definition: DetectorStructure.cpp:59
dd4hep::tools::volume_scan::_regex
std::regex _regex
Definition: DetectorStructure.cpp:60
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:187
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:371
dd4hep::Volume::setSensitiveDetector
const Volume & setSensitiveDetector(const SensitiveDetector &obj) const
Assign the sensitive detector structure.
Definition: Volumes.cpp:1325
xml_det_t
dd4hep::xml::DetElement xml_det_t
Definition: XML.h:32
_U
#define _U(a)
Definition: Tags.h:23
dd4hep::DetElement::placementPath
const std::string & placementPath() const
Access to the full path to the placed object.
Definition: DetElement.cpp:85
dd4hep::DetectorStructure::_set_volid
void _set_volid(PlacedVolume pv, const std::string &volid, int value)
Assign volume ID to placement.
Definition: DetectorStructure.cpp:111
dd4hep::tools::volume_collect::_regex
std::regex _regex
Definition: DetectorStructure.cpp:81
dd4hep::tools::volume_scan::volume_scan
volume_scan(const std::string &v)
Default constructor.
Definition: DetectorStructure.cpp:62
dd4hep::tools::placement_scan
Definition: DetectorStructure.cpp:42
dd4hep::DetElement::setPlacement
DetElement & setPlacement(const PlacedVolume &volume)
Set the physical volumes of the detector element.
Definition: DetElement.cpp:330
dd4hep::PlacedVolume::num_daughters
std::size_t num_daughters() const
Number of daughters placed in this volume.
Definition: Volumes.cpp:482
dd4hep::tools::volume_collect::volume_collect
volume_collect(const std::string &v)
Default constructor.
Definition: DetectorStructure.cpp:85
dd4hep::Volume::setVisAttributes
const Volume & setVisAttributes(const VisAttr &obj) const
Set Visualization attributes to the volume.
Definition: Volumes.cpp:1172
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::PlacedVolume::copyNumber
int copyNumber() const
Access the copy number of this placement within its mother.
Definition: Volumes.cpp:462
dd4hep::PlacedVolume::volume
Volume volume() const
Logical volume of this placement.
Definition: Volumes.cpp:472
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:89
dd4hep::Readout
Handle to the implementation of the readout structure of a subdetector.
Definition: Readout.h:38
dd4hep::tools::volume_scan::scan
std::pair< std::string, PlacedVolume > scan(std::string p, PlacedVolume node) const
Definition: DetectorStructure.cpp:64
dd4hep::DetElement::id
int id() const
Get the detector identifier.
Definition: DetElement.cpp:169
dd4hep::PlacedVolume::volIDs
const PlacedVolumeExtension::VolIDs & volIDs() const
Access to the volume IDs.
Definition: Volumes.cpp:500
dd4hep::tools::volume_collect::collect
void collect(std::string p, PlacedVolume node)
Definition: DetectorStructure.cpp:86
dd4hep::DetectorStructure::add_children
void add_children(DetElement parent, xml_det_t e)
Add sub-branch of DetElements to subdetector.
Definition: DetectorStructure.cpp:224
dd4hep::Volume::visAttributes
VisAttr visAttributes() const
Access the visualisation attributes.
Definition: Volumes.cpp:1255
dd4hep::tools::volume_collect::placements
std::map< std::string, PlacedVolume > placements
Definition: DetectorStructure.cpp:82