CMS 3D CMS Logo

GeometryInterface.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: SiPixelPhase1Common
4 // Class: GeometryInterface
5 //
6 // Geometry depedence goes here.
7 //
8 // Original Author: Marcel Schneider
9 
11 
12 // general plotting helpers
14 
15 // edm stuff
18 
19 // Tracker Geometry/Topology stuff
30 
31 // Pixel names
34 
35 // C++ stuff
36 #include <cassert>
37 #include <cstdint>
38 #include <iostream>
39 #include <iomanip>
40 #include <memory>
41 
43 
45  //loadFromAlignment(iSetup, iConfig);
46  loadFromTopology(iSetup, iConfig);
47  loadTimebased(iSetup, iConfig);
48  loadModuleLevel(iSetup, iConfig);
49  loadFEDCabling(iSetup, iConfig);
51  edm::LogInfo log("GeometryInterface");
52  log << "Known colum names:\n";
53  for (auto e : ids) log << "+++ column: " << e.first
54  << " ok " << bool(extractors[e.second]) << " min " << min_value[e.second] << " max " << max_value[e.second] << "\n";
55  is_loaded = true;
56 }
57 
59  // Get a Topology
60  edm::ESHandle<TrackerTopology> trackerTopologyHandle;
61  iSetup.get<TrackerTopologyRcd>().get(trackerTopologyHandle);
62  assert(trackerTopologyHandle.isValid());
63 
64  std::vector<ID> geomquantities;
65 
66  struct TTField {
67  const TrackerTopology* tt;
69  Value operator()(InterestingQuantities const& iq) {
70  if (tt->hasField(iq.sourceModule, field))
71  return tt->getField(iq.sourceModule, field);
72  else
73  return UNDEFINED;
74  };
75  };
76 
77  const TrackerTopology* tt = trackerTopologyHandle.operator->();
78 
79 
80  std::vector<std::pair<std::string, TTField>> namedPartitions {
81  {"PXEndcap" , {tt, TrackerTopology::PFSide}},
82 
83  {"PXLayer" , {tt, TrackerTopology::PBLayer}},
84  {"PXLadder" , {tt, TrackerTopology::PBLadder}},
85  {"PXBModule", {tt, TrackerTopology::PBModule}},
86 
87  {"PXBlade" , {tt, TrackerTopology::PFBlade}},
88  {"PXDisk" , {tt, TrackerTopology::PFDisk}},
89  {"PXPanel" , {tt, TrackerTopology::PFPanel}},
90  {"PXFModule", {tt, TrackerTopology::PFModule}},
91  };
92 
93  for (auto& e : namedPartitions) {
94  geomquantities.push_back(intern(e.first));
95  addExtractor(intern(e.first), e.second, UNDEFINED, UNDEFINED);
96  }
97 
98  auto pxbarrel = [] (InterestingQuantities const& iq) { return iq.sourceModule.subdetId() == PixelSubdetector::PixelBarrel ? 0 : UNDEFINED; };
99  auto pxforward = [] (InterestingQuantities const& iq) { return iq.sourceModule.subdetId() == PixelSubdetector::PixelEndcap ? 0 : UNDEFINED; };
100  auto pxall = [] (InterestingQuantities const& iq) { return 0 ; };
101  addExtractor(intern("PXBarrel"), pxbarrel, 0, 0);
102  addExtractor(intern("PXForward"), pxforward, 0, 0);
103  addExtractor(intern("PXAll"), pxall, 0, 0);
104 
105  // Redefine the disk numbering to use the sign
106  auto pxendcap = extractors[intern("PXEndcap")];
107  auto diskid = intern("PXDisk");
108  auto pxdisk = extractors[diskid];
109  extractors[diskid] = [pxdisk, pxendcap] (InterestingQuantities const& iq) {
110  auto disk = pxdisk(iq);
111  if (disk == UNDEFINED) return UNDEFINED;
112  auto endcap = pxendcap(iq);
113  return endcap == 1 ? -disk : disk;
114  };
115 
116  // DetId and module names
117  auto detid = [] (InterestingQuantities const& iq) {
118  uint32_t id = iq.sourceModule.rawId();
119  return Value(id);
120  };
121  addExtractor(intern("DetId"), detid,
122  0, 0 // No sane value possible here.
123  );
124  // these are just aliases with special handling in formatting
125  // the names are created with PixelBarrelName et. al. later
126  addExtractor(intern("PXModuleName"), detid, 0, 0);
127 
128  int phase = iConfig.getParameter<int>("upgradePhase");
129  bool isUpgrade = phase == 1;
130 
131  // Get a Geometry
132  edm::ESHandle<TrackerGeometry> trackerGeometryHandle;
133  iSetup.get<TrackerDigiGeometryRecord>().get(trackerGeometryHandle);
134  assert(trackerGeometryHandle.isValid());
135 
136  // Now traverse the detector and collect whatever we need.
137  auto detids = trackerGeometryHandle->detIds();
138  for (DetId id : detids) {
139  if (id.subdetId() != PixelSubdetector::PixelBarrel && id.subdetId() != PixelSubdetector::PixelEndcap) continue;
140  auto iq = InterestingQuantities{nullptr, id, 0, 0};
141 
142  // prepare pretty names
143  std::string name = "";
144  if (id.subdetId() == PixelSubdetector::PixelBarrel) { // Barrel
145  PixelBarrelName mod(id, tt, isUpgrade);
146  name = mod.name();
147  } else { // assume Endcap
148  PixelEndcapName mod(id, tt, isUpgrade);
149  name = mod.name();
150  }
151  format_value[std::make_pair(intern("PXModuleName"), Value(id.rawId()))] = name;
152 
153  // we record each module 4 times, one for each corner, so we also get ROCs
154  // in booking (at least for the ranges)
155  const PixelGeomDetUnit* detUnit = dynamic_cast<const PixelGeomDetUnit*>(trackerGeometryHandle->idToDetUnit(id));
156  assert(detUnit);
157  const PixelTopology* topo = &detUnit->specificTopology();
158  iq.row = 0; iq.col = 0;
159  all_modules.push_back(iq);
160  iq.row = topo->nrows()-1; iq.col = 0;
161  all_modules.push_back(iq);
162  iq.row = 0; iq.col = topo->ncolumns()-1;
163  all_modules.push_back(iq);
164  iq.row = topo->nrows()-1; iq.col = topo->ncolumns()-1;
165  all_modules.push_back(iq);
166  }
167 }
168 
170  // TODO: SiPixelCoordinates has a large overlap with theis GeometryInterface
171  // in general.
172  // Rough convention is to use own code for things that are easy and fast to
173  // determine, and use SiPixelCoordinates for complicated things.
174  // SiPixelCoordinates uses lookup maps for everything, so it is faster than
175  // most other code, but still slow on DQM scales.
176  int phase = iConfig.getParameter<int>("upgradePhase");
177 
178  // this shared pointer is kept alive by the references in the lambdas that follow.
179  // That is a bit less obvious than keeping it as a member but more correct.
180  auto coord = std::make_shared<SiPixelCoordinates>(phase);
181 
182  // note that we should reeinit for each event. But this probably won't explode
183  // thanks to the massive memoization in SiPixelCoordinates which is completely
184  // initialized while booking.
185  coord->init(iSetup);
186 
187  // SiPixelCoordinates uses a different convention for UNDEFINED:
188  auto from_coord = [](double in) { return (in == -9999.0) ? UNDEFINED : Value(in); };
189 
190  // Rings are a concept that cannot be derived from bitmasks.
191  addExtractor(intern("PXRing"),
192  [coord, from_coord] (InterestingQuantities const& iq) {
193  return from_coord(coord->ring(iq.sourceModule));
194  }
195  );
196 
197  // Quadrant names.
198  auto pxbarrel = extractors[intern("PXBarrel")];
199  addExtractor(intern("HalfCylinder"),
200  [coord, pxbarrel] (InterestingQuantities const& iq) {
201  if (pxbarrel(iq) != UNDEFINED) return UNDEFINED;
202  int quadrant = coord->quadrant(iq.sourceModule);
203  switch (quadrant) {
204  case 1: return Value(12); // mO
205  case 2: return Value(11); // mI
206  case 3: return Value(22); // pO
207  case 4: return Value(21); // pI
208  default: return UNDEFINED;
209  }
210  }, 0, 0 // N/A
211  );
212  addExtractor(intern("Shell"),
213  [coord, pxbarrel] (InterestingQuantities const& iq) {
214  if (pxbarrel(iq) == UNDEFINED) return UNDEFINED;
215  int quadrant = coord->quadrant(iq.sourceModule);
216  switch (quadrant) {
217  case 1: return Value(12); // mO
218  case 2: return Value(11); // mI
219  case 3: return Value(22); // pO
220  case 4: return Value(21); // pI
221  default: return UNDEFINED;
222  }
223  }, 0, 0 // N/A
224  );
225 
226  // Online Numbering.
227  addExtractor(intern("SignedLadder"),
228  [coord, from_coord] (InterestingQuantities const& iq) {
229  return from_coord(coord->signed_ladder(iq.sourceModule()));
230  }
231  );
232  addExtractor(intern("SignedModule"),
233  [coord, from_coord] (InterestingQuantities const& iq) {
234  return from_coord(coord->signed_module(iq.sourceModule()));
235  }
236  );
237  addExtractor(intern("SignedBlade"),
238  [coord, from_coord] (InterestingQuantities const& iq) {
239  return from_coord(coord->signed_blade(iq.sourceModule()));
240  }
241  );
242 
243  // Flipped and Outer ladders
244  addExtractor(intern("OuterLadder"),
245  [coord, from_coord] (InterestingQuantities const& iq) {
246  return from_coord(coord->outer(iq.sourceModule()));
247  }
248  );
249  addExtractor(intern("FlippedLadder"),
250  [coord, from_coord] (InterestingQuantities const& iq) {
251  return from_coord(coord->flipped(iq.sourceModule()));
252  }
253  );
254 
255  // Pixel Map axis.
256  // TODO: automatic range and binning for phase0 are incorrect.
257  // Should be set manually here.
258  addExtractor(intern("SignedModuleCoord"), // BPIX x
259  [coord, from_coord] (InterestingQuantities const& iq) {
260  return from_coord(coord->signed_module_coord(iq.sourceModule(),
261  std::make_pair(int(iq.row), int(iq.col))));
262  }, UNDEFINED, UNDEFINED, 1.0/8.0
263  );
264  addExtractor(intern("SignedLadderCoord"), // BPIX y
265  [coord, from_coord] (InterestingQuantities const& iq) {
266  return from_coord(coord->signed_ladder_coord(iq.sourceModule(),
267  std::make_pair(int(iq.row), int(iq.col))));
268  }, UNDEFINED, UNDEFINED, 1.0/2.0
269  );
270  addExtractor(intern("SignedDiskCoord"), // FPIX x (per-ring)
271  [coord, from_coord] (InterestingQuantities const& iq) {
272  return from_coord(coord->signed_disk_coord(iq.sourceModule(),
273  std::make_pair(int(iq.row), int(iq.col))));
274  }, UNDEFINED, UNDEFINED, 1.0/8.0
275  );
276  addExtractor(intern("SignedDiskRingCoord"), // FPIX x (FPIX-as-one-plot)
277  [coord, from_coord] (InterestingQuantities const& iq) {
278  return from_coord(coord->signed_disk_ring_coord(iq.sourceModule(),
279  std::make_pair(int(iq.row), int(iq.col))));
280  }, UNDEFINED, UNDEFINED, 1.0/16.0
281  );
282  addExtractor(intern("SignedBladePanelCoord"), // FPIX y
283  [coord, from_coord, phase] (InterestingQuantities const& iq) {
284  if (phase == 0) {
285  return from_coord(coord->signed_blade_coord(
286  iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
287  } else if (phase == 1) {
288  return from_coord(coord->signed_blade_panel_coord(
289  iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
290  } else {
291  return UNDEFINED; // TODO: phase2
292  }
293  }, UNDEFINED, UNDEFINED, phase == 1 ? 0.25 : 0.2
294  );
295  addExtractor(intern("SignedShiftedBladePanelCoord"), // FPIX-as-one y
296  [coord, from_coord, phase] (InterestingQuantities const& iq) {
297  if (phase == 0) {
298  return from_coord(coord->signed_blade_coord(
299  iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
300  } else if (phase == 1) {
301  return from_coord(coord->signed_shifted_blade_panel_coord(
302  iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
303  } else {
304  return UNDEFINED; // TODO: phase2
305  }
306  }, UNDEFINED, UNDEFINED, phase == 1 ? 0.25 : 0.1 // half-roc for phase0
307  );
308  addExtractor(intern("SignedBladePanel"), // per-module FPIX y
309  [coord, from_coord] (InterestingQuantities const& iq) {
310  return from_coord(coord->signed_blade_panel_coord(iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
311  }, UNDEFINED, UNDEFINED, 1.0/2.0
312  );
313 
314  addExtractor(intern("SignedBladePanel"),
315  [coord, from_coord] (InterestingQuantities const& iq) {
316  return from_coord(coord->signed_blade_panel_coord(iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
317  }, UNDEFINED, UNDEFINED, 1.0/2.0
318  );
319 
320  // more readout-related things.
321  addExtractor(intern("ROC"),
322  [coord, from_coord] (InterestingQuantities const& iq) {
323  return from_coord(coord->roc(iq.sourceModule(),
324  std::make_pair(int(iq.row), int(iq.col))));
325  }
326  );
327  addExtractor(intern("Sector"),
328  [coord, from_coord] (InterestingQuantities const& iq) {
329  return from_coord(coord->sector(iq.sourceModule()));
330  }
331  );
332  addExtractor(intern("Channel"),
333  [coord, from_coord] (InterestingQuantities const& iq) {
334  return from_coord(coord->channel(iq.sourceModule(), std::make_pair(int(iq.row), int(iq.col))));
335  }
336  );
337 
338 }
339 
341  // extractors for quantities that are roughly time-based. We cannot book plots based on these; they have to
342  // be grouped away in step1.
343  addExtractor(intern("Lumisection"),
344  [] (InterestingQuantities const& iq) {
345  if(!iq.sourceEvent) return UNDEFINED;
346  return Value(iq.sourceEvent->luminosityBlock());
347  },
348  1, iConfig.getParameter<int>("max_lumisection")
349  );
350 
351  int onlineblock = iConfig.getParameter<int>("onlineblock");
352  int n_onlineblocks = iConfig.getParameter<int>("n_onlineblocks");
353  addExtractor(intern("OnlineBlock"),
354  [onlineblock] (InterestingQuantities const& iq) {
355  if(!iq.sourceEvent) return UNDEFINED;
356  return Value(onlineblock + iq.sourceEvent->luminosityBlock() / onlineblock);
357  },
358  // note: this range is not visible anywhere (if the RenderPlugin does its job),
359  // but the strange range allows the RenderPlugin to know the block size.
360  onlineblock, onlineblock+n_onlineblocks-1
361  );
362 
363  int lumiblock = iConfig.getParameter<int>("lumiblock");
364  addExtractor(intern("LumiBlock"),
365  [lumiblock] (InterestingQuantities const& iq) {
366  if(!iq.sourceEvent) return UNDEFINED;
367  // The '-1' is for making 1-10 the same block rather than 0-9
368  // The '+0.5' makes the block span an integer range rather n.5-m.5
369  return Value( ((iq.sourceEvent->luminosityBlock()-1)/lumiblock) + 0.5 );
370  },
371  -0.5, iConfig.getParameter<int>("max_lumisection")/lumiblock
372  );
373 
374  addExtractor(intern("BX"),
375  [] (InterestingQuantities const& iq) {
376  if(!iq.sourceEvent) return UNDEFINED;
377  return Value(iq.sourceEvent->bunchCrossing());
378  },
379  1, iConfig.getParameter<int>("max_bunchcrossing")
380  );
381 }
382 
384  // stuff that is within modules. Might require some phase0/phase1/strip switching later
385  addExtractor(intern("row"),
386  [] (InterestingQuantities const& iq) {
387  return Value(iq.row);
388  },
389  0, iConfig.getParameter<int>("module_rows") - 1
390  );
391  addExtractor(intern("col"),
392  [] (InterestingQuantities const& iq) {
393  return Value(iq.col);
394  },
395  0, iConfig.getParameter<int>("module_cols") - 1
396  );
397 
398 }
399 
401  auto cablingMapLabel = iConfig.getParameter<std::string>("CablingMapLabel");
403  iSetup.get<SiPixelFedCablingMapRcd>().get(cablingMapLabel, theCablingMap);
404 
405  std::shared_ptr<SiPixelFrameReverter> siPixelFrameReverter =
406  // I think passing the bare pointer here is safe, but who knows...
407  std::make_shared<SiPixelFrameReverter>(iSetup, theCablingMap.operator->());
408 
409  addExtractor(intern("FED"),
410  [siPixelFrameReverter] (InterestingQuantities const& iq) {
411  if (iq.sourceModule == 0xFFFFFFFF)
412  return Value(iq.col); // hijacked for the raw data plugin
413  return Value(siPixelFrameReverter->findFedId(iq.sourceModule.rawId()));
414  }
415  );
416 
417  // TODO: ranges should be set manually below, since booking probably cannot
418  // infer them correctly (no ROC-level granularity)
419  // PERF: this is slow. Prefer SiPixelCordinates versions here.
420  addExtractor(intern("LinkInFed"),
421  [siPixelFrameReverter] (InterestingQuantities const& iq) {
422  if (iq.sourceModule == 0xFFFFFFFF)
423  return Value(iq.row); // hijacked for the raw data plugin
424  sipixelobjects::GlobalPixel gp = {iq.row, iq.col};
425  return Value(siPixelFrameReverter->findLinkInFed(iq.sourceModule.rawId(), gp));
426  }
427  );
428  // not sure if this is useful anywhere.
429  addExtractor(intern("RocInLink"),
430  [siPixelFrameReverter] (InterestingQuantities const& iq) {
432  return Value(siPixelFrameReverter->findRocInLink(iq.sourceModule.rawId(), gp));
433  }
434  );
435  // This might be equivalent to our ROC numbering.
436  addExtractor(intern("RocInDet"),
437  [siPixelFrameReverter] (InterestingQuantities const& iq) {
439  return Value(siPixelFrameReverter->findRocInDet(iq.sourceModule.rawId(), gp));
440  }
441  );
442 }
443 
445  auto it = format_value.find(std::make_pair(col, val));
446  if (it != format_value.end()) return it->second;
447 
448  // non-number output names (_pO etc.) are hardwired here.
449  std::string name = pretty(col);
450  std::string value = "_" + std::to_string(int(val));
451  if (val == 0) value = ""; // hide Barrel_0 etc.
452  if (name == "PXDisk" && val > 0) // +/- sign for disk num
453  value = "_+" + std::to_string(int(val));
454  // pretty (legacy?) names for Shells and HalfCylinders
455  std::map<int, std::string> shellname{
456  {11, "_mI"}, {12, "_mO"}, {21, "_pI"}, {22, "_pO"}};
457  if (name == "HalfCylinder" || name == "Shell") value = shellname[int(val)];
458  if (val == UNDEFINED) value = "_UNDEFINED";
459  return format_value[std::make_pair(col, val)] = name+value;
460 }
std::map< ID, Value > max_value
bool hasField(const DetId &id, DetIdFields idx) const
T getParameter(std::string const &) const
virtual int nrows() const =0
std::map< std::pair< Column, Value >, std::string > format_value
std::map< std::string, ID > ids
std::string pretty(Column col)
void addExtractor(ID id, std::function< Value(InterestingQuantities const &iq)> func, Value min=UNDEFINED, Value max=UNDEFINED, Value binwidth=1)
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:47
std::string formatValue(Column, Value)
int bunchCrossing() const
Definition: EventBase.h:66
edm::LuminosityBlockNumber_t luminosityBlock() const
Definition: EventBase.h:63
std::string name() const override
from base class
global coordinates (row and column in DetUnit, as in PixelDigi)
Definition: GlobalPixel.h:6
const TrackerGeomDet * idToDetUnit(DetId) const override
Return the pointer to the GeomDetUnit corresponding to a given DetId.
void loadFromTopology(edm::EventSetup const &iSetup, const edm::ParameterSet &iConfig)
void load(edm::EventSetup const &iSetup)
const edm::ParameterSet iConfig
const DetIdContainer & detIds() const override
Returm a vector of all GeomDet DetIds (including those of GeomDetUnits)
std::vector< InterestingQuantities > all_modules
std::string name() const override
from base class
Definition: value.py:1
static const Value UNDEFINED
Definition: DetId.h:18
virtual const PixelTopology & specificTopology() const
Returns a reference to the pixel proxy topology.
unsigned int getField(const DetId &id, DetIdFields idx) const
void loadFEDCabling(edm::EventSetup const &iSetup, const edm::ParameterSet &iConfig)
virtual int ncolumns() const =0
T get() const
Definition: EventSetup.h:63
col
Definition: cuy.py:1009
void loadModuleLevel(edm::EventSetup const &iSetup, const edm::ParameterSet &iConfig)
std::vector< std::function< Value(InterestingQuantities const &iq)> > extractors
std::map< ID, Value > min_value
bool isValid() const
Definition: ESHandle.h:47
ID intern(std::string const &id)
T mod(const T &a, const T &b)
Definition: ecalDccMap.h:4
void loadTimebased(edm::EventSetup const &iSetup, const edm::ParameterSet &iConfig)
void loadFromSiPixelCoordinates(edm::EventSetup const &iSetup, const edm::ParameterSet &iConfig)