Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-14 02:27:49

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_(consumes<edm::DetSetVector<TotemRPLocalTrack>>(ps.getParameter<edm::InputTag>("tagLocalTrack"))),
0408       tokenDigi_(consumes<edm::DetSetVector<TotemTimingDigi>>(ps.getParameter<edm::InputTag>("tagDigi"))),
0409       tokenRecHit_(consumes<edm::DetSetVector<TotemTimingRecHit>>(ps.getParameter<edm::InputTag>("tagRecHits"))),
0410       // tokenTrack_(consumes<edm::DetSetVector<TotemTimingLocalTrack>>(
0411       //     ps.getParameter<edm::InputTag>("tagLocalTracks"))),
0412       tokenFEDInfo_(consumes<std::vector<TotemFEDInfo>>(ps.getParameter<edm::InputTag>("tagFEDInfo"))),
0413       geometryToken_(esConsumes()),
0414       geometryTokenBeginRun_(esConsumes<edm::Transition::BeginRun>()),
0415       minimumStripAngleForTomography_(ps.getParameter<double>("minimumStripAngleForTomography")),
0416       maximumStripAngleForTomography_(ps.getParameter<double>("maximumStripAngleForTomography")),
0417       samplesForNoise_(ps.getUntrackedParameter<unsigned int>("samplesForNoise", 5)),
0418       perLSsaving_(ps.getUntrackedParameter<bool>("perLSsaving", false)),
0419       verbosity_(ps.getUntrackedParameter<unsigned int>("verbosity", 0)),
0420       timeOfPreviousEvent_(0) {}
0421 
0422 //----------------------------------------------------------------------------------------------------
0423 
0424 TotemTimingDQMSource::~TotemTimingDQMSource() {}
0425 
0426 //----------------------------------------------------------------------------------------------------
0427 
0428 void TotemTimingDQMSource::dqmBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup) {
0429   // Get detector shifts from the geometry (if present)
0430   auto const &geom = iSetup.getData(geometryTokenBeginRun_);
0431 
0432   const TotemTimingDetId detid_top(0, TOTEM_TIMING_STATION_ID, TOTEM_TIMING_BOT_RP_ID, 0, 0);
0433   const TotemTimingDetId detid_bot(0, TOTEM_TIMING_STATION_ID, TOTEM_TIMING_TOP_RP_ID, 0, 7);
0434   verticalShiftTop_ = 0;
0435   verticalShiftBot_ = 0;
0436   {
0437     const DetGeomDesc *det_top = geom.sensorNoThrow(detid_top);
0438     if (det_top) {
0439       verticalShiftTop_ = det_top->translation().y() + det_top->getDiamondDimensions().yHalfWidth;
0440     }
0441     const DetGeomDesc *det_bot = geom.sensorNoThrow(detid_bot);
0442     if (det_bot)
0443       verticalShiftBot_ = det_bot->translation().y() + det_bot->getDiamondDimensions().yHalfWidth;
0444   }
0445 }
0446 
0447 //----------------------------------------------------------------------------------------------------
0448 
0449 void TotemTimingDQMSource::bookHistograms(DQMStore::IBooker &ibooker, const edm::Run &, const edm::EventSetup &) {
0450   ibooker.cd();
0451   ibooker.setCurrentFolder("CTPPS");
0452 
0453   globalPlot_ = GlobalPlots(ibooker);
0454 
0455   for (unsigned short arm = 0; arm < CTPPS_NUM_OF_ARMS; ++arm) {
0456     for (unsigned short rp = TOTEM_TIMING_TOP_RP_ID; rp <= TOTEM_TIMING_BOT_RP_ID; ++rp) {
0457       const TotemTimingDetId rpId(arm, TOTEM_TIMING_STATION_ID, rp);
0458       potPlots_[rpId] = PotPlots(ibooker, rpId);
0459       for (unsigned short pl = 0; pl < TOTEM_TIMING_NUM_OF_PLANES; ++pl) {
0460         const TotemTimingDetId plId(arm, TOTEM_TIMING_STATION_ID, rp, pl);
0461         planePlots_[plId] = PlanePlots(ibooker, plId);
0462         for (unsigned short ch = 0; ch < TOTEM_TIMING_NUM_OF_CHANNELS; ++ch) {
0463           const TotemTimingDetId chId(arm, TOTEM_TIMING_STATION_ID, rp, pl, ch);
0464           channelPlots_[chId] = ChannelPlots(ibooker, chId);
0465         }
0466       }
0467     }
0468   }
0469 }
0470 
0471 //----------------------------------------------------------------------------------------------------
0472 
0473 std::shared_ptr<totemds::Cache> TotemTimingDQMSource::globalBeginLuminosityBlock(const edm::LuminosityBlock &,
0474                                                                                  const edm::EventSetup &) const {
0475   auto d = std::make_shared<totemds::Cache>();
0476   d->hitDistribution2dMap.reserve(potPlots_.size());
0477   if (!perLSsaving_) {
0478     for (auto &plot : potPlots_)
0479       d->hitDistribution2dMap[plot.first] =
0480           std::unique_ptr<TH2F>(static_cast<TH2F *>(plot.second.hitDistribution2d_lumisection->getTH2F()->Clone()));
0481   }
0482   return d;
0483 }
0484 
0485 //----------------------------------------------------------------------------------------------------
0486 
0487 void TotemTimingDQMSource::analyze(const edm::Event &event, const edm::EventSetup &eventSetup) {
0488   // get event setup data
0489   auto const &geometry = eventSetup.getData(geometryToken_);
0490 
0491   // get event data
0492   edm::Handle<edm::DetSetVector<TotemRPLocalTrack>> stripTracks;
0493   event.getByToken(tokenLocalTrack_, stripTracks);
0494 
0495   edm::Handle<edm::DetSetVector<TotemTimingDigi>> timingDigis;
0496   event.getByToken(tokenDigi_, timingDigis);
0497 
0498   edm::Handle<std::vector<TotemFEDInfo>> fedInfo;
0499   event.getByToken(tokenFEDInfo_, fedInfo);
0500 
0501   edm::Handle<edm::DetSetVector<TotemTimingRecHit>> timingRecHits;
0502   event.getByToken(tokenRecHit_, timingRecHits);
0503 
0504   // check validity
0505   bool valid = true;
0506   valid &= timingDigis.isValid();
0507   valid &= fedInfo.isValid();
0508 
0509   if (!valid) {
0510     if (verbosity_) {
0511       edm::LogProblem("TotemTimingDQMSource") << "ERROR in TotemTimingDQMSource::analyze > some of the required inputs "
0512                                                  "are not valid. Skipping this event.\n"
0513                                               << "    timingDigis.isValid = " << timingDigis.isValid() << "\n"
0514                                               << "    fedInfo.isValid = " << fedInfo.isValid();
0515     }
0516 
0517     return;
0518   }
0519 
0520   // Using TotemTimingDigi
0521   std::set<uint8_t> boardSet;
0522   std::unordered_map<unsigned int, unsigned int> channelsPerPlane;
0523   std::unordered_map<unsigned int, unsigned int> channelsPerPlaneWithTime;
0524 
0525   auto lumiCache = luminosityBlockCache(event.getLuminosityBlock().index());
0526   for (const auto &digis : *timingDigis) {
0527     const TotemTimingDetId detId(digis.detId());
0528     TotemTimingDetId detId_pot(digis.detId());
0529     detId_pot.setPlane(0);
0530     detId_pot.setChannel(0);
0531     TotemTimingDetId detId_plane(digis.detId());
0532     detId_plane.setChannel(0);
0533 
0534     for (const auto &digi : digis) {
0535       // Pot Plots
0536       if (potPlots_.find(detId_pot) != potPlots_.end()) {
0537         potPlots_[detId_pot].activityPerBX->Fill(event.bunchCrossing());
0538 
0539         potPlots_[detId_pot].digiDistribution->Fill(detId.plane(), detId.channel());
0540 
0541         for (auto it = digi.samplesBegin(); it != digi.samplesEnd(); ++it)
0542           potPlots_[detId_pot].dataSamplesRaw->Fill(*it);
0543 
0544         float boardId = digi.eventInfo().hardwareBoardId() + 0.5 * digi.eventInfo().hardwareSampicId();
0545         potPlots_[detId_pot].digiSent->Fill(boardId, digi.hardwareChannelId());
0546         if (boardSet.find(digi.eventInfo().hardwareId()) == boardSet.end()) {
0547           // This guarantees that every board is counted only once
0548           boardSet.insert(digi.eventInfo().hardwareId());
0549           std::bitset<16> chMap(digi.eventInfo().channelMap());
0550           for (int i = 0; i < 16; ++i) {
0551             if (chMap.test(i)) {
0552               potPlots_[detId_pot].digiAll->Fill(boardId, i);
0553             }
0554           }
0555         }
0556 
0557         potPlots_[detId_pot].planesWithDigisSet.insert(detId.plane());
0558       }
0559 
0560       // Plane Plots
0561       if (planePlots_.find(detId_plane) != planePlots_.end()) {
0562         planePlots_[detId_plane].digiDistribution->Fill(detId.channel());
0563 
0564         if (channelsPerPlane.find(detId_plane) != channelsPerPlane.end())
0565           channelsPerPlane[detId_plane]++;
0566         else
0567           channelsPerPlane[detId_plane] = 0;
0568       }
0569 
0570       // Channel Plots
0571       if (channelPlots_.find(detId) != channelPlots_.end()) {
0572         channelPlots_[detId].activityPerBX->Fill(event.bunchCrossing());
0573 
0574         for (auto it = digi.samplesBegin(); it != digi.samplesEnd(); ++it)
0575           channelPlots_[detId].dataSamplesRaw->Fill(*it);
0576         for (unsigned short i = 0; i < samplesForNoise_; ++i)
0577           channelPlots_[detId].noiseSamples->Fill(SAMPIC_ADC_V * digi.sampleAt(i));
0578 
0579         unsigned int cellOfMax = std::max_element(digi.samplesBegin(), digi.samplesEnd()) - digi.samplesBegin();
0580         channelPlots_[detId].cellOfMax->Fill((int)cellOfMax);
0581 
0582         if (timeOfPreviousEvent_ != 0)
0583           channelPlots_[detId].hitTime->Fill(1e-3 * LHC_CLOCK_PERIOD_NS *
0584                                              (event.time().value() - timeOfPreviousEvent_));
0585         ++(lumiCache->hitsCounterMap[detId]);
0586       }
0587     }
0588   }
0589   // End digis
0590 
0591   for (const auto &rechits : *timingRecHits) {
0592     const TotemTimingDetId detId(rechits.detId());
0593     TotemTimingDetId detId_pot(rechits.detId());
0594     detId_pot.setPlane(0);
0595     detId_pot.setChannel(0);
0596     TotemTimingDetId detId_plane(rechits.detId());
0597     detId_plane.setChannel(0);
0598 
0599     for (const auto &rechit : rechits) {
0600       if (potPlots_.find(detId_pot) != potPlots_.end()) {
0601         potPlots_[detId_pot].amplitude->Fill(rechit.amplitude());
0602 
0603         TH2F *hitHistoTmp = potPlots_[detId_pot].hitDistribution2d->getTH2F();
0604         TAxis *hitHistoTmpYAxis = hitHistoTmp->GetYaxis();
0605         float yCorrected = rechit.y();
0606         yCorrected += (detId.rp() == TOTEM_TIMING_TOP_RP_ID) ? verticalShiftTop_ : verticalShiftBot_;
0607         float x_shift = detId.plane();
0608         x_shift += (rechit.x() > 2) ? 0.25 : 0;
0609         int startBin = hitHistoTmpYAxis->FindBin(yCorrected - 0.5 * rechit.yWidth());
0610         int numOfBins = rechit.yWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0611         for (int i = 0; i < numOfBins; ++i) {
0612           potPlots_[detId_pot].hitDistribution2d->Fill(detId.plane() + 0.25 * (rechit.x() > 2),
0613                                                        hitHistoTmpYAxis->GetBinCenter(startBin + i));
0614           if (!perLSsaving_)
0615             potPlots_[detId_pot].hitDistribution2d_lumisection->Fill(x_shift,
0616                                                                      hitHistoTmpYAxis->GetBinCenter(startBin + i));
0617         }
0618 
0619         //All plots with Time
0620         if (rechit.time() != TotemTimingRecHit::NO_T_AVAILABLE) {
0621           for (int i = 0; i < numOfBins; ++i)
0622             potPlots_[detId_pot].hitDistribution2dWithTime->Fill(detId.plane() + 0.25 * (rechit.x() > 2),
0623                                                                  hitHistoTmpYAxis->GetBinCenter(startBin + i));
0624 
0625           potPlots_[detId_pot].recHitTime->Fill(rechit.time());
0626           potPlots_[detId_pot].planesWithTimeSet.insert(detId.plane());
0627 
0628           // Plane Plots
0629           if (planePlots_.find(detId_plane) != planePlots_.end()) {
0630             // Visualization tricks
0631             float x_shift = (rechit.x() > 2) ? 15 : 0;
0632             TH1F *hitProfileHistoTmp = planePlots_[detId_plane].hitProfile->getTH1F();
0633             int numOfBins = rechit.yWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM;
0634             if (detId.rp() == TOTEM_TIMING_TOP_RP_ID) {
0635               float yCorrected = rechit.y() + verticalShiftTop_ - 0.5 * rechit.yWidth() + x_shift;
0636               int startBin = hitProfileHistoTmp->FindBin(yCorrected);
0637               for (int i = 0; i < numOfBins; ++i)
0638                 hitProfileHistoTmp->Fill(hitProfileHistoTmp->GetBinCenter(startBin + i));
0639             } else {
0640               float yCorrected = rechit.y() + verticalShiftBot_ + 0.5 * rechit.yWidth() + (15 - x_shift);
0641               int startBin = hitProfileHistoTmp->FindBin(yCorrected);
0642               int totBins = hitProfileHistoTmp->GetNbinsX();
0643               for (int i = 0; i < numOfBins; ++i)
0644                 hitProfileHistoTmp->Fill(hitProfileHistoTmp->GetBinCenter(totBins - startBin + i));
0645             }
0646 
0647             if (channelsPerPlaneWithTime.find(detId_plane) != channelsPerPlaneWithTime.end())
0648               channelsPerPlaneWithTime[detId_plane]++;
0649             else
0650               channelsPerPlaneWithTime[detId_plane] = 0;
0651           }
0652 
0653           if (channelPlots_.find(detId) != channelPlots_.end()) {
0654             potPlots_[detId_pot].tirggerCellTime->Fill(rechit.sampicThresholdTime());
0655             channelPlots_[detId].tirggerCellTime->Fill(rechit.sampicThresholdTime());
0656             channelPlots_[detId].recHitTime->Fill(rechit.time());
0657             channelPlots_[detId].amplitude->Fill(rechit.amplitude());
0658           }
0659         }
0660       }
0661     }
0662   }
0663   // End RecHits
0664 
0665   // Tomography of timing using strips
0666   for (const auto &rechits : *timingRecHits) {
0667     const TotemTimingDetId detId(rechits.detId());
0668     TotemTimingDetId detId_pot(rechits.detId());
0669     detId_pot.setPlane(0);
0670     detId_pot.setChannel(0);
0671     TotemTimingDetId detId_plane(rechits.detId());
0672     detId_plane.setChannel(0);
0673 
0674     float y_shift = (detId.rp() == TOTEM_TIMING_TOP_RP_ID) ? 20 : 5;
0675 
0676     for (const auto &rechit : rechits) {
0677       if (rechit.time() != TotemTimingRecHit::NO_T_AVAILABLE && potPlots_.find(detId_pot) != potPlots_.end() &&
0678           planePlots_.find(detId_plane) != planePlots_.end() && channelPlots_.find(detId) != channelPlots_.end()) {
0679         if (stripTracks.isValid()) {
0680           for (const auto &ds : *stripTracks) {
0681             const CTPPSDetId stripId(ds.detId());
0682             // mean position of U and V planes
0683             TotemRPDetId plId_V(stripId);
0684             plId_V.setPlane(0);
0685             TotemRPDetId plId_U(stripId);
0686             plId_U.setPlane(1);
0687 
0688             double rp_x = 0;
0689             double rp_y = 0;
0690             try {
0691               rp_x = (geometry.sensor(plId_V)->translation().x() + geometry.sensor(plId_U)->translation().x()) / 2;
0692               rp_y = (geometry.sensor(plId_V)->translation().y() + geometry.sensor(plId_U)->translation().y()) / 2;
0693             } catch (const cms::Exception &) {
0694               continue;
0695             }
0696 
0697             for (const auto &striplt : ds) {
0698               if (striplt.isValid() && stripId.arm() == detId.arm()) {
0699                 if (striplt.tx() > maximumStripAngleForTomography_ || striplt.ty() > maximumStripAngleForTomography_)
0700                   continue;
0701                 if (striplt.tx() < minimumStripAngleForTomography_ || striplt.ty() < minimumStripAngleForTomography_)
0702                   continue;
0703                 if (stripId.rp() - detId.rp() == (TOTEM_STRIP_MAX_RP_ID - TOTEM_TIMING_BOT_RP_ID)) {
0704                   double x = striplt.x0() - rp_x;
0705                   double y = striplt.y0() - rp_y;
0706                   if (stripId.station() == TOTEM_STATION_210) {
0707                     potPlots_[detId_pot].stripTomography210->Fill(x + detId.plane() * 50, y + y_shift);
0708                     channelPlots_[detId].stripTomography210->Fill(x, y + y_shift);
0709                   } else if (stripId.station() == TOTEM_STATION_220) {
0710                     potPlots_[detId_pot].stripTomography220->Fill(x + detId.plane() * 50, y + y_shift);
0711                     channelPlots_[detId].stripTomography220->Fill(x, y + y_shift);
0712                   }
0713                 }
0714               }
0715             }
0716           }
0717         }
0718       }
0719     }
0720   }
0721 
0722   for (auto &plt : potPlots_) {
0723     plt.second.planesWithDigis->Fill(plt.second.planesWithDigisSet.size());
0724     plt.second.planesWithDigisSet.clear();
0725     plt.second.planesWithTime->Fill(plt.second.planesWithTimeSet.size());
0726     plt.second.planesWithTimeSet.clear();
0727   }
0728 
0729   for (const auto &plt : channelsPerPlane) {
0730     planePlots_[plt.first].hitMultiplicity->Fill(plt.second);
0731   }
0732   for (const auto &plt : channelsPerPlaneWithTime) {
0733     planePlots_[plt.first].hitMultiplicityWithTime->Fill(plt.second);
0734   }
0735 
0736   timeOfPreviousEvent_ = event.time().value();
0737 }
0738 
0739 //----------------------------------------------------------------------------------------------------
0740 
0741 void TotemTimingDQMSource::globalEndLuminosityBlock(const edm::LuminosityBlock &iLumi, const edm::EventSetup &) {
0742   auto lumiCache = luminosityBlockCache(iLumi.index());
0743   if (!perLSsaving_) {
0744     for (auto &plot : potPlots_) {
0745       *(plot.second.hitDistribution2d_lumisection->getTH2F()) = *(lumiCache->hitDistribution2dMap[plot.first]);
0746     }
0747 
0748     globalPlot_.digiSentPercentage->Reset();
0749     TH2F *hitHistoGlobalTmp = globalPlot_.digiSentPercentage->getTH2F();
0750     for (auto &plot : potPlots_) {
0751       TH2F *hitHistoTmp = plot.second.digiSentPercentage->getTH2F();
0752       TH2F *histoSent = plot.second.digiSent->getTH2F();
0753       TH2F *histoAll = plot.second.digiAll->getTH2F();
0754 
0755       hitHistoTmp->Divide(histoSent, histoAll);
0756       hitHistoTmp->Scale(100);
0757       hitHistoGlobalTmp->Add(hitHistoTmp, 1);
0758 
0759       plot.second.baseline->Reset();
0760       plot.second.noiseRMS->Reset();
0761       plot.second.meanAmplitude->Reset();
0762       plot.second.cellOfMax->Reset();
0763       plot.second.hitRate->Reset();
0764       TotemTimingDetId rpId(plot.first);
0765       for (auto &chPlot : channelPlots_) {
0766         TotemTimingDetId chId(chPlot.first);
0767         if (chId.arm() == rpId.arm() && chId.rp() == rpId.rp()) {
0768           plot.second.baseline->Fill(chId.plane(), chId.channel(), chPlot.second.noiseSamples->getTH1F()->GetMean());
0769           plot.second.noiseRMS->Fill(chId.plane(), chId.channel(), chPlot.second.noiseSamples->getTH1F()->GetRMS());
0770           plot.second.meanAmplitude->Fill(chId.plane(), chId.channel(), chPlot.second.amplitude->getTH1F()->GetMean());
0771           plot.second.cellOfMax->Fill(chId.plane(), chId.channel(), chPlot.second.cellOfMax->getTH1F()->GetMean());
0772           auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[chPlot.first];
0773           plot.second.hitRate->Fill(chId.plane(), chId.channel(), (double)hitsCounterPerLumisection * HIT_RATE_FACTOR);
0774         }
0775       }
0776     }
0777 
0778     for (auto &plot : channelPlots_) {
0779       auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[plot.first];
0780       if (hitsCounterPerLumisection != 0) {
0781         plot.second.hitRate->Fill((double)hitsCounterPerLumisection * HIT_RATE_FACTOR);
0782       }
0783     }
0784   }
0785 }
0786 
0787 DEFINE_FWK_MODULE(TotemTimingDQMSource);