CMS 3D CMS Logo

CTPPSDiamondDQMSource.cc
Go to the documentation of this file.
1 /****************************************************************************
2 *
3 * This is a part of CTPPSDQM software.
4 * Authors:
5 * Jan Kašpar (jan.kaspar@gmail.com)
6 * Nicola Minafra
7 * Laurent Forthomme
8 * Christopher Misan
9 *
10 ****************************************************************************/
11 
20 
23 
28 
31 
34 
39 
40 #include <string>
41 
42 //----------------------------------------------------------------------------------------------------
43 
44 // Utility for efficiency computations
46  const CTPPSDiamondDetId& detid,
47  const CTPPSDiamondLocalTrack& localTrack,
48  const float tolerance = 1) {
49  const DetGeomDesc* det = geom->sensor(detid);
50  const float x_pos = det->translation().x(),
51  x_width = 2.0 * det->getDiamondDimensions().xHalfWidth; // parameters stand for half the size
52  return ((x_pos + 0.5 * x_width > localTrack.x0() - localTrack.x0Sigma() - tolerance &&
53  x_pos + 0.5 * x_width < localTrack.x0() + localTrack.x0Sigma() + tolerance) ||
54  (x_pos - 0.5 * x_width > localTrack.x0() - localTrack.x0Sigma() - tolerance &&
55  x_pos - 0.5 * x_width < localTrack.x0() + localTrack.x0Sigma() + tolerance) ||
56  (x_pos - 0.5 * x_width < localTrack.x0() - localTrack.x0Sigma() - tolerance &&
57  x_pos + 0.5 * x_width > localTrack.x0() + localTrack.x0Sigma() + tolerance));
58 }
59 
60 namespace dds {
61  struct Cache {
62  std::unordered_map<unsigned int, std::unique_ptr<TH2F>> hitDistribution2dMap;
63 
64  std::unordered_map<unsigned int, unsigned long> hitsCounterMap;
65  };
66 } // namespace dds
67 
68 class CTPPSDiamondDQMSource : public DQMOneEDAnalyzer<edm::LuminosityBlockCache<dds::Cache>> {
69 public:
71 
72 protected:
73  void dqmBeginRun(const edm::Run&, const edm::EventSetup&) override;
74  void dqmEndRun(edm::Run const&, edm::EventSetup const&) override;
75  void bookHistograms(DQMStore::IBooker&, const edm::Run&, const edm::EventSetup&) override;
76  void analyze(const edm::Event&, const edm::EventSetup&) override;
77  std::shared_ptr<dds::Cache> globalBeginLuminosityBlock(const edm::LuminosityBlock&,
78  const edm::EventSetup&) const override;
80 
81 private:
82  // Constants
84  static constexpr double SEC_PER_LUMI_SECTION = 23.31;
86  static constexpr unsigned short CHANNEL_OF_VFAT_CLOCK = 30;
91  static constexpr double HPTDC_BIN_WIDTH_NS = 25. / 1024;
92  static constexpr unsigned short CTPPS_PIXEL_STATION_ID = 2;
93  static constexpr unsigned short CTPPS_FAR_RP_ID = 3;
94  static constexpr unsigned short CTPPS_DIAMOND_NUM_OF_CHANNELS = 12;
95  static constexpr unsigned short CTPPS_FED_ID_45 = 583;
96  static constexpr unsigned short CTPPS_FED_ID_56 = 582;
97  static constexpr unsigned short HPTDC_0_CHANNEL = 6;
98  static constexpr unsigned short HPTDC_1_CHANNEL = 7;
100  static constexpr unsigned int FIRST_RUN_W_PIXELS = 300000;
101 
102  bool perLSsaving_; //to avoid nanoDQMIO crashing, driven by DQMServices/Core/python/DQMStore_cfi.py
103 
105  struct GlobalPlots {
106  GlobalPlots() = default;
107  GlobalPlots(DQMStore::IBooker& ibooker);
108  };
110  struct SectorPlots {
111  // Tracks
116  SectorPlots(DQMStore::IBooker& ibooker, unsigned int id, bool plotOnline);
117  };
119  struct PotPlots {
120  std::unordered_map<unsigned int, MonitorElement*> activity_per_bx;
121 
127 
130 
131  std::unordered_map<unsigned int, MonitorElement*> pixelTomographyAll;
132 
135  MonitorElement* timeOverThresholdCumulativePot = nullptr; //, *leadingTrailingCorrelationPot = nullptr;
137 
139 
142 
144 
145  // MonitorElement* clock_Digi1_le = nullptr;
146  // MonitorElement* clock_Digi1_te = nullptr;
147  // MonitorElement* clock_Digi3_le = nullptr;
148  // MonitorElement* clock_Digi3_te = nullptr;
149 
151 
152  std::map<int, int> effTriplecountingChMap;
153  std::map<int, int> effDoublecountingChMap;
156 
157  // MonitorElement* TOTVsLS = nullptr;
158  // MonitorElement* trackTimeVsLS = nullptr;
160  // MonitorElement* trackTimeVsXAngle = nullptr;
161 
162  // MonitorElement* TOTVsLSProfile = nullptr;
163  // MonitorElement* trackTimeVsLSProfile = nullptr;
165  // MonitorElement* trackTimeVsXAngleProfile = nullptr;
166 
167  PotPlots() = default;
168  PotPlots(DQMStore::IBooker& ibooker,
169  unsigned int id,
170  unsigned int windowsNum,
171  bool plotOnline,
172  bool plotOffline,
173  bool perLSsaving);
174  };
176  struct PlanePlots {
180 
183 
185 
186  PlanePlots() = default;
187  PlanePlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int windowsNum);
188  };
190  struct ChannelPlots {
191  std::unordered_map<unsigned int, MonitorElement*> activity_per_bx;
192 
197  //MonitorElement* LeadingTrailingCorrelationPerChannel = nullptr;
202 
204 
205  ChannelPlots() = default;
206  ChannelPlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int windowsNum);
207  };
208 
209  void checkEventNumber(const CTPPSDiamondDetId&, const TotemFEDInfo&, const TotemVFATStatus&, PotPlots&, int&) const;
210 
217 
220 
222  const bool extract_digi_info_;
223  struct DiamondShifts {
225  };
226  std::unordered_map<CTPPSDetId, DiamondShifts> diamShifts_;
227  std::vector<std::pair<edm::EventRange, int>> runParameters_;
229  unsigned int verbosity_;
230  const bool plotOnline_;
231  const bool plotOffline_;
232  unsigned int windowsNum_;
234 
236  std::unordered_map<unsigned int, PotPlots> potPlots_;
237  std::unordered_map<unsigned int, SectorPlots> sectorPlots_;
238  std::unordered_map<unsigned int, PlanePlots> planePlots_;
239  std::unordered_map<unsigned int, ChannelPlots> channelPlots_;
240 
242 };
243 
244 //----------------------------------------------------------------------------------------------------
245 
247 
248 //----------------------------------------------------------------------------------------------------
249 
253  ibooker.setCurrentFolder(path);
254 
256 
257  trackCorrelation = ibooker.book2D("tracks correlation near-far",
258  title + " tracks correlation near-far;x (mm);x (mm)",
260  -1,
261  18,
263  -1,
264  18);
265  trackCorrelationLowMultiplicity =
266  ibooker.book2D("tracks correlation with low multiplicity near-far",
267  title + " tracks correlation with low multiplicity near-far;x (mm);x (mm)",
269  -1,
270  18,
272  -1,
273  18);
274 }
275 
276 //----------------------------------------------------------------------------------------------------
278  unsigned int id,
279  unsigned int windowsNum,
280  bool plotOnline,
281  bool plotOffline,
282  bool perLSsaving)
283  : HitCounter(0),
284  MHCounter(0),
285  LeadingOnlyCounter(0),
286  TrailingOnlyCounter(0),
287  CompleteCounter(0),
288  pixelTracksMap("Pixel track maps for efficiency", "Pixel track maps for efficiency", 25, 0, 25, 12, -2, 10) {
291  ibooker.setCurrentFolder(path);
292 
294 
295  if (plotOnline) {
297  ibooker.book2D("hits in planes lumisection",
298  title + " hits in planes in the last lumisection;plane number;x (mm)",
299  10,
300  -0.5,
301  4.5,
303  -0.5,
304  18.5);
305 
307  ibooker.book2D("hits with OOT in planes (le only)",
308  title + " hits with OOT in planes (le only);plane number, OOT index;x (mm)",
309  1 + windowsNum * 4,
310  -1. / windowsNum,
311  4,
313  -0.5,
314  18.5);
315 
317  ibooker.book1D("active planes inclusive",
318  title + " active planes, MH and le only included (per event);number of active planes",
319  6,
320  -0.5,
321  5.5);
322 
323  ECCheck = ibooker.book1D("optorxEC(8bit) - vfatEC", title + " EC Error;optorxEC-vfatEC", 50, -25, 25);
324 
326  ibooker.book2D("Efficiency in channels",
327  title + " Efficiency (%) in channels (diamonds only);plane number;ch number",
328  10,
329  -0.5,
330  4.5,
331  14,
332  -1,
333  13);
334  }
335 
336  if (plotOffline && !perLSsaving) {
337  ibooker.setCurrentFolder(path + "/timing_profiles");
338  // TOTVsLS=ibooker.book2D("ToT vs LS",title +" ToT vs LS;LS;ToT(ns)",4000,0,4000, 200,5,25);
339  // trackTimeVsLS=ibooker.book2D("track time vs LS",title+" track time vs LS;LS;track_time(ns)",4000,0,4000, 500, -25, 25);
340  trackTimeVsBX =
341  ibooker.book2D("track time vs BX", title + " track time vs BX;BX;track_time(ns)", 4000, 0, 4000, 500, -25, 25);
342  // trackTimeVsXAngle = ibooker.book2D(
343  // "track time vs xangle", title + " track time vs xangle;xangle;track_time(ns)", 60, 120, 180, 500, -25, 25);
344 
345  // TOTVsLSProfile=ibooker.bookProfile("ToT vs LS profile",title+" ToT vs LS profile;LS;track_time(ns)", 500, -25, 25,4000,0,4000);
346  // trackTimeVsLSProfile=ibooker.bookProfile("track time vs LS profile",title+" track time vs LS profile;LS;track_time(ns)", 500, -25, 25,4000,0,4000);
348  "track time vs BX profile", title + " track time vs BX profile;BX;track_time(ns)", 500, -25, 25, 4000, 0, 4000);
349  // trackTimeVsXAngleProfile = ibooker.bookProfile("track time vs xangle profile",
350  // title + " track time vs xangle profile;xangle;track_time(ns)",
351  // 500,
352  // -25,
353  // 25,
354  // 60,
355  // 120,
356  // 180);
357  ibooker.setCurrentFolder(path);
358  }
359 
360  for (unsigned int i = 0; i < windowsNum; i++) {
361  std::string window = std::to_string(i * 25) + "-" + std::to_string((i + 1) * 25);
362  activity_per_bx[i] = ibooker.book1D(
363  "activity per BX " + window, title + " Activity per BX " + window + " ns;Event.BX", 3600, -1.5, 3598. + 0.5);
365  ibooker.book2D("tomography pixel " + window,
366  title + " tomography with pixel " + window + " ns (all planes);x + 25*plane(mm);y (mm)",
367  100,
368  0,
369  100,
370  10,
371  -5,
372  5);
373  }
374 
375  hitDistribution2d = ibooker.book2D("hits in planes",
376  title + " hits in planes;plane number;x (mm)",
377  10,
378  -0.5,
379  4.5,
381  -0.5,
382  18.5);
383 
384  hitDistribution2dOOT = ibooker.book2D("hits with OOT in planes",
385  title + " hits with OOT in planes;plane number, OOT index;x (mm)",
386  1 + windowsNum * 4,
387  -1. / windowsNum,
388  4,
390  -0.5,
391  18.5);
392 
393  { // bin labelling (for clarity)
394  int idx = 2; // start counting at 1, first bin is empty
395  for (int pl = 0; pl < 4; ++pl)
396  for (unsigned int oot = 0; oot < windowsNum; ++oot) {
397  const std::string bin_label =
398  (oot == 0 ? "Plane " + std::to_string(pl) + ", " : "") + "OOT" + std::to_string(oot);
399  hitDistribution2dOOT->setBinLabel(idx, bin_label);
400  if (plotOnline)
402  ++idx;
403  }
404  }
405 
406  recHitTime = ibooker.book1D("recHit time", title + " recHit time; t (ns)", 500, -25, 25);
407 
408  activePlanes =
409  ibooker.book1D("active planes", title + " active planes (per event);number of active planes", 6, -0.5, 5.5);
410 
412  ibooker.book1D("tracks", title + " tracks;x (mm)", 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, -0.5, 18.5);
413  trackDistributionOOT = ibooker.book2D("tracks with OOT",
414  title + " tracks with OOT;plane number;x (mm)",
415  9,
416  -0.5,
417  4,
419  -0.5,
420  18.5);
421 
422  leadingEdgeCumulative_both = ibooker.book1D("leading edge (le and te)",
423  title + " leading edge (le and te) (recHits); leading edge (ns)",
424  25 * windowsNum,
425  0,
426  25 * windowsNum);
427  leadingEdgeCumulative_all = ibooker.book1D("leading edge (all)",
428  title + " leading edge (with or without te) (DIGIs); leading edge (ns)",
429  25 * windowsNum,
430  0,
431  25 * windowsNum);
432  leadingEdgeCumulative_le = ibooker.book1D("leading edge (le only)",
433  title + " leading edge (le only) (DIGIs); leading edge (ns)",
434  25 * windowsNum,
435  0,
436  25 * windowsNum);
437  trailingEdgeCumulative_te = ibooker.book1D("trailing edge (te only)",
438  title + " trailing edge (te only) (DIGIs); trailing edge (ns)",
439  25 * windowsNum,
440  0,
441  25 * windowsNum);
443  ibooker.book1D("time over threshold", title + " time over threshold;time over threshold (ns)", 250, -25, 100);
444  // leadingTrailingCorrelationPot =
445  // ibooker.book2D("leading trailing correlation",
446  // title + " leading trailing correlation;leading edge (ns);trailing edge (ns)",
447  // 75,
448  // 0,
449  // 75,
450  // 75,
451  // 0,
452  // 75);
453 
455  ibooker.book1D("event category", title + " leading edges without trailing;;%", 3, 0.5, 3.5);
459 
460  HPTDCErrorFlags_2D = ibooker.book2D("HPTDC Errors", title + " HPTDC Errors", 16, -0.5, 16.5, 9, -0.5, 8.5);
461  for (unsigned short error_index = 1; error_index < 16; ++error_index)
462  HPTDCErrorFlags_2D->setBinLabel(error_index, HPTDCErrorFlags::hptdcErrorName(error_index - 1));
463  HPTDCErrorFlags_2D->setBinLabel(16, "Wrong EC");
464 
465  int tmpIndex = 0;
466  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 18", /* axis */ 2);
467  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 17", /* axis */ 2);
468  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 16", /* axis */ 2);
469  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 15", /* axis */ 2);
470  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 18", /* axis */ 2);
471  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 17", /* axis */ 2);
472  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 16", /* axis */ 2);
473  HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 15", /* axis */ 2);
474 
475  MHComprensive =
476  ibooker.book2D("MH in channels", title + " MH (%) in channels;plane number;ch number", 10, -0.5, 4.5, 14, -1, 13);
477 
478  // ibooker.setCurrentFolder( path+"/clock/" );
479  // clock_Digi1_le = ibooker.book1D( "clock1 leading edge", title+" clock1;leading edge (ns)", 250, 0, 25 );
480  // clock_Digi1_te = ibooker.book1D( "clock1 trailing edge", title+" clock1;trailing edge (ns)", 75, 0, 75 );
481  // clock_Digi3_le = ibooker.book1D( "clock3 leading edge", title+" clock3;leading edge (ns)", 250, 0, 25 );
482  // clock_Digi3_te = ibooker.book1D( "clock3 trailing edge", title+" clock3;trailing edge (ns)", 75, 0, 75 );
483 }
484 
485 //----------------------------------------------------------------------------------------------------
486 
488  : pixelTracksMapWithDiamonds("Pixel track maps for efficiency with coincidence",
489  "Pixel track maps for efficiency with coincidence",
490  25,
491  0,
492  25,
493  12,
494  -2,
495  10) {
498  ibooker.setCurrentFolder(path);
499 
501 
502  digiProfileCumulativePerPlane = ibooker.book1D("digi profile",
503  title + " digi profile; ch number",
505  -0.5,
507  hitProfile = ibooker.book1D(
508  "hit profile", title + " hit profile;x (mm)", 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, -0.5, 18.5);
509  hit_multiplicity = ibooker.book1D("channels per plane", title + " channels per plane; ch per plane", 13, -0.5, 12.5);
510 
511  pixelTomography_far = ibooker.book2D("tomography pixel",
512  title + " tomography with pixel;x + 25 OOT (mm);y (mm)",
513  25 * windowsNum,
514  0,
515  25 * windowsNum,
516  8,
517  0,
518  8);
520  ibooker.book2D("Efficiency wrt pixels", title + " Efficiency wrt pixels;x (mm);y (mm)", 25, 0, 25, 12, -2, 10);
521 }
522 
523 //----------------------------------------------------------------------------------------------------
524 
526  : HitCounter(0), MHCounter(0), LeadingOnlyCounter(0), TrailingOnlyCounter(0), CompleteCounter(0) {
529  ibooker.setCurrentFolder(path);
530 
532 
533  leadingWithoutTrailing = ibooker.book1D("event category", title + " Event Category;;%", 3, 0.5, 3.5);
534  leadingWithoutTrailing->setBinLabel(1, "Leading only");
535  leadingWithoutTrailing->setBinLabel(2, "Trailing only");
537 
538  for (unsigned int i = 0; i < windowsNum; i++) {
539  std::string window = std::to_string(i * 25) + "-" + std::to_string((i + 1) * 25);
540  activity_per_bx[i] = ibooker.book1D(
541  "activity per BX " + window, title + " Activity per BX " + window + " ns;Event.BX", 3600, -1.5, 3598. + 0.5);
542  }
543 
544  HPTDCErrorFlags = ibooker.book1D("hptdc_Errors", title + " HPTDC Errors", 16, -0.5, 16.5);
545  for (unsigned short error_index = 1; error_index < 16; ++error_index)
546  HPTDCErrorFlags->setBinLabel(error_index, HPTDCErrorFlags::hptdcErrorName(error_index - 1));
547  HPTDCErrorFlags->setBinLabel(16, "MH (%)");
548 
549  leadingEdgeCumulative_both = ibooker.book1D("leading edge (le and te)",
550  title + " leading edge (recHits); leading edge (ns)",
551  25 * windowsNum,
552  0,
553  25 * windowsNum);
555  "leading edge (le only)", title + " leading edge (DIGIs); leading edge (ns)", 25 * windowsNum, 0, 25 * windowsNum);
556  trailingEdgeCumulative_te = ibooker.book1D("trailing edge (te only)",
557  title + " trailing edge (te only) (DIGIs); trailing edge (ns)",
558  25 * windowsNum,
559  0,
560  25 * windowsNum);
562  ibooker.book1D("time over threshold", title + " time over threshold;time over threshold (ns)", 75, -25, 50);
563  // LeadingTrailingCorrelationPerChannel =
564  // ibooker.book2D("leading trailing correlation",
565  // title + " leading trailing correlation;leading edge (ns);trailing edge (ns)",
566  // 75,
567  // 0,
568  // 75,
569  // 75,
570  // 0,
571  // 75);
572 
573  pixelTomography_far = ibooker.book2D(
574  "tomography pixel", "tomography with pixel;x + 25 OOT (mm);y (mm)", 25 * windowsNum, 0, 25 * windowsNum, 8, 0, 8);
575 
576  hit_rate = ibooker.book1D("hit rate", title + "hit rate;rate (Hz)", 40, 0, 20);
577 
578  recHitTime = ibooker.book1D("recHit Time", title + " recHit Time; t (ns)", 500, -25, 25);
579 }
580 
581 //----------------------------------------------------------------------------------------------------
582 
584  : perLSsaving_(ps.getUntrackedParameter<bool>("perLSsaving", false)),
586  ps.getUntrackedParameter<edm::InputTag>("tagPixelLocalTracks"))),
588  ps.getUntrackedParameter<edm::InputTag>("tagDiamondRecHits"))),
590  ps.getUntrackedParameter<edm::InputTag>("tagDiamondLocalTracks"))),
593  excludeMultipleHits_(ps.getParameter<bool>("excludeMultipleHits")),
594  extract_digi_info_(ps.getParameter<bool>("extractDigiInfo")),
595  centralOOT_(-999),
596  verbosity_(ps.getUntrackedParameter<unsigned int>("verbosity", 0)),
597  plotOnline_(ps.getUntrackedParameter<bool>("plotOnline", true)),
598  plotOffline_(ps.getUntrackedParameter<bool>("plotOffline", false)),
599  windowsNum_(ps.getUntrackedParameter<unsigned int>("windowsNum", 3)),
600  trackCorrelationThreshold_(ps.getUntrackedParameter<unsigned int>("trackCorrelationThreshold", 3)),
601  EC_difference_56_(-500),
602  EC_difference_45_(-500) {
603  if (extract_digi_info_) {
604  tokenStatus_ = consumes<edm::DetSetVector<TotemVFATStatus>>(ps.getUntrackedParameter<edm::InputTag>("tagStatus"));
605  tokenFEDInfo_ = consumes<std::vector<TotemFEDInfo>>(ps.getUntrackedParameter<edm::InputTag>("tagFEDInfo"));
606  tokenDigi_ = consumes<edm::DetSetVector<CTPPSDiamondDigi>>(ps.getUntrackedParameter<edm::InputTag>("tagDigi"));
607  }
608  for (const auto& pset : ps.getParameter<std::vector<edm::ParameterSet>>("offsetsOOT")) {
609  runParameters_.emplace_back(
610  std::make_pair(pset.getParameter<edm::EventRange>("validityRange"), pset.getParameter<int>("centralOOT")));
611  }
612 }
613 
614 //----------------------------------------------------------------------------------------------------
615 
617  centralOOT_ = -999;
618  for (const auto& oot : runParameters_) {
619  if (edm::contains(oot.first, edm::EventID(iRun.run(), 0, 1))) {
620  centralOOT_ = oot.second;
621  break;
622  }
623  }
624 
625  // Get detector shifts from the geometry
627  for (auto it = geom.beginRP(); it != geom.endRP(); ++it)
628  if (CTPPSDiamondDetId::check(it->first)) {
629  const CTPPSDiamondDetId diam_id(it->first);
630  const auto diam = geom.sensor(it->first);
631  diamShifts_[diam_id].global = diam->translation().x() - diam->getDiamondDimensions().xHalfWidth;
632  if (iRun.run() > FIRST_RUN_W_PIXELS) { // pixel installed
634  auto pix = geom.sensor(pixid);
635  // Rough alignement of pixel detector for diamond tomography
636  diamShifts_[diam_id].withPixels =
637  pix->translation().x() - pix->getDiamondDimensions().xHalfWidth - diamShifts_[diam_id].global - 1.;
638  }
639  }
640 }
641 
642 //----------------------------------------------------------------------------------------------------
643 
645  ibooker.cd();
646  ibooker.setCurrentFolder("CTPPS");
647 
648  globalPlot_ = GlobalPlots(ibooker);
649 
650  // book plots from the geometry
652  for (auto it = geom.beginSensor(); it != geom.endSensor(); ++it) {
653  if (!CTPPSDiamondDetId::check(it->first))
654  continue;
655  // per-channel plots
656  const CTPPSDiamondDetId chId(it->first);
657  if (plotOnline_ && channelPlots_.count(chId) == 0)
658  channelPlots_[chId] = ChannelPlots(ibooker, chId, windowsNum_);
659 
660  // per-plane plots
661  const CTPPSDiamondDetId plId(chId.planeId());
662  if (planePlots_.count(plId) == 0)
663  planePlots_[plId] = PlanePlots(ibooker, plId, windowsNum_);
664  // per-pot plots
665  const CTPPSDiamondDetId rpId(chId.rpId());
666  if (potPlots_.count(rpId) == 0)
668 
669  // per-sector plots
670  const CTPPSDiamondDetId secId(chId.armId());
671  if (plotOffline_ && sectorPlots_.count(secId) == 0)
672  sectorPlots_[secId] = SectorPlots(ibooker, secId, plotOnline_);
673  }
674 }
675 
676 //----------------------------------------------------------------------------------------------------
677 
679  const edm::EventSetup&) const {
680  auto d = std::make_shared<dds::Cache>();
681  d->hitDistribution2dMap.reserve(potPlots_.size());
682  if (!perLSsaving_ && plotOnline_) {
683  for (auto& plot : potPlots_) {
684  d->hitDistribution2dMap[plot.first] = std::make_unique<TH2F>(
685  "hits in planes lumisection",
686  (std::string(plot.second.hitDistribution2d_lumisection->getTH2F()->GetTitle()) + ";plane number;x (mm)")
687  .c_str(),
688  10,
689  -0.5,
690  4.5,
692  -0.5,
693  18.5);
694  }
695  }
696  return d;
697 }
698 
699 //----------------------------------------------------------------------------------------------------
700 
702  // get event data
703 
707  if (extract_digi_info_) {
708  event.getByToken(tokenStatus_, diamondVFATStatus);
709  event.getByToken(tokenDigi_, diamondDigis);
710  event.getByToken(tokenFEDInfo_, fedInfo);
711  }
712 
714  event.getByToken(tokenPixelTrack_, pixelTracks);
715 
717  event.getByToken(tokenDiamondHit_, diamondRecHits);
718 
720  event.getByToken(tokenDiamondTrack_, diamondLocalTracks);
721 
722  const CTPPSGeometry* ctppsGeometry = &iSetup.getData(ctppsGeometryEventToken_);
723 
724  // check validity
725  bool valid = true;
726  if (extract_digi_info_) { // drop DIGI-level validity checks if not monitored
727  valid &= diamondVFATStatus.isValid();
728  valid &= diamondDigis.isValid();
729  valid &= fedInfo.isValid();
730  }
731  valid &= pixelTracks.isValid();
732  valid &= diamondRecHits.isValid();
733  valid &= diamondLocalTracks.isValid();
734 
735  if (!valid) {
736  if (verbosity_)
737  edm::LogProblem("CTPPSDiamondDQMSource")
738  << "ERROR in CTPPSDiamondDQMSource::analyze > some of the required inputs are not valid. Skipping this "
739  "event.\n"
740  << " DIGI-level: (checked? " << std::boolalpha << extract_digi_info_ << ")\n"
741  << " diamondVFATStatus.isValid = " << diamondVFATStatus.isValid() << "\n"
742  << " diamondDigis.isValid = " << diamondDigis.isValid() << "\n"
743  << " fedInfo.isValid = " << fedInfo.isValid() << "\n"
744  << " RECO-level:\n"
745  << " pixelTracks.isValid = " << pixelTracks.isValid() << "\n"
746  << " diamondRecHits.isValid = " << diamondRecHits.isValid() << "\n"
747  << " diamondLocalTracks.isValid = " << diamondLocalTracks.isValid();
748  return;
749  }
750 
751  //------------------------------
752  // Sector Plots
753  //------------------------------
754  // Using CTPPSDiamondLocalTrack
755  if (plotOffline_)
756  for (const auto& tracks : *diamondLocalTracks) {
757  const CTPPSDiamondDetId detId_near(tracks.detId());
758 
759  for (const auto& track : tracks) {
760  if (!track.isValid())
761  continue;
762  if (potPlots_.count(detId_near.rpId()) == 0)
763  continue;
764  TH1F* trackHistoInTimeTmp = potPlots_[detId_near.rpId()].trackDistribution->getTH1F();
765  int startBin_near =
766  trackHistoInTimeTmp->FindBin(track.x0() - diamShifts_[detId_near.rpId()].global - track.x0Sigma());
767  int numOfBins_near = 2 * track.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
768 
769  for (const auto& tracks_far : *diamondLocalTracks) {
770  CTPPSDiamondDetId detId_far(tracks_far.detId());
771  if (detId_near.arm() != detId_far.arm() || detId_near.station() == detId_far.station())
772  continue;
773  for (const auto& track_far : tracks_far) {
774  if (!track.isValid())
775  continue;
776  if (sectorPlots_.count(detId_far.armId()) == 0)
777  continue;
778  TH2F* trackHistoTmp = sectorPlots_[detId_far.armId()].trackCorrelation->getTH2F();
779  TAxis* trackHistoTmpXAxis = trackHistoTmp->GetXaxis();
780  TAxis* trackHistoTmpYAxis = trackHistoTmp->GetYaxis();
781  int startBin_far = trackHistoTmpYAxis->FindBin(track_far.x0() - diamShifts_[detId_far.rpId()].global -
782  track_far.x0Sigma());
783  int numOfBins_far = 2 * track_far.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
784  for (int i = 0; i < numOfBins_near; ++i)
785  for (int y = 0; y < numOfBins_far; ++y) {
786  trackHistoTmp->Fill(trackHistoTmpXAxis->GetBinCenter(startBin_near + i),
787  trackHistoTmpYAxis->GetBinCenter(startBin_far + y));
788  if (tracks.size() < 3 && tracks_far.size() < trackCorrelationThreshold_)
789  sectorPlots_[detId_far.armId()].trackCorrelationLowMultiplicity->Fill(
790  trackHistoTmpXAxis->GetBinCenter(startBin_near + i),
791  trackHistoTmpYAxis->GetBinCenter(startBin_far + y));
792  }
793  }
794  }
795  }
796  }
797 
798  //------------------------------
799  // RP Plots
800  //------------------------------
801 
802  //------------------------------
803  // Correlation Plots
804  //------------------------------
805 
806  if (extract_digi_info_) {
807  // Using CTPPSDiamondDigi
808  for (const auto& digis : *diamondDigis) {
809  const CTPPSDiamondDetId detId(digis.detId()), detId_pot(detId.rpId());
810  for (const auto& digi : digis) {
811  if (detId.channel() == CHANNEL_OF_VFAT_CLOCK)
812  continue;
813  if (potPlots_.count(detId_pot) == 0)
814  continue;
815  //Leading without trailing investigation
816  if (digi.leadingEdge() != 0 || digi.trailingEdge() != 0) {
817  ++potPlots_[detId_pot].HitCounter;
818  if (digi.leadingEdge() != 0) {
819  potPlots_[detId_pot].leadingEdgeCumulative_all->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
820  }
821  if (digi.leadingEdge() != 0 && digi.trailingEdge() == 0) {
822  ++potPlots_[detId_pot].LeadingOnlyCounter;
823  potPlots_[detId_pot].leadingEdgeCumulative_le->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
824  }
825  if (digi.leadingEdge() == 0 && digi.trailingEdge() != 0) {
826  ++potPlots_[detId_pot].TrailingOnlyCounter;
827  potPlots_[detId_pot].trailingEdgeCumulative_te->Fill(HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
828  }
829  if (digi.leadingEdge() != 0 && digi.trailingEdge() != 0) {
830  ++potPlots_[detId_pot].CompleteCounter;
831  // potPlots_[detId_pot].leadingTrailingCorrelationPot->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge(),
832  // HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
833  }
834  }
835 
836  // HPTDC Errors
837  const HPTDCErrorFlags hptdcErrors = digi.hptdcErrorFlags();
838  if (detId.channel() == HPTDC_0_CHANNEL ||
839  detId.channel() == HPTDC_1_CHANNEL) { // ch6 for HPTDC 0 and ch7 for HPTDC 1
840  int verticalIndex = 2 * detId.plane() + (detId.channel() - HPTDC_0_CHANNEL);
841  for (unsigned short hptdcErrorIndex = 1; hptdcErrorIndex < 16; ++hptdcErrorIndex)
842  if (hptdcErrors.errorId(hptdcErrorIndex - 1))
843  potPlots_[detId_pot].HPTDCErrorFlags_2D->Fill(hptdcErrorIndex, verticalIndex);
844  }
845  if (digi.multipleHit())
846  ++potPlots_[detId_pot].MHCounter;
847  }
848  }
849  }
850 
851  // EC Errors
852  if (extract_digi_info_) {
853  for (const auto& vfat_status : *diamondVFATStatus) {
854  const CTPPSDiamondDetId detId(vfat_status.detId());
855  for (const auto& status : vfat_status) {
856  if (!status.isOK())
857  continue;
858  if (potPlots_.count(detId.rpId()) == 0)
859  continue;
860  if (channelPlots_.count(detId) == 0)
861  continue;
862 
863  // Check Event Number
864  for (const auto& optorx : *fedInfo) {
865  if (detId.arm() == 1 && optorx.fedId() == CTPPS_FED_ID_56)
867  else if (detId.arm() == 0 && optorx.fedId() == CTPPS_FED_ID_45)
869  }
870  }
871  }
872  }
873 
874  // Using CTPPSDiamondRecHit
875  std::unordered_map<unsigned int, std::set<unsigned int>> planes;
876  std::unordered_map<unsigned int, std::set<unsigned int>> planes_inclusive;
877 
878  auto lumiCache = luminosityBlockCache(event.getLuminosityBlock().index());
879  for (const auto& rechits : *diamondRecHits) {
880  const CTPPSDiamondDetId detId(rechits.detId()), detId_pot(detId.rpId());
881  const auto& x_shift = diamShifts_.at(detId_pot);
882 
883  for (const auto& rechit : rechits) {
884  planes_inclusive[detId_pot].insert(detId.plane());
885  if (excludeMultipleHits_ && rechit.multipleHits() > 0)
886  continue;
887  if (rechit.toT() != 0 && centralOOT_ != -999 && rechit.ootIndex() == centralOOT_)
888  planes[detId_pot].insert(detId.plane());
889 
890  if (potPlots_.count(detId_pot) == 0)
891  continue;
892 
893  potPlots_[detId_pot].recHitTime->Fill(rechit.time());
894 
895  float UFSDShift = 0.0;
896  if (rechit.yWidth() < 3)
897  UFSDShift = 0.5; // Display trick for UFSD that have 2 pixels with same X
898 
899  if (rechit.toT() != 0 && centralOOT_ != -999 && rechit.ootIndex() == centralOOT_) {
900  TH2F* hitHistoTmp = potPlots_[detId_pot].hitDistribution2d->getTH2F();
901  TAxis* hitHistoTmpYAxis = hitHistoTmp->GetYaxis();
902  int startBin = hitHistoTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
903  int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
904  for (int i = 0; i < numOfBins; ++i)
905  hitHistoTmp->Fill(detId.plane() + UFSDShift, hitHistoTmpYAxis->GetBinCenter(startBin + i));
906 
907  if (!perLSsaving_ && plotOnline_) {
908  hitHistoTmp = lumiCache->hitDistribution2dMap[detId_pot].get();
909  hitHistoTmpYAxis = hitHistoTmp->GetYaxis();
910  startBin = hitHistoTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
911  numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
912  for (int i = 0; i < numOfBins; ++i)
913  hitHistoTmp->Fill(detId.plane() + UFSDShift, hitHistoTmpYAxis->GetBinCenter(startBin + i));
914  }
915  }
916 
917  if (rechit.toT() > 0) {
918  // Both
919  potPlots_[detId_pot].leadingEdgeCumulative_both->Fill(rechit.time() + 25 * rechit.ootIndex());
920  potPlots_[detId_pot].timeOverThresholdCumulativePot->Fill(rechit.toT());
921 
922  TH2F* hitHistoOOTTmp = potPlots_[detId_pot].hitDistribution2dOOT->getTH2F();
923  TAxis* hitHistoOOTTmpYAxis = hitHistoOOTTmp->GetYaxis();
924  int startBin = hitHistoOOTTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
925  int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
926  for (int i = 0; i < numOfBins; ++i)
927  hitHistoOOTTmp->Fill(detId.plane() + 1. / windowsNum_ * rechit.ootIndex(),
928  hitHistoOOTTmpYAxis->GetBinCenter(startBin + i));
929 
930  } else if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING && plotOnline_) {
931  // Only leading
932  TH2F* hitHistoOOTTmp = potPlots_[detId_pot].hitDistribution2dOOT_le->getTH2F();
933  TAxis* hitHistoOOTTmpYAxis = hitHistoOOTTmp->GetYaxis();
934  int startBin = hitHistoOOTTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
935  int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
936  for (int i = 0; i < numOfBins; ++i)
937  hitHistoOOTTmp->Fill(detId.plane() + 1. / windowsNum_ * rechit.ootIndex(),
938  hitHistoOOTTmpYAxis->GetBinCenter(startBin + i));
939  }
940  if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING &&
941  potPlots_[detId_pot].activity_per_bx.count(rechit.ootIndex()) > 0)
942  potPlots_[detId_pot].activity_per_bx.at(rechit.ootIndex())->Fill(event.bunchCrossing());
943 
944  // if(plotOffline_)
945  // potPlots_[detId_pot].TOTVsLS->Fill(event.luminosityBlock(),rechit.toT());
946  }
947  }
948 
949  for (const auto& plt : potPlots_) {
950  plt.second.activePlanes->Fill(planes[plt.first].size());
951  if (plotOnline_)
952  plt.second.activePlanesInclusive->Fill(planes_inclusive[plt.first].size());
953  }
954 
955  // Using CTPPSDiamondLocalTrack
956  for (const auto& tracks : *diamondLocalTracks) {
957  const CTPPSDiamondDetId detId(tracks.detId()), detId_pot(detId.rpId());
958  const auto& x_shift = diamShifts_.at(detId_pot);
959 
960  for (const auto& track : tracks) {
961  if (!track.isValid())
962  continue;
964  continue;
965  if (excludeMultipleHits_ && track.multipleHits() > 0)
966  continue;
967  if (potPlots_.count(detId_pot) == 0)
968  continue;
969 
970  TH2F* trackHistoOOTTmp = potPlots_[detId_pot].trackDistributionOOT->getTH2F();
971  TAxis* trackHistoOOTTmpYAxis = trackHistoOOTTmp->GetYaxis();
972  int startBin = trackHistoOOTTmpYAxis->FindBin(track.x0() - x_shift.global - track.x0Sigma());
973  int numOfBins = 2 * track.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
974  for (int i = 0; i < numOfBins; ++i)
975  trackHistoOOTTmp->Fill(track.ootIndex(), trackHistoOOTTmpYAxis->GetBinCenter(startBin + i));
976 
977  if (centralOOT_ != -999 && track.ootIndex() == centralOOT_) {
978  TH1F* trackHistoInTimeTmp = potPlots_[detId_pot].trackDistribution->getTH1F();
979  int startBin = trackHistoInTimeTmp->FindBin(track.x0() - x_shift.global - track.x0Sigma());
980  int numOfBins = 2 * track.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
981  for (int i = 0; i < numOfBins; ++i)
982  trackHistoInTimeTmp->Fill(trackHistoInTimeTmp->GetBinCenter(startBin + i));
983  }
984  if (plotOffline_ && !perLSsaving_) {
985  // potPlots_[detId_pot].trackTimeVsLS->Fill(event.luminosityBlock(),track.time());
986  potPlots_[detId_pot].trackTimeVsBX->Fill(event.bunchCrossing(), track.time());
987  }
988  }
989  }
990 
991  // Channel efficiency using CTPPSDiamondLocalTrack
992  for (const auto& tracks : *diamondLocalTracks) {
993  const CTPPSDiamondDetId detId(tracks.detId()), detId_pot(detId.rpId());
994  for (const auto& track : tracks) {
995  // Find hits and planes in the track
996  int numOfHits = 0;
997  std::set<int> planesInTrackSet;
998  for (const auto& vec : *diamondRecHits) {
999  const CTPPSDiamondDetId detid(vec.detId());
1000  if (detid.arm() != detId_pot.arm())
1001  continue;
1002 
1003  for (const auto& hit : vec) {
1004  // first check if the hit contributes to the track
1005  if (track.containsHit(hit)) {
1006  ++numOfHits;
1007  planesInTrackSet.insert(detid.plane());
1008  }
1009  }
1010  }
1011 
1012  if (numOfHits > 0 && numOfHits <= 10 && planesInTrackSet.size() > 2) {
1013  for (const auto& plt_vs_ch : channelPlots_) { // loop over all channels registered in geometry
1014  const CTPPSDiamondDetId detId(plt_vs_ch.first);
1015  if (detId.rpId() != detId_pot)
1016  continue;
1017  const unsigned short map_index = detId.plane() * 100 + detId.channel();
1018  if (potPlots_[detId_pot].effDoublecountingChMap.count(map_index) == 0) {
1019  potPlots_[detId_pot].effTriplecountingChMap[map_index] = 0;
1020  potPlots_[detId_pot].effDoublecountingChMap[map_index] = 0;
1021  }
1022  if (channelAlignedWithTrack(ctppsGeometry, detId, track, 0.2)) {
1023  // Channel should fire
1024  ++potPlots_[detId_pot].effDoublecountingChMap[map_index];
1025  for (const auto& rechits : *diamondRecHits) {
1026  const CTPPSDiamondDetId detId_hit(rechits.detId());
1027  if (detId_hit == detId)
1028  for (const auto& rechit : rechits)
1029  if (track.containsHit(rechit, 1)) // Channel fired
1030  ++potPlots_[detId_pot].effTriplecountingChMap[map_index];
1031  }
1032  }
1033  }
1034  }
1035  }
1036  }
1037 
1038  // Tomography of diamonds using pixel
1039  for (const auto& rechits : *diamondRecHits) {
1040  const CTPPSDiamondDetId detId(rechits.detId()), detId_pot(detId.rpId());
1041  const auto pix_shift = diamShifts_.at(detId_pot).withPixels;
1042  for (const auto& rechit : rechits) {
1043  if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1044  continue;
1045  if (rechit.toT() == 0)
1046  continue;
1047  if (!pixelTracks.isValid())
1048  continue;
1049  if (potPlots_.count(detId_pot) == 0)
1050  continue;
1051 
1052  for (const auto& ds : *pixelTracks) {
1053  if (ds.size() > 1)
1054  continue;
1055  const CTPPSPixelDetId pixId(ds.detId());
1056  if (pixId.station() != CTPPS_PIXEL_STATION_ID || pixId.rp() != CTPPS_FAR_RP_ID)
1057  continue;
1058  for (const auto& lt : ds) {
1059  if (lt.isValid() && pixId.arm() == detId_pot.arm()) {
1060  if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING && rechit.ootIndex() >= 0 &&
1061  potPlots_[detId_pot].pixelTomographyAll.count(rechit.ootIndex()) > 0 && lt.x0() - pix_shift < 24)
1062  potPlots_[detId_pot]
1063  .pixelTomographyAll.at(rechit.ootIndex())
1064  ->Fill(lt.x0() - pix_shift + 25 * detId.plane(), lt.y0());
1065  }
1066  }
1067  }
1068  }
1069  }
1070 
1071  //------------------------------
1072  // Clock Plots
1073  //------------------------------
1074  // Commented out to save space in the DQM files, but code should be kept
1075  // for ( const auto& digis : *diamondDigis ) {
1076  // const CTPPSDiamondDetId detId(digis.detId()), detId_pot(detId.rpId());
1077  // if ( detId.channel() == CHANNEL_OF_VFAT_CLOCK ) {
1078  // for ( const auto& digi : digis ) {
1079  // if ( digi.leadingEdge() != 0 ) {
1080  // if ( detId.plane() == 1 ) {
1081  // potPlots_[detId_pot].clock_Digi1_le->Fill( HPTDC_BIN_WIDTH_NS * digi.leadingEdge() );
1082  // potPlots_[detId_pot].clock_Digi1_te->Fill( HPTDC_BIN_WIDTH_NS * digi.trailingEdge() );
1083  // }
1084  // if ( detId.plane() == 3 ) {
1085  // potPlots_[detId_pot].clock_Digi3_le->Fill( HPTDC_BIN_WIDTH_NS * digi.leadingEdge() );
1086  // potPlots_[detId_pot].clock_Digi3_te->Fill( HPTDC_BIN_WIDTH_NS * digi.trailingEdge() );
1087  // }
1088  // }
1089  // }
1090  // }
1091  // }
1092 
1093  //------------------------------
1094  // Plane Plots
1095  //------------------------------
1096 
1097  // Using CTPPSDiamondDigi
1098  std::unordered_map<unsigned int, unsigned int> channelsPerPlane;
1099  if (extract_digi_info_) {
1100  for (const auto& digis : *diamondDigis) {
1101  const CTPPSDiamondDetId detId(digis.detId()), detId_plane(detId.planeId());
1102  for (const auto& digi : digis) {
1103  if (detId.channel() == CHANNEL_OF_VFAT_CLOCK)
1104  continue;
1105  if (planePlots_.count(detId_plane) == 0)
1106  continue;
1107 
1108  if (digi.leadingEdge() != 0) {
1109  planePlots_[detId_plane].digiProfileCumulativePerPlane->Fill(detId.channel());
1110  channelsPerPlane[detId_plane]++;
1111  }
1112  }
1113  }
1114  }
1115 
1116  for (const auto& plt : channelsPerPlane)
1117  planePlots_[plt.first].hit_multiplicity->Fill(plt.second);
1118 
1119  // Using CTPPSDiamondRecHit
1120  for (const auto& rechits : *diamondRecHits) {
1121  const CTPPSDiamondDetId detId(rechits.detId()), detId_plane(detId.planeId()), detId_pot(detId.rpId());
1122  for (const auto& rechit : rechits) {
1123  if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1124  continue;
1125  if (rechit.toT() == 0)
1126  continue;
1127  if (planePlots_.count(detId_plane) != 0) {
1128  if (centralOOT_ != -999 && rechit.ootIndex() == centralOOT_) {
1129  TH1F* hitHistoTmp = planePlots_[detId_plane].hitProfile->getTH1F();
1130  int startBin = hitHistoTmp->FindBin(rechit.x() - diamShifts_.at(detId_pot).global - 0.5 * rechit.xWidth());
1131  int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
1132  for (int i = 0; i < numOfBins; ++i)
1133  hitHistoTmp->Fill(hitHistoTmp->GetBinCenter(startBin + i));
1134  }
1135  }
1136  }
1137  }
1138 
1139  //Tomography of diamonds using pixel and Efficiency WRT Pixels
1140  for (const auto& ds : *pixelTracks) {
1141  const CTPPSPixelDetId pixId(ds.detId());
1142  if (pixId.station() != CTPPS_PIXEL_STATION_ID || pixId.rp() != CTPPS_FAR_RP_ID)
1143  continue;
1144  if (ds.size() > 1)
1145  continue;
1146  for (const auto& lt : ds) {
1147  if (lt.isValid()) {
1148  for (const auto& sh_vs_id : diamShifts_) {
1149  const CTPPSDiamondDetId& detId_pot = sh_vs_id.first;
1150  const auto& shift = sh_vs_id.second;
1151  if (detId_pot.arm() == pixId.arm())
1152  // For efficieny
1153  potPlots_[detId_pot].pixelTracksMap.Fill(lt.x0() - shift.withPixels, lt.y0());
1154  }
1155 
1156  std::set<CTPPSDiamondDetId> planesWitHits_set;
1157  for (const auto& rechits : *diamondRecHits) {
1158  const CTPPSDiamondDetId detId(rechits.detId()), detId_plane(detId.planeId()), detId_pot(detId.rpId());
1159  const auto pix_shift = diamShifts_.at(detId_pot).withPixels;
1160  for (const auto& rechit : rechits) {
1161  if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1162  continue;
1163  if (rechit.ootIndex() == CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING || rechit.toT() == 0)
1164  continue;
1165  if (planePlots_.count(detId_plane) == 0)
1166  continue;
1167  if (pixId.arm() == detId_plane.arm() && lt.x0() - pix_shift < 24) {
1168  planePlots_[detId_plane].pixelTomography_far->Fill(lt.x0() - pix_shift + 25 * rechit.ootIndex(), lt.y0());
1169  if (centralOOT_ != -999 && rechit.ootIndex() == centralOOT_)
1170  planesWitHits_set.insert(detId_plane);
1171  }
1172  }
1173  }
1174 
1175  for (auto& planeId : planesWitHits_set)
1176  planePlots_[planeId].pixelTracksMapWithDiamonds.Fill(lt.x0() - diamShifts_.at(planeId.rpId()).withPixels,
1177  lt.y0());
1178  }
1179  }
1180  }
1181 
1182  //------------------------------
1183  // Channel Plots
1184  //------------------------------
1185 
1186  // digi profile cumulative
1187  if (extract_digi_info_) {
1188  for (const auto& digis : *diamondDigis) {
1189  const CTPPSDiamondDetId detId(digis.detId());
1190  for (const auto& digi : digis) {
1191  if (detId.channel() == CHANNEL_OF_VFAT_CLOCK)
1192  continue;
1193  if (channelPlots_.count(detId) != 0) {
1194  // HPTDC Errors
1195  const HPTDCErrorFlags hptdcErrors = digi.hptdcErrorFlags();
1196  for (unsigned short hptdcErrorIndex = 1; hptdcErrorIndex < 16; ++hptdcErrorIndex)
1197  if (hptdcErrors.errorId(hptdcErrorIndex - 1))
1198  channelPlots_[detId].HPTDCErrorFlags->Fill(hptdcErrorIndex);
1199  if (digi.multipleHit())
1200  ++channelPlots_[detId].MHCounter;
1201 
1202  // Check dropped trailing edges
1203  if (digi.leadingEdge() != 0 || digi.trailingEdge() != 0) {
1204  ++channelPlots_[detId].HitCounter;
1205  if (digi.trailingEdge() == 0) {
1206  ++channelPlots_[detId].LeadingOnlyCounter;
1207  channelPlots_[detId].leadingEdgeCumulative_le->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
1208  } else if (digi.leadingEdge() == 0) {
1209  ++channelPlots_[detId].TrailingOnlyCounter;
1210  channelPlots_[detId].trailingEdgeCumulative_te->Fill(HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
1211  } else {
1212  ++channelPlots_[detId].CompleteCounter;
1213  // channelPlots_[detId].LeadingTrailingCorrelationPerChannel->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge(),
1214  // HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
1215  }
1216  }
1217  }
1218  }
1219  }
1220  }
1221 
1222  // Using CTPPSDiamondRecHit
1223 
1224  for (const auto& rechits : *diamondRecHits) {
1225  CTPPSDiamondDetId detId(rechits.detId());
1226  for (const auto& rechit : rechits) {
1227  if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1228  continue;
1229  if (channelPlots_.count(detId) != 0) {
1230  channelPlots_[detId].recHitTime->Fill(rechit.time());
1231  if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING && rechit.toT() != 0) {
1232  channelPlots_[detId].leadingEdgeCumulative_both->Fill(rechit.time() + 25 * rechit.ootIndex());
1233  channelPlots_[detId].TimeOverThresholdCumulativePerChannel->Fill(rechit.toT());
1234  }
1235  ++lumiCache->hitsCounterMap[detId];
1236 
1237  if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING &&
1238  channelPlots_[detId].activity_per_bx.count(rechit.ootIndex()) > 0)
1239  channelPlots_[detId].activity_per_bx.at(rechit.ootIndex())->Fill(event.bunchCrossing());
1240  }
1241  }
1242  }
1243 
1244  // Tomography of diamonds using pixel
1245  for (const auto& rechits : *diamondRecHits) {
1246  const CTPPSDiamondDetId detId(rechits.detId()), detId_pot(detId.rpId());
1247  const auto shift_pix = diamShifts_.at(detId_pot).withPixels;
1248  for (const auto& rechit : rechits) {
1249  if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1250  continue;
1251  if (rechit.ootIndex() == CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING || rechit.toT() == 0)
1252  continue;
1253  if (!pixelTracks.isValid())
1254  continue;
1255  if (channelPlots_.count(detId) == 0)
1256  continue;
1257 
1258  for (const auto& ds : *pixelTracks) {
1259  const CTPPSPixelDetId pixId(ds.detId());
1260  if (pixId.station() != CTPPS_PIXEL_STATION_ID || pixId.rp() != CTPPS_FAR_RP_ID)
1261  continue;
1262  if (ds.size() > 1)
1263  continue;
1264  for (const auto& lt : ds) {
1265  if (lt.isValid() && pixId.arm() == detId.arm() && lt.x0() - shift_pix < 24)
1266  channelPlots_[detId].pixelTomography_far->Fill(lt.x0() - shift_pix + 25 * rechit.ootIndex(), lt.y0());
1267  }
1268  }
1269  }
1270  }
1271 }
1272 
1273 //----------------------------------------------------------------------------------------------------
1274 
1276  auto lumiCache = luminosityBlockCache(iLumi.index());
1277  if (!perLSsaving_) {
1278  if (plotOnline_)
1279  for (auto& plot : potPlots_)
1280  *(plot.second.hitDistribution2d_lumisection->getTH2F()) = *(lumiCache->hitDistribution2dMap[plot.first]);
1281 
1282  for (auto& plot : channelPlots_) {
1283  auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[plot.first];
1284  if (hitsCounterPerLumisection != 0) {
1285  plot.second.hit_rate->Fill((double)hitsCounterPerLumisection / SEC_PER_LUMI_SECTION);
1286  }
1287 
1288  double HundredOverHitCounter = .0;
1289  if (plot.second.HitCounter != 0)
1290  HundredOverHitCounter = 100. / plot.second.HitCounter;
1291  plot.second.HPTDCErrorFlags->setBinContent(16, HundredOverHitCounter * plot.second.MHCounter);
1292  plot.second.leadingWithoutTrailing->setBinContent(1, HundredOverHitCounter * plot.second.LeadingOnlyCounter);
1293  plot.second.leadingWithoutTrailing->setBinContent(2, HundredOverHitCounter * plot.second.TrailingOnlyCounter);
1294  plot.second.leadingWithoutTrailing->setBinContent(3, HundredOverHitCounter * plot.second.CompleteCounter);
1295  }
1296 
1297  for (auto& plot : potPlots_) {
1298  double HundredOverHitCounterPot = 0.;
1299  if (plot.second.HitCounter != 0)
1300  HundredOverHitCounterPot = 100. / plot.second.HitCounter;
1301  plot.second.leadingWithoutTrailingCumulativePot->setBinContent(
1302  1, HundredOverHitCounterPot * plot.second.LeadingOnlyCounter);
1303  plot.second.leadingWithoutTrailingCumulativePot->setBinContent(
1304  2, HundredOverHitCounterPot * plot.second.TrailingOnlyCounter);
1305  plot.second.leadingWithoutTrailingCumulativePot->setBinContent(
1306  3, HundredOverHitCounterPot * plot.second.CompleteCounter);
1307 
1308  plot.second.MHComprensive->Reset();
1309  const CTPPSDiamondDetId rpId(plot.first);
1310  for (auto& chPlot : channelPlots_) {
1311  const CTPPSDiamondDetId chId(chPlot.first);
1312  if (chId.arm() == rpId.arm() && chId.rp() == rpId.rp()) {
1313  plot.second.MHComprensive->Fill(
1314  chId.plane(), chId.channel(), chPlot.second.HPTDCErrorFlags->getBinContent(16));
1315  }
1316  }
1317  }
1318  // Efficiencies of single channels
1319  if (plotOnline_)
1320  for (auto& plot : potPlots_) {
1321  plot.second.EfficiencyOfChannelsInPot->Reset();
1322  for (auto& element : plot.second.effTriplecountingChMap) {
1323  if (plot.second.effDoublecountingChMap[element.first] > 0) {
1324  int plane = element.first / 100;
1325  int channel = element.first % 100;
1326  double counted = element.second;
1327  double total = plot.second.effDoublecountingChMap[element.first];
1328  double efficiency = counted / total;
1329  // double error = std::sqrt( efficiency * ( 1 - efficiency ) / total );
1330 
1331  plot.second.EfficiencyOfChannelsInPot->Fill(plane, channel, 100 * efficiency);
1332  }
1333  }
1334  }
1335 
1336  // Efficeincy wrt pixels //TODO
1337  for (auto& plot : planePlots_) {
1338  TH2F* hitHistoTmp = plot.second.EfficiencyWRTPixelsInPlane->getTH2F();
1339 
1340  const CTPPSDiamondDetId detId(plot.first), detId_pot(detId.rpId());
1341  hitHistoTmp->Divide(&(plot.second.pixelTracksMapWithDiamonds), &(potPlots_[detId_pot].pixelTracksMap));
1342  }
1343  } //perLSsaving
1344 }
1345 
1346 //----------------------------------------------------------------------------------------------------
1347 
1349  const TotemFEDInfo& optorx,
1350  const TotemVFATStatus& status,
1352  int& EC_difference) const {
1353  const CTPPSDiamondDetId detId_pot(detId.rpId());
1354  if (plotOnline_)
1355  plots.ECCheck->Fill((int)((optorx.lv1() & 0xFF) - ((unsigned int)status.ec() & 0xFF)) & 0xFF);
1356  if ((static_cast<int>((optorx.lv1() & 0xFF) - status.ec()) != EC_difference) &&
1357  (static_cast<uint8_t>((optorx.lv1() & 0xFF) - status.ec()) < 128))
1358  EC_difference = static_cast<int>(optorx.lv1() & 0xFF) - (static_cast<unsigned int>(status.ec()) & 0xFF);
1359  if (EC_difference != 1 && EC_difference != -500 && std::abs(EC_difference) < 127) {
1360  if (detId.channel() == HPTDC_0_CHANNEL || detId.channel() == HPTDC_1_CHANNEL)
1361  plots.HPTDCErrorFlags_2D->Fill(16, 2 * detId.plane() + (detId.channel() - HPTDC_0_CHANNEL));
1362  if (verbosity_)
1363  edm::LogProblem("CTPPSDiamondDQMSource")
1364  << "FED " << optorx.fedId() << ": ECError at EV: 0x" << std::hex << optorx.lv1() << "\t\tVFAT EC: 0x"
1365  << static_cast<unsigned int>(status.ec()) << "\twith ID: " << std::dec << detId
1366  << "\tdiff: " << EC_difference;
1367  }
1368 }
1369 
1370 //----------------------------------------------------------------------------------------------------
1371 
1373  if (plotOffline_ && !perLSsaving_)
1374  for (const auto& rpPlots : potPlots_) {
1375  auto plots = rpPlots.second;
1376  // *(plots.TOTVsLSProfile->getTProfile())=*plots.TOTVsLS->getTH2F()->ProfileX();
1377  // *(plots.trackTimeVsLSProfile->getTProfile())=*plots.trackTimeVsLS->getTH2F()->ProfileX();
1378  *(plots.trackTimeVsBXProfile->getTProfile()) = *plots.trackTimeVsBX->getTH2F()->ProfileX();
1379  // *(plots.trackTimeVsXAngleProfile->getTProfile()) = *plots.trackTimeVsXAngle->getTH2F()->ProfileX();
1380  }
1381 }
1382 
1383 //----------------------------------------------------------------------------------------------------
void analyze(const edm::Event &, const edm::EventSetup &) override
static constexpr unsigned short CTPPS_FED_ID_45
OptoRx headers and footers.
Definition: TotemFEDInfo.h:17
plots related to one Diamond plane
plots related to one Diamond detector package
edm::EDGetTokenT< edm::DetSetVector< CTPPSDiamondRecHit > > tokenDiamondHit_
static constexpr double SEC_PER_LUMI_SECTION
Number of seconds per lumisection: used to compute hit rates in Hz.
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
const Translation & translation() const
Definition: DetGeomDesc.h:80
edm::ESGetToken< CTPPSGeometry, VeryForwardRealGeometryRecord > ctppsGeometryRunToken_
edm::EDGetTokenT< std::vector< TotemFEDInfo > > tokenFEDInfo_
std::unordered_map< CTPPSDetId, DiamondShifts > diamShifts_
bool contains(EventRange const &lh, EventID const &rh)
Definition: EventRange.cc:37
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
static constexpr unsigned short CTPPS_DIAMOND_NUM_OF_CHANNELS
static constexpr double DISPLAY_RESOLUTION_FOR_HITS_MM
Bin width of histograms showing hits and tracks (in mm)
static constexpr unsigned short CTPPS_FAR_RP_ID
uint32_t arm() const
Definition: CTPPSDetId.h:57
Reconstructed hit in diamond detectors.
const double tolerance
void dqmBeginRun(const edm::Run &, const edm::EventSetup &) override
CTPPSDiamondDQMSource(const edm::ParameterSet &)
plots related to the whole system
uint32_t plane() const
static constexpr unsigned short CTPPS_PIXEL_STATION_ID
std::shared_ptr< dds::Cache > globalBeginLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) const override
void planeName(std::string &name, NameFlag flag=nFull) const
edm::ESGetToken< CTPPSGeometry, VeryForwardRealGeometryRecord > ctppsGeometryEventToken_
edm::EDGetTokenT< edm::DetSetVector< CTPPSDiamondLocalTrack > > tokenDiamondTrack_
Event setup record containing the real (actual) geometry information.
static std::string to_string(const XMLCh *ch)
MonitorElement * leadingWithoutTrailingCumulativePot
edm::EDGetTokenT< edm::DetSetVector< CTPPSPixelLocalTrack > > tokenPixelTrack_
void globalEndLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) override
static constexpr unsigned short HPTDC_0_CHANNEL
void dqmEndRun(edm::Run const &, edm::EventSetup const &) override
std::unordered_map< unsigned int, MonitorElement * > pixelTomographyAll
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
T getUntrackedParameter(std::string const &, T const &) const
static std::string hptdcErrorName(const unsigned short id)
std::vector< std::pair< edm::EventRange, int > > runParameters_
RunNumber_t run() const
Definition: RunBase.h:40
edm::EDGetTokenT< edm::DetSetVector< CTPPSDiamondDigi > > tokenDigi_
void rpName(std::string &name, NameFlag flag=nFull) const
Definition: CTPPSDetId.h:134
void bookHistograms(DQMStore::IBooker &, const edm::Run &, const edm::EventSetup &) override
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:399
void Fill(HcalDetId &id, double val, std::vector< TH2F > &depth)
CTPPSDetId rpId() const
Definition: CTPPSDetId.h:84
std::unordered_map< unsigned int, ChannelPlots > channelPlots_
uint32_t channel() const
edm::EDGetTokenT< edm::DetSetVector< TotemVFATStatus > > tokenStatus_
static constexpr unsigned short CHANNEL_OF_VFAT_CLOCK
Channel ID of the VFAT that contains clock data.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static constexpr unsigned int FIRST_RUN_W_PIXELS
Number of OOT indices monitored.
std::unordered_map< unsigned int, std::unique_ptr< TH2F > > hitDistribution2dMap
Transition
Definition: Transition.h:12
plots related to one Diamond channel
bool errorId(unsigned short id) const
void armName(std::string &name, NameFlag flag=nFull) const
Definition: CTPPSDetId.h:98
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
def window(xmin, xmax, ymin, ymax, x=0, y=0, width=100, height=100, xlogbase=None, ylogbase=None, minusInfinity=-1000, flipx=False, flipy=True)
Definition: svgfig.py:643
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:50
const DiamondDimensions & getDiamondDimensions() const
Definition: DetGeomDesc.h:90
virtual void setBinLabel(int bin, const std::string &label, int axis=1)
set bin label for x, y or z axis (axis=1, 2, 3 respectively)
void channelName(std::string &name, NameFlag flag=nFull) const
d
Definition: ztail.py:151
static bool check(unsigned int raw)
returns true if the raw ID is a PPS-timing one
The manager class for TOTEM RP geometry.
Definition: CTPPSGeometry.h:30
uint32_t rp() const
Definition: CTPPSDetId.h:71
CTPPSDetId armId() const
Definition: CTPPSDetId.h:80
int fedId() const
Definition: TotemFEDInfo.h:22
std::unordered_map< unsigned int, SectorPlots > sectorPlots_
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:212
std::unordered_map< unsigned int, MonitorElement * > activity_per_bx
bool channelAlignedWithTrack(const CTPPSGeometry *geom, const CTPPSDiamondDetId &detid, const CTPPSDiamondLocalTrack &localTrack, const float tolerance=1)
bool isValid() const
Definition: HandleBase.h:70
std::unordered_map< unsigned int, PotPlots > potPlots_
static constexpr int TIMESLICE_WITHOUT_LEADING
LuminosityBlockIndex index() const
void checkEventNumber(const CTPPSDiamondDetId &, const TotemFEDInfo &, const TotemVFATStatus &, PotPlots &, int &) const
static constexpr unsigned short CTPPS_FED_ID_56
HLT enums.
static constexpr double HPTDC_BIN_WIDTH_NS
ns per HPTDC bin
static constexpr double INV_DISPLAY_RESOLUTION_FOR_HITS_MM
uint32_t lv1() const
Definition: TotemFEDInfo.h:26
CTPPSDiamondDetId planeId() const
static unsigned int const shift
Detector ID class for CTPPS Timing Diamond detectors. Bits [19:31] : Assigend in CTPPSDetId Calss Bit...
std::unordered_map< unsigned int, PlanePlots > planePlots_
std::unordered_map< unsigned int, MonitorElement * > activity_per_bx
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
static constexpr unsigned short HPTDC_1_CHANNEL
std::unordered_map< unsigned int, unsigned long > hitsCounterMap
Definition: event.py:1
Definition: Run.h:45
Log< level::Error, true > LogProblem