Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-20 22:40:15

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