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  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;
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  ++totalCount;
137  }
138  printout(INFO, "DDCMSDetElementCreator", "++ Summary: %-24s %d.", "Total DetElements:", totalCount);
139  printout(INFO, "DDCMSDetElementCreator", "+++++++++++++++ Readout structure generation ++++++++++++++++++++++++");
140  str << endl;
141  for (const auto& f : fields) {
142  string roName = f.first.name() + string("Hits");
143  int num_bits = 8;
144  id_str.str("");
145  id_str << "system:" << num_bits;
146  for (const auto& q : f.second) {
147  int bits = 0;
148  if (q.second < 1 << 0)
149  bits = 1;
150  else if (q.second < 1 << 1)
151  bits = 1;
152  else if (q.second < 1 << 2)
153  bits = 2;
154  else if (q.second < 1 << 3)
155  bits = 3;
156  else if (q.second < 1 << 4)
157  bits = 4;
158  else if (q.second < 1 << 5)
159  bits = 5;
160  else if (q.second < 1 << 6)
161  bits = 6;
162  else if (q.second < 1 << 7)
163  bits = 7;
164  else if (q.second < 1 << 8)
165  bits = 8;
166  else if (q.second < 1 << 9)
167  bits = 9;
168  else if (q.second < 1 << 10)
169  bits = 10;
170  else if (q.second < 1 << 11)
171  bits = 11;
172  else if (q.second < 1 << 12)
173  bits = 12;
174  else if (q.second < 1 << 13)
175  bits = 13;
176  else if (q.second < 1 << 14)
177  bits = 14;
178  else if (q.second < 1 << 15)
179  bits = 15;
180  bits += 1;
181  id_str << ",Lv" << q.first << ":" << bits;
182  num_bits += bits;
183  }
184  string idspec = id_str.str();
185  str << "<readout name=\"" << roName << "\">" << endl
186  << "\t<id>" << idspec << "</id> <!-- Number of bits: " << num_bits << " -->" << endl
187  << "</readout>" << endl;
188 
190  IDDescriptor dsc(roName, idspec);
191  m_description.addIDSpecification(dsc);
192  Readout ro(roName);
193  ro.setIDDescriptor(dsc);
194  m_description.addReadout(ro);
195  dd4hep::SensitiveDetector sd = m_description.sensitiveDetector(f.first.name());
196  sd.setHitsCollection(ro.name());
197  sd.setReadout(ro);
198  printout(INFO,
199  "DDCMSDetElementCreator",
200  "++ Setting up readout for subdetector:%-24s id:%04X",
201  f.first.name(),
202  f.first.id());
203  }
204  printout(INFO, "DDCMSDetElementCreator", "+++++++++++++++ ID Descriptor generation ++++++++++++++++++++++++++++");
205  printout(INFO, "", str.str().c_str());
206  char volId[32];
207  for (auto& p : m_allPlacements) {
208  dd4hep::PlacedVolume place = p.first;
209  dd4hep::Volume volume = place.volume();
210  ::snprintf(volId, sizeof(volId), "Lv%d", p.second.first);
211  printout(DEBUG,
212  "DDCMSDetElementCreator",
213  "++ Set volid (%-24s): %-6s = %3d -> %s (%p)",
214  volume.isSensitive() ? volume.sensitiveDetector().name() : "Not Sensitive",
215  volId,
216  p.second.second,
217  place.name(),
218  place.ptr());
219  place.addPhysVolID(volId, p.second.second);
220  }
221  printout(ALWAYS,
222  "DDCMSDetElementCreator",
223  "++ Instrumented %ld subdetectors with %d DetElements %d sensitives out of %d volumes and %ld sensitive "
224  "placements.",
225  fields.size(),
226  total.elements,
227  total.sensitives,
228  total.volumes,
229  m_allPlacements.size());
230 }
231 
232 dd4hep::DetElement DDCMSDetElementCreator::createElement(const char*, PlacedVolume volume, int id) {
233  string name = detElementName(volume);
234  dd4hep::DetElement det(name, id);
235  det.setPlacement(volume);
236  return det;
237 }
239  auto& data = m_stack.back();
240  if (m_stack.size() == 2) { // Main subssystem: tracker:Tracker
241  data.element = m_tracker = addSubdetector(cms::detElementName(volume), volume, false);
242  m_tracker->SetTitle("compound");
243  } else if (m_stack.size() == 3) { // Main subsystem detector: TIB, TEC, ....
244  data.element = m_currentDetector = addSubdetector(cms::detElementName(volume), volume, true);
245  }
246 }
247 
249  dd4hep::PlacedVolume volume,
250  bool valid) {
251  auto idet = m_subdetectors.find(nam);
252  if (idet == m_subdetectors.end()) {
253  dd4hep::DetElement det(nam, m_subdetectors.size() + 1);
254  det.setPlacement(volume);
255  if (valid) {
256  det.placement().addPhysVolID("system", det.id());
257  }
258  idet = m_subdetectors.insert(make_pair(nam, det)).first;
259  m_description.add(det);
260  }
261  return idet->second;
262 }
263 
265  double fracSi = volume.volume().material().fraction(m_silicon);
266  if (fracSi > 90e-2) {
267  Data& data = m_stack.back();
268  data.sensitive = true;
269  data.hasSensitive = true;
270  ++data.volumeCount;
271  int idx = volume->GetMotherVolume()->GetIndex(volume.ptr()) + 1;
272  auto& cnt = m_leafCount[make_pair(m_currentDetector, volumeLevel)];
273  cnt.first = std::max(cnt.first, idx);
274  ++cnt.second;
275  m_allPlacements[volume] = make_pair(volumeLevel, idx);
276  return 1;
277  }
278  return 0;
279 }
280 
282  m_stack.push_back(Data(volume));
283  if (m_stack.size() <= 3) {
284  createTopLevelDetectors(volume);
285  }
286  int ret = dd4hep::PlacedVolumeProcessor::process(volume, level, recursive);
287 
289  if (m_stack.size() > 3) {
290  // Note: short-cuts to entries in the m_stack MUST be local and
291  // initialized AFTER the call to "process"! The vector may be resized!
292  auto& data = m_stack.back();
293  auto& parent = m_stack[m_stack.size() - 2];
295  if (data.sensitive) {
297  if (!m_currentSensitive.isValid()) {
298  dd4hep::SensitiveDetector sd = m_description.sensitiveDetector(m_currentDetector.name());
299  if (!sd.isValid()) {
300  sd = dd4hep::SensitiveDetector(m_currentDetector.name(), "tracker");
301  m_currentDetector->flag |= DetElement::Object::HAVE_SENSITIVE_DETECTOR;
302  m_description.add(sd);
303  }
304  m_currentSensitive = sd;
305  }
306  volume.volume().setSensitiveDetector(m_currentSensitive);
307  ++counts.sensitives;
308  }
309  ++counts.volumes;
310  bool added = false;
311  if (data.volumeCount > 0) {
312  parent.daughterCount += data.volumeCount;
313  parent.daughterCount += data.daughterCount;
314  data.hasSensitive = true;
315  } else {
316  parent.daughterCount += data.daughterCount;
317  data.hasSensitive = (data.daughterCount > 0);
318  }
319 
320  if (data.hasSensitive) {
321  // If we have sensitive elements at this level or below,
322  // we must complete the DetElement hierarchy
323  if (!data.element.isValid()) {
324  data.element = createElement("Element", data.volume, m_currentDetector.id());
325  ++counts.elements;
326  }
327  if (!parent.element.isValid()) {
328  parent.element = createElement("Parent ", parent.volume, m_currentDetector.id());
329  ++counts.elements;
330  }
331  printout(DEBUG,
332  "DDCMSDetElementCreator",
333  "++ Assign detector element: %s (%p, %ld children) to %s (%p) with %ld vols",
334  data.element.name(),
335  data.element.ptr(),
336  data.element.children().size(),
337  parent.element.name(),
338  parent.element.ptr(),
339  data.volumeCount);
340 
341  // Trickle up the tree only for sensitive pathes. Forget the passive rest
342  // This should automatically omit non-sensitive pathes
343  parent.hasSensitive = true;
344  parent.element.add(data.element);
345  added = true;
346  // It is simpler to collect the volumes and later assign the volids
347  // rather than checking if the volid already exists.
348  int volumeLevel = level;
349  int idx = data.volume->GetMotherVolume()->GetIndex(data.volume.ptr()) + 1;
350  m_allPlacements[data.volume] = make_pair(volumeLevel, idx); // 1...n
351  // Update counters
352  auto& cnt_det = m_leafCount[make_pair(m_currentDetector, volumeLevel)];
353  cnt_det.first = std::max(cnt_det.first, idx);
354  cnt_det.second += 1;
355  }
356  if (!added && data.element.isValid()) {
357  printout(WARNING,
358  "MEMORY-LEAK",
359  "Level:%3d Orpahaned DetElement:%s Daugthers:%d Parent:%s",
360  int(m_stack.size()),
361  data.element.name(),
362  data.volumeCount,
363  parent.volume.name());
364  }
365  }
367  if (m_stack.size() == 3) {
369  m_currentDetector = DetElement();
370  ret = 0;
371  }
372  m_stack.pop_back();
373  return ret;
374 }
375 
376 static void* createObject(dd4hep::Detector& description, int /* argc */, char** /* argv */) {
377  dd4hep::PlacedVolumeProcessor* proc = new DDCMSDetElementCreator(description);
378  return (void*)proc;
379 }
380 
381 // first argument is the type from the xml file
382 DECLARE_DD4HEP_CONSTRUCTOR(DDCMS_DetElementCreator, createObject);
Basic3DVector & operator=(const Basic3DVector &)=default
Assignment operator.
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)
ret
prodAgent to be discontinued
std::map< std::string, dd4hep::DetElement > Detectors
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
dd4hep::PlacedVolume PlacedVolume
double f[11][100]
dd4hep::Volume Volume
d
Definition: ztail.py:151
Namespace of DDCMS conversion namespace.
TracksUtilities< TrackerTraits > helper
std::string detElementName(dd4hep::PlacedVolume volume)
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:80
#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.
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:92
std::map< dd4hep::PlacedVolume, std::pair< int, int > > m_allPlacements