Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-11 04:32:26

0001 /****************************************************************************
0002  *
0003  * This is a part of CTPPS offline software.
0004  * Authors:
0005  *   Nicola Minafra
0006  *   Laurent Forthomme
0007  *
0008  ****************************************************************************/
0009 
0010 #include "FWCore/Framework/interface/ESHandle.h"
0011 #include "FWCore/Framework/interface/Event.h"
0012 #include "FWCore/Framework/interface/EventSetup.h"
0013 #include "FWCore/Framework/interface/MakerMacros.h"
0014 #include "FWCore/Framework/interface/Run.h"
0015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0016 #include "FWCore/Utilities/interface/InputTag.h"
0017 
0018 #include "DQMServices/Core/interface/DQMOneEDAnalyzer.h"
0019 #include "DQMServices/Core/interface/DQMStore.h"
0020 
0021 #include "DataFormats/CTPPSDigi/interface/TotemFEDInfo.h"
0022 #include "DataFormats/CTPPSDigi/interface/TotemVFATStatus.h"
0023 #include "DataFormats/CTPPSReco/interface/TotemRPLocalTrack.h"
0024 #include "DataFormats/Common/interface/DetSetVector.h"
0025 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0026 #include "DataFormats/Provenance/interface/EventRange.h"
0027 
0028 #include "DataFormats/CTPPSDetId/interface/TotemTimingDetId.h"
0029 #include "DataFormats/CTPPSDigi/interface/TotemTimingDigi.h"
0030 #include "DataFormats/CTPPSReco/interface/TotemTimingRecHit.h"
0031 
0032 #include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
0033 #include "DataFormats/CTPPSReco/interface/TotemRPLocalTrack.h"
0034 #include "Geometry/Records/interface/VeryForwardRealGeometryRecord.h"
0035 #include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h"
0036 
0037 #include <string>
0038 
0039 //----------------------------------------------------------------------------------------------------
0040 
0041 namespace totemds {
0042   struct Cache {
0043     std::unordered_map<unsigned int, std::unique_ptr<TH2F>> hitDistribution2dMap;
0044 
0045     std::unordered_map<unsigned int, unsigned long> hitsCounterMap;
0046   };
0047 }  // namespace totemds
0048 
0049 class TotemTimingDQMSource : public DQMOneEDAnalyzer<edm::LuminosityBlockCache<totemds::Cache>> {
0050 public:
0051   TotemTimingDQMSource(const edm::ParameterSet &);
0052   ~TotemTimingDQMSource() override;
0053 
0054 protected:
0055   void dqmBeginRun(const edm::Run &, const edm::EventSetup &) override;
0056   void bookHistograms(DQMStore::IBooker &, const edm::Run &, const edm::EventSetup &) override;
0057   void analyze(const edm::Event &, const edm::EventSetup &) override;
0058   std::shared_ptr<totemds::Cache> globalBeginLuminosityBlock(const edm::LuminosityBlock &,
0059                                                              const edm::EventSetup &) const override;
0060   void globalEndLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) override;
0061 
0062 private:
0063   // Constants
0064   static const double SEC_PER_LUMI_SECTION;  // Number of seconds per
0065                                              // lumisection: used to compute hit
0066                                              // rates in Hz
0067   static const double LHC_CLOCK_PERIOD_NS;
0068   static const double DQM_FRACTION_OF_EVENTS;          // approximate fraction of events
0069                                                        // sent to DQM stream
0070   static const double HIT_RATE_FACTOR;                 // factor to have real rate in Hz
0071   static const double DISPLAY_RESOLUTION_FOR_HITS_MM;  // Bin width of histograms
0072                                                        // showing hits and tracks
0073                                                        // (in mm)
0074   static const double INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0075   static const double TOMOGRAPHY_RESOLUTION_MM;
0076   static const double SAMPIC_SAMPLING_PERIOD_NS;  // ns per HPTDC bin
0077   static const double SAMPIC_MAX_NUMBER_OF_SAMPLES;
0078   static const double SAMPIC_ADC_V;
0079   static const int CTPPS_NUM_OF_ARMS;
0080   static const int TOTEM_TIMING_STATION_ID;
0081   static const int TOTEM_STATION_210;
0082   static const int TOTEM_STATION_220;
0083   static const int TOTEM_TIMING_TOP_RP_ID;
0084   static const int TOTEM_TIMING_BOT_RP_ID;
0085   static const int TOTEM_STRIP_MIN_RP_ID;
0086   static const int TOTEM_STRIP_MAX_RP_ID;
0087   static const int CTPPS_NEAR_RP_ID;
0088   static const int CTPPS_FAR_RP_ID;
0089   static const int TOTEM_TIMING_NUM_OF_PLANES;
0090   static const int TOTEM_TIMING_NUM_OF_CHANNELS;
0091   static const int TOTEM_TIMING_FED_ID_45;
0092   static const int TOTEM_TIMING_FED_ID_56;
0093   static const float COS_8_DEG;
0094   static const float SIN_8_DEG;
0095 
0096   edm::EDGetTokenT<edm::DetSetVector<TotemRPLocalTrack>> tokenLocalTrack_;
0097   edm::EDGetTokenT<edm::DetSetVector<TotemTimingDigi>> tokenDigi_;
0098   edm::EDGetTokenT<edm::DetSetVector<TotemTimingRecHit>> tokenRecHit_;
0099   edm::EDGetTokenT<std::vector<TotemFEDInfo>> tokenFEDInfo_;
0100 
0101   edm::ESGetToken<CTPPSGeometry, VeryForwardRealGeometryRecord> geometryToken_;
0102   edm::ESGetToken<CTPPSGeometry, VeryForwardRealGeometryRecord> geometryTokenBeginRun_;
0103 
0104   double minimumStripAngleForTomography_;
0105   double maximumStripAngleForTomography_;
0106   unsigned int samplesForNoise_;
0107   bool perLSsaving_;  //to avoid nanoDQMIO crashing, driven by  DQMServices/Core/python/DQMStore_cfi.py
0108   unsigned int verbosity_;
0109   edm::TimeValue_t timeOfPreviousEvent_;
0110 
0111   float verticalShiftBot_, verticalShiftTop_;
0112 
0113   /// plots related to the whole system
0114   struct GlobalPlots {
0115     MonitorElement *digiSentPercentage = nullptr;
0116 
0117     GlobalPlots() {}
0118     GlobalPlots(DQMStore::IBooker &ibooker);
0119   };
0120 
0121   GlobalPlots globalPlot_;
0122 
0123   /// plots related to one Diamond detector package
0124   struct PotPlots {
0125     // Digis
0126     MonitorElement *activityPerBX = nullptr;
0127     MonitorElement *digiDistribution = nullptr;
0128     MonitorElement *dataSamplesRaw = nullptr;
0129     MonitorElement *baseline = nullptr;
0130     MonitorElement *noiseRMS = nullptr;
0131 
0132     MonitorElement *digiSent = nullptr;
0133     MonitorElement *digiAll = nullptr;
0134     MonitorElement *digiSentPercentage = nullptr;
0135 
0136     // RecHits
0137     MonitorElement *hitDistribution2d = nullptr;
0138     MonitorElement *hitDistribution2dWithTime = nullptr;
0139     MonitorElement *hitDistribution2d_lumisection = nullptr;
0140 
0141     MonitorElement *recHitTime = nullptr;
0142     MonitorElement *amplitude = nullptr;
0143     MonitorElement *baselineRMS = nullptr;
0144     MonitorElement *tirggerCellTime = nullptr;
0145     MonitorElement *meanAmplitude = nullptr;
0146     MonitorElement *cellOfMax = nullptr;
0147 
0148     MonitorElement *hitRate = nullptr;
0149 
0150     MonitorElement *planesWithDigis = nullptr;
0151     MonitorElement *planesWithTime = nullptr;
0152 
0153     // MonitorElement *trackDistribution = nullptr;
0154 
0155     MonitorElement *stripTomography210 = nullptr;
0156     MonitorElement *stripTomography220 = nullptr;
0157 
0158     std::set<unsigned int> planesWithDigisSet;
0159     std::set<unsigned int> planesWithTimeSet;
0160 
0161     PotPlots() {}
0162     PotPlots(DQMStore::IBooker &ibooker, unsigned int id);
0163   };
0164 
0165   std::unordered_map<unsigned int, PotPlots> potPlots_;
0166 
0167   /// plots related to one Diamond plane
0168   struct PlanePlots {
0169     MonitorElement *digiDistribution = nullptr;
0170 
0171     MonitorElement *hitProfile = nullptr;
0172     MonitorElement *hitMultiplicity = nullptr;
0173     MonitorElement *hitMultiplicityWithTime = nullptr;
0174 
0175     PlanePlots() {}
0176     PlanePlots(DQMStore::IBooker &ibooker, unsigned int id);
0177   };
0178 
0179   std::unordered_map<unsigned int, PlanePlots> planePlots_;
0180 
0181   /// plots related to one Diamond channel
0182   struct ChannelPlots {
0183     // Digis
0184     MonitorElement *activityPerBX = nullptr;
0185     MonitorElement *dataSamplesRaw = nullptr;
0186     MonitorElement *cellOfMax = nullptr;
0187     MonitorElement *maxTimeAfterTrigger = nullptr;
0188 
0189     // RecHits
0190     MonitorElement *tirggerCellTime = nullptr;
0191     MonitorElement *recHitTime = nullptr;
0192     MonitorElement *amplitude = nullptr;
0193     MonitorElement *noiseSamples = nullptr;
0194 
0195     MonitorElement *hitTime = nullptr;
0196     MonitorElement *hitRate = nullptr;
0197 
0198     MonitorElement *stripTomography210 = nullptr;
0199     MonitorElement *stripTomography220 = nullptr;
0200 
0201     ChannelPlots() {}
0202     ChannelPlots(DQMStore::IBooker &ibooker, unsigned int id);
0203   };
0204 
0205   std::unordered_map<unsigned int, ChannelPlots> channelPlots_;
0206 };
0207 
0208 //----------------------------------------------------------------------------------------------------
0209 
0210 // Values for all constants
0211 const double TotemTimingDQMSource::SEC_PER_LUMI_SECTION = 23.31;
0212 const double TotemTimingDQMSource::LHC_CLOCK_PERIOD_NS = 24.95;
0213 const double TotemTimingDQMSource::DQM_FRACTION_OF_EVENTS = 1.;
0214 const double TotemTimingDQMSource::HIT_RATE_FACTOR = DQM_FRACTION_OF_EVENTS / SEC_PER_LUMI_SECTION;
0215 const double TotemTimingDQMSource::DISPLAY_RESOLUTION_FOR_HITS_MM = 0.1;
0216 const double TotemTimingDQMSource::INV_DISPLAY_RESOLUTION_FOR_HITS_MM = 1. / DISPLAY_RESOLUTION_FOR_HITS_MM;
0217 const double TotemTimingDQMSource::TOMOGRAPHY_RESOLUTION_MM = 1;
0218 const double TotemTimingDQMSource::SAMPIC_SAMPLING_PERIOD_NS = 1. / 7.8e9;
0219 const double TotemTimingDQMSource::SAMPIC_MAX_NUMBER_OF_SAMPLES = 64;
0220 const double TotemTimingDQMSource::SAMPIC_ADC_V = 1. / 256;
0221 const int TotemTimingDQMSource::CTPPS_NUM_OF_ARMS = 2;
0222 const int TotemTimingDQMSource::TOTEM_TIMING_STATION_ID = 2;
0223 const int TotemTimingDQMSource::TOTEM_STATION_210 = 0;
0224 const int TotemTimingDQMSource::TOTEM_STATION_220 = 2;
0225 const int TotemTimingDQMSource::TOTEM_TIMING_TOP_RP_ID = 0;
0226 const int TotemTimingDQMSource::TOTEM_TIMING_BOT_RP_ID = 1;
0227 const int TotemTimingDQMSource::TOTEM_STRIP_MIN_RP_ID = 4;
0228 const int TotemTimingDQMSource::TOTEM_STRIP_MAX_RP_ID = 5;
0229 const int TotemTimingDQMSource::CTPPS_NEAR_RP_ID = 2;
0230 const int TotemTimingDQMSource::CTPPS_FAR_RP_ID = 3;
0231 const int TotemTimingDQMSource::TOTEM_TIMING_NUM_OF_PLANES = 4;
0232 const int TotemTimingDQMSource::TOTEM_TIMING_NUM_OF_CHANNELS = 12;
0233 const int TotemTimingDQMSource::TOTEM_TIMING_FED_ID_45 = FEDNumbering::MAXTotemRPTimingVerticalFEDID;
0234 const int TotemTimingDQMSource::TOTEM_TIMING_FED_ID_56 = FEDNumbering::MINTotemRPTimingVerticalFEDID;
0235 const float TotemTimingDQMSource::COS_8_DEG = 0.990268;
0236 const float TotemTimingDQMSource::SIN_8_DEG = -0.139173;
0237 
0238 //----------------------------------------------------------------------------------------------------
0239 
0240 TotemTimingDQMSource::GlobalPlots::GlobalPlots(DQMStore::IBooker &ibooker) {
0241   ibooker.setCurrentFolder("CTPPS/TimingFastSilicon");
0242 
0243   digiSentPercentage = ibooker.book2D(
0244       "sent digis percentage", "sent digis percentage (sampic);board + 0.5 sampic;channel", 14, -0.5, 6.5, 16, 0, 16);
0245 }
0246 
0247 //----------------------------------------------------------------------------------------------------
0248 
0249 TotemTimingDQMSource::PotPlots::PotPlots(DQMStore::IBooker &ibooker, unsigned int id) {
0250   std::string path, title;
0251   TotemTimingDetId(id).rpName(path, TotemTimingDetId::nPath);
0252   ibooker.setCurrentFolder(path);
0253 
0254   TotemTimingDetId(id).rpName(title, TotemTimingDetId::nFull);
0255 
0256   activityPerBX = ibooker.book1D("activity per BX CMS", title + " Activity per BX;Event.BX", 3600, -1.5, 3598. + 0.5);
0257 
0258   digiDistribution =
0259       ibooker.book2D("digi distribution", title + " digi distribution;plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0260 
0261   dataSamplesRaw = ibooker.book1D("raw Samples", title + " Raw Samples; ADC", 256, 0, 256);
0262 
0263   baseline = ibooker.book2D("baseline", title + " baseline (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0264   noiseRMS = ibooker.book2D("noise RMS", title + " noise RMS (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0265 
0266   digiSent =
0267       ibooker.book2D("digis sent", title + " digi sent (sampic);board + 0.5 sampic;channel", 14, -0.5, 6.5, 16, 0, 16);
0268   digiAll =
0269       ibooker.book2D("all digis", title + " all digis(sampic);board + 0.5 sampic;channel", 14, -0.5, 6.5, 16, 0, 16);
0270   digiSentPercentage = ibooker.book2D("sent digis percentage",
0271                                       title + " sent digis percentage (sampic);board + 0.5 sampic;channel",
0272                                       14,
0273                                       -0.5,
0274                                       6.5,
0275                                       16,
0276                                       0,
0277                                       16);
0278 
0279   hitDistribution2d = ibooker.book2D("hits in planes",
0280                                      title + " hits in planes;plane number;x (mm)",
0281                                      18,
0282                                      -0.5,
0283                                      4,
0284                                      15. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0285                                      0,
0286                                      15);
0287   hitDistribution2dWithTime = ibooker.book2D("hits in planes with time",
0288                                              title + " hits in planes with time;plane number;x (mm)",
0289                                              18,
0290                                              -0.5,
0291                                              4,
0292                                              15. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0293                                              0,
0294                                              15);
0295   hitDistribution2d_lumisection = ibooker.book2D("hits in planes lumisection",
0296                                                  title + " hits in planes in the last lumisection;plane number;x (mm)",
0297                                                  18,
0298                                                  -0.5,
0299                                                  4,
0300                                                  15. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0301                                                  0,
0302                                                  15);
0303 
0304   recHitTime = ibooker.book1D("recHit time", title + " time in the recHits; t (ns)", 500, -25, 25);
0305   amplitude = ibooker.book1D("amplitude", title + " amplitude above baseline; amplitude (V)", 50, 0, 1);
0306   tirggerCellTime = ibooker.book1D("trigger cell time", title + " Trigger Cell Time; t (ns)", 390, -25, 25);
0307   baselineRMS = ibooker.book2D("noise RMS", title + " noise RMS (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0308   meanAmplitude =
0309       ibooker.book2D("mean amplitude", title + " Mean Amplitude (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0310   cellOfMax = ibooker.book2D("cell of max", title + " cell of max (0-23);plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0311 
0312   hitRate = ibooker.book2D("hit rate", title + " hit rate (Hz);plane;channel", 10, -0.5, 4.5, 12, 0, 12);
0313 
0314   planesWithDigis = ibooker.book1D(
0315       "active planes digis", title + " active planes with digis sent (per event);number of active planes", 6, -0.5, 5.5);
0316   planesWithTime = ibooker.book1D(
0317       "active planes with time", title + " active planes with time (per event);number of active planes", 6, -0.5, 5.5);
0318 
0319   // trackDistribution = ibooker.book1D( "tracks", title+" tracks;x (mm)",
0320   //     19.*INV_DISPLAY_RESOLUTION_FOR_HITS_MM, -1, 18 );    //TODO needs tracks
0321 
0322   stripTomography210 =
0323       ibooker.book2D("tomography 210",
0324                      title + " tomography (only with time) with strips 210 (all planes);x + 50*plane(mm);y (mm)",
0325                      190 / TOMOGRAPHY_RESOLUTION_MM,
0326                      -20,
0327                      170,
0328                      25 / TOMOGRAPHY_RESOLUTION_MM,
0329                      0,
0330                      25);
0331   stripTomography220 =
0332       ibooker.book2D("tomography 220",
0333                      title + " tomography (only with time) with strips 220 (all planes);x + 50*plane(mm);y (mm)",
0334                      190 / TOMOGRAPHY_RESOLUTION_MM,
0335                      -20,
0336                      170,
0337                      25 / TOMOGRAPHY_RESOLUTION_MM,
0338                      0,
0339                      25);
0340 }
0341 
0342 //----------------------------------------------------------------------------------------------------
0343 
0344 TotemTimingDQMSource::PlanePlots::PlanePlots(DQMStore::IBooker &ibooker, unsigned int id) {
0345   std::string path, title;
0346   TotemTimingDetId(id).planeName(path, TotemTimingDetId::nPath);
0347   ibooker.setCurrentFolder(path);
0348 
0349   TotemTimingDetId(id).planeName(title, TotemTimingDetId::nFull);
0350 
0351   digiDistribution = ibooker.book1D("digi distribution", title + " digi distribution;channel", 12, 0, 12);
0352 
0353   hitProfile = ibooker.book1D("hit distribution with time",
0354                               title + " hit distribution (with time);y (+ 15 for x>3) (mm)",
0355                               30. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM,
0356                               0,
0357                               30);
0358 
0359   hitMultiplicity = ibooker.book1D("channels per plane", title + " channels per plane; ch per plane", 13, -0.5, 12.5);
0360 
0361   hitMultiplicityWithTime = ibooker.book1D(
0362       "channels per plane with time", title + " channels per plane with time; ch per plane", 13, -0.5, 12.5);
0363 }
0364 
0365 //----------------------------------------------------------------------------------------------------
0366 
0367 TotemTimingDQMSource::ChannelPlots::ChannelPlots(DQMStore::IBooker &ibooker, unsigned int id) {
0368   std::string path, title;
0369   TotemTimingDetId(id).channelName(path, TotemTimingDetId::nPath);
0370   ibooker.setCurrentFolder(path);
0371 
0372   TotemTimingDetId(id).channelName(title, TotemTimingDetId::nFull);
0373 
0374   activityPerBX = ibooker.book1D("activity per BX", title + " Activity per BX;Event.BX", 1000, -1.5, 998. + 0.5);
0375   dataSamplesRaw = ibooker.book1D("raw samples", title + " Raw Samples; ADC", 256, 0, 256);
0376   cellOfMax = ibooker.book1D("cell of max", title + " cell of max; cell", 24, 0, 24);
0377 
0378   tirggerCellTime = ibooker.book1D("sampic trigger time", title + " Sampic Trigger Time; t (ns)", 100, -25, 25);
0379   recHitTime = ibooker.book1D("recHit Time", title + " recHit Time; t (ns)", 500, -25, 25);
0380   amplitude = ibooker.book1D("amplitude", title + " amplitude above baseline; amplitude (V)", 50, 0, 1);
0381   noiseSamples = ibooker.book1D("noise samples", title + " noise samples; V", 50, 0, 1);
0382 
0383   hitTime = ibooker.book1D("hit time", title + "hit time;t - t_previous (us)", 100, 0, 10000);
0384   hitRate = ibooker.book1D("hit rate", title + "hit rate;rate (Hz)", 100, 0, 10000);
0385 
0386   stripTomography210 = ibooker.book2D("tomography 210",
0387                                       title + " tomography with strips 210;x (mm);y (mm)",
0388                                       20 / TOMOGRAPHY_RESOLUTION_MM,
0389                                       -20,
0390                                       20,
0391                                       25 / TOMOGRAPHY_RESOLUTION_MM,
0392                                       0,
0393                                       25);
0394   stripTomography220 = ibooker.book2D("tomography 220",
0395                                       title + " tomography with strips 220;x (mm);y (mm)",
0396                                       20 / TOMOGRAPHY_RESOLUTION_MM,
0397                                       -20,
0398                                       20,
0399                                       25 / TOMOGRAPHY_RESOLUTION_MM,
0400                                       0,
0401                                       25);
0402 }
0403 
0404 //----------------------------------------------------------------------------------------------------
0405 
0406 TotemTimingDQMSource::TotemTimingDQMSource(const edm::ParameterSet &ps)
0407     : tokenLocalTrack_(
0408           consumes<edm::DetSetVector<TotemRPLocalTrack>>(ps.getUntrackedParameter<edm::InputTag>("tagLocalTrack"))),
0409       tokenDigi_(consumes<edm::DetSetVector<TotemTimingDigi>>(ps.getUntrackedParameter<edm::InputTag>("tagDigi"))),
0410       tokenRecHit_(
0411           consumes<edm::DetSetVector<TotemTimingRecHit>>(ps.getUntrackedParameter<edm::InputTag>("tagRecHits"))),
0412       // tokenTrack_(consumes<edm::DetSetVector<TotemTimingLocalTrack>>(
0413       //     ps.getParameter<edm::InputTag>("tagLocalTracks"))),
0414       tokenFEDInfo_(consumes<std::vector<TotemFEDInfo>>(ps.getUntrackedParameter<edm::InputTag>("tagFEDInfo"))),
0415       geometryToken_(esConsumes()),
0416       geometryTokenBeginRun_(esConsumes<edm::Transition::BeginRun>()),
0417       minimumStripAngleForTomography_(ps.getParameter<double>("minimumStripAngleForTomography")),
0418       maximumStripAngleForTomography_(ps.getParameter<double>("maximumStripAngleForTomography")),
0419       samplesForNoise_(ps.getUntrackedParameter<unsigned int>("samplesForNoise", 5)),
0420       perLSsaving_(ps.getUntrackedParameter<bool>("perLSsaving", false)),
0421       verbosity_(ps.getUntrackedParameter<unsigned int>("verbosity", 0)),
0422       timeOfPreviousEvent_(0) {}
0423 
0424 //----------------------------------------------------------------------------------------------------
0425 
0426 TotemTimingDQMSource::~TotemTimingDQMSource() {}
0427 
0428 //----------------------------------------------------------------------------------------------------
0429 
0430 void TotemTimingDQMSource::dqmBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup) {
0431   // Get detector shifts from the geometry (if present)
0432   auto const &geom = iSetup.getData(geometryTokenBeginRun_);
0433 
0434   const TotemTimingDetId detid_top(0, TOTEM_TIMING_STATION_ID, TOTEM_TIMING_BOT_RP_ID, 0, 0);
0435   const TotemTimingDetId detid_bot(0, TOTEM_TIMING_STATION_ID, TOTEM_TIMING_TOP_RP_ID, 0, 7);
0436   verticalShiftTop_ = 0;
0437   verticalShiftBot_ = 0;
0438   {
0439     const DetGeomDesc *det_top = geom.sensorNoThrow(detid_top);
0440     if (det_top) {
0441       verticalShiftTop_ = det_top->translation().y() + det_top->getDiamondDimensions().yHalfWidth;
0442     }
0443     const DetGeomDesc *det_bot = geom.sensorNoThrow(detid_bot);
0444     if (det_bot)
0445       verticalShiftBot_ = det_bot->translation().y() + det_bot->getDiamondDimensions().yHalfWidth;
0446   }
0447 }
0448 
0449 //----------------------------------------------------------------------------------------------------
0450 
0451 void TotemTimingDQMSource::bookHistograms(DQMStore::IBooker &ibooker, const edm::Run &, const edm::EventSetup &) {
0452   ibooker.cd();
0453   ibooker.setCurrentFolder("CTPPS");
0454 
0455   globalPlot_ = GlobalPlots(ibooker);
0456 
0457   for (unsigned short arm = 0; arm < CTPPS_NUM_OF_ARMS; ++arm) {
0458     for (unsigned short rp = TOTEM_TIMING_TOP_RP_ID; rp <= TOTEM_TIMING_BOT_RP_ID; ++rp) {
0459       const TotemTimingDetId rpId(arm, TOTEM_TIMING_STATION_ID, rp);
0460       potPlots_[rpId] = PotPlots(ibooker, rpId);
0461       for (unsigned short pl = 0; pl < TOTEM_TIMING_NUM_OF_PLANES; ++pl) {
0462         const TotemTimingDetId plId(arm, TOTEM_TIMING_STATION_ID, rp, pl);
0463         planePlots_[plId] = PlanePlots(ibooker, plId);
0464         for (unsigned short ch = 0; ch < TOTEM_TIMING_NUM_OF_CHANNELS; ++ch) {
0465           const TotemTimingDetId chId(arm, TOTEM_TIMING_STATION_ID, rp, pl, ch);
0466           channelPlots_[chId] = ChannelPlots(ibooker, chId);
0467         }
0468       }
0469     }
0470   }
0471 }
0472 
0473 //----------------------------------------------------------------------------------------------------
0474 
0475 std::shared_ptr<totemds::Cache> TotemTimingDQMSource::globalBeginLuminosityBlock(const edm::LuminosityBlock &,
0476                                                                                  const edm::EventSetup &) const {
0477   auto d = std::make_shared<totemds::Cache>();
0478   d->hitDistribution2dMap.reserve(potPlots_.size());
0479   if (!perLSsaving_) {
0480     for (auto &plot : potPlots_)
0481       d->hitDistribution2dMap[plot.first] =
0482           std::unique_ptr<TH2F>(static_cast<TH2F *>(plot.second.hitDistribution2d_lumisection->getTH2F()->Clone()));
0483   }
0484   return d;
0485 }
0486 
0487 //----------------------------------------------------------------------------------------------------
0488 
0489 void TotemTimingDQMSource::analyze(const edm::Event &event, const edm::EventSetup &eventSetup) {
0490   // get event setup data
0491   auto const &geometry = eventSetup.getData(geometryToken_);
0492 
0493   // get event data
0494   edm::Handle<edm::DetSetVector<TotemRPLocalTrack>> stripTracks;
0495   event.getByToken(tokenLocalTrack_, stripTracks);
0496 
0497   edm::Handle<edm::DetSetVector<TotemTimingDigi>> timingDigis;
0498   event.getByToken(tokenDigi_, timingDigis);
0499 
0500   edm::Handle<std::vector<TotemFEDInfo>> fedInfo;
0501   event.getByToken(tokenFEDInfo_, fedInfo);
0502 
0503   edm::Handle<edm::DetSetVector<TotemTimingRecHit>> timingRecHits;
0504   event.getByToken(tokenRecHit_, timingRecHits);
0505 
0506   // check validity
0507   bool valid = true;
0508   valid &= timingDigis.isValid();
0509   valid &= fedInfo.isValid();
0510 
0511   if (!valid) {
0512     if (verbosity_) {
0513       edm::LogProblem("TotemTimingDQMSource") << "ERROR in TotemTimingDQMSource::analyze > some of the required inputs "
0514                                                  "are not valid. Skipping this event.\n"
0515                                               << "    timingDigis.isValid = " << timingDigis.isValid() << "\n"
0516                                               << "    fedInfo.isValid = " << fedInfo.isValid();
0517     }
0518 
0519     return;
0520   }
0521 
0522   // Using TotemTimingDigi
0523   std::set<uint8_t> boardSet;
0524   std::unordered_map<unsigned int, unsigned int> channelsPerPlane;
0525   std::unordered_map<unsigned int, unsigned int> channelsPerPlaneWithTime;
0526 
0527   auto lumiCache = luminosityBlockCache(event.getLuminosityBlock().index());
0528   for (const auto &digis : *timingDigis) {
0529     const TotemTimingDetId detId(digis.detId());
0530     TotemTimingDetId detId_pot(digis.detId());
0531     detId_pot.setPlane(0);
0532     detId_pot.setChannel(0);
0533     TotemTimingDetId detId_plane(digis.detId());
0534     detId_plane.setChannel(0);
0535 
0536     for (const auto &digi : digis) {
0537       // Pot Plots
0538       if (potPlots_.find(detId_pot) != potPlots_.end()) {
0539         potPlots_[detId_pot].activityPerBX->Fill(event.bunchCrossing());
0540 
0541         potPlots_[detId_pot].digiDistribution->Fill(detId.plane(), detId.channel());
0542 
0543         for (auto it = digi.samplesBegin(); it != digi.samplesEnd(); ++it)
0544           potPlots_[detId_pot].dataSamplesRaw->Fill(*it);
0545 
0546         float boardId = digi.eventInfo().hardwareBoardId() + 0.5 * digi.eventInfo().hardwareSampicId();
0547         potPlots_[detId_pot].digiSent->Fill(boardId, digi.hardwareChannelId());
0548         if (boardSet.find(digi.eventInfo().hardwareId()) == boardSet.end()) {
0549           // This guarantees that every board is counted only once
0550           boardSet.insert(digi.eventInfo().hardwareId());
0551           std::bitset<16> chMap(digi.eventInfo().channelMap());
0552           for (int i = 0; i < 16; ++i) {
0553             if (chMap.test(i)) {
0554               potPlots_[detId_pot].digiAll->Fill(boardId, i);
0555             }
0556           }
0557         }
0558 
0559         potPlots_[detId_pot].planesWithDigisSet.insert(detId.plane());
0560       }
0561 
0562       // Plane Plots
0563       if (planePlots_.find(detId_plane) != planePlots_.end()) {
0564         planePlots_[detId_plane].digiDistribution->Fill(detId.channel());
0565 
0566         if (channelsPerPlane.find(detId_plane) != channelsPerPlane.end())
0567           channelsPerPlane[detId_plane]++;
0568         else
0569           channelsPerPlane[detId_plane] = 0;
0570       }
0571 
0572       // Channel Plots
0573       if (channelPlots_.find(detId) != channelPlots_.end()) {
0574         channelPlots_[detId].activityPerBX->Fill(event.bunchCrossing());
0575 
0576         for (auto it = digi.samplesBegin(); it != digi.samplesEnd(); ++it)
0577           channelPlots_[detId].dataSamplesRaw->Fill(*it);
0578         for (unsigned short i = 0; i < samplesForNoise_; ++i)
0579           channelPlots_[detId].noiseSamples->Fill(SAMPIC_ADC_V * digi.sampleAt(i));
0580 
0581         unsigned int cellOfMax = std::max_element(digi.samplesBegin(), digi.samplesEnd()) - digi.samplesBegin();
0582         channelPlots_[detId].cellOfMax->Fill((int)cellOfMax);
0583 
0584         if (timeOfPreviousEvent_ != 0)
0585           channelPlots_[detId].hitTime->Fill(1e-3 * LHC_CLOCK_PERIOD_NS *
0586                                              (event.time().value() - timeOfPreviousEvent_));
0587         ++(lumiCache->hitsCounterMap[detId]);
0588       }
0589     }
0590   }
0591   // End digis
0592 
0593   for (const auto &rechits : *timingRecHits) {
0594     const TotemTimingDetId detId(rechits.detId());
0595     TotemTimingDetId detId_pot(rechits.detId());
0596     detId_pot.setPlane(0);
0597     detId_pot.setChannel(0);
0598     TotemTimingDetId detId_plane(rechits.detId());
0599     detId_plane.setChannel(0);
0600 
0601     for (const auto &rechit : rechits) {
0602       if (potPlots_.find(detId_pot) != potPlots_.end()) {
0603         potPlots_[detId_pot].amplitude->Fill(rechit.amplitude());
0604 
0605         TH2F *hitHistoTmp = potPlots_[detId_pot].hitDistribution2d->getTH2F();
0606         TAxis *hitHistoTmpYAxis = hitHistoTmp->GetYaxis();
0607         float yCorrected = rechit.y();
0608         yCorrected += (detId.rp() == TOTEM_TIMING_TOP_RP_ID) ? verticalShiftTop_ : verticalShiftBot_;
0609         float x_shift = detId.plane();
0610         x_shift += (rechit.x() > 2) ? 0.25 : 0;
0611         int startBin = hitHistoTmpYAxis->FindBin(yCorrected - 0.5 * rechit.yWidth());
0612         int numOfBins = rechit.yWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0613         for (int i = 0; i < numOfBins; ++i) {
0614           potPlots_[detId_pot].hitDistribution2d->Fill(detId.plane() + 0.25 * (rechit.x() > 2),
0615                                                        hitHistoTmpYAxis->GetBinCenter(startBin + i));
0616           if (!perLSsaving_)
0617             potPlots_[detId_pot].hitDistribution2d_lumisection->Fill(x_shift,
0618                                                                      hitHistoTmpYAxis->GetBinCenter(startBin + i));
0619         }
0620 
0621         //All plots with Time
0622         if (rechit.time() != TotemTimingRecHit::NO_T_AVAILABLE) {
0623           for (int i = 0; i < numOfBins; ++i)
0624             potPlots_[detId_pot].hitDistribution2dWithTime->Fill(detId.plane() + 0.25 * (rechit.x() > 2),
0625                                                                  hitHistoTmpYAxis->GetBinCenter(startBin + i));
0626 
0627           potPlots_[detId_pot].recHitTime->Fill(rechit.time());
0628           potPlots_[detId_pot].planesWithTimeSet.insert(detId.plane());
0629 
0630           // Plane Plots
0631           if (planePlots_.find(detId_plane) != planePlots_.end()) {
0632             // Visualization tricks
0633             float x_shift = (rechit.x() > 2) ? 15 : 0;
0634             TH1F *hitProfileHistoTmp = planePlots_[detId_plane].hitProfile->getTH1F();
0635             int numOfBins = rechit.yWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0636             if (detId.rp() == TOTEM_TIMING_TOP_RP_ID) {
0637               float yCorrected = rechit.y() + verticalShiftTop_ - 0.5 * rechit.yWidth() + x_shift;
0638               int startBin = hitProfileHistoTmp->FindBin(yCorrected);
0639               for (int i = 0; i < numOfBins; ++i)
0640                 hitProfileHistoTmp->Fill(hitProfileHistoTmp->GetBinCenter(startBin + i));
0641             } else {
0642               float yCorrected = rechit.y() + verticalShiftBot_ + 0.5 * rechit.yWidth() + (15 - x_shift);
0643               int startBin = hitProfileHistoTmp->FindBin(yCorrected);
0644               int totBins = hitProfileHistoTmp->GetNbinsX();
0645               for (int i = 0; i < numOfBins; ++i)
0646                 hitProfileHistoTmp->Fill(hitProfileHistoTmp->GetBinCenter(totBins - startBin + i));
0647             }
0648 
0649             if (channelsPerPlaneWithTime.find(detId_plane) != channelsPerPlaneWithTime.end())
0650               channelsPerPlaneWithTime[detId_plane]++;
0651             else
0652               channelsPerPlaneWithTime[detId_plane] = 0;
0653           }
0654 
0655           if (channelPlots_.find(detId) != channelPlots_.end()) {
0656             potPlots_[detId_pot].tirggerCellTime->Fill(rechit.sampicThresholdTime());
0657             channelPlots_[detId].tirggerCellTime->Fill(rechit.sampicThresholdTime());
0658             channelPlots_[detId].recHitTime->Fill(rechit.time());
0659             channelPlots_[detId].amplitude->Fill(rechit.amplitude());
0660           }
0661         }
0662       }
0663     }
0664   }
0665   // End RecHits
0666 
0667   // Tomography of timing using strips
0668   for (const auto &rechits : *timingRecHits) {
0669     const TotemTimingDetId detId(rechits.detId());
0670     TotemTimingDetId detId_pot(rechits.detId());
0671     detId_pot.setPlane(0);
0672     detId_pot.setChannel(0);
0673     TotemTimingDetId detId_plane(rechits.detId());
0674     detId_plane.setChannel(0);
0675 
0676     float y_shift = (detId.rp() == TOTEM_TIMING_TOP_RP_ID) ? 20 : 5;
0677 
0678     for (const auto &rechit : rechits) {
0679       if (rechit.time() != TotemTimingRecHit::NO_T_AVAILABLE && potPlots_.find(detId_pot) != potPlots_.end() &&
0680           planePlots_.find(detId_plane) != planePlots_.end() && channelPlots_.find(detId) != channelPlots_.end()) {
0681         if (stripTracks.isValid()) {
0682           for (const auto &ds : *stripTracks) {
0683             const CTPPSDetId stripId(ds.detId());
0684             // mean position of U and V planes
0685             TotemRPDetId plId_V(stripId);
0686             plId_V.setPlane(0);
0687             TotemRPDetId plId_U(stripId);
0688             plId_U.setPlane(1);
0689 
0690             double rp_x = 0;
0691             double rp_y = 0;
0692             try {
0693               rp_x = (geometry.sensor(plId_V)->translation().x() + geometry.sensor(plId_U)->translation().x()) / 2;
0694               rp_y = (geometry.sensor(plId_V)->translation().y() + geometry.sensor(plId_U)->translation().y()) / 2;
0695             } catch (const cms::Exception &) {
0696               continue;
0697             }
0698 
0699             for (const auto &striplt : ds) {
0700               if (striplt.isValid() && stripId.arm() == detId.arm()) {
0701                 if (striplt.tx() > maximumStripAngleForTomography_ || striplt.ty() > maximumStripAngleForTomography_)
0702                   continue;
0703                 if (striplt.tx() < minimumStripAngleForTomography_ || striplt.ty() < minimumStripAngleForTomography_)
0704                   continue;
0705                 if (stripId.rp() - detId.rp() == (TOTEM_STRIP_MAX_RP_ID - TOTEM_TIMING_BOT_RP_ID)) {
0706                   double x = striplt.x0() - rp_x;
0707                   double y = striplt.y0() - rp_y;
0708                   if (stripId.station() == TOTEM_STATION_210) {
0709                     potPlots_[detId_pot].stripTomography210->Fill(x + detId.plane() * 50, y + y_shift);
0710                     channelPlots_[detId].stripTomography210->Fill(x, y + y_shift);
0711                   } else if (stripId.station() == TOTEM_STATION_220) {
0712                     potPlots_[detId_pot].stripTomography220->Fill(x + detId.plane() * 50, y + y_shift);
0713                     channelPlots_[detId].stripTomography220->Fill(x, y + y_shift);
0714                   }
0715                 }
0716               }
0717             }
0718           }
0719         }
0720       }
0721     }
0722   }
0723 
0724   for (auto &plt : potPlots_) {
0725     plt.second.planesWithDigis->Fill(plt.second.planesWithDigisSet.size());
0726     plt.second.planesWithDigisSet.clear();
0727     plt.second.planesWithTime->Fill(plt.second.planesWithTimeSet.size());
0728     plt.second.planesWithTimeSet.clear();
0729   }
0730 
0731   for (const auto &plt : channelsPerPlane) {
0732     planePlots_[plt.first].hitMultiplicity->Fill(plt.second);
0733   }
0734   for (const auto &plt : channelsPerPlaneWithTime) {
0735     planePlots_[plt.first].hitMultiplicityWithTime->Fill(plt.second);
0736   }
0737 
0738   timeOfPreviousEvent_ = event.time().value();
0739 }
0740 
0741 //----------------------------------------------------------------------------------------------------
0742 
0743 void TotemTimingDQMSource::globalEndLuminosityBlock(const edm::LuminosityBlock &iLumi, const edm::EventSetup &) {
0744   auto lumiCache = luminosityBlockCache(iLumi.index());
0745   if (!perLSsaving_) {
0746     for (auto &plot : potPlots_) {
0747       *(plot.second.hitDistribution2d_lumisection->getTH2F()) = *(lumiCache->hitDistribution2dMap[plot.first]);
0748     }
0749 
0750     globalPlot_.digiSentPercentage->Reset();
0751     TH2F *hitHistoGlobalTmp = globalPlot_.digiSentPercentage->getTH2F();
0752     for (auto &plot : potPlots_) {
0753       TH2F *hitHistoTmp = plot.second.digiSentPercentage->getTH2F();
0754       TH2F *histoSent = plot.second.digiSent->getTH2F();
0755       TH2F *histoAll = plot.second.digiAll->getTH2F();
0756 
0757       hitHistoTmp->Divide(histoSent, histoAll);
0758       hitHistoTmp->Scale(100);
0759       hitHistoGlobalTmp->Add(hitHistoTmp, 1);
0760 
0761       plot.second.baseline->Reset();
0762       plot.second.noiseRMS->Reset();
0763       plot.second.meanAmplitude->Reset();
0764       plot.second.cellOfMax->Reset();
0765       plot.second.hitRate->Reset();
0766       TotemTimingDetId rpId(plot.first);
0767       for (auto &chPlot : channelPlots_) {
0768         TotemTimingDetId chId(chPlot.first);
0769         if (chId.arm() == rpId.arm() && chId.rp() == rpId.rp()) {
0770           plot.second.baseline->Fill(chId.plane(), chId.channel(), chPlot.second.noiseSamples->getTH1F()->GetMean());
0771           plot.second.noiseRMS->Fill(chId.plane(), chId.channel(), chPlot.second.noiseSamples->getTH1F()->GetRMS());
0772           plot.second.meanAmplitude->Fill(chId.plane(), chId.channel(), chPlot.second.amplitude->getTH1F()->GetMean());
0773           plot.second.cellOfMax->Fill(chId.plane(), chId.channel(), chPlot.second.cellOfMax->getTH1F()->GetMean());
0774           auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[chPlot.first];
0775           plot.second.hitRate->Fill(chId.plane(), chId.channel(), (double)hitsCounterPerLumisection * HIT_RATE_FACTOR);
0776         }
0777       }
0778     }
0779 
0780     for (auto &plot : channelPlots_) {
0781       auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[plot.first];
0782       if (hitsCounterPerLumisection != 0) {
0783         plot.second.hitRate->Fill((double)hitsCounterPerLumisection * HIT_RATE_FACTOR);
0784       }
0785     }
0786   }
0787 }
0788 
0789 DEFINE_FWK_MODULE(TotemTimingDQMSource);