Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-12 23:19:34

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