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