CMS 3D CMS Logo

DDCMSDetElementCreator.cc
Go to the documentation of this file.
1 #include "DD4hep/VolumeProcessor.h"
2 #include "DD4hep/detail/DetectorInterna.h"
3 #include "DD4hep/DetFactoryHelper.h"
4 #include "DD4hep/DetectorHelper.h"
5 #include "DD4hep/Printout.h"
7 
8 #include <sstream>
9 
10 using namespace std;
11 using namespace cms;
12 using namespace dd4hep;
13 
14 namespace cms {
15 
16  // Heuristically assign DetElement structures
17  // to the sensitive volume pathes
18  //
19  class DDCMSDetElementCreator : public dd4hep::PlacedVolumeProcessor
20  {
21  public:
22 
24  ~DDCMSDetElementCreator() override;
25 
27  int operator()( dd4hep::PlacedVolume volume, int level ) override;
29  int process( dd4hep::PlacedVolume volume, int level, bool recursive ) override;
30 
31  private:
32 
33  dd4hep::DetElement addSubdetector( const std::string& nam, dd4hep::PlacedVolume volume, bool valid );
34  dd4hep::DetElement createElement( const char* debugTag, dd4hep::PlacedVolume volume, int id );
35  void createTopLevelDetectors( dd4hep::PlacedVolume volume );
36 
37  struct Data
38  {
39  Data() = default;
40  Data( dd4hep::PlacedVolume v ) : volume( v ) {}
41  Data( const Data& d ) = default;
42  Data& operator=( const Data& d ) = default;
43 
44  dd4hep::PlacedVolume volume {nullptr};
45  dd4hep::DetElement element {};
46  bool sensitive = false;
47  bool hasSensitive = false;
48  int volumeCount = 0;
49  int daughterCount = 0;
50  int sensitiveCount = 0;
51  };
52 
53  struct Count
54  {
55  Count() = default;
56  Count( const Count& ) = default;
57  Count& operator=( const Count& ) = default;
58 
59  int elements = 0;
60  int volumes = 0;
61  int sensitives = 0;
62  };
63 
64  using Detectors = std::map<std::string, dd4hep::DetElement>;
65  using Counters = std::map<dd4hep::DetElement, Count>;
66  using LeafCount = std::map<std::pair<dd4hep::DetElement, int>, std::pair<int, int> >;
67  using VolumeStack = std::vector<Data>;
68 
69  std::map<dd4hep::PlacedVolume, std::pair<int,int> > m_allPlacements;
70 
75  dd4hep::DetElement m_tracker, m_currentDetector;
76  dd4hep::SensitiveDetector m_currentSensitive;
78  dd4hep::Atom m_silicon;
79  };
80 
81  std::string detElementName( dd4hep::PlacedVolume volume );
82 }
83 
85 cms::detElementName( dd4hep::PlacedVolume volume ) {
86  if( volume.isValid()) {
87  std::string name = volume.name();
88  std::string nnam = name.substr( name.find(NAMESPACE_SEP) + 1 );
89  return nnam;
90  }
91  except("DD4CMS","++ Cannot deduce name from invalid PlacedVolume handle!");
92  return std::string();
93 }
94 
95 DDCMSDetElementCreator::DDCMSDetElementCreator( dd4hep::Detector& desc )
96  : m_description( desc )
97 {
98  dd4hep::DetectorHelper helper( m_description );
99  m_silicon = helper.element( "SI" );
100  if( !m_silicon.isValid()) {
101  except( "DDCMSDetElementCreator",
102  "++ Failed to extract SILICON from the element table." );
103  }
104  m_stack.reserve(32);
105 }
106 
108 {
109  Count total;
110  stringstream str, id_str;
111 
112  printout( INFO, "DDCMSDetElementCreator", "+++++++++++++++ Summary of sensitve elements ++++++++++++++++++++++++" );
113  for( const auto& c : m_counters ) {
114  printout( INFO, "DDCMSDetElementCreator", "++ Summary: SD: %-24s %7d DetElements %7d sensitives out of %7d volumes",
115  ( c.first.name() + string(":")).c_str(), c.second.elements, c.second.sensitives, c.second.volumes );
116  total.elements += c.second.elements;
117  total.sensitives += c.second.sensitives;
118  total.volumes += c.second.volumes;
119  }
120  printout( INFO, "DDCMSDetElementCreator", "++ Summary: %-24s %7d DetElements %7d sensitives out of %7d volumes",
121  "Grand Total:", total.elements, total.sensitives, total.volumes );
122  printout( INFO, "DDCMSDetElementCreator", "+++++++++++++++ Summary of geometry depth analysis ++++++++++++++++++" );
123  int totalCount = 0, totalDepth = 0;
124  map<dd4hep::DetElement, vector<pair<int,int> > > fields;
125  for( const auto& l : m_leafCount ) {
126  dd4hep::DetElement de = l.first.first;
127  printout( INFO,"DDCMSDetElementCreator", "++ Summary: SD: %-24s system:%04X Lvl:%3d Sensitives: %6d [Max: %6d].",
128  ( de.name() + string(":")).c_str(), de.id(),
129  l.first.second, l.second.second, l.second.first );
130  fields[de].push_back( make_pair( l.first.second, l.second.first ));
131  totalDepth += l.second.second;
132  ++totalCount;
133  }
134  printout( INFO, "DDCMSDetElementCreator", "++ Summary: %-24s %d.","Total DetElements:", totalCount );
135  printout( INFO, "DDCMSDetElementCreator", "+++++++++++++++ Readout structure generation ++++++++++++++++++++++++" );
136  str << endl;
137  for( const auto& f : fields ) {
138  string roName = f.first.name() + string("Hits");
139  int num_bits = 8;
140  id_str.str("");
141  id_str << "system:" << num_bits;
142  for( const auto& q : f.second ) {
143  int bits = 0;
144  if ( q.second < 1<<0 ) bits = 1;
145  else if ( q.second < 1<<1 ) bits = 1;
146  else if ( q.second < 1<<2 ) bits = 2;
147  else if ( q.second < 1<<3 ) bits = 3;
148  else if ( q.second < 1<<4 ) bits = 4;
149  else if ( q.second < 1<<5 ) bits = 5;
150  else if ( q.second < 1<<6 ) bits = 6;
151  else if ( q.second < 1<<7 ) bits = 7;
152  else if ( q.second < 1<<8 ) bits = 8;
153  else if ( q.second < 1<<9 ) bits = 9;
154  else if ( q.second < 1<<10 ) bits = 10;
155  else if ( q.second < 1<<11 ) bits = 11;
156  else if ( q.second < 1<<12 ) bits = 12;
157  else if ( q.second < 1<<13 ) bits = 13;
158  else if ( q.second < 1<<14 ) bits = 14;
159  else if ( q.second < 1<<15 ) bits = 15;
160  bits += 1;
161  id_str << ",Lv" << q.first << ":" << bits;
162  num_bits += bits;
163  }
164  string idspec = id_str.str();
165  str << "<readout name=\"" << roName << "\">" << endl
166  << "\t<id>"
167  << idspec
168  << "</id> <!-- Number of bits: " << num_bits << " -->" << endl
169  << "</readout>" << endl;
170 
172  IDDescriptor dsc( roName, idspec );
173  m_description.addIDSpecification( dsc );
174  Readout ro( roName );
175  ro.setIDDescriptor( dsc );
176  m_description.addReadout( ro );
177  dd4hep::SensitiveDetector sd = m_description.sensitiveDetector( f.first.name());
178  sd.setHitsCollection( ro.name());
179  sd.setReadout( ro );
180  printout( INFO, "DDCMSDetElementCreator",
181  "++ Setting up readout for subdetector:%-24s id:%04X",
182  f.first.name(), f.first.id());
183  }
184  printout( INFO, "DDCMSDetElementCreator","+++++++++++++++ ID Descriptor generation ++++++++++++++++++++++++++++");
185  printout( INFO, "", str.str().c_str());
186  char volId[32];
187  for(auto& p : m_allPlacements ) {
188  dd4hep::PlacedVolume place = p.first;
189  dd4hep::Volume volume = place.volume();
190  ::snprintf( volId, sizeof(volId), "Lv%d", p.second.first );
191  printout( DEBUG,"DDCMSDetElementCreator",
192  "++ Set volid (%-24s): %-6s = %3d -> %s (%p)",
193  volume.isSensitive() ? volume.sensitiveDetector().name() : "Not Sensitive",
194  volId, p.second.second, place.name(), place.ptr());
195  place.addPhysVolID( volId, p.second.second);
196  }
197  printout( ALWAYS, "DDCMSDetElementCreator",
198  "++ Instrumented %ld subdetectors with %d DetElements %d sensitives out of %d volumes and %ld sensitive placements.",
199  fields.size(), total.elements, total.sensitives, total.volumes, m_allPlacements.size());
200 }
201 
202 dd4hep::DetElement
203 DDCMSDetElementCreator::createElement( const char*, PlacedVolume volume, int id )
204 {
205  string name = detElementName( volume );
206  dd4hep::DetElement det( name, id );
207  det.setPlacement( volume );
208  return det;
209 }
210 void
212 {
213  auto& data = m_stack.back();
214  if( m_stack.size() == 2 ) { // Main subssystem: tracker:Tracker
215  data.element = m_tracker = addSubdetector( cms::detElementName(volume), volume, false );
216  m_tracker->SetTitle( "compound" );
217  }
218  else if( m_stack.size() == 3 ) { // Main subsystem detector: TIB, TEC, ....
219  data.element = m_currentDetector = addSubdetector( cms::detElementName(volume), volume, true );
220  }
221 }
222 
223 dd4hep::DetElement
224 DDCMSDetElementCreator::addSubdetector( const std::string& nam, dd4hep::PlacedVolume volume, bool valid )
225 {
226  auto idet = m_subdetectors.find(nam);
227  if( idet == m_subdetectors.end()) {
228  dd4hep::DetElement det( nam, m_subdetectors.size() + 1 );
229  det.setPlacement( volume );
230  if( valid ) {
231  det.placement().addPhysVolID( "system", det.id());
232  }
233  idet = m_subdetectors.insert( make_pair( nam, det)).first;
234  m_description.add( det );
235  }
236  return idet->second;
237 }
238 
239 int
240 DDCMSDetElementCreator::operator()( dd4hep::PlacedVolume volume, int volumeLevel )
241 {
242  double fracSi = volume.volume().material().fraction( m_silicon );
243  if( fracSi > 90e-2 ) {
244  Data& data = m_stack.back();
245  data.sensitive = true;
246  data.hasSensitive = true;
247  ++data.volumeCount;
248  int idx = volume->GetMotherVolume()->GetIndex( volume.ptr())+1;
249  auto& cnt = m_leafCount[make_pair( m_currentDetector, volumeLevel )];
250  cnt.first = std::max( cnt.first, idx );
251  ++cnt.second;
252  m_allPlacements[volume] = make_pair( volumeLevel, idx );
253  return 1;
254  }
255  return 0;
256 }
257 
258  int
259 DDCMSDetElementCreator::process( dd4hep::PlacedVolume volume, int level,
260  bool recursive )
261  {
262  m_stack.push_back(Data(volume));
263  if ( m_stack.size() <= 3 ) {
264  createTopLevelDetectors(volume);
265  }
266  int ret = dd4hep::PlacedVolumeProcessor::process( volume, level, recursive );
267 
269  if( m_stack.size() > 3 ) {
270  // Note: short-cuts to entries in the m_stack MUST be local and
271  // initialized AFTER the call to "process"! The vector may be resized!
272  auto& data = m_stack.back();
273  auto& parent = m_stack[ m_stack.size() - 2 ];
274  auto& counts = m_counters[ m_currentDetector ];
275  if( data.sensitive ) {
277  if ( !m_currentSensitive.isValid()) {
278  dd4hep::SensitiveDetector sd = m_description.sensitiveDetector( m_currentDetector.name());
279  if( !sd.isValid()) {
280  sd = dd4hep::SensitiveDetector( m_currentDetector.name(), "tracker" );
281  m_currentDetector->flag |= DetElement::Object::HAVE_SENSITIVE_DETECTOR;
282  m_description.add( sd );
283  }
285  }
286  volume.volume().setSensitiveDetector( m_currentSensitive );
287  ++counts.sensitives;
288  }
289  ++counts.volumes;
290  bool added = false;
291  if( data.volumeCount > 0 ) {
292  parent.daughterCount += data.volumeCount;
293  parent.daughterCount += data.daughterCount;
294  data.hasSensitive = true;
295  }
296  else {
297  parent.daughterCount += data.daughterCount;
298  data.hasSensitive = ( data.daughterCount > 0 );
299  }
300 
301  if( data.hasSensitive ) {
302  // If we have sensitive elements at this level or below,
303  // we must complete the DetElement hierarchy
304  if( !data.element.isValid()) {
305  data.element = createElement( "Element", data.volume, m_currentDetector.id());
306  ++counts.elements;
307  }
308  if( !parent.element.isValid()) {
309  parent.element = createElement( "Parent ", parent.volume, m_currentDetector.id());
310  ++counts.elements;
311  }
312  printout( DEBUG, "DDCMSDetElementCreator",
313  "++ Assign detector element: %s (%p, %ld children) to %s (%p) with %ld vols",
314  data.element.name(), data.element.ptr(), data.element.children().size(),
315  parent.element.name(), parent.element.ptr(),
316  data.volumeCount );
317 
318  // Trickle up the tree only for sensitive pathes. Forget the passive rest
319  // This should automatically omit non-sensitive pathes
320  parent.hasSensitive = true;
321  parent.element.add( data.element );
322  added = true;
323  // It is simpler to collect the volumes and later assign the volids
324  // rather than checking if the volid already exists.
325  int volumeLevel = level;
326  int idx = data.volume->GetMotherVolume()->GetIndex( data.volume.ptr())+1;
327  m_allPlacements[data.volume] = make_pair( volumeLevel, idx ); // 1...n
328  // Update counters
329  auto& cnt_det = m_leafCount[make_pair( m_currentDetector, volumeLevel )];
330  cnt_det.first = std::max( cnt_det.first, idx );
331  cnt_det.second += 1;
332  }
333  if ( !added && data.element.isValid() ) {
334  printout(WARNING,"MEMORY-LEAK","Level:%3d Orpahaned DetElement:%s Daugthers:%d Parent:%s",
335  int(m_stack.size()), data.element.name(), data.volumeCount, parent.volume.name());
336  }
337  }
339  if( m_stack.size() == 3 ) {
341  m_currentDetector = DetElement();
342  ret = 0;
343  }
344  m_stack.pop_back();
345  return ret;
346 }
347 
348 static void*
349 createObject( dd4hep::Detector& description, int /* argc */, char** /* argv */) {
350  dd4hep::PlacedVolumeProcessor* proc = new DDCMSDetElementCreator( description );
351  return (void*)proc;
352 }
353 
354 // first argument is the type from the xml file
355 DECLARE_DD4HEP_CONSTRUCTOR( DDCMS_DetElementCreator, createObject);
356 
#define DEBUG
static void * createObject(dd4hep::Detector &description, int, char **)
void createTopLevelDetectors(dd4hep::PlacedVolume volume)
Definition: helper.py:1
dd4hep::DetElement createElement(const char *debugTag, dd4hep::PlacedVolume volume, int id)
TrainProcessor *const proc
Definition: MVATrainer.cc:101
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision bits
std::map< std::string, dd4hep::DetElement > Detectors
static const int WARNING
std::map< dd4hep::PlacedVolume, std::pair< int, int > > m_allPlacements
DDCMSDetElementCreator(dd4hep::Detector &)
int process(dd4hep::PlacedVolume volume, int level, bool recursive) override
Callback to output PlacedVolume information of an entire Placement.
DECLARE_DD4HEP_CONSTRUCTOR(DDCMS_DetElementCreator, createObject)
std::map< dd4hep::DetElement, Count > Counters
double f[11][100]
Namespace of DDCMS conversion namespace.
double sd
std::string detElementName(dd4hep::PlacedVolume volume)
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
std::map< std::pair< dd4hep::DetElement, int >, std::pair< int, int > > LeafCount
int operator()(dd4hep::PlacedVolume volume, int level) override
Callback to output PlacedVolume information of an single Placement.
dd4hep::DetElement addSubdetector(const std::string &nam, dd4hep::PlacedVolume volume, bool valid)
dd4hep::SensitiveDetector m_currentSensitive
#define str(s)
#define NAMESPACE_SEP
Definition: DDNamespace.h:78