CMS 3D CMS Logo

DDCmsMTDConstruction.cc
Go to the documentation of this file.
2 
3 #include <utility>
4 #include <sstream>
5 
14 
17 
18 #ifdef EDM_ML_DEBUG
21 #endif
22 
23 class DDNameFilter : public DDFilter {
24 public:
25  void addNS(const std::string& addNS) { allowedNS_.emplace_back(addNS); }
26  void add(const std::string& add) { allowed_.emplace_back(add); }
27  void veto(const std::string& veto) { veto_.emplace_back(veto); }
28 
29  bool accept(const DDExpandedView& ev) const final {
30  if (allowedNS_.size() == 0 && allowed_.size() == 0 && veto_.size() == 0) {
31  return true;
32  }
33  bool out(false);
34  std::string_view currentNSName(ev.logicalPart().name().ns());
35  for (const auto& test : allowedNS_) {
36  if (currentNSName.find(test) != std::string::npos) {
37  out = true;
38  if (allowed_.size() > 0 || veto_.size() > 0) {
39  std::string_view currentName(ev.logicalPart().name().name());
40  for (const auto& test : veto_) {
41  if (currentName.find(test) != std::string::npos) {
42  return false;
43  }
44  }
45  for (const auto& test : allowed_) {
46  if (currentName.find(test) != std::string::npos) {
47  return true;
48  }
49  }
50  }
51  break;
52  }
53  }
54  return out;
55  }
56 
57 private:
58  std::vector<std::string> allowedNS_;
59  std::vector<std::string> allowed_;
60  std::vector<std::string> veto_;
61 };
62 
63 std::unique_ptr<GeometricTimingDet> DDCmsMTDConstruction::construct(const DDCompactView& cpv) {
64  std::string attribute{"CMSCutsRegion"};
66  filter.addNS("mtd");
67  filter.addNS("btl");
68  filter.addNS("etl");
69 
70  DDFilteredView fv(cpv, filter);
71 
72  CmsMTDStringToEnum theCmsMTDStringToEnum;
73  // temporary workaround to distinguish BTL scenarios ordering without introducing a dependency on MTDTopologyMode
74  auto isBTLV2 = false;
75  // temporary workaround to distinguish ETL scenarios ordering without introducing a dependency on MTDTopologyMode
76  const bool prev8(fv.name().find("EModule") != std::string::npos);
77 
78  // Specify ETL end component
80  if (prev8) {
81  ETLEndComponent = GeometricTimingDet::ETLSensor;
82  } else {
83  ETLEndComponent = GeometricTimingDet::ETLSensor;
84  }
85 
86  auto check_root = theCmsMTDStringToEnum.type(ExtractStringFromDD<DDFilteredView>::getString(attribute, &fv));
87  if (check_root != GeometricTimingDet::MTD) {
88  fv.firstChild();
89  auto check_child = theCmsMTDStringToEnum.type(ExtractStringFromDD<DDFilteredView>::getString(attribute, &fv));
90  if (check_child != GeometricTimingDet::MTD) {
91  throw cms::Exception("Configuration") << " The first child of the DDFilteredView is not what is expected \n"
92  << ExtractStringFromDD<DDFilteredView>::getString(attribute, &fv) << "\n";
93  }
94  fv.parent();
95  }
96 
97 #ifdef EDM_ML_DEBUG
98  edm::LogInfo("MTDNumbering") << "Top level node = " << fv.name();
99 #endif
100 
101  auto mtd = std::make_unique<GeometricTimingDet>(&fv, GeometricTimingDet::MTD);
102  size_t limit = 0;
103  CmsMTDConstruction<DDFilteredView> theCmsMTDConstruction;
104 
105  std::vector<GeometricTimingDet*> subdet;
106  std::vector<GeometricTimingDet*> layer;
107 
108  do {
109  GeometricTimingDet::GeometricTimingEnumType fullNode = theCmsMTDStringToEnum.type(fv.name());
111  theCmsMTDStringToEnum.type(fv.name().substr(0, CmsMTDStringToEnum::kModStrLen));
112  size_t num = fv.geoHistory().size();
113 
114 #ifdef EDM_ML_DEBUG
115  edm::LogVerbatim("MTDNumbering") << "Module = " << fv.name() << " fullNode = " << fullNode
116  << " thisNode = " << thisNode;
117 #endif
118 
119  if (fullNode == GeometricTimingDet::BTL || fullNode == GeometricTimingDet::ETL) {
120  limit = 0;
121 
122  // define subdetectors as GeometricTimingDet components
123 
124  subdet.emplace_back(theCmsMTDConstruction.buildSubdet(fv));
125  }
126  if (fullNode == GeometricTimingDet::BTLLayer || fullNode == GeometricTimingDet::ETLDisc) {
127  layer.emplace_back(theCmsMTDConstruction.buildLayer(fv));
128 #ifdef EDM_ML_DEBUG
129  edm::LogVerbatim("MTDNumbering") << "Number of layers: " << layer.size();
130 #endif
131  }
132  //
133  // workaround to make old and TDR structure to cohexist until needed
134  // the level chosen for old corresponds to wafers for D50 and previous scenarios
135  //
136  if ((thisNode == GeometricTimingDet::BTLModule) && limit == 0) {
137  if (theCmsMTDConstruction.isBTLV2(fv)) {
138  limit = num;
139  isBTLV2 = true;
140  } else {
141  limit = num + 1;
142  }
143  } else if ((thisNode == ETLEndComponent) && limit == 0) {
144  limit = num;
145  }
146  if (num != limit && limit > 0) {
147  continue;
148  }
149  if (thisNode == GeometricTimingDet::BTLModule) {
150 #ifdef EDM_ML_DEBUG
151  edm::LogVerbatim("MTDNumbering") << "Registered in GeometricTimingDet as type " << thisNode;
152 #endif
153  theCmsMTDConstruction.buildBTLModule(fv, layer.back());
154  limit = num;
155  } else if (thisNode == ETLEndComponent) {
156 #ifdef EDM_ML_DEBUG
157  edm::LogVerbatim("MTDNumbering") << "Registered in GeometricTimingDet as type " << thisNode;
158 #endif
159  theCmsMTDConstruction.buildETLModule(fv, layer.back());
160  limit = num;
161  }
162  } while (fv.next());
163 
164  // sort GeometricTimingDet
165 
166 #ifdef EDM_ML_DEBUG
167  auto comp = mtd->deepComponents();
168  std::stringstream before(std::stringstream::in | std::stringstream::out);
169  for (const auto& it : comp) {
170  before << "ORDER1 " << it->geographicalId().rawId() << " " << it->type() << " " << it->translation().z() << "\n";
171  }
172  edm::LogVerbatim("MTDNumbering") << "GeometricTimingDet order before sorting \n" << before.str();
173 #endif
174 
175  if (!isBTLV2) {
176  for (size_t index = 0; index < layer.size(); index++) {
178  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderZ);
179  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderRR);
180  if (index > 0) {
181  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderPhi);
182  }
183  }
184  } else {
185  for (size_t index = 0; index < layer.size(); index++) {
187  if (index > 0) {
188  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderZ);
189  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderRR);
190  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderPhi);
191  } else {
192  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::btlOrderPhi);
193  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::btlOrderZ);
194  }
195  }
196  }
197 
198  // Add layers to subdetectors:
199  // first BTL (one layer only)
200 
201  subdet[0]->addComponent(layer[0]);
202 
203  // then ETL (number of layers depend on preTDR design or not)
204 
205  if (layer.size() == kNLayerPreTDR) {
206  subdet[1]->addComponent(layer[1]);
207  subdet[2]->addComponent(layer[2]);
208  } else if (layer.size() == kNLayerTDR) {
209  subdet[1]->addComponent(layer[1]);
210  subdet[1]->addComponent(layer[2]);
211  subdet[2]->addComponent(layer[3]);
212  subdet[2]->addComponent(layer[4]);
213  } else {
214  throw cms::Exception("MTDNumbering") << "Wrong number of layers: " << layer.size();
215  }
216 
217  // Add subdetectors to MTD
218 
219  mtd.get()->addComponents(subdet);
220 
221 #ifdef EDM_ML_DEBUG
222  comp.clear();
223  comp = mtd->deepComponents();
224  std::stringstream after(std::stringstream::in | std::stringstream::out);
225  for (const auto& it : comp) {
226  after << "ORDER2 " << it->geographicalId().rawId() << " " << static_cast<MTDDetId>(it->geographicalId()).mtdRR()
227  << " " << it->type() << " " << it->translation().z() << " "
228  << convertRadToDeg(angle0to2pi::make0To2pi(it->phi())) << "\n";
229  }
230  edm::LogVerbatim("MTDNumbering") << "GeometricTimingDet order after sorting \n" << after.str();
231 #endif
232 
233  return mtd;
234 }
235 
236 std::unique_ptr<GeometricTimingDet> DDCmsMTDConstruction::construct(const cms::DDCompactView& cpv) {
237  cms::DDFilteredView fv(cpv.detector(), cpv.detector()->worldVolume());
238 
239  fv.next(0);
240  edm::LogVerbatim("DD4hep_MTDNumbering") << fv.path();
241  auto mtd = std::make_unique<GeometricTimingDet>(&fv, GeometricTimingDet::MTD);
242 
243  cms::DDSpecParRefs ref;
244  const cms::DDSpecParRegistry& mypar = cpv.specpars();
245  std::string attribute("MtdDDStructure");
246  mypar.filter(ref, attribute, "BarrelTimingLayer");
247  mypar.filter(ref, attribute, "EndcapTimingLayer");
248  fv.mergedSpecifics(ref);
249 
250 #ifdef EDM_ML_DEBUG
251  edm::LogVerbatim("DD4hep_MTDNumbering") << "Active filters using " << attribute << ":";
252  fv.printFilter();
253  edm::LogVerbatim("Geometry").log([&ref](auto& log) {
254  log << "Filtered DD SpecPar Registry size: " << ref.size() << "\n";
255  for (const auto& t : ref) {
256  log << "\nSpecPar " << t.first << ":\nRegExps { ";
257  for (const auto& ki : t.second->paths)
258  log << ki << " ";
259  log << "};\n ";
260  for (const auto& kl : t.second->spars) {
261  log << kl.first << " = ";
262  for (const auto& kil : kl.second) {
263  log << kil << " ";
264  }
265  log << "\n ";
266  }
267  }
268  });
269 #endif
270 
271  bool doSubdet = fv.firstChild();
272  edm::LogVerbatim("DD4hep_MTDNumbering") << fv.path();
273 
274  CmsMTDStringToEnum theCmsMTDStringToEnum;
275 
276  CmsMTDConstruction<cms::DDFilteredView> theCmsMTDConstruction;
277  // temporary workaround to distinguish BTL scenarios ordering without introducing a dependency on MTDTopologyMode
278  auto isBTLV2 = false;
279  // temporary workaround to distinguish ETL scenarios ordering without introducing a dependency on MTDTopologyMode
280  const bool prev8(fv.name().find("EModule") != std::string::npos);
281 
282  // Specify ETL end component
284  if (prev8) {
285  ETLEndComponent = GeometricTimingDet::ETLSensor;
286  } else {
287  ETLEndComponent = GeometricTimingDet::ETLSensor;
288  }
289 
290  std::vector<GeometricTimingDet*> subdet;
291  std::vector<GeometricTimingDet*> layer;
292 
293  while (doSubdet) {
294  std::string nodeName(fv.name());
295  GeometricTimingDet::GeometricTimingEnumType fullNode = theCmsMTDStringToEnum.type(nodeName);
297  theCmsMTDStringToEnum.type(nodeName.substr(0, CmsMTDStringToEnum::kModStrLen));
298 
299 #ifdef EDM_ML_DEBUG
300  edm::LogVerbatim("DD4hep_MTDNumbering") << fv.path();
301  edm::LogVerbatim("DD4hep_MTDNumbering")
302  << "Module = " << fv.name() << " fullNode = " << fullNode << " thisNode = " << thisNode;
303 #endif
304 
305  if (fullNode == GeometricTimingDet::BTL || fullNode == GeometricTimingDet::ETL) {
306  // define subdetectors as GeometricTimingDet components
307 
308  subdet.emplace_back(theCmsMTDConstruction.buildSubdet(fv));
309  }
310  if (fullNode == GeometricTimingDet::BTLLayer || fullNode == GeometricTimingDet::ETLDisc) {
311  layer.emplace_back(theCmsMTDConstruction.buildLayer(fv));
312 #ifdef EDM_ML_DEBUG
313  edm::LogVerbatim("DD4hep_MTDNumbering") << "Number of layers: " << layer.size();
314 #endif
315  }
316  if (thisNode == GeometricTimingDet::BTLModule) {
317 #ifdef EDM_ML_DEBUG
318  edm::LogVerbatim("DD4hep_MTDNumbering") << "Registered in GeometricTimingDet as type " << thisNode;
319 #endif
320  if (isBTLV2 == false) {
321  if (theCmsMTDConstruction.isBTLV2(fv)) {
322  isBTLV2 = true;
323  }
324  }
325  theCmsMTDConstruction.buildBTLModule(fv, layer.back());
326  } else if (thisNode == ETLEndComponent) {
327 #ifdef EDM_ML_DEBUG
328  edm::LogVerbatim("DD4hep_MTDNumbering") << "Registered in GeometricTimingDet as type " << thisNode;
329 #endif
330  theCmsMTDConstruction.buildETLModule(fv, layer.back());
331  }
332 
333  doSubdet = fv.firstChild();
334  }
335 
336  // sort GeometricTimingDet
337 
338 #ifdef EDM_ML_DEBUG
339  auto comp = mtd->deepComponents();
340  std::stringstream before(std::stringstream::in | std::stringstream::out);
341  for (const auto& it : comp) {
342  before << "ORDER1 " << it->geographicalId().rawId() << " " << it->type() << " " << it->translation().z() << "\n";
343  }
344  edm::LogVerbatim("DD4hep_MTDNumbering") << "GeometricTimingDet order before sorting \n" << before.str();
345 #endif
346 
347  if (!isBTLV2) {
348  for (size_t index = 0; index < layer.size(); index++) {
350  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderZ);
351  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderRR);
352  if (index > 0) {
353  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderPhi);
354  }
355  }
356  } else {
357  for (size_t index = 0; index < layer.size(); index++) {
359  if (index > 0) {
360  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderZ);
361  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderRR);
362  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::mtdOrderPhi);
363  } else {
364  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::btlOrderPhi);
365  std::stable_sort(icomp.begin(), icomp.end(), CmsMTDConstruction<DDFilteredView>::btlOrderZ);
366  }
367  }
368  }
369 
370  // Add layers to subdetectors:
371  // first BTL (one layer only)
372 
373  subdet[0]->addComponent(layer[0]);
374 
375  // then ETL (number of layers depend on preTDR design or not)
376 
377  if (layer.size() == kNLayerPreTDR) {
378  subdet[1]->addComponent(layer[1]);
379  subdet[2]->addComponent(layer[2]);
380  } else if (layer.size() == kNLayerTDR) {
381  subdet[1]->addComponent(layer[1]);
382  subdet[1]->addComponent(layer[2]);
383  subdet[2]->addComponent(layer[3]);
384  subdet[2]->addComponent(layer[4]);
385  } else {
386  throw cms::Exception("DD4hep_MTDNumbering") << "Wrong number of layers: " << layer.size();
387  }
388 
389  // Add subdetectors to MTD
390 
391  mtd.get()->addComponents(subdet);
392 
393 #ifdef EDM_ML_DEBUG
394  comp.clear();
395  comp = mtd->deepComponents();
396  std::stringstream after(std::stringstream::in | std::stringstream::out);
397  for (const auto& it : comp) {
398  after << "ORDER2 " << it->geographicalId().rawId() << " " << static_cast<MTDDetId>(it->geographicalId()).mtdRR()
399  << " " << it->type() << " " << it->translation().z() << " "
400  << convertRadToDeg(angle0to2pi::make0To2pi(it->phi())) << "\n";
401  }
402  edm::LogVerbatim("DD4hep_MTDNumbering") << "GeometricTimingDet order after sorting \n" << after.str();
403 #endif
404 
405  return mtd;
406 }
Log< level::Info, true > LogVerbatim
bool isBTLV2(FilteredView &)
void addNS(const std::string &addNS)
bool parent()
set the current node to the parent node ...
void buildBTLModule(FilteredView &, GeometricTimingDet *)
GeometricTimingDet * buildSubdet(FilteredView &)
GeometricTimingDet::GeometricTimingEnumType type(std::string const &) const
dd4hep::SpecParRefs DDSpecParRefs
Definition: DDCompactView.h:29
std::vector< std::string > allowedNS_
constexpr NumType convertRadToDeg(NumType radians)
Definition: angle_units.h:21
const cms::DDDetector * detector() const
Definition: DDCompactView.h:34
const std::string & name() const
The name of a logical-part of the current node in the filtered-view.
DDSpecParRegistry const & specpars() const
Definition: DDCompactView.h:35
static constexpr size_t kNLayerTDR
Compact representation of the geometrical detector hierarchy.
Definition: DDCompactView.h:81
static constexpr size_t kModStrLen
static constexpr size_t kNLayerPreTDR
Detector identifier base class for the MIP Timing Layer.
Definition: MTDDetId.h:21
std::vector< std::string > veto_
dd4hep::SpecParRegistry DDSpecParRegistry
Definition: DDCompactView.h:28
static std::unique_ptr< GeometricTimingDet > construct(const DDCompactView &cpv)
static std::string getString(const std::string &, FilteredView *)
void add(const std::string &add)
GeometricTimingDet * buildLayer(FilteredView &)
bool next(int)
set current node to the next node in the filtered tree
std::vector< std::string > allowed_
Log< level::Info, false > LogInfo
void buildETLModule(FilteredView &, GeometricTimingDet *)
dd4hep::Volume worldVolume() const
Handle to the world volume containing everything.
Definition: DDDetector.cc:67
bool accept(const DDExpandedView &ev) const final
true, if the DDExpandedNode fulfills the filter criteria
constexpr valType make0To2pi(valType angle)
Definition: deltaPhi.h:67
enum GTDEnumType { unknown=100, MTD=0, BTL=1, BTLLayer=2, BTLTray=3, BTLModule=4, BTLSensor=5, BTLCrystal=6, ETL=7, ETLDisc=8, ETLRing=9, ETLModule=10, ETLSensor=11 } GeometricTimingEnumType
std::vector< GeometricTimingDet const * > ConstGeometricTimingDetContainer
bool firstChild()
set the current node to the first child ...
A Filter accepts or rejects a DDExpandedNode based on a user-coded decision rule. ...
Definition: DDFilter.h:15
void veto(const std::string &veto)
Provides an exploded view of the detector (tree-view)