Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-08-30 04:06:16

0001 // -*- C++ -*-
0002 //
0003 // Package:    Validation/MtdValidation
0004 // Class:      EtlLocalRecoValidation
0005 //
0006 /**\class EtlLocalRecoValidation EtlLocalRecoValidation.cc Validation/MtdValidation/plugins/EtlLocalRecoValidation.cc
0007 
0008  Description: ETL RECO hits and clusters validation
0009 
0010  Implementation:
0011      [Notes on implementation]
0012 */
0013 
0014 #include <string>
0015 
0016 #include "FWCore/Framework/interface/Frameworkfwd.h"
0017 #include "FWCore/Framework/interface/Event.h"
0018 #include "FWCore/Framework/interface/MakerMacros.h"
0019 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0020 
0021 #include "DQMServices/Core/interface/DQMEDAnalyzer.h"
0022 #include "DQMServices/Core/interface/DQMStore.h"
0023 
0024 #include "DataFormats/Common/interface/ValidHandle.h"
0025 #include "DataFormats/Math/interface/GeantUnits.h"
0026 #include "DataFormats/ForwardDetId/interface/ETLDetId.h"
0027 #include "DataFormats/FTLRecHit/interface/FTLRecHitCollections.h"
0028 #include "DataFormats/FTLRecHit/interface/FTLClusterCollections.h"
0029 #include "DataFormats/TrackerRecHit2D/interface/MTDTrackingRecHit.h"
0030 
0031 #include "SimDataFormats/CrossingFrame/interface/CrossingFrame.h"
0032 #include "SimDataFormats/CrossingFrame/interface/MixCollection.h"
0033 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
0034 
0035 #include "Geometry/Records/interface/MTDDigiGeometryRecord.h"
0036 #include "Geometry/MTDGeometryBuilder/interface/MTDGeometry.h"
0037 #include "Geometry/MTDGeometryBuilder/interface/ProxyMTDTopology.h"
0038 #include "Geometry/MTDGeometryBuilder/interface/RectangularMTDTopology.h"
0039 #include "Geometry/MTDNumberingBuilder/interface/MTDTopology.h"
0040 #include "Geometry/MTDCommonData/interface/MTDTopologyMode.h"
0041 
0042 #include "MTDHit.h"
0043 
0044 class EtlLocalRecoValidation : public DQMEDAnalyzer {
0045 public:
0046   explicit EtlLocalRecoValidation(const edm::ParameterSet&);
0047   ~EtlLocalRecoValidation() override;
0048 
0049   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0050 
0051 private:
0052   void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&) override;
0053 
0054   void analyze(const edm::Event&, const edm::EventSetup&) override;
0055 
0056   bool isSameCluster(const FTLCluster&, const FTLCluster&);
0057 
0058   // ------------ member data ------------
0059 
0060   const std::string folder_;
0061   const float hitMinEnergy1Dis_;
0062   const float hitMinEnergy2Dis_;
0063   const bool optionalPlots_;
0064   const bool uncalibRecHitsPlots_;
0065   const double hitMinAmplitude_;
0066 
0067   edm::EDGetTokenT<FTLRecHitCollection> etlRecHitsToken_;
0068   edm::EDGetTokenT<FTLUncalibratedRecHitCollection> etlUncalibRecHitsToken_;
0069   edm::EDGetTokenT<CrossingFrame<PSimHit> > etlSimHitsToken_;
0070   edm::EDGetTokenT<FTLClusterCollection> etlRecCluToken_;
0071   edm::EDGetTokenT<MTDTrackingDetSetVector> mtdTrackingHitToken_;
0072 
0073   edm::ESGetToken<MTDGeometry, MTDDigiGeometryRecord> mtdgeoToken_;
0074   edm::ESGetToken<MTDTopology, MTDTopologyRcd> mtdtopoToken_;
0075 
0076   // --- histograms declaration
0077 
0078   MonitorElement* meNhits_[4];
0079   MonitorElement* meHitEnergy_[4];
0080   MonitorElement* meHitTime_[4];
0081   MonitorElement* meHitTimeError_[4];
0082 
0083   MonitorElement* meOccupancy_[4];
0084 
0085   MonitorElement* meLocalOccupancy_[2];
0086   MonitorElement* meHitXlocal_[2];
0087   MonitorElement* meHitYlocal_[2];
0088 
0089   MonitorElement* meHitX_[4];
0090   MonitorElement* meHitY_[4];
0091   MonitorElement* meHitZ_[4];
0092   MonitorElement* meHitPhi_[4];
0093   MonitorElement* meHitEta_[4];
0094 
0095   MonitorElement* meHitTvsE_[4];
0096   MonitorElement* meHitEvsPhi_[4];
0097   MonitorElement* meHitEvsEta_[4];
0098   MonitorElement* meHitTvsPhi_[4];
0099   MonitorElement* meHitTvsEta_[4];
0100 
0101   MonitorElement* meCluTime_[4];
0102   MonitorElement* meCluTimeError_[4];
0103   MonitorElement* meCluEnergy_[4];
0104   MonitorElement* meCluPhi_[4];
0105   MonitorElement* meCluEta_[4];
0106   MonitorElement* meCluHits_[4];
0107   MonitorElement* meCluOccupancy_[4];
0108 
0109   MonitorElement* meTimeRes_;
0110   MonitorElement* meEnergyRes_;
0111   MonitorElement* meTPullvsE_;
0112   MonitorElement* meTPullvsEta_;
0113 
0114   MonitorElement* meCluTimeRes_[2];
0115   MonitorElement* meCluEnergyRes_[2];
0116   MonitorElement* meCluTPullvsE_[2];
0117   MonitorElement* meCluTPullvsEta_[2];
0118   MonitorElement* meCluXRes_[2];
0119   MonitorElement* meCluYRes_[2];
0120   MonitorElement* meCluZRes_[2];
0121   MonitorElement* meCluXPull_[2];
0122   MonitorElement* meCluYPull_[2];
0123   MonitorElement* meCluYXLocal_[2];
0124   MonitorElement* meCluYXLocalSim_[2];
0125   MonitorElement* meCluXLocalErr_[2];
0126   MonitorElement* meCluYLocalErr_[2];
0127 
0128   MonitorElement* meUnmatchedCluEnergy_[2];
0129 
0130   // --- UncalibratedRecHits histograms
0131 
0132   static constexpr int nBinsQ_ = 20;
0133   static constexpr float binWidthQ_ = 1.3;  // in MIP units
0134 
0135   MonitorElement* meTimeResQ_[2][nBinsQ_];
0136 
0137   static constexpr int nBinsEta_ = 26;
0138   static constexpr float binWidthEta_ = 0.05;
0139   static constexpr float etaMin_ = 1.65;
0140 
0141   MonitorElement* meTimeResEta_[2][nBinsEta_];
0142 };
0143 
0144 bool EtlLocalRecoValidation::isSameCluster(const FTLCluster& clu1, const FTLCluster& clu2) {
0145   return clu1.id() == clu2.id() && clu1.size() == clu2.size() && clu1.x() == clu2.x() && clu1.y() == clu2.y() &&
0146          clu1.time() == clu2.time();
0147 }
0148 
0149 // ------------ constructor and destructor --------------
0150 EtlLocalRecoValidation::EtlLocalRecoValidation(const edm::ParameterSet& iConfig)
0151     : folder_(iConfig.getParameter<std::string>("folder")),
0152       hitMinEnergy1Dis_(iConfig.getParameter<double>("hitMinimumEnergy1Dis")),
0153       hitMinEnergy2Dis_(iConfig.getParameter<double>("hitMinimumEnergy2Dis")),
0154       optionalPlots_(iConfig.getParameter<bool>("optionalPlots")),
0155       uncalibRecHitsPlots_(iConfig.getParameter<bool>("UncalibRecHitsPlots")),
0156       hitMinAmplitude_(iConfig.getParameter<double>("HitMinimumAmplitude")) {
0157   etlRecHitsToken_ = consumes<FTLRecHitCollection>(iConfig.getParameter<edm::InputTag>("recHitsTag"));
0158   if (uncalibRecHitsPlots_)
0159     etlUncalibRecHitsToken_ =
0160         consumes<FTLUncalibratedRecHitCollection>(iConfig.getParameter<edm::InputTag>("uncalibRecHitsTag"));
0161   etlSimHitsToken_ = consumes<CrossingFrame<PSimHit> >(iConfig.getParameter<edm::InputTag>("simHitsTag"));
0162   etlRecCluToken_ = consumes<FTLClusterCollection>(iConfig.getParameter<edm::InputTag>("recCluTag"));
0163   mtdTrackingHitToken_ = consumes<MTDTrackingDetSetVector>(iConfig.getParameter<edm::InputTag>("trkHitTag"));
0164 
0165   mtdgeoToken_ = esConsumes<MTDGeometry, MTDDigiGeometryRecord>();
0166   mtdtopoToken_ = esConsumes<MTDTopology, MTDTopologyRcd>();
0167 }
0168 
0169 EtlLocalRecoValidation::~EtlLocalRecoValidation() {}
0170 
0171 // ------------ method called for each event  ------------
0172 void EtlLocalRecoValidation::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
0173   using namespace edm;
0174   using namespace std;
0175   using namespace geant_units::operators;
0176 
0177   auto geometryHandle = iSetup.getTransientHandle(mtdgeoToken_);
0178   const MTDGeometry* geom = geometryHandle.product();
0179 
0180   auto topologyHandle = iSetup.getTransientHandle(mtdtopoToken_);
0181   const MTDTopology* topology = topologyHandle.product();
0182 
0183   bool topo1Dis = false;
0184   bool topo2Dis = false;
0185   if (MTDTopologyMode::etlLayoutFromTopoMode(topology->getMTDTopologyMode()) == ETLDetId::EtlLayout::tp) {
0186     topo1Dis = true;
0187   } else {
0188     topo2Dis = true;
0189   }
0190 
0191   auto etlRecHitsHandle = makeValid(iEvent.getHandle(etlRecHitsToken_));
0192   auto etlSimHitsHandle = makeValid(iEvent.getHandle(etlSimHitsToken_));
0193   auto etlRecCluHandle = makeValid(iEvent.getHandle(etlRecCluToken_));
0194   auto mtdTrkHitHandle = makeValid(iEvent.getHandle(mtdTrackingHitToken_));
0195   MixCollection<PSimHit> etlSimHits(etlSimHitsHandle.product());
0196 
0197 #ifdef EDM_ML_DEBUG
0198   for (const auto& hits : *mtdTrkHitHandle) {
0199     if (MTDDetId(hits.id()).mtdSubDetector() == MTDDetId::MTDType::ETL) {
0200       LogDebug("EtlLocalRecoValidation") << "MTD cluster DetId " << hits.id() << " # cluster " << hits.size();
0201       for (const auto& hit : hits) {
0202         LogDebug("EtlLocalRecoValidation")
0203             << "MTD_TRH: " << hit.localPosition().x() << "," << hit.localPosition().y() << " : "
0204             << hit.localPositionError().xx() << "," << hit.localPositionError().yy() << " : " << hit.time() << " : "
0205             << hit.timeError();
0206       }
0207     }
0208   }
0209 #endif
0210 
0211   // --- Loop over the ETL SIM hits
0212   std::unordered_map<uint32_t, MTDHit> m_etlSimHits[4];
0213   for (auto const& simHit : etlSimHits) {
0214     // --- Use only hits compatible with the in-time bunch-crossing
0215     if (simHit.tof() < 0 || simHit.tof() > 25.)
0216       continue;
0217 
0218     ETLDetId id = simHit.detUnitId();
0219 
0220     int idet = -1;
0221 
0222     if ((id.zside() == -1) && (id.nDisc() == 1))
0223       idet = 0;
0224     else if ((id.zside() == -1) && (id.nDisc() == 2))
0225       idet = 1;
0226     else if ((id.zside() == 1) && (id.nDisc() == 1))
0227       idet = 2;
0228     else if ((id.zside() == 1) && (id.nDisc() == 2))
0229       idet = 3;
0230     else
0231       continue;
0232 
0233     auto simHitIt = m_etlSimHits[idet].emplace(id.rawId(), MTDHit()).first;
0234 
0235     // --- Accumulate the energy (in MeV) of SIM hits in the same detector cell
0236     (simHitIt->second).energy += convertUnitsTo(0.001_MeV, simHit.energyLoss());
0237 
0238     // --- Get the time of the first SIM hit in the cell
0239     if ((simHitIt->second).time == 0 || simHit.tof() < (simHitIt->second).time) {
0240       (simHitIt->second).time = simHit.tof();
0241 
0242       auto hit_pos = simHit.entryPoint();
0243       (simHitIt->second).x = hit_pos.x();
0244       (simHitIt->second).y = hit_pos.y();
0245       (simHitIt->second).z = hit_pos.z();
0246     }
0247 
0248   }  // simHit loop
0249 
0250   // --- Loop over the ELT RECO hits
0251   unsigned int n_reco_etl[4] = {0, 0, 0, 0};
0252   for (const auto& recHit : *etlRecHitsHandle) {
0253     double weight = 1.0;
0254     ETLDetId detId = recHit.id();
0255     DetId geoId = detId.geographicalId();
0256     const MTDGeomDet* thedet = geom->idToDet(geoId);
0257     if (thedet == nullptr)
0258       throw cms::Exception("EtlLocalRecoValidation") << "GeographicalID: " << std::hex << geoId.rawId() << " ("
0259                                                      << detId.rawId() << ") is invalid!" << std::dec << std::endl;
0260     const ProxyMTDTopology& topoproxy = static_cast<const ProxyMTDTopology&>(thedet->topology());
0261     const RectangularMTDTopology& topo = static_cast<const RectangularMTDTopology&>(topoproxy.specificTopology());
0262 
0263     Local3DPoint local_point(topo.localX(recHit.row()), topo.localY(recHit.column()), 0.);
0264     const auto& global_point = thedet->toGlobal(local_point);
0265 
0266     int idet = 999;
0267 
0268     if (topo1Dis) {
0269       if (detId.zside() == -1) {
0270         idet = 0;
0271       } else if (detId.zside() == 1) {
0272         idet = 2;
0273       } else {
0274         continue;
0275       }
0276     }
0277 
0278     if (topo2Dis) {
0279       if (detId.discSide() == 1) {
0280         weight = -weight;
0281       }
0282       if ((detId.zside() == -1) && (detId.nDisc() == 1)) {
0283         idet = 0;
0284       } else if ((detId.zside() == -1) && (detId.nDisc() == 2)) {
0285         idet = 1;
0286       } else if ((detId.zside() == 1) && (detId.nDisc() == 1)) {
0287         idet = 2;
0288       } else if ((detId.zside() == 1) && (detId.nDisc() == 2)) {
0289         idet = 3;
0290       } else {
0291         continue;
0292       }
0293     }
0294 
0295     // --- Fill the histograms
0296 
0297     meHitEnergy_[idet]->Fill(recHit.energy());
0298     meHitTime_[idet]->Fill(recHit.time());
0299     meHitTimeError_[idet]->Fill(recHit.timeError());
0300 
0301     meOccupancy_[idet]->Fill(global_point.x(), global_point.y(), weight);
0302 
0303     if (optionalPlots_) {
0304       if ((idet == 0) || (idet == 1)) {
0305         meLocalOccupancy_[0]->Fill(local_point.x(), local_point.y());
0306         meHitXlocal_[0]->Fill(local_point.x());
0307         meHitYlocal_[0]->Fill(local_point.y());
0308       }
0309       if ((idet == 2) || (idet == 3)) {
0310         meLocalOccupancy_[1]->Fill(local_point.x(), local_point.y());
0311         meHitXlocal_[1]->Fill(local_point.x());
0312         meHitYlocal_[1]->Fill(local_point.y());
0313       }
0314     }
0315     meHitX_[idet]->Fill(global_point.x());
0316     meHitY_[idet]->Fill(global_point.y());
0317     meHitZ_[idet]->Fill(global_point.z());
0318     meHitPhi_[idet]->Fill(global_point.phi());
0319     meHitEta_[idet]->Fill(global_point.eta());
0320     meHitTvsE_[idet]->Fill(recHit.energy(), recHit.time());
0321     meHitEvsPhi_[idet]->Fill(global_point.phi(), recHit.energy());
0322     meHitEvsEta_[idet]->Fill(global_point.eta(), recHit.energy());
0323     meHitTvsPhi_[idet]->Fill(global_point.phi(), recHit.time());
0324     meHitTvsEta_[idet]->Fill(global_point.eta(), recHit.time());
0325 
0326     // Resolution histograms
0327     if (m_etlSimHits[idet].count(detId.rawId()) == 1) {
0328       if ((topo1Dis && m_etlSimHits[idet][detId.rawId()].energy > hitMinEnergy1Dis_) ||
0329           (topo2Dis && m_etlSimHits[idet][detId.rawId()].energy > hitMinEnergy2Dis_)) {
0330         float time_res = recHit.time() - m_etlSimHits[idet][detId.rawId()].time;
0331         float energy_res = recHit.energy() - m_etlSimHits[idet][detId.rawId()].energy;
0332 
0333         meTimeRes_->Fill(time_res);
0334         meEnergyRes_->Fill(energy_res);
0335 
0336         meTPullvsEta_->Fill(std::abs(global_point.eta()), time_res / recHit.timeError());
0337         meTPullvsE_->Fill(m_etlSimHits[idet][detId.rawId()].energy, time_res / recHit.timeError());
0338       }
0339     }
0340 
0341     n_reco_etl[idet]++;
0342   }  // recHit loop
0343 
0344   if (topo1Dis) {
0345     meNhits_[0]->Fill(n_reco_etl[0]);
0346     meNhits_[2]->Fill(n_reco_etl[2]);
0347   }
0348 
0349   if (topo2Dis) {
0350     for (int i = 0; i < 4; i++) {
0351       meNhits_[i]->Fill(n_reco_etl[i]);
0352     }
0353   }
0354 
0355   // --- Loop over the ETL RECO clusters ---
0356   for (const auto& DetSetClu : *etlRecCluHandle) {
0357     for (const auto& cluster : DetSetClu) {
0358       double weight = 1.0;
0359       if (topo1Dis) {
0360         if (cluster.energy() < hitMinEnergy1Dis_)
0361           continue;
0362       }
0363       if (topo2Dis) {
0364         if (cluster.energy() < hitMinEnergy2Dis_)
0365           continue;
0366       }
0367       ETLDetId cluId = cluster.id();
0368       DetId detIdObject(cluId);
0369       const auto& genericDet = geom->idToDetUnit(detIdObject);
0370       if (genericDet == nullptr) {
0371         throw cms::Exception("EtlLocalRecoValidation")
0372             << "GeographicalID: " << std::hex << cluId << " is invalid!" << std::dec << std::endl;
0373       }
0374       const ProxyMTDTopology& topoproxy = static_cast<const ProxyMTDTopology&>(genericDet->topology());
0375       const RectangularMTDTopology& topo = static_cast<const RectangularMTDTopology&>(topoproxy.specificTopology());
0376 
0377       Local3DPoint local_point(topo.localX(cluster.x()), topo.localY(cluster.y()), 0.);
0378       const auto& global_point = genericDet->toGlobal(local_point);
0379 
0380       int idet = 999;
0381 
0382       if (topo1Dis) {
0383         if (cluId.zside() == -1) {
0384           idet = 0;
0385         } else if (cluId.zside() == 1) {
0386           idet = 2;
0387         } else {
0388           continue;
0389         }
0390       }
0391 
0392       if (topo2Dis) {
0393         if (cluId.discSide() == 1) {
0394           weight = -weight;
0395         }
0396         if ((cluId.zside() == -1) && (cluId.nDisc() == 1)) {
0397           idet = 0;
0398         } else if ((cluId.zside() == -1) && (cluId.nDisc() == 2)) {
0399           idet = 1;
0400         } else if ((cluId.zside() == 1) && (cluId.nDisc() == 1)) {
0401           idet = 2;
0402         } else if ((cluId.zside() == 1) && (cluId.nDisc() == 2)) {
0403           idet = 3;
0404         } else {
0405           continue;
0406         }
0407       }
0408 
0409       meCluEnergy_[idet]->Fill(cluster.energy());
0410       meCluTime_[idet]->Fill(cluster.time());
0411       meCluTimeError_[idet]->Fill(cluster.timeError());
0412       meCluPhi_[idet]->Fill(global_point.phi());
0413       meCluEta_[idet]->Fill(global_point.eta());
0414       meCluOccupancy_[idet]->Fill(global_point.x(), global_point.y(), weight);
0415       meCluHits_[idet]->Fill(cluster.size());
0416 
0417       // --- Get the SIM hits associated to the cluster and calculate
0418       //     the cluster SIM energy, time and position
0419 
0420       double cluEneSIM = 0.;
0421       double cluTimeSIM = 0.;
0422       double cluLocXSIM = 0.;
0423       double cluLocYSIM = 0.;
0424       double cluLocZSIM = 0.;
0425 
0426       for (int ihit = 0; ihit < cluster.size(); ++ihit) {
0427         int hit_row = cluster.minHitRow() + cluster.hitOffset()[ihit * 2];
0428         int hit_col = cluster.minHitCol() + cluster.hitOffset()[ihit * 2 + 1];
0429 
0430         // Match the RECO hit to the corresponding SIM hit
0431         for (const auto& recHit : *etlRecHitsHandle) {
0432           ETLDetId hitId(recHit.id().rawId());
0433 
0434           if (m_etlSimHits[idet].count(hitId.rawId()) == 0)
0435             continue;
0436 
0437           // Check the hit position
0438           if (hitId.zside() != cluId.zside() || hitId.mtdRR() != cluId.mtdRR() || hitId.module() != cluId.module() ||
0439               recHit.row() != hit_row || recHit.column() != hit_col)
0440             continue;
0441 
0442           // Check the hit energy and time
0443           if (recHit.energy() != cluster.hitENERGY()[ihit] || recHit.time() != cluster.hitTIME()[ihit])
0444             continue;
0445 
0446           // SIM hit's position in the module reference frame
0447           Local3DPoint local_point_sim(convertMmToCm(m_etlSimHits[idet][recHit.id().rawId()].x),
0448                                        convertMmToCm(m_etlSimHits[idet][recHit.id().rawId()].y),
0449                                        convertMmToCm(m_etlSimHits[idet][recHit.id().rawId()].z));
0450 
0451           // Calculate the SIM cluster's position in the module reference frame
0452           cluLocXSIM += local_point_sim.x() * m_etlSimHits[idet][recHit.id().rawId()].energy;
0453           cluLocYSIM += local_point_sim.y() * m_etlSimHits[idet][recHit.id().rawId()].energy;
0454           cluLocZSIM += local_point_sim.z() * m_etlSimHits[idet][recHit.id().rawId()].energy;
0455 
0456           // Calculate the SIM cluster energy and time
0457           cluEneSIM += m_etlSimHits[idet][recHit.id().rawId()].energy;
0458           cluTimeSIM += m_etlSimHits[idet][recHit.id().rawId()].time * m_etlSimHits[idet][recHit.id().rawId()].energy;
0459 
0460           break;
0461 
0462         }  // recHit loop
0463 
0464       }  // ihit loop
0465 
0466       // Find the MTDTrackingRecHit corresponding to the cluster
0467       MTDTrackingRecHit* comp(nullptr);
0468       bool matchClu = false;
0469       const auto& trkHits = (*mtdTrkHitHandle)[detIdObject];
0470       for (const auto& trkHit : trkHits) {
0471         if (isSameCluster(trkHit.mtdCluster(), cluster)) {
0472           comp = trkHit.clone();
0473           matchClu = true;
0474           break;
0475         }
0476       }
0477       if (!matchClu) {
0478         edm::LogWarning("BtlLocalRecoValidation")
0479             << "No valid TrackingRecHit corresponding to cluster, detId = " << detIdObject.rawId();
0480       }
0481 
0482       // --- Fill the cluster resolution histograms
0483       int iside = (cluId.zside() == -1 ? 0 : 1);
0484       if (cluTimeSIM > 0. && cluEneSIM > 0.) {
0485         cluTimeSIM /= cluEneSIM;
0486 
0487         Local3DPoint cluLocalPosSIM(cluLocXSIM / cluEneSIM, cluLocYSIM / cluEneSIM, cluLocZSIM / cluEneSIM);
0488         const auto& cluGlobalPosSIM = genericDet->toGlobal(cluLocalPosSIM);
0489 
0490         float time_res = cluster.time() - cluTimeSIM;
0491         float energy_res = cluster.energy() - cluEneSIM;
0492         float x_res = global_point.x() - cluGlobalPosSIM.x();
0493         float y_res = global_point.y() - cluGlobalPosSIM.y();
0494         float z_res = global_point.z() - cluGlobalPosSIM.z();
0495 
0496         meCluTimeRes_[iside]->Fill(time_res);
0497         meCluEnergyRes_[iside]->Fill(energy_res);
0498         meCluXRes_[iside]->Fill(x_res);
0499         meCluYRes_[iside]->Fill(y_res);
0500         meCluZRes_[iside]->Fill(z_res);
0501 
0502         meCluTPullvsEta_[iside]->Fill(cluGlobalPosSIM.eta(), time_res / cluster.timeError());
0503         meCluTPullvsE_[iside]->Fill(cluEneSIM, time_res / cluster.timeError());
0504 
0505         if (optionalPlots_) {
0506           if (matchClu && comp != nullptr) {
0507             meCluXPull_[iside]->Fill(x_res / std::sqrt(comp->globalPositionError().cxx()));
0508             meCluYPull_[iside]->Fill(y_res / std::sqrt(comp->globalPositionError().cyy()));
0509             meCluXLocalErr_[iside]->Fill(std::sqrt(comp->localPositionError().xx()));
0510             meCluYLocalErr_[iside]->Fill(std::sqrt(comp->localPositionError().yy()));
0511           }
0512           meCluYXLocal_[iside]->Fill(local_point.x(), local_point.y());
0513           meCluYXLocalSim_[iside]->Fill(cluLocalPosSIM.x(), cluLocalPosSIM.y());
0514         }
0515 
0516       }  // if ( cluTimeSIM > 0. &&  cluEneSIM > 0. )
0517       else {
0518         meUnmatchedCluEnergy_[iside]->Fill(std::log10(cluster.energy()));
0519       }
0520 
0521     }  // cluster loop
0522 
0523   }  // DetSetClu loop
0524 
0525   // --- Loop over the ETL Uncalibrated RECO hits
0526   if (uncalibRecHitsPlots_) {
0527     auto etlUncalibRecHitsHandle = makeValid(iEvent.getHandle(etlUncalibRecHitsToken_));
0528 
0529     for (const auto& uRecHit : *etlUncalibRecHitsHandle) {
0530       ETLDetId detId = uRecHit.id();
0531 
0532       int idet = detId.zside() + detId.nDisc();
0533 
0534       // --- Skip UncalibratedRecHits not matched to SimHits
0535       if (m_etlSimHits[idet].count(detId.rawId()) != 1)
0536         continue;
0537 
0538       DetId geoId = detId.geographicalId();
0539       const MTDGeomDet* thedet = geom->idToDet(geoId);
0540       if (thedet == nullptr)
0541         throw cms::Exception("EtlLocalRecoValidation") << "GeographicalID: " << std::hex << geoId.rawId() << " ("
0542                                                        << detId.rawId() << ") is invalid!" << std::dec << std::endl;
0543 
0544       const ProxyMTDTopology& topoproxy = static_cast<const ProxyMTDTopology&>(thedet->topology());
0545       const RectangularMTDTopology& topo = static_cast<const RectangularMTDTopology&>(topoproxy.specificTopology());
0546 
0547       Local3DPoint local_point(topo.localX(uRecHit.row()), topo.localY(uRecHit.column()), 0.);
0548       const auto& global_point = thedet->toGlobal(local_point);
0549 
0550       // --- Fill the histograms
0551 
0552       if (uRecHit.amplitude().first < hitMinAmplitude_)
0553         continue;
0554 
0555       float time_res = uRecHit.time().first - m_etlSimHits[idet][detId.rawId()].time;
0556 
0557       int iside = (detId.zside() == -1 ? 0 : 1);
0558 
0559       // amplitude histograms
0560 
0561       int qBin = (int)(uRecHit.amplitude().first / binWidthQ_);
0562       if (qBin > nBinsQ_ - 1)
0563         qBin = nBinsQ_ - 1;
0564 
0565       meTimeResQ_[iside][qBin]->Fill(time_res);
0566 
0567       // eta histograms
0568 
0569       int etaBin = (int)((fabs(global_point.eta()) - etaMin_) / binWidthEta_);
0570       if (etaBin < 0)
0571         etaBin = 0;
0572       else if (etaBin > nBinsEta_ - 1)
0573         etaBin = nBinsEta_ - 1;
0574 
0575       meTimeResEta_[iside][etaBin]->Fill(time_res);
0576 
0577     }  // uRecHit loop
0578   }
0579 }
0580 
0581 // ------------ method for histogram booking ------------
0582 void EtlLocalRecoValidation::bookHistograms(DQMStore::IBooker& ibook,
0583                                             edm::Run const& run,
0584                                             edm::EventSetup const& iSetup) {
0585   ibook.setCurrentFolder(folder_);
0586 
0587   // --- histograms booking
0588 
0589   meNhits_[0] = ibook.book1D(
0590       "EtlNhitsZnegD1", "Number of ETL RECO hits (-Z, Single(topo1D)/First(topo2D) disk);N_{RECO}", 100, 0., 5000.);
0591   meNhits_[1] = ibook.book1D("EtlNhitsZnegD2", "Number of ETL RECO hits (-Z, Second disk);N_{RECO}", 100, 0., 5000.);
0592   meNhits_[2] = ibook.book1D(
0593       "EtlNhitsZposD1", "Number of ETL RECO hits (+Z, Single(topo1D)/First(topo2D) disk);N_{RECO}", 100, 0., 5000.);
0594   meNhits_[3] = ibook.book1D("EtlNhitsZposD2", "Number of ETL RECO hits (+Z, Second disk);N_{RECO}", 100, 0., 5000.);
0595   meHitEnergy_[0] = ibook.book1D(
0596       "EtlHitEnergyZnegD1", "ETL RECO hits energy (-Z, Single(topo1D)/First(topo2D) disk);E_{RECO} [MeV]", 100, 0., 3.);
0597   meHitEnergy_[1] =
0598       ibook.book1D("EtlHitEnergyZnegD2", "ETL RECO hits energy (-Z, Second disk);E_{RECO} [MeV]", 100, 0., 3.);
0599   meHitEnergy_[2] = ibook.book1D(
0600       "EtlHitEnergyZposD1", "ETL RECO hits energy (+Z, Single(topo1D)/First(topo2D) disk);E_{RECO} [MeV]", 100, 0., 3.);
0601   meHitEnergy_[3] =
0602       ibook.book1D("EtlHitEnergyZposD2", "ETL RECO hits energy (+Z, Second disk);E_{RECO} [MeV]", 100, 0., 3.);
0603   meHitTime_[0] = ibook.book1D(
0604       "EtlHitTimeZnegD1", "ETL RECO hits ToA (-Z, Single(topo1D)/First(topo2D) disk);ToA_{RECO} [ns]", 100, 0., 25.);
0605   meHitTime_[1] = ibook.book1D("EtlHitTimeZnegD2", "ETL RECO hits ToA (-Z, Second disk);ToA_{RECO} [ns]", 100, 0., 25.);
0606   meHitTime_[2] = ibook.book1D(
0607       "EtlHitTimeZposD1", "ETL RECO hits ToA (+Z, Single(topo1D)/First(topo2D) disk);ToA_{RECO} [ns]", 100, 0., 25.);
0608   meHitTime_[3] = ibook.book1D("EtlHitTimeZposD2", "ETL RECO hits ToA (+Z, Second disk);ToA_{RECO} [ns]", 100, 0., 25.);
0609   meHitTimeError_[0] =
0610       ibook.book1D("EtlHitTimeErrorZnegD1",
0611                    "ETL RECO hits ToA error (-Z, Single(topo1D)/First(topo2D) disk);#sigma^{ToA}_{RECO} [ns]",
0612                    50,
0613                    0.,
0614                    0.1);
0615   meHitTimeError_[1] = ibook.book1D(
0616       "EtlHitTimeErrorZnegD2", "ETL RECO hits ToA error(-Z, Second disk);#sigma^{ToA}_{RECO} [ns]", 50, 0., 0.1);
0617   meHitTimeError_[2] =
0618       ibook.book1D("EtlHitTimeErrorZposD1",
0619                    "ETL RECO hits ToA error (+Z, Single(topo1D)/First(topo2D) disk);#sigma^{ToA}_{RECO} [ns]",
0620                    50,
0621                    0.,
0622                    0.1);
0623   meHitTimeError_[3] = ibook.book1D(
0624       "EtlHitTimeErrorZposD2", "ETL RECO hits ToA error(+Z, Second disk);#sigma^{ToA}_{RECO} [ns]", 50, 0., 0.1);
0625 
0626   meOccupancy_[0] =
0627       ibook.book2D("EtlOccupancyZnegD1",
0628                    "ETL RECO hits occupancy (-Z, Single(topo1D)/First(topo2D) disk);X_{RECO} [cm];Y_{RECO} [cm]",
0629                    135,
0630                    -135.,
0631                    135.,
0632                    135,
0633                    -135.,
0634                    135.);
0635   meOccupancy_[1] = ibook.book2D("EtlOccupancyZnegD2",
0636                                  "ETL RECO hits occupancy (-Z, Second disk);X_{RECO} [cm];Y_{RECO} [cm]",
0637                                  135,
0638                                  -135.,
0639                                  135.,
0640                                  135,
0641                                  -135.,
0642                                  135.);
0643   meOccupancy_[2] =
0644       ibook.book2D("EtlOccupancyZposD1",
0645                    "ETL RECO hits occupancy (+Z, Single(topo1D)/First(topo2D) disk);X_{RECO} [cm];Y_{RECO} [cm]",
0646                    135,
0647                    -135.,
0648                    135.,
0649                    135,
0650                    -135.,
0651                    135.);
0652   meOccupancy_[3] = ibook.book2D("EtlOccupancyZposD2",
0653                                  "ETL RECO hits occupancy (+Z, Second disk);X_{RECO} [cm];Y_{RECO} [cm]",
0654                                  135,
0655                                  -135.,
0656                                  135.,
0657                                  135,
0658                                  -135.,
0659                                  135.);
0660   if (optionalPlots_) {
0661     meLocalOccupancy_[0] = ibook.book2D("EtlLocalOccupancyZneg",
0662                                         "ETL RECO hits local occupancy (-Z);X_{RECO} [cm];Y_{RECO} [cm]",
0663                                         100,
0664                                         -2.2,
0665                                         2.2,
0666                                         50,
0667                                         -1.1,
0668                                         1.1);
0669     meLocalOccupancy_[1] = ibook.book2D("EtlLocalOccupancyZpos",
0670                                         "ETL RECO hits local occupancy (+Z);X_{RECO} [cm];Y_{RECO} [cm]",
0671                                         100,
0672                                         -2.2,
0673                                         2.2,
0674                                         50,
0675                                         -1.1,
0676                                         1.1);
0677     meHitXlocal_[0] = ibook.book1D("EtlHitXlocalZneg", "ETL RECO local X (-Z);X_{RECO}^{LOC} [cm]", 100, -2.2, 2.2);
0678     meHitXlocal_[1] = ibook.book1D("EtlHitXlocalZpos", "ETL RECO local X (+Z);X_{RECO}^{LOC} [cm]", 100, -2.2, 2.2);
0679     meHitYlocal_[0] = ibook.book1D("EtlHitYlocalZneg", "ETL RECO local Y (-Z);Y_{RECO}^{LOC} [cm]", 50, -1.1, 1.1);
0680     meHitYlocal_[1] = ibook.book1D("EtlHitYlocalZpos", "ETL RECO local Y (-Z);Y_{RECO}^{LOC} [cm]", 50, -1.1, 1.1);
0681   }
0682   meHitX_[0] = ibook.book1D(
0683       "EtlHitXZnegD1", "ETL RECO hits X (-Z, Single(topo1D)/First(topo2D) Disk);X_{RECO} [cm]", 100, -130., 130.);
0684   meHitX_[1] = ibook.book1D("EtlHitXZnegD2", "ETL RECO hits X (-Z, Second Disk);X_{RECO} [cm]", 100, -130., 130.);
0685   meHitX_[2] = ibook.book1D(
0686       "EtlHitXZposD1", "ETL RECO hits X (+Z, Single(topo1D)/First(topo2D) Disk);X_{RECO} [cm]", 100, -130., 130.);
0687   meHitX_[3] = ibook.book1D("EtlHitXZposD2", "ETL RECO hits X (+Z, Second Disk);X_{RECO} [cm]", 100, -130., 130.);
0688   meHitY_[0] = ibook.book1D(
0689       "EtlHitYZnegD1", "ETL RECO hits Y (-Z, Single(topo1D)/First(topo2D) Disk);Y_{RECO} [cm]", 100, -130., 130.);
0690   meHitY_[1] = ibook.book1D("EtlHitYZnegD2", "ETL RECO hits Y (-Z, Second Disk);Y_{RECO} [cm]", 100, -130., 130.);
0691   meHitY_[2] = ibook.book1D(
0692       "EtlHitYZposD1", "ETL RECO hits Y (+Z, Single(topo1D)/First(topo2D) Disk);Y_{RECO} [cm]", 100, -130., 130.);
0693   meHitY_[3] = ibook.book1D("EtlHitYZposD2", "ETL RECO hits Y (+Z, Second Disk);Y_{RECO} [cm]", 100, -130., 130.);
0694   meHitZ_[0] = ibook.book1D(
0695       "EtlHitZZnegD1", "ETL RECO hits Z (-Z, Single(topo1D)/First(topo2D) Disk);Z_{RECO} [cm]", 100, -302., -298.);
0696   meHitZ_[1] = ibook.book1D("EtlHitZZnegD2", "ETL RECO hits Z (-Z, Second Disk);Z_{RECO} [cm]", 100, -304., -300.);
0697   meHitZ_[2] = ibook.book1D(
0698       "EtlHitZZposD1", "ETL RECO hits Z (+Z, Single(topo1D)/First(topo2D) Disk);Z_{RECO} [cm]", 100, 298., 302.);
0699   meHitZ_[3] = ibook.book1D("EtlHitZZposD2", "ETL RECO hits Z (+Z, Second Disk);Z_{RECO} [cm]", 100, 300., 304.);
0700   meHitPhi_[0] = ibook.book1D(
0701       "EtlHitPhiZnegD1", "ETL RECO hits #phi (-Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad]", 100, -3.2, 3.2);
0702   meHitPhi_[1] =
0703       ibook.book1D("EtlHitPhiZnegD2", "ETL RECO hits #phi (-Z, Second Disk);#phi_{RECO} [rad]", 100, -3.2, 3.2);
0704   meHitPhi_[2] = ibook.book1D(
0705       "EtlHitPhiZposD1", "ETL RECO hits #phi (+Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad]", 100, -3.2, 3.2);
0706   meHitPhi_[3] =
0707       ibook.book1D("EtlHitPhiZposD2", "ETL RECO hits #phi (+Z, Second Disk);#phi_{RECO} [rad]", 100, -3.2, 3.2);
0708   meHitEta_[0] = ibook.book1D(
0709       "EtlHitEtaZnegD1", "ETL RECO hits #eta (-Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO}", 100, -3.2, -1.56);
0710   meHitEta_[1] = ibook.book1D("EtlHitEtaZnegD2", "ETL RECO hits #eta (-Z, Second Disk);#eta_{RECO}", 100, -3.2, -1.56);
0711   meHitEta_[2] = ibook.book1D(
0712       "EtlHitEtaZposD1", "ETL RECO hits #eta (+Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO}", 100, 1.56, 3.2);
0713   meHitEta_[3] = ibook.book1D("EtlHitEtaZposD2", "ETL RECO hits #eta (+Z, Second Disk);#eta_{RECO}", 100, 1.56, 3.2);
0714   meTimeRes_ = ibook.book1D("EtlTimeRes", "ETL time resolution;T_{RECO}-T_{SIM}", 100, -0.5, 0.5);
0715   meEnergyRes_ = ibook.book1D("EtlEnergyRes", "ETL energy resolution;E_{RECO}-E_{SIM}", 100, -0.5, 0.5);
0716   meHitTvsE_[0] = ibook.bookProfile(
0717       "EtlHitTvsEZnegD1",
0718       "ETL RECO time vs energy (-Z, Single(topo1D)/First(topo2D) Disk);E_{RECO} [MeV];ToA_{RECO} [ns]",
0719       50,
0720       0.,
0721       2.,
0722       0.,
0723       100.);
0724   meHitTvsE_[1] = ibook.bookProfile("EtlHitTvsEZnegD2",
0725                                     "ETL RECO time vs energy (-Z, Second Disk);E_{RECO} [MeV];ToA_{RECO} [ns]",
0726                                     50,
0727                                     0.,
0728                                     2.,
0729                                     0.,
0730                                     100.);
0731   meHitTvsE_[2] = ibook.bookProfile(
0732       "EtlHitTvsEZposD1",
0733       "ETL RECO time vs energy (+Z, Single(topo1D)/First(topo2D) Disk);E_{RECO} [MeV];ToA_{RECO} [ns]",
0734       50,
0735       0.,
0736       2.,
0737       0.,
0738       100.);
0739   meHitTvsE_[3] = ibook.bookProfile("EtlHitTvsEZposD2",
0740                                     "ETL RECO time vs energy (+Z, Second Disk);E_{RECO} [MeV];ToA_{RECO} [ns]",
0741                                     50,
0742                                     0.,
0743                                     2.,
0744                                     0.,
0745                                     100.);
0746   meHitEvsPhi_[0] = ibook.bookProfile(
0747       "EtlHitEvsPhiZnegD1",
0748       "ETL RECO energy vs #phi (-Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad];E_{RECO} [MeV]",
0749       50,
0750       -3.2,
0751       3.2,
0752       0.,
0753       100.);
0754   meHitEvsPhi_[1] = ibook.bookProfile("EtlHitEvsPhiZnegD2",
0755                                       "ETL RECO energy vs #phi (-Z, Second Disk);#phi_{RECO} [rad];E_{RECO} [MeV]",
0756                                       50,
0757                                       -3.2,
0758                                       3.2,
0759                                       0.,
0760                                       100.);
0761   meHitEvsPhi_[2] = ibook.bookProfile(
0762       "EtlHitEvsPhiZposD1",
0763       "ETL RECO energy vs #phi (+Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad];E_{RECO} [MeV]",
0764       50,
0765       -3.2,
0766       3.2,
0767       0.,
0768       100.);
0769   meHitEvsPhi_[3] = ibook.bookProfile("EtlHitEvsPhiZposD2",
0770                                       "ETL RECO energy vs #phi (+Z, Second Disk);#phi_{RECO} [rad];E_{RECO} [MeV]",
0771                                       50,
0772                                       -3.2,
0773                                       3.2,
0774                                       0.,
0775                                       100.);
0776   meHitEvsEta_[0] =
0777       ibook.bookProfile("EtlHitEvsEtaZnegD1",
0778                         "ETL RECO energy vs #eta (-Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO};E_{RECO} [MeV]",
0779                         50,
0780                         -3.2,
0781                         -1.56,
0782                         0.,
0783                         100.);
0784   meHitEvsEta_[1] = ibook.bookProfile("EtlHitEvsEtaZnegD2",
0785                                       "ETL RECO energy vs #eta (-Z, Second Disk);#eta_{RECO};E_{RECO} [MeV]",
0786                                       50,
0787                                       -3.2,
0788                                       -1.56,
0789                                       0.,
0790                                       100.);
0791   meHitEvsEta_[2] =
0792       ibook.bookProfile("EtlHitEvsEtaZposD1",
0793                         "ETL RECO energy vs #eta (+Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO};E_{RECO} [MeV]",
0794                         50,
0795                         1.56,
0796                         3.2,
0797                         0.,
0798                         100.);
0799   meHitEvsEta_[3] = ibook.bookProfile("EtlHitEvsEtaZposD2",
0800                                       "ETL RECO energy vs #eta (+Z, Second Disk);#eta_{RECO};E_{RECO} [MeV]",
0801                                       50,
0802                                       1.56,
0803                                       3.2,
0804                                       0.,
0805                                       100.);
0806   meHitTvsPhi_[0] = ibook.bookProfile(
0807       "EtlHitTvsPhiZnegD1",
0808       "ETL RECO time vs #phi (-Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad];ToA_{RECO} [ns]",
0809       50,
0810       -3.2,
0811       3.2,
0812       0.,
0813       100.);
0814   meHitTvsPhi_[1] = ibook.bookProfile("EtlHitTvsPhiZnegD2",
0815                                       "ETL RECO time vs #phi (-Z, Second Disk);#phi_{RECO} [rad];ToA_{RECO} [ns]",
0816                                       50,
0817                                       -3.2,
0818                                       3.2,
0819                                       0.,
0820                                       100.);
0821   meHitTvsPhi_[2] = ibook.bookProfile(
0822       "EtlHitTvsPhiZposD1",
0823       "ETL RECO time vs #phi (+Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad];ToA_{RECO} [ns]",
0824       50,
0825       -3.2,
0826       3.2,
0827       0.,
0828       100.);
0829   meHitTvsPhi_[3] = ibook.bookProfile("EtlHitTvsPhiZposD2",
0830                                       "ETL RECO time vs #phi (+Z, Second Disk);#phi_{RECO} [rad];ToA_{RECO} [ns]",
0831                                       50,
0832                                       -3.2,
0833                                       3.2,
0834                                       0.,
0835                                       100.);
0836   meHitTvsEta_[0] =
0837       ibook.bookProfile("EtlHitTvsEtaZnegD1",
0838                         "ETL RECO time vs #eta (-Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO};ToA_{RECO} [ns]",
0839                         50,
0840                         -3.2,
0841                         -1.56,
0842                         0.,
0843                         100.);
0844   meHitTvsEta_[1] = ibook.bookProfile("EtlHitTvsEtaZnegD2",
0845                                       "ETL RECO time vs #eta (-Z, Second Disk);#eta_{RECO};ToA_{RECO} [ns]",
0846                                       50,
0847                                       -3.2,
0848                                       -1.56,
0849                                       0.,
0850                                       100.);
0851   meHitTvsEta_[2] =
0852       ibook.bookProfile("EtlHitTvsEtaZposD1",
0853                         "ETL RECO time vs #eta (+Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO};ToA_{RECO} [ns]",
0854                         50,
0855                         1.56,
0856                         3.2,
0857                         0.,
0858                         100.);
0859   meHitTvsEta_[3] = ibook.bookProfile("EtlHitTvsEtaZposD2",
0860                                       "ETL RECO time vs #eta (+Z, Second Disk);#eta_{RECO};ToA_{RECO} [ns]",
0861                                       50,
0862                                       1.56,
0863                                       3.2,
0864                                       0.,
0865                                       100.);
0866   meTPullvsE_ = ibook.bookProfile(
0867       "EtlTPullvsE", "ETL time pull vs E;E_{SIM} [MeV];(T_{RECO}-T_{SIM})/#sigma_{T_{RECO}}", 20, 0., 2., -5., 5., "S");
0868   meTPullvsEta_ = ibook.bookProfile("EtlTPullvsEta",
0869                                     "ETL time pull vs #eta;|#eta_{RECO}|;(T_{RECO}-T_{SIM})/#sigma_{T_{RECO}}",
0870                                     26,
0871                                     1.65,
0872                                     3.0,
0873                                     -5.,
0874                                     5.,
0875                                     "S");
0876   meCluTime_[0] =
0877       ibook.book1D("EtlCluTimeZnegD1", "ETL cluster ToA (-Z, Single(topo1D)/First(topo2D) Disk);ToA [ns]", 250, 0, 25);
0878   meCluTime_[1] = ibook.book1D("EtlCluTimeZnegD2", "ETL cluster ToA (-Z, Second Disk);ToA [ns]", 250, 0, 25);
0879   meCluTime_[2] =
0880       ibook.book1D("EtlCluTimeZposD1", "ETL cluster ToA (+Z, Single(topo1D)/First(topo2D) Disk);ToA [ns]", 250, 0, 25);
0881   meCluTime_[3] = ibook.book1D("EtlCluTimeZposD2", "ETL cluster ToA (+Z, Second Disk);ToA [ns]", 250, 0, 25);
0882   meCluTimeError_[0] = ibook.book1D("EtlCluTimeErrosZnegD1",
0883                                     "ETL cluster time error (-Z, Single(topo1D)/First(topo2D) Disk);#sigma_{t} [ns]",
0884                                     100,
0885                                     0,
0886                                     0.1);
0887   meCluTimeError_[1] =
0888       ibook.book1D("EtlCluTimeErrorZnegD2", "ETL cluster time error (-Z, Second Disk);#sigma_{t} [ns]", 100, 0, 0.1);
0889   meCluTimeError_[2] = ibook.book1D("EtlCluTimeErrorZposD1",
0890                                     "ETL cluster time error (+Z, Single(topo1D)/First(topo2D) Disk);#sigma_{t} [ns]",
0891                                     100,
0892                                     0,
0893                                     0.1);
0894   meCluTimeError_[3] =
0895       ibook.book1D("EtlCluTimeErrorZposD2", "ETL cluster time error (+Z, Second Disk);#sigma_{t} [ns]", 100, 0, 0.1);
0896   meCluEnergy_[0] = ibook.book1D(
0897       "EtlCluEnergyZnegD1", "ETL cluster energy (-Z, Single(topo1D)/First(topo2D) Disk);E_{RECO} [MeV]", 100, 0, 10);
0898   meCluEnergy_[1] =
0899       ibook.book1D("EtlCluEnergyZnegD2", "ETL cluster energy (-Z, Second Disk);E_{RECO} [MeV]", 100, 0, 10);
0900   meCluEnergy_[2] = ibook.book1D(
0901       "EtlCluEnergyZposD1", "ETL cluster energy (+Z, Single(topo1D)/First(topo2D) Disk);E_{RECO} [MeV]", 100, 0, 10);
0902   meCluEnergy_[3] =
0903       ibook.book1D("EtlCluEnergyZposD2", "ETL cluster energy (+Z, Second Disk);E_{RECO} [MeV]", 100, 0, 10);
0904   meCluPhi_[0] = ibook.book1D(
0905       "EtlCluPhiZnegD1", "ETL cluster #phi (-Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad]", 126, -3.2, 3.2);
0906   meCluPhi_[1] =
0907       ibook.book1D("EtlCluPhiZnegD2", "ETL cluster #phi (-Z, Second Disk);#phi_{RECO} [rad]", 126, -3.2, 3.2);
0908   meCluPhi_[2] = ibook.book1D(
0909       "EtlCluPhiZposD1", "ETL cluster #phi (+Z, Single(topo1D)/First(topo2D) Disk);#phi_{RECO} [rad]", 126, -3.2, 3.2);
0910   meCluPhi_[3] =
0911       ibook.book1D("EtlCluPhiZposD2", "ETL cluster #phi (+Z, Second Disk);#phi_{RECO} [rad]", 126, -3.2, 3.2);
0912   meCluEta_[0] = ibook.book1D(
0913       "EtlCluEtaZnegD1", "ETL cluster #eta (-Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO}", 100, -3.2, -1.4);
0914   meCluEta_[1] = ibook.book1D("EtlCluEtaZnegD2", "ETL cluster #eta (-Z, Second Disk);#eta_{RECO}", 100, -3.2, -1.4);
0915   meCluEta_[2] = ibook.book1D(
0916       "EtlCluEtaZposD1", "ETL cluster #eta (+Z, Single(topo1D)/First(topo2D) Disk);#eta_{RECO}", 100, 1.4, 3.2);
0917   meCluEta_[3] = ibook.book1D("EtlCluEtaZposD2", "ETL cluster #eta (+Z, Second Disk);#eta_{RECO}", 100, 1.4, 3.2);
0918   meCluHits_[0] = ibook.book1D(
0919       "EtlCluHitNumberZnegD1", "ETL hits per cluster (-Z, Single(topo1D)/First(topo2D) Disk);Cluster size", 10, 0, 10);
0920   meCluHits_[1] =
0921       ibook.book1D("EtlCluHitNumberZnegD2", "ETL hits per cluster (-Z, Second Disk);Cluster size", 10, 0, 10);
0922   meCluHits_[2] = ibook.book1D(
0923       "EtlCluHitNumberZposD1", "ETL hits per cluster (+Z, Single(topo1D)/First(topo2D) Disk);Cluster size", 10, 0, 10);
0924   meCluHits_[3] =
0925       ibook.book1D("EtlCluHitNumberZposD2", "ETL hits per cluster (+Z, Second Disk);Cluster size", 10, 0, 10);
0926   meCluOccupancy_[0] =
0927       ibook.book2D("EtlCluOccupancyZnegD1",
0928                    "ETL cluster X vs Y (-Z, Single(topo1D)/First(topo2D) Disk);X_{RECO} [cm]; Y_{RECO} [cm]",
0929                    100,
0930                    -150.,
0931                    150.,
0932                    100,
0933                    -150,
0934                    150);
0935   meCluOccupancy_[1] = ibook.book2D("EtlCluOccupancyZnegD2",
0936                                     "ETL cluster X vs Y (-Z, Second Disk);X_{RECO} [cm]; Y_{RECO} [cm]",
0937                                     100,
0938                                     -150.,
0939                                     150.,
0940                                     100,
0941                                     -150,
0942                                     150);
0943   meCluOccupancy_[2] =
0944       ibook.book2D("EtlCluOccupancyZposD1",
0945                    "ETL cluster X vs Y (+Z, Single(topo1D)/First(topo2D) Disk);X_{RECO} [cm]; Y_{RECO} [cm]",
0946                    100,
0947                    -150.,
0948                    150.,
0949                    100,
0950                    -150,
0951                    150);
0952   meCluOccupancy_[3] = ibook.book2D("EtlCluOccupancyZposD2",
0953                                     "ETL cluster X vs Y (+Z, Second Disk);X_{RECO} [cm]; Y_{RECO} [cm]",
0954                                     100,
0955                                     -150.,
0956                                     150.,
0957                                     100,
0958                                     -150,
0959                                     150);
0960 
0961   meCluTimeRes_[0] =
0962       ibook.book1D("EtlCluTimeResZneg", "ETL cluster time resolution (-Z);T_{RECO}-T_{SIM} [ns]", 100, -0.5, 0.5);
0963   meCluTimeRes_[1] =
0964       ibook.book1D("EtlCluTimeResZpos", "ETL cluster time resolution (+Z);T_{RECO}-T_{SIM} [MeV]", 100, -0.5, 0.5);
0965   meCluEnergyRes_[0] =
0966       ibook.book1D("EtlCluEnergyResZneg", "ETL cluster energy resolution (-Z);E_{RECO}-E_{SIM}", 100, -0.5, 0.5);
0967   meCluEnergyRes_[1] =
0968       ibook.book1D("EtlCluEnergyResZpos", "ETL cluster energy resolution (+Z);E_{RECO}-E_{SIM}", 100, -0.5, 0.5);
0969 
0970   meCluTPullvsE_[0] =
0971       ibook.bookProfile("EtlCluTPullvsEZneg",
0972                         "ETL cluster time pull vs E (-Z);E_{SIM} [MeV];(T_{RECO}-T_{SIM})/#sigma_{T_{RECO}}",
0973                         25,
0974                         0.,
0975                         0.5,
0976                         -5.,
0977                         5.,
0978                         "S");
0979   meCluTPullvsE_[1] =
0980       ibook.bookProfile("EtlCluTPullvsEZpos",
0981                         "ETL cluster time pull vs E (+Z);E_{SIM} [MeV];(T_{RECO}-T_{SIM})/#sigma_{T_{RECO}}",
0982                         25,
0983                         0.,
0984                         0.5,
0985                         -5.,
0986                         5.,
0987                         "S");
0988   meCluTPullvsEta_[0] =
0989       ibook.bookProfile("EtlCluTPullvsEtaZneg",
0990                         "ETL cluster time pull vs #eta (-Z);|#eta_{RECO}|;(T_{RECO}-T_{SIM})/#sigma_{T_{RECO}}",
0991                         30,
0992                         -3.,
0993                         -1.65,
0994                         -5.,
0995                         5.,
0996                         "S");
0997   meCluTPullvsEta_[1] =
0998       ibook.bookProfile("EtlCluTPullvsEtaZpos",
0999                         "ETL cluster time pull vs #eta (+Z);|#eta_{RECO}|;(T_{RECO}-T_{SIM})/#sigma_{T_{RECO}}",
1000                         30,
1001                         1.65,
1002                         3.,
1003                         -5.,
1004                         5.,
1005                         "S");
1006   meCluXRes_[0] = ibook.book1D("EtlCluXResZneg", "ETL cluster X resolution (-Z);X_{RECO}-X_{SIM} [cm]", 100, -0.1, 0.1);
1007   meCluXRes_[1] = ibook.book1D("EtlCluXResZpos", "ETL cluster X resolution (+Z);X_{RECO}-X_{SIM} [cm]", 100, -0.1, 0.1);
1008   meCluYRes_[0] = ibook.book1D("EtlCluYResZneg", "ETL cluster Y resolution (-Z);Y_{RECO}-Y_{SIM} [cm]", 100, -0.1, 0.1);
1009   meCluYRes_[1] = ibook.book1D("EtlCluYResZpos", "ETL cluster Y resolution (+Z);Y_{RECO}-Y_{SIM} [cm]", 100, -0.1, 0.1);
1010   meCluZRes_[0] =
1011       ibook.book1D("EtlCluZResZneg", "ETL cluster Z resolution (-Z);Z_{RECO}-Z_{SIM} [cm]", 100, -0.003, 0.003);
1012   meCluZRes_[1] =
1013       ibook.book1D("EtlCluZResZpos", "ETL cluster Z resolution (+Z);Z_{RECO}-Z_{SIM} [cm]", 100, -0.003, 0.003);
1014   if (optionalPlots_) {
1015     meCluXPull_[0] =
1016         ibook.book1D("EtlCluXPullZneg", "ETL cluster X pull (-Z);X_{RECO}-X_{SIM}/sigmaX_[RECO] [cm]", 100, -5., 5.);
1017     meCluXPull_[1] =
1018         ibook.book1D("EtlCluXPullZpos", "ETL cluster X pull (+Z);X_{RECO}-X_{SIM}/sigmaX_[RECO] [cm]", 100, -5., 5.);
1019     meCluYPull_[0] =
1020         ibook.book1D("EtlCluYPullZneg", "ETL cluster Y pull (-Z);Y_{RECO}-Y_{SIM}/sigmaY_[RECO] [cm]", 100, -5., 5.);
1021     meCluYPull_[1] =
1022         ibook.book1D("EtlCluYPullZpos", "ETL cluster Y pull (+Z);Y_{RECO}-Y_{SIM}/sigmaY_[RECO] [cm]", 100, -5., 5.);
1023     meCluYXLocal_[0] = ibook.book2D("EtlCluYXLocalZneg",
1024                                     "ETL cluster local Y vs X (-Z);X^{local}_{RECO} [cm];Y^{local}_{RECO} [cm]",
1025                                     100,
1026                                     -2.2,
1027                                     2.2,
1028                                     100,
1029                                     -1.1,
1030                                     1.1);
1031     meCluYXLocal_[1] = ibook.book2D("EtlCluYXLocalZpos",
1032                                     "ETL cluster local Y vs X (+Z);X^{local}_{RECO} [cm];Y^{local}_{RECO} [cm]",
1033                                     100,
1034                                     -2.2,
1035                                     2.2,
1036                                     100,
1037                                     -1.1,
1038                                     1.1);
1039     meCluYXLocalSim_[0] = ibook.book2D("EtlCluYXLocalSimZneg",
1040                                        "ETL cluster local Y vs X (-Z);X^{local}_{SIM} [cm];Y^{local}_{SIM} [cm]",
1041                                        200,
1042                                        -2.2,
1043                                        2.2,
1044                                        200,
1045                                        -1.1,
1046                                        1.1);
1047     meCluYXLocalSim_[1] = ibook.book2D("EtlCluYXLocalSimZpos",
1048                                        "ETL cluster local Y vs X (+Z);X^{local}_{SIM} [cm];Y^{local}_{SIM} [cm]",
1049                                        200,
1050                                        -2.2,
1051                                        2.2,
1052                                        200,
1053                                        -1.1,
1054                                        1.1);
1055     meCluXLocalErr_[0] =
1056         ibook.book1D("EtlCluXLocalErrNeg", "ETL cluster X local error (-Z);sigmaX_{RECO,loc} [cm]", 50, 0., 0.2);
1057     meCluXLocalErr_[1] =
1058         ibook.book1D("EtlCluXLocalErrPos", "ETL cluster X local error (+Z);sigmaX_{RECO,loc} [cm]", 50, 0., 0.2);
1059     meCluYLocalErr_[0] =
1060         ibook.book1D("EtlCluYLocalErrNeg", "ETL cluster Y local error (-Z);sigmaY_{RECO,loc} [cm]", 50., 0., 0.2);
1061     meCluYLocalErr_[1] =
1062         ibook.book1D("EtlCluYLocalErrPos", "ETL cluster Y local error (+Z);sigmaY_{RECO,loc} [cm]", 50, 0., 0.2);
1063   }
1064   meUnmatchedCluEnergy_[0] = ibook.book1D(
1065       "EtlUnmatchedCluEnergyNeg", "ETL unmatched cluster log10(energy) (-Z);log10(E_{RECO} [MeV])", 5, -3, 2);
1066   meUnmatchedCluEnergy_[1] = ibook.book1D(
1067       "EtlUnmatchedCluEnergyPos", "ETL unmatched cluster log10(energy) (+Z);log10(E_{RECO} [MeV])", 5, -3, 2);
1068 
1069   // --- UncalibratedRecHits histograms
1070 
1071   if (uncalibRecHitsPlots_) {
1072     const std::string det_name[2] = {"ETL-", "ETL+"};
1073     for (unsigned int iside = 0; iside < 2; ++iside) {
1074       for (unsigned int ihistoQ = 0; ihistoQ < nBinsQ_; ++ihistoQ) {
1075         std::string hname = Form("TimeResQ_%d_%d", iside, ihistoQ);
1076         std::string htitle =
1077             Form("%s time resolution (Q bin = %d);T_{RECO} - T_{SIM} [ns]", det_name[iside].data(), ihistoQ);
1078         meTimeResQ_[iside][ihistoQ] = ibook.book1D(hname, htitle, 200, -0.5, 0.5);
1079 
1080       }  // ihistoQ loop
1081 
1082       for (unsigned int ihistoEta = 0; ihistoEta < nBinsEta_; ++ihistoEta) {
1083         std::string hname = Form("TimeResEta_%d_%d", iside, ihistoEta);
1084         std::string htitle =
1085             Form("%s time resolution (|#eta| bin = %d);T_{RECO} - T_{SIM} [ns]", det_name[iside].data(), ihistoEta);
1086         meTimeResEta_[iside][ihistoEta] = ibook.book1D(hname, htitle, 200, -0.5, 0.5);
1087 
1088       }  // ihistoEta loop
1089     }
1090   }
1091 }
1092 
1093 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
1094 void EtlLocalRecoValidation::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
1095   edm::ParameterSetDescription desc;
1096 
1097   desc.add<std::string>("folder", "MTD/ETL/LocalReco");
1098   desc.add<edm::InputTag>("recHitsTag", edm::InputTag("mtdRecHits", "FTLEndcap"));
1099   desc.add<edm::InputTag>("uncalibRecHitsTag", edm::InputTag("mtdUncalibratedRecHits", "FTLEndcap"));
1100   desc.add<edm::InputTag>("simHitsTag", edm::InputTag("mix", "g4SimHitsFastTimerHitsEndcap"));
1101   desc.add<edm::InputTag>("recCluTag", edm::InputTag("mtdClusters", "FTLEndcap"));
1102   desc.add<edm::InputTag>("trkHitTag", edm::InputTag("mtdTrackingRecHits"));
1103   desc.add<double>("hitMinimumEnergy1Dis", 1.);     // [MeV]
1104   desc.add<double>("hitMinimumEnergy2Dis", 0.001);  // [MeV]
1105   desc.add<bool>("optionalPlots", false);
1106   desc.add<bool>("UncalibRecHitsPlots", false);
1107   desc.add<double>("HitMinimumAmplitude", 0.33);  // [MIP]
1108 
1109   descriptions.add("etlLocalRecoValid", desc);
1110 }
1111 
1112 DEFINE_FWK_MODULE(EtlLocalRecoValidation);