CMS 3D CMS Logo

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