Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 10:06:48

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