diff --git a/Validation/HGCalValidation/interface/HGVHistoProducerAlgo.h b/Validation/HGCalValidation/interface/HGVHistoProducerAlgo.h index 7530f2fbe2e47..97097df3247a4 100644 --- a/Validation/HGCalValidation/interface/HGVHistoProducerAlgo.h +++ b/Validation/HGCalValidation/interface/HGVHistoProducerAlgo.h @@ -4,8 +4,8 @@ /* \author HGCal */ -#include #include +#include #include #include @@ -163,10 +163,16 @@ struct HGVHistoProducerAlgoHistograms { std::vector h_num_trackster_phi[numberOfValidationTypes_]; std::vector h_num_trackster_en[numberOfValidationTypes_]; std::vector h_num_trackster_pt[numberOfValidationTypes_]; + std::vector h_num_trackster_R[numberOfValidationTypes_]; + std::vector h_num_trackster_alpha[numberOfValidationTypes_]; + std::vector h_num_trackster_time[numberOfValidationTypes_]; std::vector h_numMerge_trackster_eta[numberOfValidationTypes_]; std::vector h_numMerge_trackster_phi[numberOfValidationTypes_]; std::vector h_numMerge_trackster_en[numberOfValidationTypes_]; std::vector h_numMerge_trackster_pt[numberOfValidationTypes_]; + std::vector h_numMerge_trackster_R[numberOfValidationTypes_]; + std::vector h_numMerge_trackster_alpha[numberOfValidationTypes_]; + std::vector h_numMerge_trackster_time[numberOfValidationTypes_]; std::vector h_sharedenergy_trackster2caloparticle[numberOfValidationTypes_]; std::vector h_sharedenergy_trackster2bestCaloparticle[numberOfValidationTypes_]; std::vector h_sharedenergy_trackster2bestCaloparticle2[numberOfValidationTypes_]; @@ -181,22 +187,37 @@ struct HGVHistoProducerAlgoHistograms { std::vector h_denom_trackster_phi[numberOfValidationTypes_]; std::vector h_denom_trackster_en[numberOfValidationTypes_]; std::vector h_denom_trackster_pt[numberOfValidationTypes_]; + std::vector h_denom_trackster_R[numberOfValidationTypes_]; + std::vector h_denom_trackster_alpha[numberOfValidationTypes_]; + std::vector h_denom_trackster_time[numberOfValidationTypes_]; std::vector h_numEff_caloparticle_eta[numberOfValidationTypes_]; std::vector h_numEff_caloparticle_phi[numberOfValidationTypes_]; std::vector h_numEff_caloparticle_en[numberOfValidationTypes_]; std::vector h_numEff_caloparticle_pt[numberOfValidationTypes_]; + std::vector h_numEff_caloparticle_R[numberOfValidationTypes_]; + std::vector h_numEff_caloparticle_alpha[numberOfValidationTypes_]; + std::vector h_numEff_caloparticle_time[numberOfValidationTypes_]; std::vector h_num_caloparticle_eta[numberOfValidationTypes_]; std::vector h_num_caloparticle_phi[numberOfValidationTypes_]; std::vector h_num_caloparticle_en[numberOfValidationTypes_]; std::vector h_num_caloparticle_pt[numberOfValidationTypes_]; + std::vector h_num_caloparticle_R[numberOfValidationTypes_]; + std::vector h_num_caloparticle_alpha[numberOfValidationTypes_]; + std::vector h_num_caloparticle_time[numberOfValidationTypes_]; std::vector h_numDup_trackster_eta[numberOfValidationTypes_]; std::vector h_numDup_trackster_phi[numberOfValidationTypes_]; std::vector h_numDup_trackster_en[numberOfValidationTypes_]; std::vector h_numDup_trackster_pt[numberOfValidationTypes_]; + std::vector h_numDup_trackster_R[numberOfValidationTypes_]; + std::vector h_numDup_trackster_alpha[numberOfValidationTypes_]; + std::vector h_numDup_trackster_time[numberOfValidationTypes_]; std::vector h_denom_caloparticle_eta[numberOfValidationTypes_]; std::vector h_denom_caloparticle_phi[numberOfValidationTypes_]; std::vector h_denom_caloparticle_en[numberOfValidationTypes_]; std::vector h_denom_caloparticle_pt[numberOfValidationTypes_]; + std::vector h_denom_caloparticle_R[numberOfValidationTypes_]; + std::vector h_denom_caloparticle_alpha[numberOfValidationTypes_]; + std::vector h_denom_caloparticle_time[numberOfValidationTypes_]; // Generic histograms std::vector h_tracksternum; std::vector h_conttracksternum; @@ -219,6 +240,9 @@ struct HGVHistoProducerAlgoHistograms { std::vector h_trackster_x; std::vector h_trackster_y; std::vector h_trackster_z; + std::vector h_trackster_R; + std::vector h_trackster_alpha; + std::vector h_trackster_time; std::vector h_trackster_firstlayer; std::vector h_trackster_lastlayer; std::vector h_trackster_layersnum; @@ -304,6 +328,7 @@ class HGVHistoProducerAlgo { const TracksterToTracksterMap& simTrackstersToTrackstersMap, const validationType valType, const SimClusterToCaloParticleMap& scToCpMap, + const std::vector& cP, const std::vector& cPIndices, const std::vector& cPSelectedIndices, const edm::ProductID& cPHandle_id) const; @@ -428,6 +453,12 @@ class HGVHistoProducerAlgo { int nintPt_; double minPhi_, maxPhi_; int nintPhi_; + double minR_, maxR_; + int nintR_; + double minAlpha_, maxAlpha_; + int nintAlpha_; + double minTime_, maxTime_; + int nintTime_; double minMixedHitsSimCluster_, maxMixedHitsSimCluster_; int nintMixedHitsSimCluster_; double minMixedHitsCluster_, maxMixedHitsCluster_; @@ -446,6 +477,10 @@ class HGVHistoProducerAlgo { int nintEneClperlay_; double minScore_, maxScore_; int nintScore_; + double maxRecoToSimScoreForNonFake_; + double maxRecoToSimScoreForMerge_; + double maxSimToRecoScoreForPurity_; + double maxSimToRecoScoreForDuplicate_; double minSharedEneFrac_, maxSharedEneFrac_; int nintSharedEneFrac_; double minTSTSharedEneFracEfficiency_; diff --git a/Validation/HGCalValidation/plugins/HGCalValidator.cc b/Validation/HGCalValidation/plugins/HGCalValidator.cc index bef9ab9ead147..39de6b04f64d7 100644 --- a/Validation/HGCalValidation/plugins/HGCalValidator.cc +++ b/Validation/HGCalValidation/plugins/HGCalValidator.cc @@ -1,14 +1,11 @@ #include -#include "Validation/HGCalValidation/interface/HGCalValidator.h" - -#include "SimCalorimetry/HGCalAssociatorProducers/interface/AssociatorTools.h" - #include "FWCore/Framework/interface/MakerMacros.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" - #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "SimCalorimetry/HGCalAssociatorProducers/interface/AssociatorTools.h" +#include "Validation/HGCalValidation/interface/HGCalValidator.h" using namespace std; using namespace edm; @@ -691,6 +688,22 @@ void HGCalValidator::fillDescriptions(edm::ConfigurationDescriptions& descriptio psd1.add("minPhi", -3.2); psd1.add("maxPhi", 3.2); psd1.add("nintPhi", 80); + psd1.add("minR", 0.) + ->setComment( + "Minimum histogram value for the displacement radius R, defined as the transverse distance " + "from the z axis of the trajectory extrapolated to z = 0, in cm"); + psd1.add("maxR", 100.); + psd1.add("nintR", 50); + psd1.add("minAlpha", 0.) + ->setComment( + "Minimum histogram value for the displacement angle alpha, defined at the HGCal front surface " + "as the angle between the particle direction and the vector from the origin to the surface " + "intersection, in radians"); + psd1.add("maxAlpha", std::numbers::pi / 4.); + psd1.add("nintAlpha", 50); + psd1.add("minTime", -50.); + psd1.add("maxTime", 50.); + psd1.add("nintTime", 50); psd1.add("minMixedHitsSimCluster", 0.0); psd1.add("maxMixedHitsSimCluster", 800.0); psd1.add("nintMixedHitsSimCluster", 100); @@ -718,6 +731,10 @@ void HGCalValidator::fillDescriptions(edm::ConfigurationDescriptions& descriptio psd1.add("minScore", 0.0); psd1.add("maxScore", 1.02); psd1.add("nintScore", 51); + psd1.add("maxRecoToSimScoreForNonFake", 0.6); + psd1.add("maxRecoToSimScoreForMerge", 0.6); + psd1.add("maxSimToRecoScoreForPurity", 0.2); + psd1.add("maxSimToRecoScoreForDuplicate", 0.2); psd1.add("minSharedEneFrac", 0.0); psd1.add("maxSharedEneFrac", 1.02); psd1.add("nintSharedEneFrac", 51); diff --git a/Validation/HGCalValidation/python/HGVHistoProducerAlgoBlock_cfi.py b/Validation/HGCalValidation/python/HGVHistoProducerAlgoBlock_cfi.py index 86e7f1142c4dc..70e41a46e56c8 100644 --- a/Validation/HGCalValidation/python/HGVHistoProducerAlgoBlock_cfi.py +++ b/Validation/HGCalValidation/python/HGVHistoProducerAlgoBlock_cfi.py @@ -67,6 +67,10 @@ minScore = cms.double(0.), maxScore = cms.double(1.02), nintScore = cms.int32(51), + maxRecoToSimScoreForNonFake = cms.double(0.6), + maxRecoToSimScoreForMerge = cms.double(0.6), + maxSimToRecoScoreForPurity = cms.double(0.2), + maxSimToRecoScoreForDuplicate = cms.double(0.2), #Parameters for shared energy fraction. That is: #1. Fraction of each of the layer clusters energy related to a diff --git a/Validation/HGCalValidation/python/PostProcessorHGCAL_cfi.py b/Validation/HGCalValidation/python/PostProcessorHGCAL_cfi.py index 0f9d308005cdd..66ff67acaddbd 100644 --- a/Validation/HGCalValidation/python/PostProcessorHGCAL_cfi.py +++ b/Validation/HGCalValidation/python/PostProcessorHGCAL_cfi.py @@ -55,7 +55,8 @@ # Must be in sync with labels in HGVHistoProducerAlgo.cc simDict = {"SimTrackster_fromCP_byHits":"_byHits_CP", "SimTrackster_byLCs":"_byLCs", "SimTrackster_fromCP_byLCs":"_byLCs_CP", "SimTrackster_byHits":"_byHits"} metrics = {"purity":["Purity","_"], "effic":["Efficiency","Eff_"], "fake":["Fake Rate","_"], "duplicate":["Duplicate(Split)","Dup_"], "merge":["Merge Rate","Merge_"]} -variables = {"eta":["#eta",""], "phi":["#phi",""], "energy":["energy"," [GeV]"], "pt":["p_{T}"," [GeV]"]} +variables = {"eta":["#eta",""], "phi":["#phi",""], "energy":["energy"," [GeV]"], "pt":["p_{T}"," [GeV]"], + "R":["R"," [cm]"], "alpha":["#alpha"," [rad]"], "time":["time"," [ns]"]} for elem in simDict: for m in list(metrics.keys())[:2]: for v in variables: diff --git a/Validation/HGCalValidation/python/hgcalPlots.py b/Validation/HGCalValidation/python/hgcalPlots.py index 066d945b1b835..eddd94ce2fecf 100644 --- a/Validation/HGCalValidation/python/hgcalPlots.py +++ b/Validation/HGCalValidation/python/hgcalPlots.py @@ -11,9 +11,6 @@ from Validation.RecoTrack.plotting.plotting import Plot, PlotGroup, PlotFolder, Plotter, PlotOnSideGroup from Validation.RecoTrack.plotting.html import PlotPurpose -import Validation.RecoTrack.plotting.plotting as plotting -import Validation.RecoTrack.plotting.validation as validation -import Validation.RecoTrack.plotting.html as html from Validation.HGCalValidation.HGCalValidator_cff import hgcalValidator from Validation.HGCalValidation.PostProcessorHGCAL_cfi import lcToCP_linking, simDict, TSbyHits_CP, TSbyLCs, TSbyLCs_CP, TSbyHits, variables @@ -1782,6 +1779,9 @@ _trackster_eppe_plots.extend([Plot("trackster_phi", **_common)]) _trackster_eppe_plots.extend([Plot("trackster_pt", **_common)]) _trackster_eppe_plots.extend([Plot("trackster_energy", **_common)]) +_trackster_eppe_plots.extend([Plot("trackster_R", **_common)]) +_trackster_eppe_plots.extend([Plot("trackster_alpha", **_common)]) +_trackster_eppe_plots.extend([Plot("trackster_time", **_common)]) _trackster_eppe = PlotGroup("EtaPhiPtEnergy", _trackster_eppe_plots, ncols=2) _trackster_xyz_plots = [Plot("trackster_x", **_common)] diff --git a/Validation/HGCalValidation/src/HGVHistoProducerAlgo.cc b/Validation/HGCalValidation/src/HGVHistoProducerAlgo.cc index fd05c9106c0e3..c6f06549d9204 100644 --- a/Validation/HGCalValidation/src/HGVHistoProducerAlgo.cc +++ b/Validation/HGCalValidation/src/HGVHistoProducerAlgo.cc @@ -1,4 +1,5 @@ -#include +#include +#include #include #include @@ -11,14 +12,125 @@ using namespace std; +namespace { + + class ThresholdCounter { + public: + static ThresholdCounter below(double threshold, unsigned int minimumCount) { + return ThresholdCounter(threshold, minimumCount, Comparison::below); + } + + static ThresholdCounter above(double threshold, unsigned int minimumCount) { + return ThresholdCounter(threshold, minimumCount, Comparison::above); + } + + void consider(double value) { + if (doesPass(value)) { + ++count_; + } + } + + bool isSatisfied() const { return count_ >= minimumCount_; } + + private: + enum class Comparison { below, above }; + + ThresholdCounter(double threshold, unsigned int minimumCount, Comparison comparison) + : threshold_(threshold), minimumCount_(minimumCount), comparison_(comparison) {} + + bool doesPass(double value) const { + switch (comparison_) { + case Comparison::below: + return value < threshold_; + case Comparison::above: + return value > threshold_; + } + return false; + } + + double threshold_; + unsigned int minimumCount_; + Comparison comparison_; + unsigned int count_ = 0; + }; + + struct CaloParticleDisplacement { + double R; + double alpha; + }; + + /* Given a point and direction along a straight trajectory, returns + R=sqrt(x*x+y*y) at z=0 and the displacement angle alpha at the + HGCAL front surface. Works for uncharged particles only. + + The displacement angle is the angle between the trajectory of the particle + and the trajectory that a particle crossing the HGCAL surface at the same point + would have. It measures how non-pointing a given particle's trajectory is. + */ + CaloParticleDisplacement resolveDisplacement(const math::XYZVectorF& point, const math::XYZVectorF& unitDirection) { + const float tToOrigin = -point.z() / unitDirection.z(); + const float x = point.x() + tToOrigin * unitDirection.x(); + const float y = point.y() + tToOrigin * unitDirection.y(); + + const double R = std::hypot(x, y); + + constexpr float hgcalFrontSurfaceZ = 320.99f; + const float surfaceZ = std::copysign(hgcalFrontSurfaceZ, point.z()); + const float tToSurface = (surfaceZ - point.z()) / unitDirection.z(); + const math::XYZVectorF surfacePoint( + point.x() + tToSurface * unitDirection.x(), point.y() + tToSurface * unitDirection.y(), surfaceZ); + const auto surfaceDirection = surfacePoint.Unit(); + const double cosAlpha = std::clamp(static_cast(unitDirection.Dot(surfaceDirection)), -1.0, 1.0); + + return {R, std::acos(cosAlpha)}; + } + + CaloParticleDisplacement resolveSimTrackDisplacement(const SimTrack& simTrack) { + const auto& boundaryPos = simTrack.getPositionAtBoundary(); + const auto& boundaryMom = simTrack.getMomentumAtBoundary(); + + const math::XYZVectorF point(boundaryPos.x(), boundaryPos.y(), boundaryPos.z()); + const math::XYZVectorF direction(boundaryMom.x(), boundaryMom.y(), boundaryMom.z()); + + return resolveDisplacement(point, direction.unit()); + } + + const ticl::Trackster::Vector& resolveTracksterDirection(const ticl::Trackster& trackster) { + // eigenvectors()[0] is the unit-norm principal PCA axis of the trackster, + // oriented along the particle direction regarding z sign + return trackster.eigenvectors()[0]; + } + + CaloParticleDisplacement resolveRecoTracksterDisplacement(const ticl::Trackster& trackster) { + return resolveDisplacement(trackster.barycenter(), resolveTracksterDirection(trackster)); + } + + const SimTrack& getSimTrack(const CaloParticle& caloParticle) { + if (caloParticle.g4Tracks().empty()) + throw cms::Exception("HGVHistoProducerAlgo") << "SimTrack not found!"; + + return caloParticle.g4Tracks().front(); + } + + int getCaloParticleId(const ticl::Trackster& simTS, + const edm::ProductID& cPHandle_id, + const HGVHistoProducerAlgo::SimClusterToCaloParticleMap& scToCpMap) { + const auto productID = simTS.seedID(); + if (productID == cPHandle_id) { + return simTS.seedIndex(); + } + + return static_cast(scToCpMap.at(simTS.seedIndex()).index()); + } + +} // namespace + //Parameters for the score cut. Later, this will become part of the //configuration parameter for the HGCAL associator. const double ScoreCutLCtoCP_ = 0.1; const double ScoreCutCPtoLC_ = 0.1; const double ScoreCutLCtoSC_ = 0.1; const double ScoreCutSCtoLC_ = 0.1; -const double ScoreCutTStoSTSFakeMerge_[] = {0.6, FLT_MIN}; //1.e-09 -const double ScoreCutSTStoTSPurDup_[] = {0.2, FLT_MIN}; //1.e-11 HGVHistoProducerAlgo::HGVHistoProducerAlgo(const edm::ParameterSet& pset) : //parameters for eta @@ -42,6 +154,21 @@ HGVHistoProducerAlgo::HGVHistoProducerAlgo(const edm::ParameterSet& pset) maxPhi_(pset.getParameter("maxPhi")), nintPhi_(pset.getParameter("nintPhi")), + //parameters for R + minR_(pset.getParameter("minR")), + maxR_(pset.getParameter("maxR")), + nintR_(pset.getParameter("nintR")), + + //parameters for alpha + minAlpha_(pset.getParameter("minAlpha")), + maxAlpha_(pset.getParameter("maxAlpha")), + nintAlpha_(pset.getParameter("nintAlpha")), + + //parameters for time + minTime_(pset.getParameter("minTime")), + maxTime_(pset.getParameter("maxTime")), + nintTime_(pset.getParameter("nintTime")), + //parameters for counting mixed hits SimClusters minMixedHitsSimCluster_(pset.getParameter("minMixedHitsSimCluster")), maxMixedHitsSimCluster_(pset.getParameter("maxMixedHitsSimCluster")), @@ -52,7 +179,7 @@ HGVHistoProducerAlgo::HGVHistoProducerAlgo(const edm::ParameterSet& pset) maxMixedHitsCluster_(pset.getParameter("maxMixedHitsCluster")), nintMixedHitsCluster_(pset.getParameter("nintMixedHitsCluster")), - //parameters for the total amount of energy clustered by all layer clusters (fraction over CaloParticless) + //parameters for the total amount of energy clustered by all layer clusters (fraction over CaloParticles) minEneCl_(pset.getParameter("minEneCl")), maxEneCl_(pset.getParameter("maxEneCl")), nintEneCl_(pset.getParameter("nintEneCl")), @@ -77,7 +204,7 @@ HGVHistoProducerAlgo::HGVHistoProducerAlgo(const edm::ParameterSet& pset) maxTotNClsperlay_(pset.getParameter("maxTotNClsperlay")), nintTotNClsperlay_(pset.getParameter("nintTotNClsperlay")), - //Parameters for the energy clustered by layer clusters per layer (fraction over CaloParticless) + //Parameters for the energy clustered by layer clusters per layer (fraction over CaloParticles) minEneClperlay_(pset.getParameter("minEneClperlay")), maxEneClperlay_(pset.getParameter("maxEneClperlay")), nintEneClperlay_(pset.getParameter("nintEneClperlay")), @@ -88,6 +215,10 @@ HGVHistoProducerAlgo::HGVHistoProducerAlgo(const edm::ParameterSet& pset) minScore_(pset.getParameter("minScore")), maxScore_(pset.getParameter("maxScore")), nintScore_(pset.getParameter("nintScore")), + maxRecoToSimScoreForNonFake_(pset.getParameter("maxRecoToSimScoreForNonFake")), + maxRecoToSimScoreForMerge_(pset.getParameter("maxRecoToSimScoreForMerge")), + maxSimToRecoScoreForPurity_(pset.getParameter("maxSimToRecoScoreForPurity")), + maxSimToRecoScoreForDuplicate_(pset.getParameter("maxSimToRecoScoreForDuplicate")), //Parameters for shared energy fraction. That is: //1. Fraction of each of the layer clusters energy related to a @@ -626,14 +757,14 @@ void HGVHistoProducerAlgo::bookClusterHistos_ClusterLevel(DQMStore::IBooker& ibo //z- histograms.h_energyclustered_zminus.push_back( ibook.book1D("energyclustered_zminus", - "percent of total energy clustered by all layer clusters over CaloParticless energy in z-", + "percent of total energy clustered by all layer clusters over CaloParticles energy in z-", nintEneCl_, minEneCl_, maxEneCl_)); //z+ histograms.h_energyclustered_zplus.push_back( ibook.book1D("energyclustered_zplus", - "percent of total energy clustered by all layer clusters over CaloParticless energy in z+", + "percent of total energy clustered by all layer clusters over CaloParticles energy in z+", nintEneCl_, minEneCl_, maxEneCl_)); @@ -674,12 +805,12 @@ void HGVHistoProducerAlgo::bookClusterHistos_ClusterLevel(DQMStore::IBooker& ibo nintTotNClsperlay_, minTotNClsperlay_, maxTotNClsperlay_); - histograms.h_energyclustered_perlayer[ilayer] = ibook.book1D( - "energyclustered_perlayer" + istr1, - "percent of total energy clustered by layer clusters over CaloParticless energy for layer " + istr2, - nintEneClperlay_, - minEneClperlay_, - maxEneClperlay_); + histograms.h_energyclustered_perlayer[ilayer] = + ibook.book1D("energyclustered_perlayer" + istr1, + "percent of total energy clustered by layer clusters over CaloParticles energy for layer " + istr2, + nintEneClperlay_, + minEneClperlay_, + maxEneClperlay_); } //--------------------------------------------------------------------------------------------------------------------------- @@ -1099,6 +1230,12 @@ void HGVHistoProducerAlgo::bookTracksterHistos(DQMStore::IBooker& ibook, Histogr ibook.book1D("trackster_y", "Y position of the Trackster;Trackster y", nintY_, minY_, maxY_)); histograms.h_trackster_z.push_back( ibook.book1D("trackster_z", "Z position of the Trackster;Trackster z", nintZ_, minZ_, maxZ_)); + histograms.h_trackster_R.push_back( + ibook.book1D("trackster_R", "R of the Trackster;Trackster R [cm]", nintR_, minR_, maxR_)); + histograms.h_trackster_alpha.push_back(ibook.book1D( + "trackster_alpha", "#alpha of the Trackster;Trackster #alpha [rad]", nintAlpha_, minAlpha_, maxAlpha_)); + histograms.h_trackster_time.push_back( + ibook.book1D("trackster_time", "Time of the Trackster;Trackster time [ns]", nintTime_, minTime_, maxTime_)); histograms.h_trackster_firstlayer.push_back(ibook.book1D( "trackster_firstlayer", "First layer of the Trackster;Trackster First Layer", 2 * layers, 0., (float)2 * layers)); histograms.h_trackster_lastlayer.push_back(ibook.book1D( @@ -1271,6 +1408,48 @@ void HGVHistoProducerAlgo::bookTracksterSTSHistos(DQMStore::IBooker& ibook, nintPt_, minPt_, maxPt_)); + // R + histograms.h_num_trackster_R[valType].push_back(ibook.book1D( + "Num_Trackster_R" + valSuffix_[valType], "Num Trackster R per Trackster;R [cm]", nintR_, minR_, maxR_)); + histograms.h_numMerge_trackster_R[valType].push_back(ibook.book1D( + "NumMerge_Trackster_R" + valSuffix_[valType], "Num Merge Trackster R per Trackster;R [cm]", nintR_, minR_, maxR_)); + histograms.h_denom_trackster_R[valType].push_back(ibook.book1D( + "Denom_Trackster_R" + valSuffix_[valType], "Denom Trackster R per Trackster;R [cm]", nintR_, minR_, maxR_)); + // Displacement angle (alpha) + histograms.h_num_trackster_alpha[valType].push_back(ibook.book1D("Num_Trackster_Alpha" + valSuffix_[valType], + "Num Trackster #alpha per Trackster;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + histograms.h_numMerge_trackster_alpha[valType].push_back( + ibook.book1D("NumMerge_Trackster_Alpha" + valSuffix_[valType], + "Num Merge Trackster #alpha per Trackster;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + histograms.h_denom_trackster_alpha[valType].push_back( + ibook.book1D("Denom_Trackster_Alpha" + valSuffix_[valType], + "Denom Trackster #alpha per Trackster;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + // time + histograms.h_num_trackster_time[valType].push_back(ibook.book1D("Num_Trackster_Time" + valSuffix_[valType], + "Num Trackster time per Trackster;time [ns]", + nintTime_, + minTime_, + maxTime_)); + histograms.h_numMerge_trackster_time[valType].push_back( + ibook.book1D("NumMerge_Trackster_Time" + valSuffix_[valType], + "Num Merge Trackster time per Trackster;time [ns]", + nintTime_, + minTime_, + maxTime_)); + histograms.h_denom_trackster_time[valType].push_back(ibook.book1D("Denom_Trackster_Time" + valSuffix_[valType], + "Denom Trackster time per Trackster;time [ns]", + nintTime_, + minTime_, + maxTime_)); histograms.h_sharedenergy_trackster2caloparticle[valType].push_back( ibook.book1D("SharedEnergy_trackster2" + ref_[valType], @@ -1408,6 +1587,7 @@ void HGVHistoProducerAlgo::bookTracksterSTSHistos(DQMStore::IBooker& ibook, nintEne_, minEne_, maxEne_)); + // pT histograms.h_numEff_caloparticle_pt[valType].push_back( ibook.book1D("NumEff_" + ref_[valType] + "_Pt", @@ -1432,6 +1612,74 @@ void HGVHistoProducerAlgo::bookTracksterSTSHistos(DQMStore::IBooker& ibook, nintPt_, minPt_, maxPt_)); + + // R + histograms.h_numEff_caloparticle_R[valType].push_back( + ibook.book1D("NumEff_" + ref_[valType] + "_R", + "Num Efficiency " + refText_[valType] + " R per Trackster;R [cm]", + nintR_, + minR_, + maxR_)); + histograms.h_num_caloparticle_R[valType].push_back( + ibook.book1D("Num_" + ref_[valType] + "_R", + "Num Purity " + refText_[valType] + " R per Trackster;R [cm]", + nintR_, + minR_, + maxR_)); + histograms.h_numDup_trackster_R[valType].push_back(ibook.book1D( + "NumDup_Trackster_R" + valSuffix_[valType], "Num Duplicate Trackster vs R;R [cm]", nintR_, minR_, maxR_)); + histograms.h_denom_caloparticle_R[valType].push_back(ibook.book1D( + "Denom_" + ref_[valType] + "_R", "Denom " + refText_[valType] + " R per Trackster;R [cm]", nintR_, minR_, maxR_)); + + // Displacement angle alpha + histograms.h_numEff_caloparticle_alpha[valType].push_back( + ibook.book1D("NumEff_" + ref_[valType] + "_Alpha", + "Num Efficiency " + refText_[valType] + " #alpha per Trackster;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + histograms.h_num_caloparticle_alpha[valType].push_back( + ibook.book1D("Num_" + ref_[valType] + "_Alpha", + "Num Purity " + refText_[valType] + " #alpha per Trackster;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + histograms.h_numDup_trackster_alpha[valType].push_back(ibook.book1D("NumDup_Trackster_Alpha" + valSuffix_[valType], + "Num Duplicate Trackster vs #alpha;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + histograms.h_denom_caloparticle_alpha[valType].push_back( + ibook.book1D("Denom_" + ref_[valType] + "_Alpha", + "Denom " + refText_[valType] + " #alpha per Trackster;#alpha [rad]", + nintAlpha_, + minAlpha_, + maxAlpha_)); + + // time + histograms.h_numEff_caloparticle_time[valType].push_back( + ibook.book1D("NumEff_" + ref_[valType] + "_Time", + "Num Efficiency " + refText_[valType] + " time per Trackster;time [ns]", + nintTime_, + minTime_, + maxTime_)); + histograms.h_num_caloparticle_time[valType].push_back( + ibook.book1D("Num_" + ref_[valType] + "_Time", + "Num Purity " + refText_[valType] + " time per Trackster;time [ns]", + nintTime_, + minTime_, + maxTime_)); + histograms.h_numDup_trackster_time[valType].push_back(ibook.book1D("NumDup_Trackster_Time" + valSuffix_[valType], + "Num Duplicate Trackster vs time;time [ns]", + nintTime_, + minTime_, + maxTime_)); + histograms.h_denom_caloparticle_time[valType].push_back( + ibook.book1D("Denom_" + ref_[valType] + "_Time", + "Denom " + refText_[valType] + " time per Trackster;time [ns]", + nintTime_, + minTime_, + maxTime_)); } void HGVHistoProducerAlgo::fill_info_histos(const Histograms& histograms, unsigned int layers) const { @@ -1834,15 +2082,11 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( const auto& hit_find_in_CP = detIdToCaloParticleId_Map.find(rh_detid); - // if the fraction is zero or the hit does not belong to any calo - // particle, set the caloparticleId for the hit to -1 this will - // contribute to the number of noise hits - - // MR Remove the case in which the fraction is 0, since this could be a - // real hit that has been marked as halo. if (rhFraction == 0.) { hitsToCaloParticleId[iHit] = -2; } + + // if the hit does not belong to any calo particle, subtract 1 (resulting in -1 or -3) if (hit_find_in_CP == detIdToCaloParticleId_Map.end()) { hitsToCaloParticleId[iHit] -= 1; } else { @@ -1868,7 +2112,7 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( // Fill the plots to compute the different metrics linked to // reco-level, namely fake-rate an merge-rate. In this loop should *not* - // restrict only to the selected caloParaticles. + // restrict only to the selected caloParticles. for (unsigned int lcId = 0; lcId < nLayerClusters; ++lcId) { const auto firstHitDetId = (clusters[lcId].hitsAndFractions())[0].first; if (recHitTools_->isBarrel(firstHitDetId)) @@ -1937,7 +2181,7 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( // Here Fill the plots to compute the different metrics linked to // gen-level, namely efficiency and duplicate. In this loop should restrict - // only to the selected caloParaticles. + // only to the selected caloParticles. for (const auto& cpId : cPSelectedIndices) { const edm::Ref cpRef(caloParticleHandle, cpId); const auto& lcsIt = cPOnLayerMap.find(cpRef); @@ -1962,11 +2206,13 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( } for (unsigned int layerId = 0; layerId < layers * 2; ++layerId) { - if (!cPEnergyOnLayer[layerId]) + auto& cpEn = cPEnergyOnLayer[layerId]; + if (!cpEn) continue; - histograms.h_denom_caloparticle_eta_perlayer.at(layerId)->Fill(cP[cpId].g4Tracks()[0].momentum().eta()); - histograms.h_denom_caloparticle_phi_perlayer.at(layerId)->Fill(cP[cpId].g4Tracks()[0].momentum().phi()); + auto& simtrack = cP[cpId].g4Tracks()[0]; + histograms.h_denom_caloparticle_eta_perlayer.at(layerId)->Fill(simtrack.momentum().eta()); + histograms.h_denom_caloparticle_phi_perlayer.at(layerId)->Fill(simtrack.momentum().phi()); if (lcsIt == cPOnLayerMap.end()) continue; @@ -1987,10 +2233,9 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( if (getLCLayerId(lcPair.first.index()) != layerId) continue; histograms.h_score_caloparticle2layercl_perlayer.at(layerId)->Fill(lcPair.second.second); - histograms.h_sharedenergy_caloparticle2layercl_perlayer.at(layerId)->Fill( - lcPair.second.first / cPEnergyOnLayer[layerId], cPEnergyOnLayer[layerId]); - histograms.h_energy_vs_score_caloparticle2layercl_perlayer.at(layerId)->Fill( - lcPair.second.second, lcPair.second.first / cPEnergyOnLayer[layerId]); + histograms.h_sharedenergy_caloparticle2layercl_perlayer.at(layerId)->Fill(lcPair.second.first / cpEn, cpEn); + histograms.h_energy_vs_score_caloparticle2layercl_perlayer.at(layerId)->Fill(lcPair.second.second, + lcPair.second.first / cpEn); } const auto assoc = std::count_if(std::begin(lcs), std::end(lcs), [&](const auto& obj) { if (getLCLayerId(obj.first.index()) != layerId) @@ -1999,11 +2244,11 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( return obj.second.second < ScoreCutCPtoLC_; }); if (assoc) { - histograms.h_num_caloparticle_eta_perlayer.at(layerId)->Fill(cP[cpId].g4Tracks()[0].momentum().eta()); - histograms.h_num_caloparticle_phi_perlayer.at(layerId)->Fill(cP[cpId].g4Tracks()[0].momentum().phi()); + histograms.h_num_caloparticle_eta_perlayer.at(layerId)->Fill(simtrack.momentum().eta()); + histograms.h_num_caloparticle_phi_perlayer.at(layerId)->Fill(simtrack.momentum().phi()); if (assoc > 1) { - histograms.h_numDup_caloparticle_eta_perlayer.at(layerId)->Fill(cP[cpId].g4Tracks()[0].momentum().eta()); - histograms.h_numDup_caloparticle_phi_perlayer.at(layerId)->Fill(cP[cpId].g4Tracks()[0].momentum().phi()); + histograms.h_numDup_caloparticle_eta_perlayer.at(layerId)->Fill(simtrack.momentum().eta()); + histograms.h_numDup_caloparticle_phi_perlayer.at(layerId)->Fill(simtrack.momentum().phi()); } const auto best = std::min_element(std::begin(lcs), std::end(lcs), [&](const auto& obj1, const auto& obj2) { if (getLCLayerId(obj1.first.index()) != layerId) @@ -2013,10 +2258,10 @@ void HGVHistoProducerAlgo::layerClusters_to_CaloParticles( else return true; }); - histograms.h_sharedenergy_caloparticle2layercl_vs_eta_perlayer.at(layerId)->Fill( - cP[cpId].g4Tracks()[0].momentum().eta(), best->second.first / cPEnergyOnLayer[layerId]); - histograms.h_sharedenergy_caloparticle2layercl_vs_phi_perlayer.at(layerId)->Fill( - cP[cpId].g4Tracks()[0].momentum().phi(), best->second.first / cPEnergyOnLayer[layerId]); + histograms.h_sharedenergy_caloparticle2layercl_vs_eta_perlayer.at(layerId)->Fill(simtrack.momentum().eta(), + best->second.first / cpEn); + histograms.h_sharedenergy_caloparticle2layercl_vs_phi_perlayer.at(layerId)->Fill(simtrack.momentum().phi(), + best->second.first / cpEn); } } } @@ -2536,26 +2781,13 @@ void HGVHistoProducerAlgo::tracksters_to_SimTracksters_fp(const Histograms& hist const TracksterToTracksterMap& simTrackstersToTrackstersMap, const validationType valType, const SimClusterToCaloParticleMap& scToCpMap, + const std::vector& cP, const std::vector& cPIndices, const std::vector& cPSelectedIndices, const edm::ProductID& cPHandle_id) const { const auto nTracksters = trackstersToSimTrackstersMap.getMap().size(); const auto nSimTracksters = simTrackstersToTrackstersMap.getMap().size(); - std::vector tracksters_FakeMerge(nTracksters, 0); - std::vector tracksters_PurityDuplicate(nSimTracksters, 0); - auto getCPId = [](const ticl::Trackster& simTS, - const edm::ProductID& cPHandle_id, - const SimClusterToCaloParticleMap& scToCpMap) { - const auto productID = simTS.seedID(); - if (productID == cPHandle_id) { - return simTS.seedIndex(); - } else { - return int(scToCpMap.at(simTS.seedIndex()).index()); - } - }; - auto ScoreCutSTStoTSPurDup = ScoreCutSTStoTSPurDup_[0]; - auto ScoreCutTStoSTSFakeMerge = ScoreCutTStoSTSFakeMerge_[0]; for (unsigned int tracksterIndex = 0; tracksterIndex < nTracksters; ++tracksterIndex) { const auto& trackster = *(trackstersToSimTrackstersMap.getRefFirst(tracksterIndex)); if (trackster.vertices().empty()) @@ -2569,10 +2801,19 @@ void HGVHistoProducerAlgo::tracksters_to_SimTracksters_fp(const Histograms& hist histograms.h_denom_trackster_en[valType][count]->Fill(iTS_en); histograms.h_denom_trackster_pt[valType][count]->Fill(iTS_pt); + const auto displacement = resolveRecoTracksterDisplacement(trackster); + histograms.h_denom_trackster_R[valType][count]->Fill(displacement.R); + histograms.h_denom_trackster_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_denom_trackster_time[valType][count]->Fill(trackster.time()); + + auto nonFake = ThresholdCounter::below(maxRecoToSimScoreForNonFake_, 1); + auto merge = ThresholdCounter::below(maxRecoToSimScoreForMerge_, 2); + // loop over trackstersToSimTrackstersMap[tracksterIndex] by index for (unsigned int i = 0; i < trackstersToSimTrackstersMap[tracksterIndex].size(); ++i) { - auto sharedEnergy = trackstersToSimTrackstersMap[tracksterIndex][i].sharedEnergy(); - auto score = trackstersToSimTrackstersMap[tracksterIndex][i].score(); + const auto& simTracksterAssociation = trackstersToSimTrackstersMap[tracksterIndex][i]; + auto sharedEnergy = simTracksterAssociation.sharedEnergy(); + auto score = simTracksterAssociation.score(); float sharedEnergyFraction = sharedEnergy / trackster.raw_energy(); if (i == 0) { histograms.h_score_trackster2bestCaloparticle[valType][count]->Fill(score); @@ -2591,49 +2832,61 @@ void HGVHistoProducerAlgo::tracksters_to_SimTracksters_fp(const Histograms& hist histograms.h_score_trackster2caloparticle[valType][count]->Fill(score); histograms.h_sharedenergy_trackster2caloparticle[valType][count]->Fill(sharedEnergyFraction); histograms.h_energy_vs_score_trackster2caloparticle[valType][count]->Fill(score, sharedEnergyFraction); - tracksters_FakeMerge[tracksterIndex] += score < ScoreCutTStoSTSFakeMerge; + nonFake.consider(score); + merge.consider(score); } - if (tracksters_FakeMerge[tracksterIndex] > 0) { + if (nonFake.isSatisfied()) { histograms.h_num_trackster_eta[valType][count]->Fill(iTS_eta); histograms.h_num_trackster_phi[valType][count]->Fill(iTS_phi); histograms.h_num_trackster_en[valType][count]->Fill(iTS_en); histograms.h_num_trackster_pt[valType][count]->Fill(iTS_pt); + histograms.h_num_trackster_R[valType][count]->Fill(displacement.R); + histograms.h_num_trackster_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_num_trackster_time[valType][count]->Fill(trackster.time()); + } - if (tracksters_FakeMerge[tracksterIndex] > 1) { - histograms.h_numMerge_trackster_eta[valType][count]->Fill(iTS_eta); - histograms.h_numMerge_trackster_phi[valType][count]->Fill(iTS_phi); - histograms.h_numMerge_trackster_en[valType][count]->Fill(iTS_en); - histograms.h_numMerge_trackster_pt[valType][count]->Fill(iTS_pt); - } + if (merge.isSatisfied()) { + histograms.h_numMerge_trackster_eta[valType][count]->Fill(iTS_eta); + histograms.h_numMerge_trackster_phi[valType][count]->Fill(iTS_phi); + histograms.h_numMerge_trackster_en[valType][count]->Fill(iTS_en); + histograms.h_numMerge_trackster_pt[valType][count]->Fill(iTS_pt); + histograms.h_numMerge_trackster_R[valType][count]->Fill(displacement.R); + histograms.h_numMerge_trackster_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_numMerge_trackster_time[valType][count]->Fill(trackster.time()); } } // Fill the plots to compute the different metrics linked to // gen-level, namely efficiency, purity and duplicate. In this loop should restrict - // only to the selected caloParaticles. + // only to the selected caloParticles. for (unsigned int simTracksterIndex = 0; simTracksterIndex < nSimTracksters; ++simTracksterIndex) { const auto& simTrackster = *(simTrackstersToTrackstersMap.getRefFirst(simTracksterIndex)); - const auto cpId = getCPId(simTrackster, cPHandle_id, scToCpMap); + const auto cpId = getCaloParticleId(simTrackster, cPHandle_id, scToCpMap); if (std::find(cPSelectedIndices.begin(), cPSelectedIndices.end(), cpId) == cPSelectedIndices.end()) continue; + const auto sts_eta = simTrackster.barycenter().eta(); const auto sts_phi = simTrackster.barycenter().phi(); const auto sts_en = simTrackster.raw_energy(); const auto sts_pt = simTrackster.raw_pt(); + const auto sts_time = simTrackster.time(); float inv_simtrackster_energy = 1.f / sts_en; + + const auto displacement = resolveSimTrackDisplacement(getSimTrack(cP[cpId])); + histograms.h_denom_caloparticle_eta[valType][count]->Fill(sts_eta); histograms.h_denom_caloparticle_phi[valType][count]->Fill(sts_phi); histograms.h_denom_caloparticle_en[valType][count]->Fill(sts_en); histograms.h_denom_caloparticle_pt[valType][count]->Fill(sts_pt); - //Loop through related Tracksters here - // In case the threshold to associate a CaloParticle to a Trackster is - // below 50%, there could be cases in which the CP is linked to more than - // one tracksters, leading to efficiencies >1. This boolean is used to - // avoid "over counting". - bool sts_considered_efficient = false; - bool sts_considered_pure = false; + histograms.h_denom_caloparticle_R[valType][count]->Fill(displacement.R); + histograms.h_denom_caloparticle_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_denom_caloparticle_time[valType][count]->Fill(sts_time); + + auto efficiency = ThresholdCounter::above(minTSTSharedEneFracEfficiency_, 1); + auto purity = ThresholdCounter::below(maxSimToRecoScoreForPurity_, 1); + auto duplicate = ThresholdCounter::below(maxSimToRecoScoreForDuplicate_, 2); for (unsigned int i = 0; i < simTrackstersToTrackstersMap[simTracksterIndex].size(); ++i) { const auto sharedEnergy = simTrackstersToTrackstersMap[simTracksterIndex][i].sharedEnergy(); @@ -2659,38 +2912,40 @@ void HGVHistoProducerAlgo::tracksters_to_SimTracksters_fp(const Histograms& hist histograms.h_sharedenergy_caloparticle2trackster[valType][count]->Fill(sharedEnergyFraction); histograms.h_energy_vs_score_caloparticle2trackster[valType][count]->Fill(score, sharedEnergyFraction); - // Fill the numerator for the efficiency calculation. The efficiency is computed by considering the energy shared between a Trackster and a _corresponding_ caloParticle. The threshold is configurable via python. - if (!sts_considered_efficient && (sharedEnergyFraction >= minTSTSharedEneFracEfficiency_)) { - sts_considered_efficient = true; - histograms.h_numEff_caloparticle_eta[valType][count]->Fill(sts_eta); - histograms.h_numEff_caloparticle_phi[valType][count]->Fill(sts_phi); - histograms.h_numEff_caloparticle_en[valType][count]->Fill(sts_en); - histograms.h_numEff_caloparticle_pt[valType][count]->Fill(sts_pt); - } + efficiency.consider(sharedEnergyFraction); + purity.consider(score); + duplicate.consider(score); + } // end of loop through Tracksters related to SimTrackster - if (score < ScoreCutSTStoTSPurDup) { - if (tracksters_PurityDuplicate[simTracksterIndex] < 1) - tracksters_PurityDuplicate[simTracksterIndex]++; // for Purity - if (sts_considered_pure) - tracksters_PurityDuplicate[simTracksterIndex]++; // for Duplicate - sts_considered_pure = true; - } + if (efficiency.isSatisfied()) { + histograms.h_numEff_caloparticle_eta[valType][count]->Fill(sts_eta); + histograms.h_numEff_caloparticle_phi[valType][count]->Fill(sts_phi); + histograms.h_numEff_caloparticle_en[valType][count]->Fill(sts_en); + histograms.h_numEff_caloparticle_pt[valType][count]->Fill(sts_pt); + histograms.h_numEff_caloparticle_R[valType][count]->Fill(displacement.R); + histograms.h_numEff_caloparticle_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_numEff_caloparticle_time[valType][count]->Fill(sts_time); + } - } // end of loop through Tracksters related to SimTrackster - if (tracksters_PurityDuplicate[simTracksterIndex] > 0) { + if (purity.isSatisfied()) { histograms.h_num_caloparticle_eta[valType][count]->Fill(sts_eta); histograms.h_num_caloparticle_phi[valType][count]->Fill(sts_phi); histograms.h_num_caloparticle_en[valType][count]->Fill(sts_en); histograms.h_num_caloparticle_pt[valType][count]->Fill(sts_pt); - - if (tracksters_PurityDuplicate[simTracksterIndex] > 1) { - histograms.h_numDup_trackster_eta[valType][count]->Fill(sts_eta); - histograms.h_numDup_trackster_phi[valType][count]->Fill(sts_phi); - histograms.h_numDup_trackster_en[valType][count]->Fill(sts_en); - histograms.h_numDup_trackster_pt[valType][count]->Fill(sts_pt); - } + histograms.h_num_caloparticle_R[valType][count]->Fill(displacement.R); + histograms.h_num_caloparticle_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_num_caloparticle_time[valType][count]->Fill(sts_time); } + if (duplicate.isSatisfied()) { + histograms.h_numDup_trackster_eta[valType][count]->Fill(sts_eta); + histograms.h_numDup_trackster_phi[valType][count]->Fill(sts_phi); + histograms.h_numDup_trackster_en[valType][count]->Fill(sts_en); + histograms.h_numDup_trackster_pt[valType][count]->Fill(sts_pt); + histograms.h_numDup_trackster_R[valType][count]->Fill(displacement.R); + histograms.h_numDup_trackster_alpha[valType][count]->Fill(displacement.alpha); + histograms.h_numDup_trackster_time[valType][count]->Fill(sts_time); + } } // end of loop through SimTracksters } @@ -2880,8 +3135,12 @@ void HGVHistoProducerAlgo::fill_trackster_histos( histograms.h_trackster_pt[count]->Fill(tst.raw_pt()); histograms.h_trackster_energy[count]->Fill(tst.raw_energy()); - } + histograms.h_trackster_time[count]->Fill(tst.time()); + const auto displacement = resolveRecoTracksterDisplacement(tst); + histograms.h_trackster_R[count]->Fill(displacement.R); + histograms.h_trackster_alpha[count]->Fill(displacement.alpha); + } } //end of loop through Tracksters histograms.h_tracksternum[count]->Fill(totNTstZm + totNTstZp); @@ -2903,6 +3162,7 @@ void HGVHistoProducerAlgo::fill_trackster_histos( simTrackstersToTrackstersByLCsMap, validationType::byLCs, scToCpMap, + cP, cPIndices, cPSelectedIndices, cPHandle_id); @@ -2913,6 +3173,7 @@ void HGVHistoProducerAlgo::fill_trackster_histos( simTrackstersFromCPsToTrackstersByLCsMap, validationType::byLCs_CP, scToCpMap, + cP, cPIndices, cPSelectedIndices, cPHandle_id); @@ -2923,6 +3184,7 @@ void HGVHistoProducerAlgo::fill_trackster_histos( simTrackstersFromCPsToTrackstersByHitsMap, validationType::byHits_CP, scToCpMap, + cP, cPIndices, cPSelectedIndices, cPHandle_id); @@ -2933,6 +3195,7 @@ void HGVHistoProducerAlgo::fill_trackster_histos( simTrackstersToTrackstersByHitsMap, validationType::byHits, scToCpMap, + cP, cPIndices, cPSelectedIndices, cPHandle_id); diff --git a/Validation/RecoTrack/python/plotting/plotting.py b/Validation/RecoTrack/python/plotting/plotting.py index a988eeff79c50..ca1c68a2c5098 100644 --- a/Validation/RecoTrack/python/plotting/plotting.py +++ b/Validation/RecoTrack/python/plotting/plotting.py @@ -195,12 +195,13 @@ def __init__(self, th1, uncertainty): xaxis = th1.GetXaxis() xaxis_arr = xaxis.GetXbins() + ratio_name = f"ratio_{id(self)}" if xaxis_arr.GetSize() > 0: # unequal binning lst = [xaxis_arr[i] for i in range(0, xaxis_arr.GetSize())] arr = array.array("d", lst) - self._ratio = ROOT.TH1F("foo", "foo", xaxis.GetNbins(), arr) + self._ratio = ROOT.TH1F(ratio_name, ratio_name, xaxis.GetNbins(), arr) else: - self._ratio = ROOT.TH1F("foo", "foo", xaxis.GetNbins(), xaxis.GetXmin(), xaxis.GetXmax()) + self._ratio = ROOT.TH1F(ratio_name, ratio_name, xaxis.GetNbins(), xaxis.GetXmin(), xaxis.GetXmax()) _copyStyle(th1, self._ratio) self._ratio.SetStats(0) self._ratio.SetLineColor(ROOT.kBlack) @@ -1212,7 +1213,6 @@ def _drawFrame(pad, bounds, zmax=None, xbinlabels=None, xbinlabelsize=None, xbin frame.SetMaximum(zmax) frame.SetBit(ROOT.TH1.kNoStats) - frame.SetBit(ROOT.kCanDelete) frame.Draw("") xaxis = frame.GetXaxis() @@ -2264,6 +2264,7 @@ def _set(attr, default): _set("onlyForPileup", False) self._ratioFactor = 1.25 + self._canvasId = 0 def setProperties(self, **kwargs): for name, value in kwargs.items(): @@ -2397,14 +2398,15 @@ def _drawSeparate(self, legendLabels, prefix, saveFormat, ratio, directory): lx2def = 0.95 ly1def = 0.85 ly2def = 0.95 - + ret = [] for plot in self._plots: if plot.isEmpty(): continue - canvas = _createCanvas(self._name+'Single', width, height) - canvasRatio = _createCanvas(self._name+'SingleRatio', width, int(height*self._ratioFactor)) + canvasId = self._resolveNextCanvasId() + canvas = _createCanvas(self._name+'Single'+canvasId, width, height) + canvasRatio = _createCanvas(self._name+'SingleRatio'+canvasId, width, int(height*self._ratioFactor)) # from TDRStyle for c in [canvas, canvasRatio]: @@ -2448,9 +2450,14 @@ def _drawSeparate(self, legendLabels, prefix, saveFormat, ratio, directory): del canvas del canvasRatio - + return ret + def _resolveNextCanvasId(self): + """Return an id for unique ROOT canvas names.""" + self._canvasId += 1 + return str(self._canvasId) + def _modifyPadForRatio(self, pad): """Internal method to set divide a pad to two for ratio plots""" _modifyPadForRatio(pad, self._ratioFactor)