Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-04 04:04:22

0001 /****************************************************************************
0002 *
0003 * This is a part of CTPPSDQM software.
0004 * Authors:
0005 *   Jan Kašpar (jan.kaspar@gmail.com)
0006 *   Nicola Minafra
0007 *   Laurent Forthomme
0008 *   Christopher Misan
0009 *
0010 ****************************************************************************/
0011 
0012 #include "FWCore/Framework/interface/MakerMacros.h"
0013 #include "FWCore/Framework/interface/Event.h"
0014 #include "FWCore/Framework/interface/EventSetup.h"
0015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0016 #include "FWCore/Utilities/interface/ESGetToken.h"
0017 #include "FWCore/Utilities/interface/InputTag.h"
0018 #include "FWCore/Utilities/interface/Transition.h"
0019 #include "FWCore/Framework/interface/Run.h"
0020 
0021 #include "DQMServices/Core/interface/DQMOneEDAnalyzer.h"
0022 #include "DQMServices/Core/interface/DQMStore.h"
0023 
0024 #include "DataFormats/Provenance/interface/EventRange.h"
0025 #include "DataFormats/CTPPSDigi/interface/TotemVFATStatus.h"
0026 #include "DataFormats/CTPPSDigi/interface/TotemFEDInfo.h"
0027 #include "DataFormats/Common/interface/DetSetVector.h"
0028 
0029 #include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h"
0030 #include "DataFormats/CTPPSDigi/interface/CTPPSDiamondDigi.h"
0031 
0032 #include "DataFormats/CTPPSReco/interface/CTPPSPixelLocalTrack.h"
0033 #include "DataFormats/CTPPSDetId/interface/CTPPSPixelDetId.h"
0034 
0035 #include "DataFormats/CTPPSReco/interface/CTPPSDiamondRecHit.h"
0036 #include "DataFormats/CTPPSReco/interface/CTPPSDiamondLocalTrack.h"
0037 #include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h"
0038 #include "Geometry/Records/interface/VeryForwardRealGeometryRecord.h"
0039 
0040 #include <string>
0041 
0042 //----------------------------------------------------------------------------------------------------
0043 
0044 // Utility for efficiency computations
0045 bool channelAlignedWithTrack(const CTPPSGeometry* geom,
0046                              const CTPPSDiamondDetId& detid,
0047                              const CTPPSDiamondLocalTrack& localTrack,
0048                              const float tolerance = 1) {
0049   const DetGeomDesc* det = geom->sensor(detid);
0050   const float x_pos = det->translation().x(),
0051               x_width = 2.0 * det->getDiamondDimensions().xHalfWidth;  // parameters stand for half the size
0052   return ((x_pos + 0.5 * x_width > localTrack.x0() - localTrack.x0Sigma() - tolerance &&
0053            x_pos + 0.5 * x_width < localTrack.x0() + localTrack.x0Sigma() + tolerance) ||
0054           (x_pos - 0.5 * x_width > localTrack.x0() - localTrack.x0Sigma() - tolerance &&
0055            x_pos - 0.5 * x_width < localTrack.x0() + localTrack.x0Sigma() + tolerance) ||
0056           (x_pos - 0.5 * x_width < localTrack.x0() - localTrack.x0Sigma() - tolerance &&
0057            x_pos + 0.5 * x_width > localTrack.x0() + localTrack.x0Sigma() + tolerance));
0058 }
0059 
0060 namespace dds {
0061   struct Cache {
0062     std::unordered_map<unsigned int, std::unique_ptr<TH2F>> hitDistribution2dMap;
0063 
0064     std::unordered_map<unsigned int, unsigned long> hitsCounterMap;
0065   };
0066 }  // namespace dds
0067 
0068 class CTPPSDiamondDQMSource : public DQMOneEDAnalyzer<edm::LuminosityBlockCache<dds::Cache>> {
0069 public:
0070   CTPPSDiamondDQMSource(const edm::ParameterSet&);
0071 
0072 protected:
0073   void dqmBeginRun(const edm::Run&, const edm::EventSetup&) override;
0074   void dqmEndRun(edm::Run const&, edm::EventSetup const&) override;
0075   void bookHistograms(DQMStore::IBooker&, const edm::Run&, const edm::EventSetup&) override;
0076   void analyze(const edm::Event&, const edm::EventSetup&) override;
0077   std::shared_ptr<dds::Cache> globalBeginLuminosityBlock(const edm::LuminosityBlock&,
0078                                                          const edm::EventSetup&) const override;
0079   void globalEndLuminosityBlock(const edm::LuminosityBlock&, const edm::EventSetup&) override;
0080 
0081 private:
0082   // Constants
0083   /// Number of seconds per lumisection: used to compute hit rates in Hz
0084   static constexpr double SEC_PER_LUMI_SECTION = 23.31;
0085   /// Channel ID of the VFAT that contains clock data
0086   static constexpr unsigned short CHANNEL_OF_VFAT_CLOCK = 30;
0087   /// Bin width of histograms showing hits and tracks (in mm)
0088   static constexpr double DISPLAY_RESOLUTION_FOR_HITS_MM = 0.1;
0089   static constexpr double INV_DISPLAY_RESOLUTION_FOR_HITS_MM = 1. / DISPLAY_RESOLUTION_FOR_HITS_MM;
0090   /// ns per HPTDC bin
0091   static constexpr double HPTDC_BIN_WIDTH_NS = 25. / 1024;
0092   static constexpr unsigned short CTPPS_PIXEL_STATION_ID = 2;
0093   static constexpr unsigned short CTPPS_PIXEL_FAR_RP_ID = 3;
0094   static constexpr unsigned short CTPPS_DIAMOND_CYL_STATION_ID = 1;
0095   static constexpr unsigned short CTPPS_DIAMOND_CYL_RP_ID = 6;
0096   static constexpr unsigned short CTPPS_DIAMOND_NUM_OF_CHANNELS = 12;
0097   static constexpr unsigned short CTPPS_FED_ID_45 = 583;
0098   static constexpr unsigned short CTPPS_FED_ID_56 = 582;
0099   static constexpr unsigned short HPTDC_0_CHANNEL = 6;
0100   static constexpr unsigned short HPTDC_1_CHANNEL = 7;
0101   /// Number of OOT indices monitored
0102   static constexpr unsigned int FIRST_RUN_W_PIXELS = 300000;
0103 
0104   bool perLSsaving_;  //to avoid nanoDQMIO crashing, driven by  DQMServices/Core/python/DQMStore_cfi.py
0105 
0106   /// plots related to the whole system
0107   struct GlobalPlots {
0108     GlobalPlots() = default;
0109     GlobalPlots(DQMStore::IBooker& ibooker);
0110   };
0111   /// plots related to one sector
0112   struct SectorPlots {
0113     // Tracks
0114     MonitorElement* trackCorrelation = nullptr;
0115     MonitorElement* trackCorrelationLowMultiplicity = nullptr;
0116     MonitorElement* digiSentPercentage = nullptr;
0117     SectorPlots(){};
0118     SectorPlots(DQMStore::IBooker& ibooker, unsigned int id, bool plotOnline);
0119   };
0120   /// plots related to one Diamond detector package
0121   struct PotPlots {
0122     std::unordered_map<unsigned int, MonitorElement*> activity_per_bx;
0123 
0124     MonitorElement* hitDistribution2d = nullptr;
0125     MonitorElement* hitDistribution2d_lumisection = nullptr;
0126     MonitorElement* hitDistribution2dOOT = nullptr;
0127     MonitorElement* hitDistribution2dOOT_le = nullptr;
0128     MonitorElement *activePlanes = nullptr, *activePlanesInclusive = nullptr;
0129 
0130     MonitorElement* trackDistribution = nullptr;
0131     MonitorElement* trackDistributionOOT = nullptr;
0132 
0133     std::unordered_map<unsigned int, MonitorElement*> pixelTomographyAll;
0134 
0135     MonitorElement *leadingEdgeCumulative_both = nullptr, *leadingEdgeCumulative_all = nullptr,
0136                    *leadingEdgeCumulative_le = nullptr, *trailingEdgeCumulative_te = nullptr;
0137     MonitorElement* timeOverThresholdCumulativePot = nullptr;  //, *leadingTrailingCorrelationPot = nullptr;
0138     MonitorElement* leadingWithoutTrailingCumulativePot = nullptr;
0139 
0140     MonitorElement* ECCheck = nullptr;
0141 
0142     MonitorElement* HPTDCErrorFlags_2D = nullptr;
0143     MonitorElement* MHComprensive = nullptr;
0144 
0145     MonitorElement* recHitTime = nullptr;
0146 
0147     // MonitorElement* clock_Digi1_le = nullptr;
0148     // MonitorElement* clock_Digi1_te = nullptr;
0149     // MonitorElement* clock_Digi3_le = nullptr;
0150     // MonitorElement* clock_Digi3_te = nullptr;
0151 
0152     unsigned int HitCounter, MHCounter, LeadingOnlyCounter, TrailingOnlyCounter, CompleteCounter;
0153 
0154     std::map<int, int> effTriplecountingChMap;
0155     std::map<int, int> effDoublecountingChMap;
0156     MonitorElement* EfficiencyOfChannelsInPot = nullptr;
0157     TH2F pixelTracksMap;
0158 
0159     // MonitorElement* TOTVsLS = nullptr;
0160     // MonitorElement* trackTimeVsLS = nullptr;
0161     MonitorElement* trackTimeVsBX = nullptr;
0162     // MonitorElement* trackTimeVsXAngle = nullptr;
0163 
0164     // MonitorElement* TOTVsLSProfile = nullptr;
0165     // MonitorElement* trackTimeVsLSProfile = nullptr;
0166     MonitorElement* trackTimeVsBXProfile = nullptr;
0167     // MonitorElement* trackTimeVsXAngleProfile = nullptr;
0168 
0169     PotPlots() = default;
0170     PotPlots(DQMStore::IBooker& ibooker,
0171              unsigned int id,
0172              unsigned int windowsNum,
0173              bool plotOnline,
0174              bool plotOffline,
0175              bool perLSsaving);
0176   };
0177   /// plots related to one Diamond plane
0178   struct PlanePlots {
0179     MonitorElement* digiProfileCumulativePerPlane = nullptr;
0180     MonitorElement* hitProfile = nullptr;
0181     MonitorElement* hit_multiplicity = nullptr;
0182 
0183     MonitorElement *leadingEdgeCumulativePerPlane_both = nullptr, *leadingEdgeCumulativePerPlane_le = nullptr,
0184                    *trailingEdgeCumulativePerPlane_te = nullptr;
0185     MonitorElement* TimeOverThresholdCumulativePerPlane = nullptr;
0186     MonitorElement* pixelTomography_far = nullptr;
0187     MonitorElement* EfficiencyWRTPixelsInPlane = nullptr;
0188 
0189     TH2F pixelTracksMapWithDiamonds;
0190 
0191     PlanePlots() = default;
0192     PlanePlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int windowsNum);
0193   };
0194   /// plots related to one Diamond channel
0195   struct ChannelPlots {
0196     std::unordered_map<unsigned int, MonitorElement*> activity_per_bx;
0197 
0198     MonitorElement* HPTDCErrorFlags = nullptr;
0199     MonitorElement *leadingEdgeCumulative_both = nullptr, *leadingEdgeCumulative_le = nullptr,
0200                    *trailingEdgeCumulative_te = nullptr;
0201     MonitorElement* TimeOverThresholdCumulativePerChannel = nullptr;
0202     //MonitorElement* LeadingTrailingCorrelationPerChannel = nullptr;
0203     MonitorElement* leadingWithoutTrailing = nullptr;
0204     MonitorElement* pixelTomography_far = nullptr;
0205     MonitorElement* hit_rate = nullptr;
0206     MonitorElement* recHitTime = nullptr;
0207 
0208     unsigned int HitCounter, MHCounter, LeadingOnlyCounter, TrailingOnlyCounter, CompleteCounter;
0209 
0210     ChannelPlots() = default;
0211     ChannelPlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int windowsNum);
0212   };
0213 
0214   void checkEventNumber(const CTPPSDiamondDetId&, const TotemFEDInfo&, const TotemVFATStatus&, PotPlots&, int&) const;
0215 
0216   edm::EDGetTokenT<edm::DetSetVector<TotemVFATStatus>> tokenStatus_;
0217   edm::EDGetTokenT<edm::DetSetVector<CTPPSPixelLocalTrack>> tokenPixelTrack_;
0218   edm::EDGetTokenT<edm::DetSetVector<CTPPSDiamondDigi>> tokenDigi_;
0219   edm::EDGetTokenT<edm::DetSetVector<CTPPSDiamondRecHit>> tokenDiamondHit_;
0220   edm::EDGetTokenT<edm::DetSetVector<CTPPSDiamondLocalTrack>> tokenDiamondTrack_;
0221   edm::EDGetTokenT<std::vector<TotemFEDInfo>> tokenFEDInfo_;
0222 
0223   edm::ESGetToken<CTPPSGeometry, VeryForwardRealGeometryRecord> ctppsGeometryRunToken_;
0224   edm::ESGetToken<CTPPSGeometry, VeryForwardRealGeometryRecord> ctppsGeometryEventToken_;
0225 
0226   bool excludeMultipleHits_;
0227   const bool extract_digi_info_;
0228   struct DiamondShifts {
0229     double global, withPixels;
0230   };
0231   std::unordered_map<CTPPSDetId, DiamondShifts> diamShifts_;
0232   std::vector<std::pair<edm::EventRange, int>> runParameters_;
0233   int centralOOT_;
0234   unsigned int verbosity_;
0235   const bool plotOnline_;
0236   const bool plotOffline_;
0237   unsigned int windowsNum_;
0238   unsigned int trackCorrelationThreshold_;
0239 
0240   GlobalPlots globalPlot_;
0241   std::unordered_map<unsigned int, PotPlots> potPlots_;
0242   std::unordered_map<unsigned int, SectorPlots> sectorPlots_;
0243   std::unordered_map<unsigned int, PlanePlots> planePlots_;
0244   std::unordered_map<unsigned int, ChannelPlots> channelPlots_;
0245 
0246   int EC_difference_56_, EC_difference_45_;
0247 };
0248 
0249 //----------------------------------------------------------------------------------------------------
0250 
0251 CTPPSDiamondDQMSource::GlobalPlots::GlobalPlots(DQMStore::IBooker& ibooker) { ibooker.setCurrentFolder("CTPPS"); }
0252 
0253 //----------------------------------------------------------------------------------------------------
0254 
0255 CTPPSDiamondDQMSource::SectorPlots::SectorPlots(DQMStore::IBooker& ibooker, unsigned int id, bool plotOnline) {
0256   std::string path, title;
0257   CTPPSDiamondDetId(id).armName(path, CTPPSDiamondDetId::nPath);
0258   ibooker.setCurrentFolder(path);
0259 
0260   CTPPSDiamondDetId(id).armName(title, CTPPSDiamondDetId::nFull);
0261 
0262   trackCorrelation = ibooker.book2D("tracks correlation near-far",
0263                                     title + " tracks correlation near-far;track x 220nr_hr (mm);track x 220cyl (mm)",
0264                                     19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0265                                     -1,
0266                                     18,
0267                                     19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0268                                     -1,
0269                                     18);
0270   trackCorrelationLowMultiplicity = ibooker.book2D(
0271       "tracks correlation with low multiplicity near-far",
0272       title + " tracks correlation with low multiplicity near-far;track x 220nr_hr (mm);track x 220cyl(mm)",
0273       19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0274       -1,
0275       18,
0276       19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0277       -1,
0278       18);
0279 }
0280 
0281 //----------------------------------------------------------------------------------------------------
0282 CTPPSDiamondDQMSource::PotPlots::PotPlots(DQMStore::IBooker& ibooker,
0283                                           unsigned int id,
0284                                           unsigned int windowsNum,
0285                                           bool plotOnline,
0286                                           bool plotOffline,
0287                                           bool perLSsaving)
0288     : HitCounter(0),
0289       MHCounter(0),
0290       LeadingOnlyCounter(0),
0291       TrailingOnlyCounter(0),
0292       CompleteCounter(0),
0293       pixelTracksMap("Pixel track maps for efficiency", "Pixel track maps for efficiency", 25, 0, 25, 16, -8, 8) {
0294   std::string path, title;
0295   CTPPSDiamondDetId(id).rpName(path, CTPPSDiamondDetId::nPath);
0296   ibooker.setCurrentFolder(path);
0297 
0298   CTPPSDiamondDetId(id).rpName(title, CTPPSDiamondDetId::nFull);
0299 
0300   if (plotOnline) {
0301     hitDistribution2d_lumisection =
0302         ibooker.book2D("hits in planes lumisection",
0303                        title + " hits in planes in the last lumisection;plane number;x (mm)",
0304                        10,
0305                        -0.5,
0306                        4.5,
0307                        19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0308                        -0.5,
0309                        18.5);
0310 
0311     hitDistribution2dOOT_le =
0312         ibooker.book2D("hits with OOT in planes (le only)",
0313                        title + " hits with OOT in planes (le only);plane number, OOT index;x (mm)",
0314                        1 + windowsNum * 4,
0315                        -1. / windowsNum,
0316                        4,
0317                        19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0318                        -0.5,
0319                        18.5);
0320 
0321     activePlanesInclusive =
0322         ibooker.book1D("active planes inclusive",
0323                        title + " active planes, MH and le only included (per event);number of active planes",
0324                        6,
0325                        -0.5,
0326                        5.5);
0327 
0328     ECCheck = ibooker.book1D("optorxEC(8bit) - vfatEC", title + " EC Error;optorxEC-vfatEC", 50, -25, 25);
0329 
0330     EfficiencyOfChannelsInPot =
0331         ibooker.book2D("Efficiency in channels",
0332                        title + " Efficiency (%) in channels (diamonds only);plane number;ch number",
0333                        10,
0334                        -0.5,
0335                        4.5,
0336                        14,
0337                        -1,
0338                        13);
0339   }
0340 
0341   if (plotOffline && !perLSsaving) {
0342     ibooker.setCurrentFolder(path + "/timing_profiles");
0343     // TOTVsLS=ibooker.book2D("ToT vs LS",title +" ToT vs LS;LS;ToT(ns)",4000,0,4000, 200,5,25);
0344     // trackTimeVsLS=ibooker.book2D("track time vs LS",title+" track time vs LS;LS;track_time(ns)",4000,0,4000, 500, -25, 25);
0345     trackTimeVsBX =
0346         ibooker.book2D("track time vs BX", title + " track time vs BX;BX;track_time(ns)", 4000, 0, 4000, 500, -25, 25);
0347     // trackTimeVsXAngle = ibooker.book2D(
0348     //     "track time vs xangle", title + " track time vs xangle;xangle;track_time(ns)", 60, 120, 180, 500, -25, 25);
0349 
0350     // TOTVsLSProfile=ibooker.bookProfile("ToT vs LS profile",title+" ToT vs LS profile;LS;track_time(ns)", 500, -25, 25,4000,0,4000);
0351     // trackTimeVsLSProfile=ibooker.bookProfile("track time vs LS profile",title+" track time vs LS profile;LS;track_time(ns)", 500, -25, 25,4000,0,4000);
0352     trackTimeVsBXProfile = ibooker.bookProfile(
0353         "track time vs BX profile", title + " track time vs BX profile;BX;track_time(ns)", 500, -25, 25, 4000, 0, 4000);
0354     // trackTimeVsXAngleProfile = ibooker.bookProfile("track time vs xangle profile",
0355     //                                                title + " track time vs xangle profile;xangle;track_time(ns)",
0356     //                                                500,
0357     //                                                -25,
0358     //                                                25,
0359     //                                                60,
0360     //                                                120,
0361     //                                                180);
0362     ibooker.setCurrentFolder(path);
0363   }
0364 
0365   for (unsigned int i = 0; i < windowsNum; i++) {
0366     std::string window = std::to_string(i * 25) + "-" + std::to_string((i + 1) * 25);
0367     activity_per_bx[i] = ibooker.book1D(
0368         "activity per BX " + window, title + " Activity per BX " + window + " ns;Event.BX", 3600, -1.5, 3598. + 0.5);
0369     pixelTomographyAll[i] =
0370         ibooker.book2D("tomography pixel " + window,
0371                        title + " tomography with pixel " + window + " ns (all planes);x + 25*plane(mm);y (mm)",
0372                        100,
0373                        0,
0374                        100,
0375                        10,
0376                        -5,
0377                        5);
0378   }
0379 
0380   hitDistribution2d = ibooker.book2D("hits in planes",
0381                                      title + " hits in planes;plane number;x (mm)",
0382                                      10,
0383                                      -0.5,
0384                                      4.5,
0385                                      19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0386                                      -0.5,
0387                                      18.5);
0388 
0389   hitDistribution2dOOT = ibooker.book2D("hits with OOT in planes",
0390                                         title + " hits with OOT in planes;plane number, OOT index;x (mm)",
0391                                         1 + windowsNum * 4,
0392                                         -1. / windowsNum,
0393                                         4,
0394                                         19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0395                                         -0.5,
0396                                         18.5);
0397 
0398   {               // bin labelling (for clarity)
0399     int idx = 2;  // start counting at 1, first bin is empty
0400     for (int pl = 0; pl < 4; ++pl)
0401       for (unsigned int oot = 0; oot < windowsNum; ++oot) {
0402         const std::string bin_label =
0403             (oot == 0 ? "Plane " + std::to_string(pl) + ", " : "") + "OOT" + std::to_string(oot);
0404         hitDistribution2dOOT->setBinLabel(idx, bin_label);
0405         if (plotOnline)
0406           hitDistribution2dOOT_le->setBinLabel(idx, bin_label);
0407         ++idx;
0408       }
0409   }
0410 
0411   recHitTime = ibooker.book1D("recHit time", title + " recHit time; t (ns)", 500, -25, 25);
0412 
0413   activePlanes =
0414       ibooker.book1D("active planes", title + " active planes (per event);number of active planes", 6, -0.5, 5.5);
0415 
0416   trackDistribution =
0417       ibooker.book1D("tracks", title + " tracks;x (mm)", 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, -0.5, 18.5);
0418   trackDistributionOOT = ibooker.book2D("tracks with OOT",
0419                                         title + " tracks with OOT;plane number;x (mm)",
0420                                         9,
0421                                         -0.5,
0422                                         4,
0423                                         19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0424                                         -0.5,
0425                                         18.5);
0426 
0427   leadingEdgeCumulative_both = ibooker.book1D("leading edge (le and te)",
0428                                               title + " leading edge (le and te) (recHits); leading edge (ns)",
0429                                               25 * windowsNum,
0430                                               0,
0431                                               25 * windowsNum);
0432   leadingEdgeCumulative_all = ibooker.book1D("leading edge (all)",
0433                                              title + " leading edge (with or without te) (DIGIs); leading edge (ns)",
0434                                              25 * windowsNum,
0435                                              0,
0436                                              25 * windowsNum);
0437   leadingEdgeCumulative_le = ibooker.book1D("leading edge (le only)",
0438                                             title + " leading edge (le only) (DIGIs); leading edge (ns)",
0439                                             25 * windowsNum,
0440                                             0,
0441                                             25 * windowsNum);
0442   trailingEdgeCumulative_te = ibooker.book1D("trailing edge (te only)",
0443                                              title + " trailing edge (te only) (DIGIs); trailing edge (ns)",
0444                                              25 * windowsNum,
0445                                              0,
0446                                              25 * windowsNum);
0447   timeOverThresholdCumulativePot =
0448       ibooker.book1D("time over threshold", title + " time over threshold;time over threshold (ns)", 250, -25, 100);
0449   // leadingTrailingCorrelationPot =
0450   //     ibooker.book2D("leading trailing correlation",
0451   //                    title + " leading trailing correlation;leading edge (ns);trailing edge (ns)",
0452   //                    75,
0453   //                    0,
0454   //                    75,
0455   //                    75,
0456   //                    0,
0457   //                    75);
0458 
0459   leadingWithoutTrailingCumulativePot =
0460       ibooker.book1D("event category", title + " leading edges without trailing;;%", 3, 0.5, 3.5);
0461   leadingWithoutTrailingCumulativePot->setBinLabel(1, "Leading only");
0462   leadingWithoutTrailingCumulativePot->setBinLabel(2, "Trailing only");
0463   leadingWithoutTrailingCumulativePot->setBinLabel(3, "Both");
0464 
0465   HPTDCErrorFlags_2D = ibooker.book2D("HPTDC Errors", title + " HPTDC Errors", 16, -0.5, 16.5, 9, -0.5, 8.5);
0466   for (unsigned short error_index = 1; error_index < 16; ++error_index)
0467     HPTDCErrorFlags_2D->setBinLabel(error_index, HPTDCErrorFlags::hptdcErrorName(error_index - 1));
0468   HPTDCErrorFlags_2D->setBinLabel(16, "Wrong EC");
0469 
0470   int tmpIndex = 0;
0471   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 18", /* axis */ 2);
0472   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 17", /* axis */ 2);
0473   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 16", /* axis */ 2);
0474   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 0 TDC 15", /* axis */ 2);
0475   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 18", /* axis */ 2);
0476   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 17", /* axis */ 2);
0477   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 16", /* axis */ 2);
0478   HPTDCErrorFlags_2D->setBinLabel(++tmpIndex, "DB 1 TDC 15", /* axis */ 2);
0479 
0480   MHComprensive =
0481       ibooker.book2D("MH in channels", title + " MH (%) in channels;plane number;ch number", 10, -0.5, 4.5, 14, -1, 13);
0482 
0483   // ibooker.setCurrentFolder( path+"/clock/" );
0484   // clock_Digi1_le = ibooker.book1D( "clock1 leading edge", title+" clock1;leading edge (ns)", 250, 0, 25 );
0485   // clock_Digi1_te = ibooker.book1D( "clock1 trailing edge", title+" clock1;trailing edge (ns)", 75, 0, 75 );
0486   // clock_Digi3_le = ibooker.book1D( "clock3 leading edge", title+" clock3;leading edge (ns)", 250, 0, 25 );
0487   // clock_Digi3_te = ibooker.book1D( "clock3 trailing edge", title+" clock3;trailing edge (ns)", 75, 0, 75 );
0488 }
0489 
0490 //----------------------------------------------------------------------------------------------------
0491 
0492 CTPPSDiamondDQMSource::PlanePlots::PlanePlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int windowsNum)
0493     : pixelTracksMapWithDiamonds("Pixel track maps for efficiency with coincidence",
0494                                  "Pixel track maps for efficiency with coincidence",
0495                                  25,
0496                                  0,
0497                                  25,
0498                                  16,
0499                                  -8,
0500                                  8) {
0501   std::string path, title;
0502   CTPPSDiamondDetId(id).planeName(path, CTPPSDiamondDetId::nPath);
0503   ibooker.setCurrentFolder(path);
0504 
0505   CTPPSDiamondDetId(id).planeName(title, CTPPSDiamondDetId::nFull);
0506 
0507   digiProfileCumulativePerPlane = ibooker.book1D("digi profile",
0508                                                  title + " digi profile; ch number",
0509                                                  CTPPS_DIAMOND_NUM_OF_CHANNELS,
0510                                                  -0.5,
0511                                                  CTPPS_DIAMOND_NUM_OF_CHANNELS - 0.5);
0512   hitProfile = ibooker.book1D(
0513       "hit profile", title + " hit profile;x (mm)", 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, -0.5, 18.5);
0514   hit_multiplicity = ibooker.book1D("channels per plane", title + " channels per plane; ch per plane", 13, -0.5, 12.5);
0515 
0516   leadingEdgeCumulativePerPlane_both = ibooker.book1D("leading edge (le and te)",
0517                                                       title + " leading edge (le and te) (recHits); leading edge (ns)",
0518                                                       25 * windowsNum,
0519                                                       0,
0520                                                       25 * windowsNum);
0521   leadingEdgeCumulativePerPlane_le = ibooker.book1D("leading edge (le only)",
0522                                                     title + " leading edge (le only) (DIGIs); leading edge (ns)",
0523                                                     25 * windowsNum,
0524                                                     0,
0525                                                     25 * windowsNum);
0526   trailingEdgeCumulativePerPlane_te = ibooker.book1D("trailing edge (te only)",
0527                                                      title + " trailing edge (te only) (DIGIs); trailing edge (ns)",
0528                                                      25 * windowsNum,
0529                                                      0,
0530                                                      25 * windowsNum);
0531   TimeOverThresholdCumulativePerPlane =
0532       ibooker.book1D("time over threshold", title + " time over threshold;time over threshold (ns)", 75, -25, 50);
0533 
0534   pixelTomography_far = ibooker.book2D("tomography pixel",
0535                                        title + " tomography with pixel;x + 25 OOT (mm);y (mm)",
0536                                        25 * windowsNum,
0537                                        0,
0538                                        25 * windowsNum,
0539                                        16,
0540                                        -8,
0541                                        8);
0542   EfficiencyWRTPixelsInPlane =
0543       ibooker.book2D("Efficiency wrt pixels", title + " Efficiency wrt pixels;x (mm);y (mm)", 25, 0, 25, 16, -8, 8);
0544 }
0545 
0546 //----------------------------------------------------------------------------------------------------
0547 
0548 CTPPSDiamondDQMSource::ChannelPlots::ChannelPlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int windowsNum)
0549     : HitCounter(0), MHCounter(0), LeadingOnlyCounter(0), TrailingOnlyCounter(0), CompleteCounter(0) {
0550   std::string path, title;
0551   CTPPSDiamondDetId(id).channelName(path, CTPPSDiamondDetId::nPath);
0552   ibooker.setCurrentFolder(path);
0553 
0554   CTPPSDiamondDetId(id).channelName(title, CTPPSDiamondDetId::nFull);
0555 
0556   leadingWithoutTrailing = ibooker.book1D("event category", title + " Event Category;;%", 3, 0.5, 3.5);
0557   leadingWithoutTrailing->setBinLabel(1, "Leading only");
0558   leadingWithoutTrailing->setBinLabel(2, "Trailing only");
0559   leadingWithoutTrailing->setBinLabel(3, "Full");
0560 
0561   for (unsigned int i = 0; i < windowsNum; i++) {
0562     std::string window = std::to_string(i * 25) + "-" + std::to_string((i + 1) * 25);
0563     activity_per_bx[i] = ibooker.book1D(
0564         "activity per BX " + window, title + " Activity per BX " + window + " ns;Event.BX", 3600, -1.5, 3598. + 0.5);
0565   }
0566 
0567   HPTDCErrorFlags = ibooker.book1D("hptdc_Errors", title + " HPTDC Errors", 16, -0.5, 16.5);
0568   for (unsigned short error_index = 1; error_index < 16; ++error_index)
0569     HPTDCErrorFlags->setBinLabel(error_index, HPTDCErrorFlags::hptdcErrorName(error_index - 1));
0570   HPTDCErrorFlags->setBinLabel(16, "MH  (%)");
0571 
0572   leadingEdgeCumulative_both = ibooker.book1D("leading edge (le and te)",
0573                                               title + " leading edge (le and te) (recHits); leading edge (ns)",
0574                                               25 * windowsNum,
0575                                               0,
0576                                               25 * windowsNum);
0577   leadingEdgeCumulative_le = ibooker.book1D("leading edge (le only)",
0578                                             title + " leading edge (le only) (DIGIs); leading edge (ns)",
0579                                             25 * windowsNum,
0580                                             0,
0581                                             25 * windowsNum);
0582   trailingEdgeCumulative_te = ibooker.book1D("trailing edge (te only)",
0583                                              title + " trailing edge (te only) (DIGIs); trailing edge (ns)",
0584                                              25 * windowsNum,
0585                                              0,
0586                                              25 * windowsNum);
0587   TimeOverThresholdCumulativePerChannel =
0588       ibooker.book1D("time over threshold", title + " time over threshold;time over threshold (ns)", 75, -25, 50);
0589   // LeadingTrailingCorrelationPerChannel =
0590   //     ibooker.book2D("leading trailing correlation",
0591   //                    title + " leading trailing correlation;leading edge (ns);trailing edge (ns)",
0592   //                    75,
0593   //                    0,
0594   //                    75,
0595   //                    75,
0596   //                    0,
0597   //                    75);
0598 
0599   pixelTomography_far = ibooker.book2D("tomography pixel",
0600                                        "tomography with pixel;x + 25 OOT (mm);y (mm)",
0601                                        25 * windowsNum,
0602                                        0,
0603                                        25 * windowsNum,
0604                                        16,
0605                                        -8,
0606                                        8);
0607 
0608   hit_rate = ibooker.book1D("hit rate", title + "hit rate;rate (Hz)", 40, 0, 20);
0609 
0610   recHitTime = ibooker.book1D("recHit Time", title + " recHit Time; t (ns)", 500, -25, 25);
0611 }
0612 
0613 //----------------------------------------------------------------------------------------------------
0614 
0615 CTPPSDiamondDQMSource::CTPPSDiamondDQMSource(const edm::ParameterSet& ps)
0616     : perLSsaving_(ps.getUntrackedParameter<bool>("perLSsaving", false)),
0617       tokenPixelTrack_(consumes<edm::DetSetVector<CTPPSPixelLocalTrack>>(
0618           ps.getUntrackedParameter<edm::InputTag>("tagPixelLocalTracks"))),
0619       tokenDiamondHit_(consumes<edm::DetSetVector<CTPPSDiamondRecHit>>(
0620           ps.getUntrackedParameter<edm::InputTag>("tagDiamondRecHits"))),
0621       tokenDiamondTrack_(consumes<edm::DetSetVector<CTPPSDiamondLocalTrack>>(
0622           ps.getUntrackedParameter<edm::InputTag>("tagDiamondLocalTracks"))),
0623       ctppsGeometryRunToken_(esConsumes<CTPPSGeometry, VeryForwardRealGeometryRecord, edm::Transition::BeginRun>()),
0624       ctppsGeometryEventToken_(esConsumes<CTPPSGeometry, VeryForwardRealGeometryRecord>()),
0625       excludeMultipleHits_(ps.getParameter<bool>("excludeMultipleHits")),
0626       extract_digi_info_(ps.getParameter<bool>("extractDigiInfo")),
0627       centralOOT_(-999),
0628       verbosity_(ps.getUntrackedParameter<unsigned int>("verbosity", 0)),
0629       plotOnline_(ps.getUntrackedParameter<bool>("plotOnline", true)),
0630       plotOffline_(ps.getUntrackedParameter<bool>("plotOffline", false)),
0631       windowsNum_(ps.getUntrackedParameter<unsigned int>("windowsNum", 3)),
0632       trackCorrelationThreshold_(ps.getUntrackedParameter<unsigned int>("trackCorrelationThreshold", 3)),
0633       EC_difference_56_(-500),
0634       EC_difference_45_(-500) {
0635   if (extract_digi_info_) {
0636     tokenStatus_ = consumes<edm::DetSetVector<TotemVFATStatus>>(ps.getUntrackedParameter<edm::InputTag>("tagStatus"));
0637     tokenFEDInfo_ = consumes<std::vector<TotemFEDInfo>>(ps.getUntrackedParameter<edm::InputTag>("tagFEDInfo"));
0638     tokenDigi_ = consumes<edm::DetSetVector<CTPPSDiamondDigi>>(ps.getUntrackedParameter<edm::InputTag>("tagDigi"));
0639   }
0640   for (const auto& pset : ps.getParameter<std::vector<edm::ParameterSet>>("offsetsOOT")) {
0641     runParameters_.emplace_back(
0642         std::make_pair(pset.getParameter<edm::EventRange>("validityRange"), pset.getParameter<int>("centralOOT")));
0643   }
0644 }
0645 
0646 //----------------------------------------------------------------------------------------------------
0647 
0648 void CTPPSDiamondDQMSource::dqmBeginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
0649   centralOOT_ = -999;
0650   for (const auto& oot : runParameters_) {
0651     if (edm::contains(oot.first, edm::EventID(iRun.run(), 0, 1))) {
0652       centralOOT_ = oot.second;
0653       break;
0654     }
0655   }
0656 
0657   // Get detector shifts from the geometry
0658   const CTPPSGeometry& geom = iSetup.getData(ctppsGeometryRunToken_);
0659   for (auto it = geom.beginRP(); it != geom.endRP(); ++it)
0660     if (CTPPSDiamondDetId::check(it->first)) {
0661       const CTPPSDiamondDetId diam_id(it->first);
0662       const auto diam = geom.sensor(it->first);
0663       diamShifts_[diam_id].global = diam->translation().x() - diam->getDiamondDimensions().xHalfWidth;
0664       if (iRun.run() > FIRST_RUN_W_PIXELS) {  // pixel installed
0665         const CTPPSPixelDetId pixid(diam_id.arm(), CTPPS_PIXEL_STATION_ID, CTPPS_PIXEL_FAR_RP_ID);
0666         auto pix = geom.sensor(pixid);
0667         // Rough alignement of pixel detector for diamond tomography
0668         diamShifts_[diam_id].withPixels =
0669             pix->translation().x() - pix->getDiamondDimensions().xHalfWidth - diamShifts_[diam_id].global - 1.;
0670       }
0671     }
0672 }
0673 
0674 //----------------------------------------------------------------------------------------------------
0675 
0676 void CTPPSDiamondDQMSource::bookHistograms(DQMStore::IBooker& ibooker, const edm::Run&, const edm::EventSetup& iSetup) {
0677   ibooker.cd();
0678   ibooker.setCurrentFolder("CTPPS");
0679 
0680   globalPlot_ = GlobalPlots(ibooker);
0681 
0682   // book plots from the geometry
0683   const CTPPSGeometry& geom = iSetup.getData(ctppsGeometryRunToken_);
0684   for (auto it = geom.beginSensor(); it != geom.endSensor(); ++it) {
0685     if (!CTPPSDiamondDetId::check(it->first))
0686       continue;
0687     // per-channel plots
0688     const CTPPSDiamondDetId chId(it->first);
0689     if (plotOnline_ && channelPlots_.count(chId) == 0)
0690       channelPlots_[chId] = ChannelPlots(ibooker, chId, windowsNum_);
0691 
0692     // per-plane plots
0693     const CTPPSDiamondDetId plId(chId.planeId());
0694     if (planePlots_.count(plId) == 0)
0695       planePlots_[plId] = PlanePlots(ibooker, plId, windowsNum_);
0696     // per-pot plots
0697     const CTPPSDiamondDetId rpId(chId.rpId());
0698     if (potPlots_.count(rpId) == 0)
0699       potPlots_[rpId] = PotPlots(ibooker, rpId, windowsNum_, plotOnline_, plotOffline_, perLSsaving_);
0700 
0701     // per-sector plots
0702     const CTPPSDiamondDetId secId(chId.armId());
0703     if (plotOffline_ && sectorPlots_.count(secId) == 0)
0704       sectorPlots_[secId] = SectorPlots(ibooker, secId, plotOnline_);
0705   }
0706 }
0707 
0708 //----------------------------------------------------------------------------------------------------
0709 
0710 std::shared_ptr<dds::Cache> CTPPSDiamondDQMSource::globalBeginLuminosityBlock(const edm::LuminosityBlock&,
0711                                                                               const edm::EventSetup&) const {
0712   auto d = std::make_shared<dds::Cache>();
0713   d->hitDistribution2dMap.reserve(potPlots_.size());
0714   if (!perLSsaving_ && plotOnline_) {
0715     for (auto& plot : potPlots_) {
0716       d->hitDistribution2dMap[plot.first] = std::make_unique<TH2F>(
0717           "hits in planes lumisection",
0718           (std::string(plot.second.hitDistribution2d_lumisection->getTH2F()->GetTitle()) + ";plane number;x (mm)")
0719               .c_str(),
0720           10,
0721           -0.5,
0722           4.5,
0723           19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0724           -0.5,
0725           18.5);
0726     }
0727   }
0728   return d;
0729 }
0730 
0731 //----------------------------------------------------------------------------------------------------
0732 
0733 void CTPPSDiamondDQMSource::analyze(const edm::Event& event, const edm::EventSetup& iSetup) {
0734   // get event data
0735 
0736   edm::Handle<edm::DetSetVector<TotemVFATStatus>> diamondVFATStatus;
0737   edm::Handle<edm::DetSetVector<CTPPSDiamondDigi>> diamondDigis;
0738   edm::Handle<std::vector<TotemFEDInfo>> fedInfo;
0739   if (extract_digi_info_) {
0740     event.getByToken(tokenStatus_, diamondVFATStatus);
0741     event.getByToken(tokenDigi_, diamondDigis);
0742     event.getByToken(tokenFEDInfo_, fedInfo);
0743   }
0744 
0745   edm::Handle<edm::DetSetVector<CTPPSPixelLocalTrack>> pixelTracks;
0746   event.getByToken(tokenPixelTrack_, pixelTracks);
0747 
0748   edm::Handle<edm::DetSetVector<CTPPSDiamondRecHit>> diamondRecHits;
0749   event.getByToken(tokenDiamondHit_, diamondRecHits);
0750 
0751   edm::Handle<edm::DetSetVector<CTPPSDiamondLocalTrack>> diamondLocalTracks;
0752   event.getByToken(tokenDiamondTrack_, diamondLocalTracks);
0753 
0754   const CTPPSGeometry* ctppsGeometry = &iSetup.getData(ctppsGeometryEventToken_);
0755 
0756   // check validity
0757   bool valid = true;
0758   if (extract_digi_info_) {  // drop DIGI-level validity checks if not monitored
0759     valid &= diamondVFATStatus.isValid();
0760     valid &= diamondDigis.isValid();
0761     valid &= fedInfo.isValid();
0762   }
0763   valid &= pixelTracks.isValid();
0764   valid &= diamondRecHits.isValid();
0765   valid &= diamondLocalTracks.isValid();
0766 
0767   if (!valid) {
0768     if (verbosity_)
0769       edm::LogProblem("CTPPSDiamondDQMSource")
0770           << "ERROR in CTPPSDiamondDQMSource::analyze > some of the required inputs are not valid. Skipping this "
0771              "event.\n"
0772           << "  DIGI-level: (checked? " << std::boolalpha << extract_digi_info_ << ")\n"
0773           << "    diamondVFATStatus.isValid = " << diamondVFATStatus.isValid() << "\n"
0774           << "    diamondDigis.isValid = " << diamondDigis.isValid() << "\n"
0775           << "    fedInfo.isValid = " << fedInfo.isValid() << "\n"
0776           << "  RECO-level:\n"
0777           << "    pixelTracks.isValid = " << pixelTracks.isValid() << "\n"
0778           << "    diamondRecHits.isValid = " << diamondRecHits.isValid() << "\n"
0779           << "    diamondLocalTracks.isValid = " << diamondLocalTracks.isValid();
0780     return;
0781   }
0782 
0783   //------------------------------
0784   // Sector Plots
0785   //------------------------------
0786   // Using CTPPSDiamondLocalTrack
0787   if (plotOffline_)
0788 
0789     // diamond timing detectors are located in:
0790     //   - 220cyl: "cylindrical pot" station  (id=1), in horizontal Roman Pot with id=6 ("far")
0791     //   - 220nr_hr: "220m"  station (id=2), in horizontal Roman Pot with id=2 ("near horizontal")
0792 
0793     for (const auto& tracks_220nr_hr : *diamondLocalTracks) {
0794       // to preprare correlation plot, we need to select tracks from nr_hr pot in 220m station
0795       const CTPPSDiamondDetId detId_220nr_hr(tracks_220nr_hr.detId());
0796 
0797       // selecting only tracks from 220nr station, realised as skipping tracks from 220cyl station
0798       if ((detId_220nr_hr.rp() == CTPPS_DIAMOND_CYL_RP_ID) &&
0799           (detId_220nr_hr.station() == CTPPS_DIAMOND_CYL_STATION_ID))
0800         continue;
0801 
0802       if (potPlots_.count(detId_220nr_hr.rpId()) == 0)
0803         continue;
0804       TH1F* trackHistoInTimeTmp = potPlots_[detId_220nr_hr.rpId()].trackDistribution->getTH1F();
0805 
0806       for (const auto& track_220nr_hr : tracks_220nr_hr) {
0807         if (!track_220nr_hr.isValid())
0808           continue;
0809 
0810         // get the bins from per-pot plots
0811         int startBin_220nr_hr = trackHistoInTimeTmp->FindBin(
0812             track_220nr_hr.x0() - diamShifts_[detId_220nr_hr.rpId()].global - track_220nr_hr.x0Sigma());
0813         int numOfBins_220nr_hr = 2 * track_220nr_hr.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0814 
0815         for (const auto& tracks_220cyl : *diamondLocalTracks) {
0816           CTPPSDiamondDetId detId_220cyl(tracks_220cyl.detId());
0817 
0818           // select tracks in the same arm, but belonging to the cylindrical pot
0819           // that means skipping tracks from the opposite arm (skip if 220nr_hr.arm != 220cyl.arm)
0820           // and skipping tracks from the 220nr_hr pot  (skip if 220nr_hr == 220cyl.station)
0821           if (detId_220nr_hr.arm() != detId_220cyl.arm() || detId_220nr_hr.station() == detId_220cyl.station())
0822             continue;
0823 
0824           if (sectorPlots_.count(detId_220cyl.armId()) == 0)
0825             continue;
0826 
0827           TH2F* trackHistoTmp = sectorPlots_[detId_220cyl.armId()].trackCorrelation->getTH2F();
0828           TAxis* trackHistoTmpXAxis = trackHistoTmp->GetXaxis();
0829           TAxis* trackHistoTmpYAxis = trackHistoTmp->GetYaxis();
0830 
0831           for (const auto& track_220cyl : tracks_220cyl) {
0832             if (!track_220cyl.isValid())
0833               continue;
0834             int startBin_220cyl = trackHistoTmpYAxis->FindBin(
0835                 track_220cyl.x0() - diamShifts_[detId_220cyl.rpId()].global - track_220cyl.x0Sigma());
0836             int numOfBins_220cyl = 2 * track_220cyl.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0837 
0838             // fill the correlation plot
0839             for (int i = 0; i < numOfBins_220nr_hr; ++i)
0840               for (int y = 0; y < numOfBins_220cyl; ++y) {
0841                 float track_220nr_hr_x = trackHistoTmpXAxis->GetBinCenter(startBin_220nr_hr + i);
0842                 float track_220cyl_x = trackHistoTmpYAxis->GetBinCenter(startBin_220cyl + y);
0843                 trackHistoTmp->Fill(track_220nr_hr_x, track_220cyl_x);
0844                 // fill low multiplicity histogram
0845                 if (tracks_220nr_hr.size() < 3 && tracks_220cyl.size() < trackCorrelationThreshold_)
0846                   sectorPlots_[detId_220cyl.armId()].trackCorrelationLowMultiplicity->Fill(track_220nr_hr_x,
0847                                                                                            track_220cyl_x);
0848               }
0849           }
0850         }
0851       }
0852     }
0853 
0854   //------------------------------
0855   // RP Plots
0856   //------------------------------
0857 
0858   //------------------------------
0859   // Correlation Plots
0860   //------------------------------
0861 
0862   if (extract_digi_info_) {
0863     // Using CTPPSDiamondDigi
0864     for (const auto& digis : *diamondDigis) {
0865       const CTPPSDiamondDetId detId(digis.detId()), detId_pot(detId.rpId());
0866       for (const auto& digi : digis) {
0867         if (detId.channel() == CHANNEL_OF_VFAT_CLOCK)
0868           continue;
0869         if (potPlots_.count(detId_pot) == 0)
0870           continue;
0871         //Leading without trailing investigation
0872         if (digi.leadingEdge() != 0 || digi.trailingEdge() != 0) {
0873           ++potPlots_[detId_pot].HitCounter;
0874           if (digi.leadingEdge() != 0) {
0875             potPlots_[detId_pot].leadingEdgeCumulative_all->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
0876           }
0877           if (digi.leadingEdge() != 0 && digi.trailingEdge() == 0) {
0878             ++potPlots_[detId_pot].LeadingOnlyCounter;
0879             potPlots_[detId_pot].leadingEdgeCumulative_le->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
0880           }
0881           if (digi.leadingEdge() == 0 && digi.trailingEdge() != 0) {
0882             ++potPlots_[detId_pot].TrailingOnlyCounter;
0883             potPlots_[detId_pot].trailingEdgeCumulative_te->Fill(HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
0884           }
0885           if (digi.leadingEdge() != 0 && digi.trailingEdge() != 0) {
0886             ++potPlots_[detId_pot].CompleteCounter;
0887             // potPlots_[detId_pot].leadingTrailingCorrelationPot->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge(),
0888             //                                                          HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
0889           }
0890         }
0891 
0892         // HPTDC Errors
0893         const HPTDCErrorFlags hptdcErrors = digi.hptdcErrorFlags();
0894         if (detId.channel() == HPTDC_0_CHANNEL ||
0895             detId.channel() == HPTDC_1_CHANNEL) {  // ch6 for HPTDC 0 and ch7 for HPTDC 1
0896           int verticalIndex = 2 * detId.plane() + (detId.channel() - HPTDC_0_CHANNEL);
0897           for (unsigned short hptdcErrorIndex = 1; hptdcErrorIndex < 16; ++hptdcErrorIndex)
0898             if (hptdcErrors.errorId(hptdcErrorIndex - 1))
0899               potPlots_[detId_pot].HPTDCErrorFlags_2D->Fill(hptdcErrorIndex, verticalIndex);
0900         }
0901         if (digi.multipleHit())
0902           ++potPlots_[detId_pot].MHCounter;
0903       }
0904     }
0905   }
0906 
0907   // EC Errors
0908   if (extract_digi_info_) {
0909     for (const auto& vfat_status : *diamondVFATStatus) {
0910       const CTPPSDiamondDetId detId(vfat_status.detId());
0911       for (const auto& status : vfat_status) {
0912         if (!status.isOK())
0913           continue;
0914         if (potPlots_.count(detId.rpId()) == 0)
0915           continue;
0916         if (channelPlots_.count(detId) == 0)
0917           continue;
0918 
0919         // Check Event Number
0920         for (const auto& optorx : *fedInfo) {
0921           if (detId.arm() == 1 && optorx.fedId() == CTPPS_FED_ID_56)
0922             checkEventNumber(detId, optorx, status, potPlots_[detId.rpId()], EC_difference_56_);
0923           else if (detId.arm() == 0 && optorx.fedId() == CTPPS_FED_ID_45)
0924             checkEventNumber(detId, optorx, status, potPlots_[detId.rpId()], EC_difference_45_);
0925         }
0926       }
0927     }
0928   }
0929 
0930   // Using CTPPSDiamondRecHit
0931   std::unordered_map<unsigned int, std::set<unsigned int>> planes;
0932   std::unordered_map<unsigned int, std::set<unsigned int>> planes_inclusive;
0933 
0934   auto lumiCache = luminosityBlockCache(event.getLuminosityBlock().index());
0935   for (const auto& rechits : *diamondRecHits) {
0936     const CTPPSDiamondDetId detId(rechits.detId()), detId_pot(detId.rpId());
0937     const auto& x_shift = diamShifts_.at(detId_pot);
0938 
0939     for (const auto& rechit : rechits) {
0940       planes_inclusive[detId_pot].insert(detId.plane());
0941       if (excludeMultipleHits_ && rechit.multipleHits() > 0)
0942         continue;
0943       if (rechit.toT() != 0 && centralOOT_ != -999 && rechit.ootIndex() == centralOOT_)
0944         planes[detId_pot].insert(detId.plane());
0945 
0946       if (potPlots_.count(detId_pot) == 0)
0947         continue;
0948 
0949       potPlots_[detId_pot].recHitTime->Fill(rechit.time());
0950 
0951       float UFSDShift = 0.0;
0952       if (rechit.yWidth() < 3)
0953         UFSDShift = 0.5;  // Display trick for UFSD that have 2 pixels with same X
0954 
0955       if (rechit.toT() != 0 && centralOOT_ != -999 && rechit.ootIndex() == centralOOT_) {
0956         TH2F* hitHistoTmp = potPlots_[detId_pot].hitDistribution2d->getTH2F();
0957         TAxis* hitHistoTmpYAxis = hitHistoTmp->GetYaxis();
0958         int startBin = hitHistoTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
0959         int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0960         for (int i = 0; i < numOfBins; ++i)
0961           hitHistoTmp->Fill(detId.plane() + UFSDShift, hitHistoTmpYAxis->GetBinCenter(startBin + i));
0962 
0963         if (!perLSsaving_ && plotOnline_) {
0964           hitHistoTmp = lumiCache->hitDistribution2dMap[detId_pot].get();
0965           hitHistoTmpYAxis = hitHistoTmp->GetYaxis();
0966           startBin = hitHistoTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
0967           numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0968           for (int i = 0; i < numOfBins; ++i)
0969             hitHistoTmp->Fill(detId.plane() + UFSDShift, hitHistoTmpYAxis->GetBinCenter(startBin + i));
0970         }
0971       }
0972 
0973       if (rechit.toT() > 0) {
0974         // Both
0975         potPlots_[detId_pot].leadingEdgeCumulative_both->Fill(rechit.time() + 25 * rechit.ootIndex());
0976         potPlots_[detId_pot].timeOverThresholdCumulativePot->Fill(rechit.toT());
0977 
0978         TH2F* hitHistoOOTTmp = potPlots_[detId_pot].hitDistribution2dOOT->getTH2F();
0979         TAxis* hitHistoOOTTmpYAxis = hitHistoOOTTmp->GetYaxis();
0980         int startBin = hitHistoOOTTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
0981         int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0982         for (int i = 0; i < numOfBins; ++i)
0983           hitHistoOOTTmp->Fill(detId.plane() + 1. / windowsNum_ * rechit.ootIndex(),
0984                                hitHistoOOTTmpYAxis->GetBinCenter(startBin + i));
0985 
0986       } else if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING && plotOnline_) {
0987         // Only leading
0988         TH2F* hitHistoOOTTmp = potPlots_[detId_pot].hitDistribution2dOOT_le->getTH2F();
0989         TAxis* hitHistoOOTTmpYAxis = hitHistoOOTTmp->GetYaxis();
0990         int startBin = hitHistoOOTTmpYAxis->FindBin(rechit.x() - x_shift.global - 0.5 * rechit.xWidth());
0991         int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0992         for (int i = 0; i < numOfBins; ++i)
0993           hitHistoOOTTmp->Fill(detId.plane() + 1. / windowsNum_ * rechit.ootIndex(),
0994                                hitHistoOOTTmpYAxis->GetBinCenter(startBin + i));
0995       }
0996       if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING &&
0997           potPlots_[detId_pot].activity_per_bx.count(rechit.ootIndex()) > 0)
0998         potPlots_[detId_pot].activity_per_bx.at(rechit.ootIndex())->Fill(event.bunchCrossing());
0999 
1000       // if(plotOffline_)
1001       //   potPlots_[detId_pot].TOTVsLS->Fill(event.luminosityBlock(),rechit.toT());
1002     }
1003   }
1004 
1005   for (const auto& plt : potPlots_) {
1006     plt.second.activePlanes->Fill(planes[plt.first].size());
1007     if (plotOnline_)
1008       plt.second.activePlanesInclusive->Fill(planes_inclusive[plt.first].size());
1009   }
1010 
1011   // Using CTPPSDiamondLocalTrack
1012   for (const auto& tracks : *diamondLocalTracks) {
1013     const CTPPSDiamondDetId detId(tracks.detId()), detId_pot(detId.rpId());
1014     const auto& x_shift = diamShifts_.at(detId_pot);
1015 
1016     for (const auto& track : tracks) {
1017       if (!track.isValid())
1018         continue;
1019       if (track.ootIndex() == CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING)
1020         continue;
1021       if (excludeMultipleHits_ && track.multipleHits() > 0)
1022         continue;
1023       if (potPlots_.count(detId_pot) == 0)
1024         continue;
1025 
1026       TH2F* trackHistoOOTTmp = potPlots_[detId_pot].trackDistributionOOT->getTH2F();
1027       TAxis* trackHistoOOTTmpYAxis = trackHistoOOTTmp->GetYaxis();
1028       int startBin = trackHistoOOTTmpYAxis->FindBin(track.x0() - x_shift.global - track.x0Sigma());
1029       int numOfBins = 2 * track.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
1030       for (int i = 0; i < numOfBins; ++i)
1031         trackHistoOOTTmp->Fill(track.ootIndex(), trackHistoOOTTmpYAxis->GetBinCenter(startBin + i));
1032 
1033       if (centralOOT_ != -999 && track.ootIndex() == centralOOT_) {
1034         TH1F* trackHistoInTimeTmp = potPlots_[detId_pot].trackDistribution->getTH1F();
1035         int startBin = trackHistoInTimeTmp->FindBin(track.x0() - x_shift.global - track.x0Sigma());
1036         int numOfBins = 2 * track.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
1037         for (int i = 0; i < numOfBins; ++i)
1038           trackHistoInTimeTmp->Fill(trackHistoInTimeTmp->GetBinCenter(startBin + i));
1039       }
1040       if (plotOffline_ && !perLSsaving_) {
1041         // potPlots_[detId_pot].trackTimeVsLS->Fill(event.luminosityBlock(),track.time());
1042         potPlots_[detId_pot].trackTimeVsBX->Fill(event.bunchCrossing(), track.time());
1043       }
1044     }
1045   }
1046 
1047   // Channel efficiency using CTPPSDiamondLocalTrack
1048   for (const auto& tracks : *diamondLocalTracks) {
1049     const CTPPSDiamondDetId detId(tracks.detId()), detId_pot(detId.rpId());
1050     for (const auto& track : tracks) {
1051       // Find hits and planes in the track
1052       int numOfHits = 0;
1053       std::set<int> planesInTrackSet;
1054       for (const auto& vec : *diamondRecHits) {
1055         const CTPPSDiamondDetId detid(vec.detId());
1056         if (detid.arm() != detId_pot.arm())
1057           continue;
1058 
1059         for (const auto& hit : vec) {
1060           // first check if the hit contributes to the track
1061           if (track.containsHit(hit)) {
1062             ++numOfHits;
1063             planesInTrackSet.insert(detid.plane());
1064           }
1065         }
1066       }
1067 
1068       if (numOfHits > 0 && numOfHits <= 10 && planesInTrackSet.size() > 2) {
1069         for (const auto& plt_vs_ch : channelPlots_) {  // loop over all channels registered in geometry
1070           const CTPPSDiamondDetId detId(plt_vs_ch.first);
1071           if (detId.rpId() != detId_pot)
1072             continue;
1073           const unsigned short map_index = detId.plane() * 100 + detId.channel();
1074           if (potPlots_[detId_pot].effDoublecountingChMap.count(map_index) == 0) {
1075             potPlots_[detId_pot].effTriplecountingChMap[map_index] = 0;
1076             potPlots_[detId_pot].effDoublecountingChMap[map_index] = 0;
1077           }
1078           if (channelAlignedWithTrack(ctppsGeometry, detId, track, 0.2)) {
1079             // Channel should fire
1080             ++potPlots_[detId_pot].effDoublecountingChMap[map_index];
1081             for (const auto& rechits : *diamondRecHits) {
1082               const CTPPSDiamondDetId detId_hit(rechits.detId());
1083               if (detId_hit == detId)
1084                 for (const auto& rechit : rechits)
1085                   if (track.containsHit(rechit, 1))  // Channel fired
1086                     ++potPlots_[detId_pot].effTriplecountingChMap[map_index];
1087             }
1088           }
1089         }
1090       }
1091     }
1092   }
1093 
1094   // Tomography of diamonds using pixel
1095   for (const auto& rechits : *diamondRecHits) {
1096     const CTPPSDiamondDetId detId(rechits.detId()), detId_pot(detId.rpId());
1097     const auto pix_shift = diamShifts_.at(detId_pot).withPixels;
1098     for (const auto& rechit : rechits) {
1099       if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1100         continue;
1101       if (rechit.toT() == 0)
1102         continue;
1103       if (!pixelTracks.isValid())
1104         continue;
1105       if (potPlots_.count(detId_pot) == 0)
1106         continue;
1107 
1108       for (const auto& ds : *pixelTracks) {
1109         if (ds.size() > 1)
1110           continue;
1111         const CTPPSPixelDetId pixId(ds.detId());
1112         if (pixId.station() != CTPPS_PIXEL_STATION_ID || pixId.rp() != CTPPS_PIXEL_FAR_RP_ID)
1113           continue;
1114         for (const auto& lt : ds) {
1115           if (lt.isValid() && pixId.arm() == detId_pot.arm()) {
1116             if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING && rechit.ootIndex() >= 0 &&
1117                 potPlots_[detId_pot].pixelTomographyAll.count(rechit.ootIndex()) > 0 && lt.x0() - pix_shift < 24)
1118               potPlots_[detId_pot]
1119                   .pixelTomographyAll.at(rechit.ootIndex())
1120                   ->Fill(lt.x0() - pix_shift + 25 * detId.plane(), lt.y0());
1121           }
1122         }
1123       }
1124     }
1125   }
1126 
1127   //------------------------------
1128   // Clock Plots
1129   //------------------------------
1130   // Commented out to save space in the DQM files, but code should be kept
1131   // for ( const auto& digis : *diamondDigis ) {
1132   //   const CTPPSDiamondDetId detId(digis.detId()), detId_pot(detId.rpId());
1133   //   if ( detId.channel() == CHANNEL_OF_VFAT_CLOCK ) {
1134   //     for ( const auto& digi : digis ) {
1135   //       if ( digi.leadingEdge() != 0 )  {
1136   //         if ( detId.plane() == 1 ) {
1137   //           potPlots_[detId_pot].clock_Digi1_le->Fill( HPTDC_BIN_WIDTH_NS * digi.leadingEdge() );
1138   //           potPlots_[detId_pot].clock_Digi1_te->Fill( HPTDC_BIN_WIDTH_NS * digi.trailingEdge() );
1139   //         }
1140   //         if ( detId.plane() == 3 ) {
1141   //           potPlots_[detId_pot].clock_Digi3_le->Fill( HPTDC_BIN_WIDTH_NS * digi.leadingEdge() );
1142   //           potPlots_[detId_pot].clock_Digi3_te->Fill( HPTDC_BIN_WIDTH_NS * digi.trailingEdge() );
1143   //         }
1144   //       }
1145   //     }
1146   //   }
1147   // }
1148 
1149   //------------------------------
1150   // Plane Plots
1151   //------------------------------
1152 
1153   // Using CTPPSDiamondDigi
1154   std::unordered_map<unsigned int, unsigned int> channelsPerPlane;
1155   if (extract_digi_info_) {
1156     for (const auto& digis : *diamondDigis) {
1157       const CTPPSDiamondDetId detId(digis.detId()), detId_plane(detId.planeId());
1158       for (const auto& digi : digis) {
1159         if (detId.channel() == CHANNEL_OF_VFAT_CLOCK)
1160           continue;
1161         if (planePlots_.count(detId_plane) == 0)
1162           continue;
1163 
1164         if (digi.leadingEdge() != 0) {
1165           planePlots_[detId_plane].digiProfileCumulativePerPlane->Fill(detId.channel());
1166           channelsPerPlane[detId_plane]++;
1167         }
1168 
1169         // Check dropped trailing edges
1170         if ((digi.trailingEdge() == 0) && (digi.leadingEdge() != 0)) {
1171           planePlots_[detId_plane].leadingEdgeCumulativePerPlane_le->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
1172         } else if ((digi.leadingEdge() == 0 && (digi.trailingEdge() != 0))) {  // check dropped leading edges
1173           planePlots_[detId_plane].trailingEdgeCumulativePerPlane_te->Fill(HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
1174         }
1175       }
1176     }
1177   }
1178 
1179   for (const auto& plt : channelsPerPlane)
1180     planePlots_[plt.first].hit_multiplicity->Fill(plt.second);
1181 
1182   // Using CTPPSDiamondRecHit
1183   for (const auto& rechits : *diamondRecHits) {
1184     const CTPPSDiamondDetId detId(rechits.detId()), detId_plane(detId.planeId()), detId_pot(detId.rpId());
1185     for (const auto& rechit : rechits) {
1186       if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1187         continue;
1188       if (rechit.toT() == 0)
1189         continue;
1190 
1191       if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING) {
1192         planePlots_[detId_plane].leadingEdgeCumulativePerPlane_both->Fill(rechit.time() + 25 * rechit.ootIndex());
1193         planePlots_[detId_plane].TimeOverThresholdCumulativePerPlane->Fill(rechit.toT());
1194       }
1195       if (planePlots_.count(detId_plane) != 0) {
1196         if (centralOOT_ != -999 && rechit.ootIndex() == centralOOT_) {
1197           TH1F* hitHistoTmp = planePlots_[detId_plane].hitProfile->getTH1F();
1198           int startBin = hitHistoTmp->FindBin(rechit.x() - diamShifts_.at(detId_pot).global - 0.5 * rechit.xWidth());
1199           int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
1200           for (int i = 0; i < numOfBins; ++i)
1201             hitHistoTmp->Fill(hitHistoTmp->GetBinCenter(startBin + i));
1202         }
1203       }
1204     }
1205   }
1206 
1207   //Tomography of diamonds using pixel and Efficiency WRT Pixels
1208   for (const auto& ds : *pixelTracks) {
1209     const CTPPSPixelDetId pixId(ds.detId());
1210     if (pixId.station() != CTPPS_PIXEL_STATION_ID || pixId.rp() != CTPPS_PIXEL_FAR_RP_ID)
1211       continue;
1212     if (ds.size() > 1)
1213       continue;
1214     for (const auto& lt : ds) {
1215       if (lt.isValid()) {
1216         for (const auto& sh_vs_id : diamShifts_) {
1217           const CTPPSDiamondDetId& detId_pot = sh_vs_id.first;
1218           const auto& shift = sh_vs_id.second;
1219           if (detId_pot.arm() == pixId.arm())
1220             // For efficieny
1221             potPlots_[detId_pot].pixelTracksMap.Fill(lt.x0() - shift.withPixels, lt.y0());
1222         }
1223 
1224         std::set<CTPPSDiamondDetId> planesWitHits_set;
1225         for (const auto& rechits : *diamondRecHits) {
1226           const CTPPSDiamondDetId detId(rechits.detId()), detId_plane(detId.planeId()), detId_pot(detId.rpId());
1227           const auto pix_shift = diamShifts_.at(detId_pot).withPixels;
1228           for (const auto& rechit : rechits) {
1229             if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1230               continue;
1231             if (rechit.ootIndex() == CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING || rechit.toT() == 0)
1232               continue;
1233             if (planePlots_.count(detId_plane) == 0)
1234               continue;
1235             if (pixId.arm() == detId_plane.arm() && lt.x0() - pix_shift < 24) {
1236               planePlots_[detId_plane].pixelTomography_far->Fill(lt.x0() - pix_shift + 25 * rechit.ootIndex(), lt.y0());
1237               if (centralOOT_ != -999 && rechit.ootIndex() == centralOOT_)
1238                 planesWitHits_set.insert(detId_plane);
1239             }
1240           }
1241         }
1242 
1243         for (auto& planeId : planesWitHits_set)
1244           planePlots_[planeId].pixelTracksMapWithDiamonds.Fill(lt.x0() - diamShifts_.at(planeId.rpId()).withPixels,
1245                                                                lt.y0());
1246       }
1247     }
1248   }
1249 
1250   //------------------------------
1251   // Channel Plots
1252   //------------------------------
1253 
1254   // digi profile cumulative
1255   if (extract_digi_info_) {
1256     for (const auto& digis : *diamondDigis) {
1257       const CTPPSDiamondDetId detId(digis.detId());
1258       for (const auto& digi : digis) {
1259         if (detId.channel() == CHANNEL_OF_VFAT_CLOCK)
1260           continue;
1261         if (channelPlots_.count(detId) != 0) {
1262           // HPTDC Errors
1263           const HPTDCErrorFlags hptdcErrors = digi.hptdcErrorFlags();
1264           for (unsigned short hptdcErrorIndex = 1; hptdcErrorIndex < 16; ++hptdcErrorIndex)
1265             if (hptdcErrors.errorId(hptdcErrorIndex - 1))
1266               channelPlots_[detId].HPTDCErrorFlags->Fill(hptdcErrorIndex);
1267           if (digi.multipleHit())
1268             ++channelPlots_[detId].MHCounter;
1269 
1270           // Check dropped trailing edges
1271           if (digi.leadingEdge() != 0 || digi.trailingEdge() != 0) {
1272             ++channelPlots_[detId].HitCounter;
1273             if (digi.trailingEdge() == 0) {
1274               ++channelPlots_[detId].LeadingOnlyCounter;
1275               channelPlots_[detId].leadingEdgeCumulative_le->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge());
1276             } else if (digi.leadingEdge() == 0) {
1277               ++channelPlots_[detId].TrailingOnlyCounter;
1278               channelPlots_[detId].trailingEdgeCumulative_te->Fill(HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
1279             } else {
1280               ++channelPlots_[detId].CompleteCounter;
1281               // channelPlots_[detId].LeadingTrailingCorrelationPerChannel->Fill(HPTDC_BIN_WIDTH_NS * digi.leadingEdge(),
1282               //                                                                 HPTDC_BIN_WIDTH_NS * digi.trailingEdge());
1283             }
1284           }
1285         }
1286       }
1287     }
1288   }
1289 
1290   // Using CTPPSDiamondRecHit
1291 
1292   for (const auto& rechits : *diamondRecHits) {
1293     CTPPSDiamondDetId detId(rechits.detId());
1294     for (const auto& rechit : rechits) {
1295       if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1296         continue;
1297       if (channelPlots_.count(detId) != 0) {
1298         channelPlots_[detId].recHitTime->Fill(rechit.time());
1299         if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING && rechit.toT() != 0) {
1300           channelPlots_[detId].leadingEdgeCumulative_both->Fill(rechit.time() + 25 * rechit.ootIndex());
1301           channelPlots_[detId].TimeOverThresholdCumulativePerChannel->Fill(rechit.toT());
1302         }
1303         ++lumiCache->hitsCounterMap[detId];
1304 
1305         if (rechit.ootIndex() != CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING &&
1306             channelPlots_[detId].activity_per_bx.count(rechit.ootIndex()) > 0)
1307           channelPlots_[detId].activity_per_bx.at(rechit.ootIndex())->Fill(event.bunchCrossing());
1308       }
1309     }
1310   }
1311 
1312   // Tomography of diamonds using pixel
1313   for (const auto& rechits : *diamondRecHits) {
1314     const CTPPSDiamondDetId detId(rechits.detId()), detId_pot(detId.rpId());
1315     const auto shift_pix = diamShifts_.at(detId_pot).withPixels;
1316     for (const auto& rechit : rechits) {
1317       if (excludeMultipleHits_ && rechit.multipleHits() > 0)
1318         continue;
1319       if (rechit.ootIndex() == CTPPSDiamondRecHit::TIMESLICE_WITHOUT_LEADING || rechit.toT() == 0)
1320         continue;
1321       if (!pixelTracks.isValid())
1322         continue;
1323       if (channelPlots_.count(detId) == 0)
1324         continue;
1325 
1326       for (const auto& ds : *pixelTracks) {
1327         const CTPPSPixelDetId pixId(ds.detId());
1328         if (pixId.station() != CTPPS_PIXEL_STATION_ID || pixId.rp() != CTPPS_PIXEL_FAR_RP_ID)
1329           continue;
1330         if (ds.size() > 1)
1331           continue;
1332         for (const auto& lt : ds) {
1333           if (lt.isValid() && pixId.arm() == detId.arm() && lt.x0() - shift_pix < 24)
1334             channelPlots_[detId].pixelTomography_far->Fill(lt.x0() - shift_pix + 25 * rechit.ootIndex(), lt.y0());
1335         }
1336       }
1337     }
1338   }
1339 }
1340 
1341 //----------------------------------------------------------------------------------------------------
1342 
1343 void CTPPSDiamondDQMSource::globalEndLuminosityBlock(const edm::LuminosityBlock& iLumi, const edm::EventSetup&) {
1344   auto lumiCache = luminosityBlockCache(iLumi.index());
1345   if (!perLSsaving_) {
1346     if (plotOnline_)
1347       for (auto& plot : potPlots_)
1348         *(plot.second.hitDistribution2d_lumisection->getTH2F()) = *(lumiCache->hitDistribution2dMap[plot.first]);
1349 
1350     for (auto& plot : channelPlots_) {
1351       auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[plot.first];
1352       if (hitsCounterPerLumisection != 0) {
1353         plot.second.hit_rate->Fill((double)hitsCounterPerLumisection / SEC_PER_LUMI_SECTION);
1354       }
1355 
1356       double HundredOverHitCounter = .0;
1357       if (plot.second.HitCounter != 0)
1358         HundredOverHitCounter = 100. / plot.second.HitCounter;
1359       plot.second.HPTDCErrorFlags->setBinContent(16, HundredOverHitCounter * plot.second.MHCounter);
1360       plot.second.leadingWithoutTrailing->setBinContent(1, HundredOverHitCounter * plot.second.LeadingOnlyCounter);
1361       plot.second.leadingWithoutTrailing->setBinContent(2, HundredOverHitCounter * plot.second.TrailingOnlyCounter);
1362       plot.second.leadingWithoutTrailing->setBinContent(3, HundredOverHitCounter * plot.second.CompleteCounter);
1363     }
1364 
1365     for (auto& plot : potPlots_) {
1366       double HundredOverHitCounterPot = 0.;
1367       if (plot.second.HitCounter != 0)
1368         HundredOverHitCounterPot = 100. / plot.second.HitCounter;
1369       plot.second.leadingWithoutTrailingCumulativePot->setBinContent(
1370           1, HundredOverHitCounterPot * plot.second.LeadingOnlyCounter);
1371       plot.second.leadingWithoutTrailingCumulativePot->setBinContent(
1372           2, HundredOverHitCounterPot * plot.second.TrailingOnlyCounter);
1373       plot.second.leadingWithoutTrailingCumulativePot->setBinContent(
1374           3, HundredOverHitCounterPot * plot.second.CompleteCounter);
1375 
1376       plot.second.MHComprensive->Reset();
1377       const CTPPSDiamondDetId rpId(plot.first);
1378       for (auto& chPlot : channelPlots_) {
1379         const CTPPSDiamondDetId chId(chPlot.first);
1380         if (chId.arm() == rpId.arm() && chId.rp() == rpId.rp()) {
1381           plot.second.MHComprensive->Fill(
1382               chId.plane(), chId.channel(), chPlot.second.HPTDCErrorFlags->getBinContent(16));
1383         }
1384       }
1385     }
1386     // Efficiencies of single channels
1387     if (plotOnline_)
1388       for (auto& plot : potPlots_) {
1389         plot.second.EfficiencyOfChannelsInPot->Reset();
1390         for (auto& element : plot.second.effTriplecountingChMap) {
1391           if (plot.second.effDoublecountingChMap[element.first] > 0) {
1392             int plane = element.first / 100;
1393             int channel = element.first % 100;
1394             double counted = element.second;
1395             double total = plot.second.effDoublecountingChMap[element.first];
1396             double efficiency = counted / total;
1397             //         double error = std::sqrt( efficiency * ( 1 - efficiency ) / total );
1398 
1399             plot.second.EfficiencyOfChannelsInPot->Fill(plane, channel, 100 * efficiency);
1400           }
1401         }
1402       }
1403 
1404     // Efficeincy wrt pixels  //TODO
1405     for (auto& plot : planePlots_) {
1406       TH2F* hitHistoTmp = plot.second.EfficiencyWRTPixelsInPlane->getTH2F();
1407 
1408       const CTPPSDiamondDetId detId(plot.first), detId_pot(detId.rpId());
1409       hitHistoTmp->Divide(&(plot.second.pixelTracksMapWithDiamonds), &(potPlots_[detId_pot].pixelTracksMap));
1410     }
1411   }  //perLSsaving
1412 }
1413 
1414 //----------------------------------------------------------------------------------------------------
1415 
1416 void CTPPSDiamondDQMSource::checkEventNumber(const CTPPSDiamondDetId& detId,
1417                                              const TotemFEDInfo& optorx,
1418                                              const TotemVFATStatus& status,
1419                                              CTPPSDiamondDQMSource::PotPlots& plots,
1420                                              int& EC_difference) const {
1421   const CTPPSDiamondDetId detId_pot(detId.rpId());
1422   if (plotOnline_)
1423     plots.ECCheck->Fill((int)((optorx.lv1() & 0xFF) - ((unsigned int)status.ec() & 0xFF)) & 0xFF);
1424   if ((static_cast<int>((optorx.lv1() & 0xFF) - status.ec()) != EC_difference) &&
1425       (static_cast<uint8_t>((optorx.lv1() & 0xFF) - status.ec()) < 128))
1426     EC_difference = static_cast<int>(optorx.lv1() & 0xFF) - (static_cast<unsigned int>(status.ec()) & 0xFF);
1427   if (EC_difference != 1 && EC_difference != -500 && std::abs(EC_difference) < 127) {
1428     if (detId.channel() == HPTDC_0_CHANNEL || detId.channel() == HPTDC_1_CHANNEL)
1429       plots.HPTDCErrorFlags_2D->Fill(16, 2 * detId.plane() + (detId.channel() - HPTDC_0_CHANNEL));
1430     if (verbosity_)
1431       edm::LogProblem("CTPPSDiamondDQMSource")
1432           << "FED " << optorx.fedId() << ": ECError at EV: 0x" << std::hex << optorx.lv1() << "\t\tVFAT EC: 0x"
1433           << static_cast<unsigned int>(status.ec()) << "\twith ID: " << std::dec << detId
1434           << "\tdiff: " << EC_difference;
1435   }
1436 }
1437 
1438 //----------------------------------------------------------------------------------------------------
1439 
1440 void CTPPSDiamondDQMSource::dqmEndRun(edm::Run const&, edm::EventSetup const&) {
1441   if (plotOffline_ && !perLSsaving_)
1442     for (const auto& rpPlots : potPlots_) {
1443       auto plots = rpPlots.second;
1444       // *(plots.TOTVsLSProfile->getTProfile())=*plots.TOTVsLS->getTH2F()->ProfileX();
1445       // *(plots.trackTimeVsLSProfile->getTProfile())=*plots.trackTimeVsLS->getTH2F()->ProfileX();
1446       *(plots.trackTimeVsBXProfile->getTProfile()) = *plots.trackTimeVsBX->getTH2F()->ProfileX();
1447       // *(plots.trackTimeVsXAngleProfile->getTProfile()) = *plots.trackTimeVsXAngle->getTH2F()->ProfileX();
1448     }
1449 }
1450 
1451 //----------------------------------------------------------------------------------------------------
1452 DEFINE_FWK_MODULE(CTPPSDiamondDQMSource);