Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:33:25

0001 from __future__ import absolute_import
0002 from builtins import range
0003 import os
0004 import copy
0005 import collections
0006 
0007 import ROOT
0008 ROOT.gROOT.SetBatch(True)
0009 ROOT.PyConfig.IgnoreCommandLineOptions = True
0010 
0011 from .plotting import Subtract, FakeDuplicate, CutEfficiency, Transform, AggregateBins, ROC, Plot, PlotEmpty, PlotGroup, PlotOnSideGroup, PlotFolder, Plotter
0012 from .html import PlotPurpose
0013 from . import plotting
0014 from . import validation
0015 from . import html
0016 
0017 ########################################
0018 #
0019 # Per track collection plots
0020 #
0021 ########################################
0022 
0023 _maxEff = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 0.8, 1.025, 1.2, 1.5, 2]
0024 _maxFake = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 0.8, 1.025]
0025 
0026 #_minMaxResol = [1e-5, 2e-5, 5e-5, 1e-4, 2e-4, 5e-4, 1e-3, 2e-3, 5e-3, 1e-2, 2e-2, 5e-2, 0.1, 0.2, 0.5, 1]
0027 _minMaxResol = [1e-5, 4e-5, 1e-4, 4e-4, 1e-3, 4e-3, 1e-2, 4e-2, 0.1, 0.4, 1]
0028 _minMaxN = [5e-1, 5, 5e1, 5e2, 5e3, 5e4, 5e5, 5e6, 5e7, 5e8, 5e9]
0029 
0030 _minHits = [0, 5, 10]
0031 _maxHits = [5, 10, 20, 40, 60, 80]
0032 _minLayers = [0, 5, 10]
0033 _maxLayers = [5, 10, 25]
0034 _maxPixelLayers = 8
0035 _min3DLayers = [0, 5, 10]
0036 _max3DLayers = [5, 10, 20]
0037 _minZ = [-60, -40, -20, -10, -5]
0038 _maxZ = [5, 10, 20, 40, 60]
0039 _minPU = [0, 10, 20, 50, 100, 150]
0040 _maxPU = [20, 50, 65, 80, 100, 150, 200, 250]
0041 _minMaxTracks = [0, 200, 500, 1000, 1500, 2000]
0042 _minMaxMVA = [-1.025, -0.5, 0, 0.5, 1.025]
0043 _maxDRJ = 0.1
0044 
0045 def _minMaxResidual(ma):
0046     return ([-x for x in ma], ma)
0047 
0048 (_minResidualPhi, _maxResidualPhi) = _minMaxResidual([1e-4, 2e-4]) # rad
0049 (_minResidualCotTheta, _maxResidualCotTheta) = _minMaxResidual([1e-4, 2e-4])
0050 (_minResidualDxy, _maxResidualDxy) = _minMaxResidual([10, 20, 50, 100]) # um
0051 (_minResidualDz, _maxResidualDz) = (_minResidualDxy, _maxResidualDxy)
0052 (_minResidualPt, _maxResidualPt) = _minMaxResidual([1, 1.5, 2, 5]) # %
0053 
0054 
0055 _legendDy_1row = 0.46
0056 _legendDy_2rows = -0.025
0057 _legendDy_2rows_3cols = -0.17
0058 _legendDy_4rows = 0.09
0059 
0060 # Ok, because of the way the "reference release" histograms are
0061 # stored, this histogram is not accessible for the summary plots. To
0062 # be fixed later with (large) reorganization of how things work.
0063 #_trackingNumberOfEventsHistogram = "DQMData/Run 1/Tracking/Run summary/Track/general_trackingParticleRecoAsssociation/tracks"
0064 
0065 _trackingIterationOrderHistogram = "DQMData/Run 1/Tracking/Run summary/TrackBuilding/num_reco_coll"
0066 
0067 def _makeEffFakeDupPlots(postfix, quantity, unit="", common={}, effopts={}, fakeopts={}):
0068     p = postfix
0069     q = quantity
0070     xq = q
0071     if unit != "":
0072         xq += " (" + unit + ")"
0073 
0074     effargs  = dict(xtitle="TP "+xq   , ytitle="efficiency vs "+q          , ymax=_maxEff)
0075     fakeargs = dict(xtitle="track "+xq, ytitle="fake+duplicates rate vs "+q, ymax=_maxFake)
0076     effargs.update(common)
0077     fakeargs.update(common)
0078     effargs.update(effopts)
0079     fakeargs.update(fakeopts)
0080 
0081     return [
0082         Plot("effic_vs_"+p, **effargs),
0083         Plot(FakeDuplicate("fakeduprate_vs_"+p, assoc="num_assoc(recoToSim)_"+p, dup="num_duplicate_"+p, reco="num_reco_"+p, title="fake+duplicates vs "+q), **fakeargs)
0084     ]
0085 
0086 def _makeFakeDupPileupPlots(postfix, quantity, unit="", xquantity="", xtitle=None, common={}):
0087     p = postfix
0088     q = quantity
0089     if xtitle is None:
0090         if xquantity != "":
0091             xq = xquantity
0092         else:
0093             xq = q
0094             if unit != "":
0095                 xq += " (" + unit + ")"
0096         xtitle="track "+xq
0097 
0098     return [
0099         Plot("fakerate_vs_"+p   , xtitle=xtitle, ytitle="fakerate vs "+q       , ymax=_maxFake, **common),
0100         Plot("duplicatesRate_"+p, xtitle=xtitle, ytitle="duplicates rate vs "+q, ymax=_maxFake, **common),
0101         Plot("pileuprate_"+p    , xtitle=xtitle, ytitle="pileup rate vs "+q    , ymax=_maxFake, **common),
0102     ]
0103 
0104 def _makeFakeDist(postfix):
0105     return Subtract("num_fake_"+postfix, "num_reco_"+postfix, "num_assoc(recoToSim)_"+postfix)
0106 
0107 def _makeDistPlots(postfix, quantity, common={}):
0108     p = postfix
0109     q = quantity
0110 
0111     args = dict(xtitle="track "+q, ylog=True, ymin=_minMaxN, ymax=_minMaxN)
0112     args.update(common)
0113 
0114     return [
0115         Plot("num_reco_"+p            , ytitle="tracks", **args),
0116         Plot("num_assoc(recoToSim)_"+p, ytitle="true tracks", **args),
0117         Plot(_makeFakeDist(p), ytitle="fake tracks", **args),
0118         Plot("num_duplicate_"+p       , ytitle="duplicate tracks", **args),
0119     ]
0120 
0121 def _makeDistSimPlots(postfix, quantity, common={}):
0122     p = postfix
0123     q = quantity
0124 
0125     args = dict(xtitle="TP "+q, ylog=True, ymin=_minMaxN, ymax=_minMaxN)
0126     args.update(common)
0127 
0128     return [
0129         Plot("num_simul_"+p            , ytitle="TrackingParticles", **args),
0130         Plot("num_assoc(simToReco)_"+p, ytitle="Reconstructed TPs", **args),
0131     ]
0132 
0133 def _makeMVAPlots(num, hp=False):
0134     pfix = "_hp" if hp else ""
0135     pfix2 = "Hp" if hp else ""
0136 
0137     xtitle = "MVA%d output"%num
0138     xtitlecut = "Cut on MVA%d output"%num
0139     args = dict(xtitle=xtitle, ylog=True, ymin=_minMaxN, ymax=_minMaxN)
0140 
0141     argsroc = dict(
0142         xtitle="Efficiency (excl. trk eff)", ytitle="Fake rate",
0143         xmax=_maxEff, ymax=_maxFake,
0144         drawStyle="EP",
0145     )
0146     argsroc2 = dict(
0147         ztitle="Cut on MVA%d"%num,
0148         xtitleoffset=5, ytitleoffset=6.5, ztitleoffset=4,
0149         adjustMarginRight=0.12
0150     )
0151     argsroc2.update(argsroc)
0152     argsroc2["drawStyle"] = "pcolz"
0153 
0154     argsprofile = dict(ymin=_minMaxMVA, ymax=_minMaxMVA)
0155 
0156     true_cuteff = CutEfficiency("trueeff_vs_mva%dcut%s"%(num,pfix), "num_assoc(recoToSim)_mva%dcut%s"%(num,pfix))
0157     fake_cuteff = CutEfficiency("fakeeff_vs_mva%dcut%s"%(num,pfix), Subtract("num_fake_mva%dcut%s"%(num,pfix), "num_reco_mva%dcut%s"%(num,pfix), "num_assoc(recoToSim)_mva%dcut%s"%(num,pfix)))
0158 
0159     return [
0160         PlotGroup("mva%d%s"%(num,pfix2), [
0161             Plot("num_assoc(recoToSim)_mva%d%s"%(num,pfix), ytitle="true tracks", **args),
0162             Plot(Subtract("num_fake_mva%d%s"%(num,pfix), "num_reco_mva%d%s"%(num,pfix), "num_assoc(recoToSim)_mva%d%s"%(num,pfix)), ytitle="fake tracks", **args),
0163             Plot("effic_vs_mva%dcut%s"%(num,pfix), xtitle=xtitlecut, ytitle="Efficiency (excl. trk eff)", ymax=_maxEff),
0164             #
0165             Plot("fakerate_vs_mva%dcut%s"%(num,pfix), xtitle=xtitlecut, ytitle="Fake rate", ymax=_maxFake),
0166             Plot(ROC("effic_vs_fake_mva%d%s"%(num,pfix), "effic_vs_mva%dcut%s"%(num,pfix), "fakerate_vs_mva%dcut%s"%(num,pfix)), **argsroc),
0167             Plot(ROC("effic_vs_fake_mva%d%s"%(num,pfix), "effic_vs_mva%dcut%s"%(num,pfix), "fakerate_vs_mva%dcut%s"%(num,pfix), zaxis=True), **argsroc2),
0168             # Same signal efficiency, background efficiency, and ROC definitions as in TMVA
0169             Plot(true_cuteff, xtitle=xtitlecut, ytitle="True track selection efficiency", ymax=_maxEff),
0170             Plot(fake_cuteff, xtitle=xtitlecut, ytitle="Fake track selection efficiency", ymax=_maxEff),
0171             Plot(ROC("true_eff_vs_fake_rej_mva%d%s"%(num,pfix), true_cuteff, Transform("fake_rej_mva%d%s"%(num,pfix), fake_cuteff, lambda x: 1-x)), xtitle="True track selection efficiency", ytitle="Fake track rejection", xmax=_maxEff, ymax=_maxEff),
0172         ], ncols=3, legendDy=_legendDy_1row),
0173         PlotGroup("mva%d%sPtEta"%(num,pfix2), [
0174             Plot("mva_assoc(recoToSim)_mva%d%s_pT"%(num,pfix), xtitle="Track p_{T} (GeV)", ytitle=xtitle+" for true tracks", xlog=True, **argsprofile),
0175             Plot("mva_fake_mva%d%s_pT"%(num,pfix), xtitle="Track p_{T} (GeV)", ytitle=xtitle+" for fake tracks", xlog=True, **argsprofile),
0176             Plot("mva_assoc(recoToSim)_mva%d%s_eta"%(num,pfix), xtitle="Track #eta", ytitle=xtitle+" for true tracks", **argsprofile),
0177             Plot("mva_fake_mva%d%s_eta"%(num,pfix), xtitle="Track #eta", ytitle=xtitle+" for fake tracks", **argsprofile),
0178         ], legendDy=_legendDy_2rows)
0179     ]
0180 
0181 _effandfakePtEtaPhi = PlotGroup("effandfakePtEtaPhi", [
0182     Plot("efficPt", title="Efficiency vs p_{T}", xtitle="TP p_{T} (GeV)", ytitle="efficiency vs p_{T}", xlog=True, ymax=_maxEff),
0183     Plot(FakeDuplicate("fakeduprate_vs_pT", assoc="num_assoc(recoToSim)_pT", dup="num_duplicate_pT", reco="num_reco_pT", title="fake+duplicates vs p_{T}"),
0184          xtitle="track p_{T} (GeV)", ytitle="fake+duplicates rate vs p_{T}", ymax=_maxFake, xlog=True),
0185     Plot("effic", xtitle="TP #eta", ytitle="efficiency vs #eta", title="", ymax=_maxEff),
0186     Plot(FakeDuplicate("fakeduprate_vs_eta", assoc="num_assoc(recoToSim)_eta", dup="num_duplicate_eta", reco="num_reco_eta", title=""),
0187          xtitle="track #eta", ytitle="fake+duplicates rate vs #eta", ymax=_maxFake),
0188 ] +
0189     _makeEffFakeDupPlots("phi", "#phi")
0190 )
0191 
0192 _effandfakeDxyDzBS = PlotGroup("effandfakeDxyDzBS",
0193                                _makeEffFakeDupPlots("dxy"  , "dxy"    , "cm") +
0194                                _makeEffFakeDupPlots("dz"   , "dz"     , "cm"),
0195                                legendDy=_legendDy_2rows
0196 )
0197 _effandfakeDxyDzPV = PlotGroup("effandfakeDxyDzPV",
0198                                _makeEffFakeDupPlots("dxypv"       , "dxy(PV)", "cm") +
0199                                _makeEffFakeDupPlots("dxypv_zoomed", "dxy(PV)", "cm") +
0200                                _makeEffFakeDupPlots("dzpv"        , "dz(PV)" , "cm") +
0201                                _makeEffFakeDupPlots("dzpv_zoomed" , "dz(PV)" , "cm"),
0202                                legendDy=_legendDy_4rows
0203 )
0204 _effandfakeHitsLayers = PlotGroup("effandfakeHitsLayers",
0205                                   _makeEffFakeDupPlots("hit"       , "hits"        , common=dict(xmin=_minHits    , xmax=_maxHits)) +
0206                                   _makeEffFakeDupPlots("layer"     , "layers"      , common=dict(xmin=_minLayers  , xmax=_maxLayers)) +
0207                                   _makeEffFakeDupPlots("pixellayer", "pixel layers", common=dict(                   xmax=_maxPixelLayers)) +
0208                                   _makeEffFakeDupPlots("3Dlayer"   , "3D layers"   , common=dict(xmin=_min3DLayers, xmax=_max3DLayers)),
0209                                   legendDy=_legendDy_4rows
0210 )
0211 _common = {"ymin": 0, "ymax": _maxEff}
0212 _effandfakePos = PlotGroup("effandfakePos",
0213                            _makeEffFakeDupPlots("vertpos", "vert r", "cm", fakeopts=dict(xtitle="track ref. point r (cm)", ytitle="fake+duplicates vs. r"), common=dict(xlog=True)) +
0214                            _makeEffFakeDupPlots("zpos"   , "vert z", "cm", fakeopts=dict(xtitle="track ref. point z (cm)", ytitle="fake+duplicates vs. z")) +
0215                            _makeEffFakeDupPlots("simpvz" , "Sim. PV z", "cm", common=dict(xtitle="Sim. PV z (cm)", xmin=_minZ, xmax=_maxZ))
0216 )
0217 _effandfakeDeltaRPU = PlotGroup("effandfakeDeltaRPU",
0218                                 _makeEffFakeDupPlots("dr"     , "#DeltaR", effopts=dict(xtitle="TP min #DeltaR"), fakeopts=dict(xtitle="track min #DeltaR"), common=dict(xlog=True)) +
0219                                 _makeEffFakeDupPlots("drj" , "#DeltaR(track, jet)", effopts=dict(xtitle="#DeltaR(TP, jet)", ytitle="efficiency vs #DeltaR(TP, jet"), fakeopts=dict(xtitle="#DeltaR(track, jet)"), common=dict(xlog=True, xmax=_maxDRJ))+
0220                                 _makeEffFakeDupPlots("pu"     , "PU"     , common=dict(xtitle="Pileup", xmin=_minPU, xmax=_maxPU)),
0221                                 legendDy=_legendDy_4rows
0222 )
0223 
0224 
0225 _algos_common = dict(removeEmptyBins=True, xbinlabelsize=10, xbinlabeloption="d")
0226 _duplicateAlgo = PlotOnSideGroup("duplicateAlgo", Plot("duplicates_oriAlgo_vs_oriAlgo", drawStyle="COLZ", adjustMarginLeft=0.1, adjustMarginRight=0.1, **_algos_common))
0227 
0228 _dupandfakePtEtaPhi = PlotGroup("dupandfakePtEtaPhi", [
0229     Plot("fakeratePt", xtitle="track p_{T} (GeV)", ytitle="fakerate vs p_{T}", xlog=True, ymax=_maxFake),
0230     Plot("duplicatesRate_Pt", xtitle="track p_{T} (GeV)", ytitle="duplicates rate vs p_{T}", ymax=_maxFake, xlog=True),
0231     Plot("pileuprate_Pt", xtitle="track p_{T} (GeV)", ytitle="pileup rate vs p_{T}", ymax=_maxFake, xlog=True),
0232     Plot("fakerate", xtitle="track #eta", ytitle="fakerate vs #eta", title="", ymax=_maxFake),
0233     Plot("duplicatesRate", xtitle="track #eta", ytitle="duplicates rate vs #eta", title="", ymax=_maxFake),
0234     Plot("pileuprate", xtitle="track #eta", ytitle="pileup rate vs #eta", title="", ymax=_maxFake),
0235 ] + _makeFakeDupPileupPlots("phi", "#phi"),
0236                          ncols=3
0237 )
0238 _dupandfakeDxyDzBS = PlotGroup("dupandfakeDxyDzBS",
0239                                _makeFakeDupPileupPlots("dxy"  , "dxy"    , "cm") +
0240                                _makeFakeDupPileupPlots("dz"   , "dz"     , "cm"),
0241                                ncols=3, legendDy=_legendDy_2rows_3cols
0242 )
0243 _dupandfakeDxyDzPV = PlotGroup("dupandfakeDxyDzPV",
0244                                _makeFakeDupPileupPlots("dxypv"       , "dxy(PV)", "cm") +
0245                                _makeFakeDupPileupPlots("dxypv_zoomed", "dxy(PV)", "cm") +
0246                                _makeFakeDupPileupPlots("dzpv"        , "dz(PV)" , "cm") +
0247                                _makeFakeDupPileupPlots("dzpv_zoomed" , "dz(PV)" , "cm"),
0248                                ncols=3, legendDy=_legendDy_4rows
0249 )
0250 _dupandfakeHitsLayers = PlotGroup("dupandfakeHitsLayers",
0251                                   _makeFakeDupPileupPlots("hit"       , "hits"        , common=dict(xmin=_minHits    , xmax=_maxHits)) +
0252                                   _makeFakeDupPileupPlots("layer"     , "layers"      , common=dict(xmin=_minLayers  , xmax=_maxLayers)) +
0253                                   _makeFakeDupPileupPlots("pixellayer", "pixel layers", common=dict(                   xmax=_maxPixelLayers)) +
0254                                   _makeFakeDupPileupPlots("3Dlayer"   , "3D layers"   , common=dict(xmin=_min3DLayers, xmax=_max3DLayers)),
0255                                   ncols=3, legendDy=_legendDy_4rows
0256 )
0257 _dupandfakePos = PlotGroup("dupandfakePos",
0258                            _makeFakeDupPileupPlots("vertpos", "r", "cm", xquantity="ref. point r (cm)", common=dict(xlog=True)) +
0259                            _makeFakeDupPileupPlots("zpos"   , "z", "cm", xquantity="ref. point z (cm)") +
0260                            _makeFakeDupPileupPlots("simpvz" , "Sim. PV z", xtitle="Sim. PV z (cm)", common=dict(xmin=_minZ, xmax=_maxZ)),
0261                            ncols=3,
0262 )
0263 _dupandfakeDeltaRPU = PlotGroup("dupandfakeDeltaRPU",
0264                                 _makeFakeDupPileupPlots("dr"     , "#DeltaR", xquantity="min #DeltaR", common=dict(xlog=True)) +
0265                                 _makeFakeDupPileupPlots("drj"     , "#DeltaR(track, jet)", xtitle="#DeltaR(track, jet)", common=dict(xlog=True, xmax=_maxDRJ)) +
0266                                 _makeFakeDupPileupPlots("pu"     , "PU"     , xtitle="Pileup", common=dict(xmin=_minPU, xmax=_maxPU)),
0267                                 ncols=3
0268 )
0269 _seedingLayerSet_common = dict(removeEmptyBins=True, xbinlabelsize=8, xbinlabeloption="d", adjustMarginRight=0.1)
0270 _dupandfakeSeedingPlots = _makeFakeDupPileupPlots("seedingLayerSet", "seeding layers", xtitle="", common=_seedingLayerSet_common)
0271 _dupandfakeChi2Seeding = PlotGroup("dupandfakeChi2Seeding",
0272                                    _makeFakeDupPileupPlots("chi2", "#chi^{2}") +
0273                                    _dupandfakeSeedingPlots,
0274                                    ncols=3, legendDy=_legendDy_2rows_3cols
0275 )
0276 
0277 _common = {
0278     "ytitle": "Fake+pileup rate",
0279     "ymax": _maxFake,
0280     "drawStyle": "EP",
0281 }
0282 _common2 = {}
0283 _common2.update(_common)
0284 _common2["drawStyle"] = "pcolz"
0285 _common2["ztitleoffset"] = 1.5
0286 _common2["xtitleoffset"] = 7
0287 _common2["ytitleoffset"] = 10
0288 _common2["ztitleoffset"] = 6
0289 _pvassociation1 = PlotGroup("pvassociation1", [
0290     Plot(ROC("effic_vs_fakepileup_dzpvcut", "effic_vs_dzpvcut", FakeDuplicate("fakepileup_vs_dzpvcut", assoc="num_assoc(recoToSim)_dzpvcut", reco="num_reco_dzpvcut", dup="num_pileup_dzpvcut")),
0291              xtitle="Efficiency vs. cut on dz(PV)", **_common),
0292     Plot(ROC("effic_vs_fakepileup2_dzpvcut", "effic_vs_dzpvcut", FakeDuplicate("fakepileup_vs_dzpvcut", assoc="num_assoc(recoToSim)_dzpvcut", reco="num_reco_dzpvcut", dup="num_pileup_dzpvcut"), zaxis=True),
0293              xtitle="Efficiency", ztitle="Cut on dz(PV)", **_common2),
0294     #
0295     Plot(ROC("effic_vs_fakepileup_dzpvsigcut",  "effic_vs_dzpvsigcut", FakeDuplicate("fakepileup_vs_dzpvsigcut", assoc="num_assoc(recoToSim)_dzpvsigcut", reco="num_reco_dzpvsigcut", dup="num_pileup_dzpvsigcut")),
0296              xtitle="Efficiency vs. cut on dz(PV)/dzError", **_common),
0297     Plot(ROC("effic_vs_fakepileup2_dzpvsigcut",  "effic_vs_dzpvsigcut", FakeDuplicate("fakepileup_vs_dzpvsigcut", assoc="num_assoc(recoToSim)_dzpvsigcut", reco="num_reco_dzpvsigcut", dup="num_pileup_dzpvsigcut"), zaxis=True),
0298              xtitle="Efficiency", ztitle="Cut on dz(PV)/dzError", **_common2),
0299 ], onlyForPileup=True,
0300                          legendDy=_legendDy_4rows
0301 )
0302 _pvassociation2 = PlotGroup("pvassociation2", [
0303     Plot("effic_vs_dzpvcut", xtitle="Cut on dz(PV) (cm)", ytitle="Efficiency vs. cut on dz(PV)", ymax=_maxEff),
0304     Plot("effic_vs_dzpvcut2", xtitle="Cut on dz(PV) (cm)", ytitle="Efficiency (excl. trk eff)", ymax=_maxEff),
0305     Plot("fakerate_vs_dzpvcut", xtitle="Cut on dz(PV) (cm)", ytitle="Fake rate vs. cut on dz(PV)", ymax=_maxFake),
0306     Plot("pileuprate_dzpvcut", xtitle="Cut on dz(PV) (cm)", ytitle="Pileup rate vs. cut on dz(PV)", ymax=_maxFake),
0307     #
0308     Plot("effic_vs_dzpvsigcut", xtitle="Cut on dz(PV)/dzError", ytitle="Efficiency vs. cut on dz(PV)/dzError", ymax=_maxEff),
0309     Plot("effic_vs_dzpvsigcut2", xtitle="Cut on dz(PV)/dzError", ytitle="Efficiency (excl. trk eff)", ymax=_maxEff),
0310     Plot("fakerate_vs_dzpvsigcut", xtitle="Cut on dz(PV)/dzError", ytitle="Fake rate vs. cut on dz(PV)/dzError", ymax=_maxFake),
0311     Plot("pileuprate_dzpvsigcut", xtitle="Cut on dz(PV)/dzError", ytitle="Pileup rate vs. cut on dz(PV)/dzError", ymax=_maxFake),
0312 ], onlyForPileup=True,
0313                          legendDy=_legendDy_4rows
0314 )
0315 
0316 
0317 # These don't exist in FastSim
0318 _common = {"normalizeToUnitArea": True, "stat": True, "drawStyle": "hist"}
0319 _dedx = PlotGroup("dedx", [
0320     Plot("h_dedx_estim1", xtitle="dE/dx, harm2", **_common),
0321     Plot("h_dedx_estim2", xtitle="dE/dx, trunc40", **_common),
0322     Plot("h_dedx_nom1", xtitle="dE/dx number of measurements", title="", **_common),
0323     Plot("h_dedx_sat1", xtitle="dE/dx number of measurements with saturation", title="", **_common),
0324     ],
0325                   legendDy=_legendDy_2rows
0326 )
0327 
0328 _chargemisid = PlotGroup("chargemisid", [
0329     Plot("chargeMisIdRate", xtitle="#eta", ytitle="charge mis-id rate vs #eta", ymax=0.05),
0330     Plot("chargeMisIdRate_Pt", xtitle="p_{T}", ytitle="charge mis-id rate vs p_{T}", xmax=300, ymax=0.1, xlog=True),
0331     Plot("chargeMisIdRate_hit", xtitle="hits", ytitle="charge mis-id rate vs hits", title=""),
0332     Plot("chargeMisIdRate_phi", xtitle="#phi", ytitle="charge mis-id rate vs #phi", title="", ymax=0.01),
0333     Plot("chargeMisIdRate_dxy", xtitle="dxy", ytitle="charge mis-id rate vs dxy", ymax=0.1),
0334     Plot("chargeMisIdRate_dz", xtitle="dz", ytitle="charge mis-id rate vs dz", ymax=0.1)
0335 ])
0336 _common = {"stat": True, "normalizeToUnitArea": True, "ylog": True, "ymin": 1e-6, "drawStyle": "hist"}
0337 _hitsAndPt = PlotGroup("hitsAndPt", [
0338     Plot("missing_inner_layers", xmin=_minLayers, xmax=_maxLayers, ymax=1, **_common),
0339     Plot("missing_outer_layers", xmin=_minLayers, xmax=_maxLayers, ymax=1, **_common),
0340     Plot("hits_eta", xtitle="track #eta", ytitle="<hits> vs #eta", ymin=_minHits, ymax=_maxHits, statyadjust=[0,0,-0.15],
0341          fallback={"name": "nhits_vs_eta", "profileX": True}),
0342     Plot("hits", stat=True, xtitle="track hits", xmin=_minHits, xmax=_maxHits, ylog=True, ymin=[5e-1, 5, 5e1, 5e2, 5e3], drawStyle="hist"),
0343     Plot("num_simul_pT", xtitle="TP p_{T}", xlog=True, ymax=[1e-1, 2e-1, 5e-1, 1], **_common),
0344     Plot("num_reco_pT", xtitle="track p_{T}", xlog=True, ymax=[1e-1, 2e-1, 5e-1, 1], **_common)
0345 ])
0346 _tuning = PlotGroup("tuning", [
0347     Plot("chi2", stat=True, normalizeToUnitArea=True, ylog=True, ymin=1e-6, ymax=[0.1, 0.2, 0.5, 1.0001], drawStyle="hist", xtitle="#chi^{2}", ratioUncertainty=False),
0348     Plot("chi2_prob", stat=True, normalizeToUnitArea=True, drawStyle="hist", xtitle="Prob(#chi^{2})"),
0349     Plot("chi2mean", title="", xtitle="#eta", ytitle="< #chi^{2} / ndf >", ymin=[0, 0.5], ymax=[2, 2.5, 3, 5],
0350          fallback={"name": "chi2_vs_eta", "profileX": True}),
0351     Plot("ptres_vs_eta_Mean", scale=100, title="", xtitle="TP #eta (PCA to beamline)", ytitle="< #delta p_{T} / p_{T} > (%)", ymin=_minResidualPt, ymax=_maxResidualPt),
0352     Plot("chi2mean_vs_pt", title="", xtitle="p_{T}", ytitle="< #chi^{2} / ndf >", ymin=[0, 0.5], ymax=[2, 2.5, 3, 5], xlog=True, fallback={"name": "chi2_vs_pt", "profileX": True}),
0353     Plot("chi2mean_vs_drj", title="", xtitle="#DeltaR(track, jet)", ytitle="< #chi^{2} / ndf >", ymin=[0, 0.5], ymax=[2, 2.5, 3, 5], xlog=True, xmax=_maxDRJ, fallback={"name": "chi2_vs_drj", "profileX": True}),
0354     Plot("ptres_vs_pt_Mean", title="", xtitle="p_{T}", ytitle="< #delta p_{T}/p_{T} > (%)", scale=100, ymin=_minResidualPt, ymax=_maxResidualPt,xlog=True)
0355 ],
0356                    legendDy=_legendDy_4rows
0357 )
0358 _common = {"stat": True, "fit": True, "normalizeToUnitArea": True, "drawStyle": "hist", "drawCommand": "", "xmin": -10, "xmax": 10, "ylog": True, "ymin": 5e-5, "ymax": [0.01, 0.05, 0.1, 0.2, 0.5, 0.8, 1.025], "ratioUncertainty": False}
0359 _pulls = PlotGroup("pulls", [
0360     Plot("pullPt", **_common),
0361     Plot("pullQoverp", **_common),
0362     Plot("pullPhi", **_common),
0363     Plot("pullTheta", **_common),
0364     Plot("pullDxy", **_common),
0365     Plot("pullDz", **_common),
0366 ],
0367                    legendDx=0.1, legendDw=-0.1, legendDh=-0.015
0368 )
0369 _common = {"title": "", "ylog": True, "xtitle": "TP #eta (PCA to beamline)", "ymin": _minMaxResol, "ymax": _minMaxResol}
0370 _resolutionsEta = PlotGroup("resolutionsEta", [
0371     Plot("phires_vs_eta_Sigma", ytitle="#sigma(#delta #phi) (rad)", **_common),
0372     Plot("cotThetares_vs_eta_Sigma", ytitle="#sigma(#delta cot(#theta))", **_common),
0373     Plot("dxyres_vs_eta_Sigma", ytitle="#sigma(#delta d_{xy}) (cm)", **_common),
0374     Plot("dzres_vs_eta_Sigma", ytitle="#sigma(#delta d_{z}) (cm)", **_common),
0375     Plot("ptres_vs_eta_Sigma", ytitle="#sigma(#delta p_{T}/p_{T})", **_common),
0376 ])
0377 _common = {"title": "", "ylog": True, "xlog": True, "xtitle": "TP p_{T} (PCA to beamline)", "xmin": 0.1, "xmax": 1000, "ymin": _minMaxResol, "ymax": _minMaxResol}
0378 _resolutionsPt = PlotGroup("resolutionsPt", [
0379     Plot("phires_vs_pt_Sigma", ytitle="#sigma(#delta #phi) (rad)", **_common),
0380     Plot("cotThetares_vs_pt_Sigma", ytitle="#sigma(#delta cot(#theta))", **_common),
0381     Plot("dxyres_vs_pt_Sigma", ytitle="#sigma(#delta d_{xy}) (cm)", **_common),
0382     Plot("dzres_vs_pt_Sigma", ytitle="#sigma(#delta d_{z}) (cm)", **_common),
0383     Plot("ptres_vs_pt_Sigma", ytitle="#sigma(#delta p_{T}/p_{T})", **_common),
0384 ])
0385 _common = {"title": "", "ylog": True, "xtitle": "TP #Phi (PCA to beamline)", "ymin": _minMaxResol, "ymax": _minMaxResol}
0386 _resolutionsPhi = PlotGroup("resolutionsPhi", [
0387     Plot("dxyres_vs_phi_Sigma", ytitle="#sigma(#delta d_{xy}) (cm)", **_common),
0388     Plot("dzres_vs_phi_Sigma", ytitle="#sigma(#delta d_{z}) (cm)", **_common),
0389     Plot("phires_vs_phi_Sigma", ytitle="#sigma(#delta #phi) (rad)", **_common),
0390     Plot("ptres_vs_phi_Sigma", ytitle="#sigma(#delta p_{T}/p_{T})", **_common),
0391 ])
0392 
0393 ## Extended set of plots
0394 _extDistPtEtaPhi = PlotGroup("distPtEtaPhi",
0395                              _makeDistPlots("pT", "p_{T} (GeV)", common=dict(xlog=True)) +
0396                              _makeDistPlots("eta", "#eta") +
0397                              _makeDistPlots("phi", "#phi"),
0398                              ncols=4)
0399 _extDistDxyDzBS = PlotGroup("distDxyDzBS",
0400                             _makeDistPlots("dxy"  , "dxy (cm)") +
0401                             _makeDistPlots("dz"   , "dz (cm)"),
0402                             ncols=4, legendDy=_legendDy_2rows)
0403 _extDistDxyDzPV = PlotGroup("distDxyDzPV",
0404                             _makeDistPlots("dxypv"       , "dxy(PV) (cm)") +
0405                             _makeDistPlots("dxypv_zoomed", "dxy(PV) (cm)") +
0406                             _makeDistPlots("dzpv"        , "dz(PV) (cm)") +
0407                             _makeDistPlots("dzpv_zoomed" , "dz(PV) (cm)"),
0408                             ncols=4, legendDy=_legendDy_4rows)
0409 _extDistHitsLayers = PlotGroup("distHitsLayers",
0410                                _makeDistPlots("hit"       , "hits"        , common=dict(xmin=_minHits    , xmax=_maxHits)) +
0411                                _makeDistPlots("layer"     , "layers"      , common=dict(xmin=_minLayers  , xmax=_maxLayers)) +
0412                                _makeDistPlots("pixellayer", "pixel layers", common=dict(                   xmax=_maxPixelLayers)) +
0413                                _makeDistPlots("3Dlayer"   , "3D layers"   , common=dict(xmin=_min3DLayers, xmax=_max3DLayers)),
0414                                ncols=4, legendDy=_legendDy_4rows,
0415 )
0416 _extDistPos = PlotGroup("distPos",
0417                               _makeDistPlots("vertpos", "ref. point r (cm)", common=dict(xlog=True)) +
0418                               _makeDistPlots("zpos"   , "ref. point z (cm)") +
0419                               _makeDistPlots("simpvz" , "Sim. PV z (cm)", common=dict(xmin=_minZ, xmax=_maxZ)),
0420                               ncols=3,
0421 )
0422 _extDistDeltaR = PlotGroup("distDeltaR",
0423                               _makeDistPlots("dr"     , "min #DeltaR", common=dict(xlog=True)) +
0424                               _makeDistPlots("drj"     , "#DeltaR(track, jet)", common=dict(xlog=True, xmax=_maxDRJ)),
0425                               ncols=2, legendDy=_legendDy_2rows,
0426 )
0427 _extDistSeedingPlots = _makeDistPlots("seedingLayerSet", "seeding layers", common=dict(xtitle="", **_seedingLayerSet_common))
0428 _extDistChi2Seeding = PlotGroup("distChi2Seeding",
0429                                 _makeDistPlots("chi2", "#chi^{2}") +
0430                                 _extDistSeedingPlots,
0431                                 ncols=4, legendDy=_legendDy_2rows_3cols
0432 )
0433 _common = dict(title="", xtitle="TP #eta (PCA to beamline)")
0434 _extResidualEta = PlotGroup("residualEta", [
0435     Plot("phires_vs_eta_Mean", ytitle="< #delta #phi > (rad)", ymin=_minResidualPhi, ymax=_maxResidualPhi, **_common),
0436     Plot("cotThetares_vs_eta_Mean", ytitle="< #delta cot(#theta) >", ymin=_minResidualCotTheta, ymax=_maxResidualCotTheta, **_common),
0437     Plot("dxyres_vs_eta_Mean", ytitle="< #delta d_{xy} > (#mum)", scale=10000, ymin=_minResidualDxy, ymax=_maxResidualDxy, **_common),
0438     Plot("dzres_vs_eta_Mean", ytitle="< #delta d_{z} > (#mum)", scale=10000, ymin=_minResidualDz, ymax=_maxResidualDz, **_common),
0439     Plot("ptres_vs_eta_Mean", ytitle="< #delta p_{T}/p_{T} > (%)", scale=100, ymin=_minResidualPt, ymax=_maxResidualPt, **_common), # same as in tuning, but to be complete
0440 ])
0441 _common = dict(title="", xlog=True, xtitle="TP p_{T} (PCA to beamline)", xmin=0.1, xmax=1000)
0442 _extResidualPt = PlotGroup("residualPt", [
0443     Plot("phires_vs_pt_Mean", ytitle="< #delta #phi > (rad)", ymin=_minResidualPhi, ymax=_maxResidualPhi, **_common),
0444     Plot("cotThetares_vs_pt_Mean", ytitle="< #delta cot(#theta > )", ymin=_minResidualCotTheta, ymax=_maxResidualCotTheta, **_common),
0445     Plot("dxyres_vs_pt_Mean", ytitle="< #delta d_{xy} > (#mum)", scale=10000, ymin=_minResidualDxy, ymax=_maxResidualDxy, **_common),
0446     Plot("dzres_vs_pt_Mean", ytitle="< #delta d_{z} > (#mum)", scale=10000, ymin=_minResidualDz, ymax=_maxResidualDz, **_common),
0447     Plot("ptres_vs_pt_Mean", ytitle="< #delta p_{T}/p_{T} > (%)", scale=100, ymin=_minResidualPt, ymax=_maxResidualPt, **_common), # same as in tuning, but to be complete
0448 ])
0449 _common = dict(title="", ytitle="Selected tracks/TrackingParticles", ymax=_maxEff)
0450 _extNrecVsNsim = PlotGroup("nrecVsNsim", [
0451     Plot("nrec_vs_nsim", title="", xtitle="TrackingParticles", ytitle="Tracks", profileX=True, xmin=_minMaxTracks, xmax=_minMaxTracks, ymin=_minMaxTracks, ymax=_minMaxTracks),
0452     Plot("nrecPerNsim_vs_pu", xtitle="Pileup", xmin=_minPU, xmax=_maxPU, **_common),
0453     Plot("nrecPerNsimPt", xtitle="p_{T} (GeV)", xlog=True, **_common),
0454     Plot("nrecPerNsim", xtitle="#eta", **_common)
0455 ], legendDy=_legendDy_2rows)
0456 _extHitsLayers = PlotGroup("hitsLayers", [
0457     Plot("PXLhits_vs_eta", xtitle="#eta", ytitle="<pixel hits>"),
0458     Plot("PXLlayersWithMeas_vs_eta", xtitle="#eta", ytitle="<pixel layers>"),
0459     Plot("STRIPhits_vs_eta", xtitle="#eta", ytitle="<strip hits>"),
0460     Plot("STRIPlayersWithMeas_vs_eta", xtitle="#eta", ytitle="<strip layers>"),
0461 ], legendDy=_legendDy_2rows)
0462 
0463 
0464 ## Extended set of plots also for simulation
0465 _extDistSimPtEtaPhi = PlotGroup("distsimPtEtaPhi",
0466                                 _makeDistSimPlots("pT", "p_{T} (GeV)", common=dict(xlog=True)) +
0467                                 _makeDistSimPlots("eta", "#eta") +
0468                                 _makeDistSimPlots("phi", "#phi"),
0469                                 ncols=2)
0470 _extDistSimDxyDzBS = PlotGroup("distsimDxyDzBS",
0471                                _makeDistSimPlots("dxy"  , "dxy (cm)") +
0472                                _makeDistSimPlots("dz"   , "dz (cm)"),
0473                                ncols=2, legendDy=_legendDy_2rows)
0474 _extDistSimDxyDzPV = PlotGroup("distsimDxyDzPV",
0475                                _makeDistSimPlots("dxypv"       , "dxy(PV) (cm)") +
0476                                _makeDistSimPlots("dxypv_zoomed", "dxy(PV) (cm)") +
0477                                _makeDistSimPlots("dzpv"        , "dz(PV) (cm)") +
0478                                _makeDistSimPlots("dzpv_zoomed" , "dz(PV) (cm)"),
0479                                ncols=2, legendDy=_legendDy_4rows)
0480 _extDistSimHitsLayers = PlotGroup("distsimHitsLayers",
0481                                   _makeDistSimPlots("hit"       , "hits"        , common=dict(xmin=_minHits    , xmax=_maxHits)) +
0482                                   _makeDistSimPlots("layer"     , "layers"      , common=dict(xmin=_minLayers  , xmax=_maxLayers)) +
0483                                   _makeDistSimPlots("pixellayer", "pixel layers", common=dict(                   xmax=_maxPixelLayers)) +
0484                                   _makeDistSimPlots("3Dlayer"   , "3D layers"   , common=dict(xmin=_min3DLayers, xmax=_max3DLayers)),
0485                                   ncols=2, legendDy=_legendDy_4rows,
0486 )
0487 _extDistSimPos = PlotGroup("distsimPos",
0488                                  _makeDistSimPlots("vertpos", "vert r (cm)", common=dict(xlog=True)) +
0489                                  _makeDistSimPlots("zpos"   , "vert z (cm)") +
0490                                  _makeDistSimPlots("simpvz" , "Sim. PV z (cm)", common=dict(xmin=_minZ, xmax=_maxZ)),
0491                                  ncols=3,
0492 )
0493 _extDistSimDeltaR = PlotGroup("distsimDeltaR",
0494                                  _makeDistSimPlots("dr"     , "min #DeltaR", common=dict(xlog=True)) +
0495                                  _makeDistSimPlots("drj" , "#DeltaR(TP, jet)", common=dict(xlog=True, xmax=_maxDRJ)),
0496                                  ncols=2, legendDy=_legendDy_2rows,
0497 )
0498 
0499 ########################################
0500 #
0501 # Summary plots
0502 #
0503 ########################################
0504 
0505 _possibleTrackingNonIterationColls = [
0506     'ak4PFJets',
0507     'btvLike',
0508 ]
0509 _possibleTrackingColls = [
0510     'initialStepPreSplitting',
0511     'initialStep',
0512     'highPtTripletStep', # phase1
0513     'detachedQuadStep', # phase1
0514     'detachedTripletStep',
0515     'lowPtQuadStep', # phase1
0516     'lowPtTripletStep',
0517     'pixelPairStepA', # seeds
0518     'pixelPairStepB', # seeds
0519     'pixelPairStepC', # seeds
0520     'pixelPairStep',
0521     'mixedTripletStepA', # seeds
0522     'mixedTripletStepB', # seeds
0523     'mixedTripletStep',
0524     'pixelLessStep',
0525     'tobTecStepPair',  # seeds
0526     'tobTecStepTripl', # seeds
0527     'tobTecStep',
0528     'displacedGeneralStep',
0529     'jetCoreRegionalStep',
0530     'muonSeededStepInOut',
0531     'muonSeededStepOutIn',
0532     'displacedRegionalStepPair',  # seeds
0533     'displacedRegionalStepTripl', # seeds
0534     'displacedRegionalStep',
0535     'duplicateMerge',
0536 ] + _possibleTrackingNonIterationColls
0537 _possibleTrackingCollsOld = {
0538     "Zero"  : "iter0",
0539     "First" : "iter1",
0540     "Second": "iter2",
0541     "Third" : "iter3",
0542     "Fourth": "iter4",
0543     "Fifth" : "iter5",
0544     "Sixth" : "iter6",
0545     "Seventh": "iter7",
0546     "Ninth" : "iter9",
0547     "Tenth" : "iter10",
0548 }
0549 
0550 def _trackingSubFoldersFallbackSLHC_Phase1PU140(subfolder):
0551     ret = subfolder.replace("trackingParticleRecoAsssociation", "AssociatorByHitsRecoDenom")
0552     for (old, new) in [("InitialStep",         "Zero"),
0553                        ("HighPtTripletStep",   "First"),
0554                        ("LowPtQuadStep",       "Second"),
0555                        ("LowPtTripletStep",    "Third"),
0556                        ("DetachedQuadStep",    "Fourth"),
0557                        ("PixelPairStep",       "Fifth"),
0558                        ("MuonSeededStepInOut", "Ninth"),
0559                        ("MuonSeededStepOutIn", "Tenth")]:
0560         ret = ret.replace(old, new)
0561     if ret == subfolder:
0562         return None
0563     return ret
0564 def _trackingRefFileFallbackSLHC_Phase1PU140(path):
0565     for (old, new) in [("initialStep",         "iter0"),
0566                        ("highPtTripletStep",   "iter1"),
0567                        ("lowPtQuadStep",       "iter2"),
0568                        ("lowPtTripletStep",    "iter3"),
0569                        ("detachedQuadStep",    "iter4"),
0570                        ("pixelPairStep",       "iter5"),
0571                        ("muonSeededStepInOut", "iter9"),
0572                        ("muonSeededStepOutIn", "iter10")]:
0573         path = path.replace(old, new)
0574     return path
0575 
0576 def _trackingSubFoldersFallbackFromPV(subfolder):
0577     return subfolder.replace("trackingParticleRecoAsssociation", "trackingParticleRecoAsssociationSignal")
0578 def _trackingSubFoldersFallbackConversion(subfolder):
0579     return subfolder.replace("quickAssociatorByHits", "quickAssociatorByHitsConversion")
0580 def _trackingSubFoldersFallbackPreSplitting(subfolder):
0581     return subfolder.replace("quickAssociatorByHits", "quickAssociatorByHitsPreSplitting")
0582 
0583 # Additional "quality" flags than highPurity. In a separate list to
0584 # allow customization.
0585 _additionalTrackQualities = [
0586     "Pt09",
0587     "ByOriginalAlgo",
0588     "ByAlgoMask"
0589 ]
0590 def _mapCollectionToAlgoQuality(collName):
0591     if "Hp" in collName:
0592         quality = "highPurity"
0593     else:
0594         quality = ""
0595     collNameNoQuality = collName.replace("Hp", "")
0596     for qual in _additionalTrackQualities:
0597         if qual in collName:
0598             quality += qual
0599             collNameNoQuality = collNameNoQuality.replace(qual, "")
0600 
0601     collNameNoQuality = collNameNoQuality.replace("Tracks", "", 1) # make summary naming consistent with iteration folders
0602     collNameLow = collNameNoQuality.lower().replace("frompv2", "").replace("frompv", "").replace("frompvalltp", "").replace("alltp", "")
0603 
0604     if collNameLow.find("seed") == 0:
0605         collNameLow = collNameLow[4:]
0606         if collNameLow == "initialstepseedspresplitting":
0607             collNameLow = "initialsteppresplittingseeds"
0608         elif collNameLow == "muonseededseedsinout":
0609             collNameLow = "muonseededstepinoutseeds"
0610         elif collNameLow == "muonseededseedsoutin":
0611             collNameLow = "muonseededstepoutinseeds"
0612 
0613         i_seeds = collNameLow.index("seeds")
0614         quality = collNameLow[i_seeds:]+quality
0615 
0616         collNameLow = collNameLow[:i_seeds]
0617 
0618     algo = None
0619     prefixes = ["cutsreco", "cutsrecofrompv", "cutsrecofrompv2", "cutsrecofrompvalltp", "cutsrecoetagreater2p7"]
0620     if collNameLow in ["general", "generalfrompv", "generaletagreater2p7"]+prefixes:
0621         algo = "ootb"
0622     elif collNameLow in ["pixel", "pixelfrompv", "pixelfrompvalltp"]:
0623         algo = "pixel"
0624     else:
0625         def testColl(coll):
0626             for pfx in prefixes:
0627                 if coll == collNameLow.replace(pfx, ""):
0628                     return True
0629             return False
0630 
0631         for coll in _possibleTrackingColls:
0632             if testColl(coll.lower()):
0633                 algo = coll
0634                 break
0635         # next try "old style"
0636         if algo is None:
0637             for coll, name in _possibleTrackingCollsOld.items():
0638                 if testColl(coll.lower()):
0639                     algo = name
0640                     break
0641 
0642         # fallback
0643         if algo is None:
0644             algo = collNameNoQuality
0645 
0646     # fix for track collection naming convention
0647     if algo == "muonSeededInOut":
0648         algo = "muonSeededStepInOut"
0649     if algo == "muonSeededOutIn":
0650         algo = "muonSeededStepOutIn"
0651 
0652     return (algo, quality)
0653 
0654 def _collhelper(name):
0655     return (name, [name])
0656 _collLabelMap = collections.OrderedDict(map(_collhelper, ["generalTracks"]+_possibleTrackingColls))
0657 _collLabelMapHp = collections.OrderedDict(map(_collhelper, ["generalTracks"]+[n for n in _possibleTrackingColls if "Step" in n]))
0658 def _summaryBinRename(binLabel, highPurity, byOriginalAlgo, byAlgoMask, ptCut, seeds):
0659     (algo, quality) = _mapCollectionToAlgoQuality(binLabel)
0660     if algo == "ootb":
0661         algo = "generalTracks"
0662     ret = None
0663 
0664     if byOriginalAlgo:
0665         if algo != "generalTracks" and "ByOriginalAlgo" not in quality: # keep generalTracks bin as well
0666             return None
0667         quality = quality.replace("ByOriginalAlgo", "")
0668     if byAlgoMask:
0669         if algo != "generalTracks" and "ByAlgoMask" not in quality: # keep generalTracks bin as well
0670             return None
0671         quality = quality.replace("ByAlgoMask", "")
0672     if ptCut:
0673         if "Pt09" not in quality:
0674             return None
0675         quality = quality.replace("Pt09", "")
0676 
0677     if highPurity:
0678         if quality == "highPurity":
0679             ret = algo
0680     elif seeds:
0681         i_seeds = quality.find("seeds")
0682         if i_seeds == 0:
0683             ret = algo
0684             seedSubColl = quality[i_seeds+5:]
0685             if seedSubColl != "":
0686                 ret += seedSubColl[0].upper() + seedSubColl[1:]
0687     else:
0688         if quality == "":
0689             ret = algo
0690 
0691     return ret
0692 
0693 def _constructSummary(mapping=None, highPurity=False, byOriginalAlgo=False, byAlgoMask=False, ptCut=False, seeds=False, midfix=""):
0694     _common = {"drawStyle": "EP", "xbinlabelsize": 10, "xbinlabeloption": "d"}
0695     _commonN = dict(ylog=True, ymin=_minMaxN, ymax=_minMaxN,
0696                     normalizeToNumberOfEvents=True,
0697     )
0698     _commonN.update(_common)
0699     _commonAB = dict(mapping=mapping,
0700                      renameBin=lambda bl: _summaryBinRename(bl, highPurity, byOriginalAlgo, byAlgoMask, ptCut, seeds),
0701                      ignoreMissingBins=True,
0702                      originalOrder=True,
0703     )
0704     if byOriginalAlgo or byAlgoMask:
0705         _commonAB["minExistingBins"] = 2
0706     prefix = "summary"+midfix
0707 
0708     h_eff = "effic_vs_coll"
0709     h_fakerate = "fakerate_vs_coll"
0710     h_duplicaterate = "duplicatesRate_coll"
0711     h_pileuprate = "pileuprate_coll"
0712 
0713     h_reco = "num_reco_coll"
0714     h_true = "num_assoc(recoToSim)_coll"
0715     h_fake = Subtract("num_fake_coll_orig", "num_reco_coll", "num_assoc(recoToSim)_coll")
0716     h_duplicate = "num_duplicate_coll"
0717     h_pileup = "num_pileup_coll"
0718     if mapping is not None:
0719         h_eff = AggregateBins("efficiency", h_eff, **_commonAB)
0720         h_fakerate = AggregateBins("fakerate", h_fakerate, **_commonAB)
0721         h_duplicaterate = AggregateBins("duplicatesRate", h_duplicaterate, **_commonAB)
0722         h_pileuprate = AggregateBins("pileuprate", h_pileuprate, **_commonAB)
0723 
0724         h_reco = AggregateBins("num_reco_coll", h_reco, **_commonAB)
0725         h_true = AggregateBins("num_true_coll", h_true, **_commonAB)
0726         h_fake = AggregateBins("num_fake_coll", h_fake, **_commonAB)
0727         h_duplicate = AggregateBins("num_duplicate_coll", h_duplicate, **_commonAB)
0728         h_pileup = AggregateBins("num_pileup_coll", h_pileup, **_commonAB)
0729 
0730     summary = PlotGroup(prefix, [
0731         Plot(h_eff, title="Efficiency vs collection", ytitle="Efficiency", ymin=1e-3, ymax=1, ylog=True, **_common),
0732         Plot(h_fakerate, title="Fakerate vs collection", ytitle="Fake rate", ymax=_maxFake, **_common),
0733         #
0734         Plot(h_duplicaterate, title="Duplicates rate vs collection", ytitle="Duplicates rate", ymax=_maxFake, **_common),
0735         Plot(h_pileuprate, title="Pileup rate vs collection", ytitle="Pileup rate", ymax=_maxFake, **_common),
0736         ],
0737                         legendDy=_legendDy_2rows
0738     )
0739     summaryN = PlotGroup(prefix+"_ntracks", [
0740         # FIXME
0741         #Plot(h_reco, ytitle="Tracks/event", title="Number of tracks/event vs collection", **_commonN),
0742         #Plot(h_true, ytitle="True tracks/event", title="Number of true tracks/event vs collection", **_commonN),
0743         #Plot(h_fake, ytitle="Fake tracks/event", title="Number of fake tracks/event vs collection", **_commonN),
0744         #Plot(h_duplicate, ytitle="Duplicate tracks/event", title="Number of duplicate tracks/event vs collection", **_commonN),
0745         #Plot(h_pileup, ytitle="Pileup tracks/event", title="Number of pileup tracks/event vs collection", **_commonN),
0746         Plot(h_reco, ytitle="Tracks", title="Number of tracks vs collection", **_commonN),
0747         Plot(h_true, ytitle="True tracks", title="Number of true tracks vs collection", **_commonN),
0748         Plot(h_fake, ytitle="Fake tracks", title="Number of fake tracks vs collection", **_commonN),
0749         Plot(h_duplicate, ytitle="Duplicate tracks", title="Number of duplicate tracks vs collection", **_commonN),
0750         Plot(h_pileup, ytitle="Pileup tracks", title="Number of pileup tracks vs collection", **_commonN),
0751     ])
0752 
0753     return (summary, summaryN)
0754 
0755 (_summaryRaw,              _summaryRawN)              = _constructSummary(midfix="Raw")
0756 (_summary,                 _summaryN)                 = _constructSummary(_collLabelMap)
0757 (_summaryHp,               _summaryNHp)               = _constructSummary(_collLabelMapHp, highPurity=True)
0758 (_summaryByOriginalAlgo,   _summaryByOriginalAlgoN)   = _constructSummary(_collLabelMapHp, byOriginalAlgo=True, midfix="ByOriginalAlgo")
0759 (_summaryByOriginalAlgoHp, _summaryByOriginalAlgoNHp) = _constructSummary(_collLabelMapHp, byOriginalAlgo=True, midfix="ByOriginalAlgo", highPurity=True)
0760 (_summaryByAlgoMask,       _summaryByAlgoMaskN)       = _constructSummary(_collLabelMapHp, byAlgoMask=True, midfix="ByAlgoMask")
0761 (_summaryByAlgoMaskHp,     _summaryByAlgoMaskNHp)     = _constructSummary(_collLabelMapHp, byAlgoMask=True, midfix="ByAlgoMask", highPurity=True)
0762 (_summaryPt09,             _summaryPt09N)             = _constructSummary(_collLabelMap, ptCut=True, midfix="Pt09")
0763 (_summaryPt09Hp,           _summaryPt09NHp)           = _constructSummary(_collLabelMap, ptCut=True, midfix="Pt09", highPurity=True)
0764 (_summarySeeds,            _summarySeedsN)            = _constructSummary(_collLabelMapHp, seeds=True)
0765 
0766 ########################################
0767 #
0768 # PackedCandidate plots
0769 #
0770 ########################################
0771 
0772 _common = {"normalizeToUnitArea": True, "ylog": True, "ymin": [1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2], "ymax": [1e-2, 1e-1, 1.1]}
0773 _commonStatus = {}
0774 _commonStatus.update(_common)
0775 _commonStatus.update({"xbinlabelsize": 10, "xbinlabeloption": "d", "drawStyle": "hist", "adjustMarginRight": 0.08})
0776 _commonLabelSize = {}
0777 _commonLabelSize.update(_common)
0778 _commonLabelSize.update({"xlabelsize": 17})
0779 
0780 _packedCandidateFlow = PlotGroup("flow", [
0781     Plot("selectionFlow", xbinlabelsize=10, xbinlabeloption="d", adjustMarginRight=0.1, drawStyle="hist", ylog=True, ymin=[0.9, 9, 9e1, 9e2, 9e3, 9e4, 9e5, 9e6, 9e7]),
0782     Plot("diffCharge", xtitle="Charge", **_common),
0783     Plot("diffIsHighPurity", xtitle="High purity status", **_common),
0784     Plot("diffNdof", xtitle="ndof", **_common),
0785     Plot("diffNormalizedChi2", xtitle="#chi^{2}/ndof", **_common),
0786 ])
0787 
0788 _packedCandidateHitsHitPattern = PlotGroup("hitsHitPattern", [
0789     Plot("diffHitPatternNumberOfValidHits", xtitle="Valid hits (via HitPattern)", **_common),
0790     Plot("diffHitPatternNumberOfValidPixelHits", xtitle="Valid pixel hits (via HitPattern)", **_common),
0791     Plot("diffHitPatternHasValidHitInFirstPixelBarrel", xtitle="Has valid hit in BPix1 layer (via HitPattern)", **_common),
0792     Plot("diffHitPatternNumberOfLostPixelHits", xtitle="Lost pixel hits (via HitPattern)", **_common),
0793 ],
0794                                            legendDy=_legendDy_2rows
0795 )
0796 _packedCandidateHits = PlotGroup("hits", [
0797     Plot("diffNumberOfHits", xtitle="Hits",  **_common),
0798     Plot("diffNumberOfPixelHits", xtitle="Pixel hits", **_common),
0799     Plot("diffLostInnerHits", xtitle="Lost inner hits", **_common),
0800     Plot("numberHitsOverMax", xtitle="Number of overflown hits", **_common),
0801     Plot("numberPixelHitsOverMax", xtitle="Number of overflown pixel hits", **_common),
0802     Plot("numberStripHitsOverMax", xtitle="Number of overflown strip hits", **_common),
0803 ],
0804                                  ncols=3, legendDy=_legendDy_2rows_3cols
0805 )
0806 
0807 _packedCandidateLayers = PlotGroup("layers", [
0808     PlotEmpty(),
0809     Plot("diffNumberOfPixelLayers", xtitle="Pixel layers",  **_common),
0810     Plot("diffNumberOfStripLayers", xtitle="Strip layers", **_common),
0811     #
0812     Plot("diffHitPatternTrackerLayersWithMeasurement", xtitle="Layers (via HitPattern)", **_common),
0813     Plot("diffHitPatternPixelLayersWithMeasurement", xtitle="Pixel layers (via HitPattern)", **_common),
0814     Plot("diffHitPatternStripLayersWithMeasurement", xtitle="Strip layers (via HitPattern)", **_common),
0815     #
0816     Plot("numberLayersOverMax", xtitle="Number of overflown layers", **_common),
0817     Plot("numberPixelLayersOverMax", xtitle="Number of overflown pixel layers", **_common),
0818     Plot("numberStripLayersOverMax", xtitle="Number of overflown strip layers", **_common),
0819 ],
0820                                    ncols=3
0821 )
0822 
0823 
0824 _packedCandidateImpactParameter1 = PlotGroup("impactParameter1", [
0825     Plot("diffDxyAssocPV", xtitle="dxy(assocPV)", adjustMarginRight=0.02, **_commonLabelSize),
0826     Plot("diffDxyAssocPVStatus", **_commonStatus),
0827     Plot("diffDxyAssocPVUnderOverFlowSign", xtitle="dxy(assocPV)", **_common),
0828     Plot("diffDzAssocPV", xtitle="dz(assocPV)", adjustMarginRight=0.02, **_commonLabelSize),
0829     Plot("diffDzAssocPVStatus", **_commonStatus),
0830     Plot("diffDzAssocPVUnderOverFlowSign", xtitle="dz(assocPV)", **_common),
0831     Plot("diffDxyError", xtitle="dxyError()", adjustMarginRight=0.02, **_commonLabelSize),
0832     Plot("diffDszError", xtitle="dszError()", adjustMarginRight=0.02, **_commonLabelSize),
0833     Plot("diffDzError", xtitle="dzError()", adjustMarginRight=0.02, **_commonLabelSize),
0834 
0835 ],
0836                                              ncols=3
0837 )
0838 
0839 _packedCandidateImpactParameter2 = PlotGroup("impactParameter2", [
0840     Plot("diffDxyPV", xtitle="dxy(PV) via PC", **_commonLabelSize),
0841     Plot("diffDzPV", xtitle="dz(PV) via PC", **_commonLabelSize),
0842     Plot("diffTrackDxyAssocPV", xtitle="dxy(PV) via PC::bestTrack()", **_commonLabelSize),
0843     Plot("diffTrackDzAssocPV", xtitle="dz(PV) via PC::bestTrack()", **_commonLabelSize),
0844     Plot("diffTrackDxyError", xtitle="dxyError() via PC::bestTrack()", adjustMarginRight=0.02, **_commonLabelSize),
0845     Plot("diffTrackDzError", xtitle="dzError() via PC::bestTrack()", **_commonLabelSize),
0846 ])
0847 
0848 _packedCandidateCovarianceMatrix1 = PlotGroup("covarianceMatrix1", [
0849     Plot("diffCovQoverpQoverp", xtitle="cov(qoverp, qoverp)", **_commonLabelSize),
0850     Plot("diffCovQoverpQoverpStatus", **_commonStatus),
0851     Plot("diffCovQoverpQoverpUnderOverFlowSign", xtitle="cov(qoverp, qoverp)", **_common),
0852     Plot("diffCovLambdaLambda", xtitle="cov(lambda, lambda)", **_commonLabelSize),
0853     Plot("diffCovLambdaLambdaStatus", **_commonStatus),
0854     Plot("diffCovLambdaLambdaUnderOverFlowSign", xtitle="cov(lambda, lambda)", **_common),
0855     Plot("diffCovLambdaDsz", xtitle="cov(lambda, dsz)", **_commonLabelSize),
0856     Plot("diffCovLambdaDszStatus", **_commonStatus),
0857     Plot("diffCovLambdaDszUnderOverFlowSign", xtitle="cov(lambda, dsz)", **_common),
0858     Plot("diffCovPhiPhi", xtitle="cov(phi, phi)", **_commonLabelSize),
0859     Plot("diffCovPhiPhiStatus", **_commonStatus),
0860     Plot("diffCovPhiPhiUnderOverFlowSign", xtitle="cov(phi, phi)", **_common),
0861 ],
0862                                               ncols=3, legendDy=_legendDy_4rows
0863 )
0864 _packedCandidateCovarianceMatrix2 = PlotGroup("covarianceMatrix2", [
0865     Plot("diffCovPhiDxy", xtitle="cov(phi, dxy)", **_commonLabelSize),
0866     Plot("diffCovPhiDxyStatus", **_commonStatus),
0867     Plot("diffCovPhiDxyUnderOverFlowSign", xtitle="cov(phi, dxy)", **_common),
0868     Plot("diffCovDxyDxy", xtitle="cov(dxy, dxy)", adjustMarginRight=0.02, **_commonLabelSize),
0869     Plot("diffCovDxyDxyStatus", **_commonStatus),
0870     Plot("diffCovDxyDxyUnderOverFlowSign", xtitle="cov(dxy, dxy)", **_common),
0871     Plot("diffCovDxyDsz", xtitle="cov(dxy, dsz)", adjustMarginRight=0.02, **_commonLabelSize),
0872     Plot("diffCovDxyDszStatus", **_commonStatus),
0873     Plot("diffCovDxyDszUnderOverFlowSign", xtitle="cov(dxy, dsz)", **_common),
0874     Plot("diffCovDszDsz", xtitle="cov(dsz, dsz)", adjustMarginRight=0.02, **_commonLabelSize),
0875     Plot("diffCovDszDszStatus", **_commonStatus),
0876     Plot("diffCovDszDszUnderOverFlowSign", xtitle="cov(dsz, dsz)", **_common),
0877 ],
0878                                               ncols=3, legendDy=_legendDy_4rows
0879 )
0880 
0881 _common["xlabelsize"] = 16
0882 _packedCandidateVertex = PlotGroup("vertex", [
0883     Plot("diffVx", xtitle="Reference point x", **_common),
0884     Plot("diffVy", xtitle="Reference point y", **_common),
0885     Plot("diffVz", xtitle="Reference point z", **_common),
0886 ],
0887                                    legendDy=_legendDy_2rows
0888 )
0889 
0890 _common["adjustMarginRight"] = 0.05
0891 _packedCandidateKinematics = PlotGroup("kinematics", [
0892     Plot("diffPt", xtitle="p_{T}", **_common),
0893     Plot("diffPtError", xtitle="p_{T} error", **_common),
0894     Plot("diffEta", xtitle="#eta", **_common),
0895     Plot("diffEtaError", xtitle="#eta error", **_common),
0896     Plot("diffPhi", xtitle="#phi", **_common),
0897 ])
0898 
0899 class TrackingPlotFolder(PlotFolder):
0900     def __init__(self, *args, **kwargs):
0901         self._fallbackRefFiles = kwargs.pop("fallbackRefFiles", [])
0902         PlotFolder.__init__(self, *args, **kwargs)
0903 
0904     def translateSubFolder(self, dqmSubFolderName):
0905         spl = dqmSubFolderName.split("_")
0906         if len(spl) != 2:
0907             return None
0908         collName = spl[0]
0909         return _mapCollectionToAlgoQuality(collName)
0910 
0911     def iterSelectionName(self, plotFolderName, translatedDqmSubFolder):
0912         (algoOrig, quality) = translatedDqmSubFolder
0913 
0914         for fallback in [lambda n: n]+self._fallbackRefFiles:
0915             algo = fallback(algoOrig)
0916 
0917             ret = ""
0918             if plotFolderName != "":
0919                 ret += "_"+plotFolderName
0920             if quality != "":
0921                 ret += "_"+quality
0922             if not (algo == "ootb" and quality != ""):
0923                 ret += "_"+algo
0924             yield ret
0925 
0926     def limitSubFolder(self, limitOnlyTo, translatedDqmSubFolder):
0927         """Return True if this subfolder should be processed
0928 
0929         Arguments:
0930         limitOnlyTo            -- Function '(algo, quality) -> bool'
0931         translatedDqmSubFolder -- Return value of translateSubFolder
0932         """
0933         (algo, quality) = translatedDqmSubFolder
0934         return limitOnlyTo(algo, quality)
0935 
0936     # track-specific hack
0937     def isAlgoIterative(self, algo):
0938         return algo not in _possibleTrackingNonIterationColls
0939 
0940 class TrackingSummaryTable:
0941     class GeneralTracks: pass
0942     class GeneralTracksPt09: pass
0943     class HighPurity: pass
0944     class HighPurityPt09: pass
0945     class BTVLike: pass
0946     class AK4PFJets: pass
0947     class Pixel: pass
0948     class PixelPt09: pass
0949 
0950     def __init__(self, section, collection=GeneralTracks):
0951         self._collection = collection
0952         self._purpose = PlotPurpose.TrackingSummary
0953         self._page = "summary"
0954         self._section = section
0955 
0956     def getPurpose(self):
0957         return self._purpose
0958 
0959     def getPage(self):
0960         return self._page
0961 
0962     def getSection(self, dqmSubFolder):
0963         return self._section
0964 
0965     def create(self, tdirectory):
0966         def _getAlgoQuality(data, algo, quality):
0967             for label, value in data.items():
0968                 (a, q) = _mapCollectionToAlgoQuality(label)
0969                 if a == algo and q == quality:
0970                     return value[0] # value is (value, uncertainty) tuple
0971             return None
0972         def _getN(hname):
0973             h = tdirectory.Get(hname)
0974             if not h:
0975                 return None
0976             data = plotting._th1ToOrderedDict(h)
0977             if self._collection == TrackingSummaryTable.GeneralTracks:
0978                 return _getAlgoQuality(data, "ootb", "")
0979             elif self._collection == TrackingSummaryTable.GeneralTracksPt09:
0980                 return _getAlgoQuality(data, "ootb", "Pt09")
0981             elif self._collection == TrackingSummaryTable.HighPurity:
0982                 return _getAlgoQuality(data, "ootb", "highPurity")
0983             elif self._collection == TrackingSummaryTable.HighPurityPt09:
0984                 return _getAlgoQuality(data, "ootb", "highPurityPt09")
0985             elif self._collection == TrackingSummaryTable.BTVLike:
0986                 return _getAlgoQuality(data, "btvLike", "")
0987             elif self._collection == TrackingSummaryTable.AK4PFJets:
0988                 return _getAlgoQuality(data, "ak4PFJets", "")
0989             elif self._collection == TrackingSummaryTable.Pixel:
0990                 return _getAlgoQuality(data, "pixel", "")
0991             elif self._collection == TrackingSummaryTable.PixelPt09:
0992                 return _getAlgoQuality(data, "pixel", "Pt09")
0993             else:
0994                 raise Exception("Collection not recognized, %s" % str(self._collection))
0995         def _formatOrNone(num, func):
0996             if num is None:
0997                 return None
0998             return func(num)
0999 
1000         n_tps = _formatOrNone(_getN("num_simul_coll"), int)
1001         n_m_tps = _formatOrNone(_getN("num_assoc(simToReco)_coll"), int)
1002 
1003         n_tracks = _formatOrNone(_getN("num_reco_coll"), int)
1004         n_true = _formatOrNone(_getN("num_assoc(recoToSim)_coll"), int)
1005         if n_tracks is not None and n_true is not None:
1006             n_fake = n_tracks-n_true
1007         else:
1008             n_fake = None
1009         n_pileup = _formatOrNone(_getN("num_pileup_coll"), int)
1010         n_duplicate = _formatOrNone(_getN("num_duplicate_coll"), int)
1011 
1012         eff = _formatOrNone(_getN("effic_vs_coll"), lambda n: "%.4f" % n)
1013         eff_nopt = _formatOrNone(_getN("effic_vs_coll_allPt"), lambda n: "%.4f" % n)
1014         fake = _formatOrNone(_getN("fakerate_vs_coll"), lambda n: "%.4f" % n)
1015         duplicate = _formatOrNone(_getN("duplicatesRate_coll"), lambda n: "%.4f" % n)
1016 
1017         ret = [eff, n_tps, n_m_tps,
1018                eff_nopt, fake, duplicate,
1019                n_tracks, n_true, n_fake, n_pileup, n_duplicate]
1020         if ret.count(None) == len(ret):
1021             return None
1022         return ret
1023 
1024     def headers(self):
1025         return [
1026             "Efficiency",
1027             "Number of TrackingParticles (after cuts)",
1028             "Number of matched TrackingParticles",
1029             "Efficiency (w/o pT cut)",
1030             "Fake rate",
1031             "Duplicate rate",
1032             "Number of tracks",
1033             "Number of true tracks",
1034             "Number of fake tracks",
1035             "Number of pileup tracks",
1036             "Number of duplicate tracks"
1037         ]
1038 
1039 # Provide a "PlotGroup" interface, but provide a html page
1040 class TrackingSeedingLayerTable:
1041     def __init__(self, fileName, plots, titles, isRate, **kwargs):
1042         self._plots = plots
1043         self._titles = titles
1044         self._fileName = fileName
1045         self._format = "%.4g" if isRate else "%d"
1046 
1047         if len(plots) != len(titles):
1048             raise Exception("Number of plots (%d) has to be the same as number of titles (%d)" % (len(plots), len(titles)))
1049 
1050         def _set(attr, default):
1051             setattr(self, "_"+attr, kwargs.get(attr, default))
1052 
1053         _set("onlyForPileup", False)
1054 
1055     def onlyForPileup(self):
1056         """Return True if the PlotGroup is intended only for pileup samples"""
1057         return self._onlyForPileup
1058 
1059     def create(self, tdirectoryNEvents, requireAllHistograms=False):
1060         # [plot][histo]
1061         for plot in self._plots:
1062             plot.create(tdirectoryNEvents, requireAllHistograms)
1063 
1064     def draw(self, legendLabels, prefix=None, directory="", *args, **kwargs):
1065         # Do not make the table if it would be empty
1066         onlyEmptyPlots = True
1067         for plot in self._plots:
1068             if not plot.isEmpty():
1069                 onlyEmptyPlots = False
1070                 break
1071         if onlyEmptyPlots:
1072             return []
1073 
1074         haveShortLabels = False
1075         legendLabels = legendLabels[:]
1076         if max(map(len, legendLabels)) > 20:
1077             haveShortLabels = True
1078             labels_short = [str(chr(ord('A')+i)) for i in range(len(legendLabels))]
1079             for i, ls in enumerate(labels_short):
1080                 legendLabels[i] = "%s: %s" % (ls, legendLabels[i])
1081         else:
1082             labels_short = legendLabels
1083 
1084         content = [
1085             '<html>',
1086             ' <body>',
1087             '  <table border="1">',
1088             '   <tr>',
1089         ]
1090 
1091 
1092         histos_linear = []
1093         histos_index = []
1094         labels = []
1095         for plot, title in zip(self._plots, self._titles):
1096             h_tmp = []
1097             l_tmp = []
1098             for h, l in zip(plot._histograms, labels_short):
1099                 if h is not None:
1100                     h_tmp.append(len(histos_linear))
1101                     histos_linear.append(h)
1102                     l_tmp.append(l)
1103 
1104             if len(h_tmp) > 0:
1105                 histos_index.append(h_tmp)
1106                 labels.append(l_tmp)
1107                 content.extend([
1108                     '    <td></td>',
1109                     '    <td colspan="%d">%s</td>' % (len(h_tmp), title),
1110                 ])
1111 
1112         if len(histos_linear) == 0:
1113             return []
1114 
1115         content.extend([
1116             '   </tr>',
1117             '   <tr>',
1118         ])
1119 
1120         xbinlabels = plotting._mergeBinLabelsX(histos_linear)
1121         histos_linear = plotting._th1IncludeOnlyBins(histos_linear, xbinlabels)
1122         if len(histos_linear) == 0:
1123             return []
1124         (histos_linear_new, xbinlabels) = plotting._th1RemoveEmptyBins(histos_linear, xbinlabels)
1125         # in practice either all histograms are returned, or none, but let's add a check anyway
1126         if len(histos_linear_new) > 0 and len(histos_linear_new) != len(histos_linear):
1127             raise Exception("This should never happen. len(histos_linear_new) %d != len(histos_linear) %d" % (len(histos_linear_new), len(histos_linear)))
1128         histos_linear = histos_linear_new
1129         if len(histos_linear) == 0:
1130             return []
1131 
1132         data = [ [h.GetBinContent(i) for i in range(1, h.GetNbinsX()+1)] for h in histos_linear]
1133         table = html.Table(["dummy"]*len(histos_linear), xbinlabels, data, None, None, None)
1134         data = table.tableAsRowColumn()
1135 
1136         for labs in labels:
1137             content.append('    <td></td>')
1138             content.extend(['    <td>%s</td>' % lab for lab in labs])
1139         content.extend([
1140             '   </tr>',
1141         ])
1142 
1143         for irow, row in enumerate(data):
1144             content.extend([
1145                 '    <tr>',
1146                 '     <td>%s</td>' % table.rowHeaders()[irow]
1147             ])
1148 
1149             for hindices in histos_index:
1150                 for hindex in hindices:
1151                     item = row[hindex]
1152                     formatted = self._format%item if item is not None else ""
1153                     content.append('     <td align="right">%s</td>' % formatted)
1154                 content.append('    <td></td>')
1155             del content[-1]
1156             content.append('    </tr>')
1157 
1158         content.append('  </table>')
1159         if haveShortLabels:
1160             for lab in legendLabels:
1161                 content.append('  %s<br/>' % lab)
1162 
1163         content.extend([
1164             ' </body>',
1165             '<html>'
1166         ])
1167 
1168         name = self._fileName
1169         if prefix is not None:
1170             name = prefix+name
1171         name += ".html"
1172         name = os.path.join(directory, name)
1173 
1174         with open(name, "w") as f:
1175             for line in content:
1176                 f.write(line)
1177                 f.write("\n")
1178         return [name]
1179 
1180 _dupandfakeSeedingTable = TrackingSeedingLayerTable("dupandfakeSeeding", [p.clone() for p in _dupandfakeSeedingPlots],
1181                                                     ["Fake rate", "Duplicate rate", "Pileup rate"], isRate=True)
1182 _extDistSeedingTable = TrackingSeedingLayerTable("distSeeding", [p.clone() for p in _extDistSeedingPlots],
1183                                                  ["All tracks", "True tracks", "Fake tracks", "Duplicate tracks"], isRate=False)
1184 
1185 def _trackingFolders(lastDirName="Track"):
1186     return [
1187         "DQMData/Run 1/Tracking/Run summary/"+lastDirName,
1188         "DQMData/Tracking/"+lastDirName,
1189         "DQMData/Run 1/RecoTrackV/Run summary/"+lastDirName,
1190         "DQMData/RecoTrackV/"+lastDirName,
1191     ]
1192 
1193 _simBasedPlots = [
1194     _effandfakePtEtaPhi,
1195     _effandfakeDxyDzBS,
1196     _effandfakeDxyDzPV,
1197     _effandfakeHitsLayers,
1198     _effandfakePos,
1199     _effandfakeDeltaRPU,
1200     _duplicateAlgo,
1201 ]
1202 _recoBasedPlots = [
1203     _dupandfakePtEtaPhi,
1204     _dupandfakeDxyDzBS,
1205     _dupandfakeDxyDzPV,
1206     _dupandfakeHitsLayers,
1207     _dupandfakePos,
1208     _dupandfakeDeltaRPU,
1209     _dupandfakeChi2Seeding,
1210     _dupandfakeSeedingTable,
1211     _pvassociation1,
1212     _pvassociation2,
1213     _dedx,
1214 #    _chargemisid,
1215     _hitsAndPt,
1216     _pulls,
1217     _resolutionsEta,
1218     _resolutionsPhi,
1219     _resolutionsPt,
1220     _tuning,
1221 ]
1222 _seedingBuildingPlots = _simBasedPlots + [
1223     _dupandfakePtEtaPhi,
1224     _dupandfakeDxyDzBS,
1225     _dupandfakeDxyDzPV,
1226     _dupandfakeHitsLayers,
1227     _dupandfakePos,
1228     _dupandfakeDeltaRPU,
1229     _dupandfakeChi2Seeding,
1230     _dupandfakeSeedingTable,
1231     _hitsAndPt,
1232 ] + _makeMVAPlots(1) \
1233   + _makeMVAPlots(2) \
1234   + _makeMVAPlots(2, hp=True) \
1235   + _makeMVAPlots(3) \
1236   + _makeMVAPlots(3, hp=True)
1237 # add more if needed
1238 _buildingExtendedPlots = [
1239     _pulls,
1240     _resolutionsEta,
1241     _resolutionsPhi,
1242     _resolutionsPt,
1243     _tuning,
1244 ]
1245 _extendedPlots = [
1246     _extDistPtEtaPhi,
1247     _extDistDxyDzBS,
1248     _extDistDxyDzPV,
1249     _extDistHitsLayers,
1250     _extDistPos,
1251     _extDistDeltaR,
1252     _extDistChi2Seeding,
1253     _extDistSeedingTable,
1254     _extResidualEta,
1255     _extResidualPt,
1256     _extNrecVsNsim,
1257     _extHitsLayers,
1258     _extDistSimPtEtaPhi,
1259     _extDistSimDxyDzBS,
1260     _extDistSimDxyDzPV,
1261     _extDistSimHitsLayers,
1262     _extDistSimPos,
1263     _extDistSimDeltaR,
1264 ]
1265 _summaryPlots = [
1266     _summary,
1267     _summaryN,
1268     _summaryByOriginalAlgo,
1269     _summaryByOriginalAlgoN,
1270     _summaryByAlgoMask,
1271     _summaryByAlgoMaskN,
1272     _summaryPt09,
1273     _summaryPt09N,
1274 ]
1275 _summaryPlotsHp = [
1276     _summaryHp,
1277     _summaryNHp,
1278     _summaryByOriginalAlgoHp,
1279     _summaryByOriginalAlgoNHp,
1280     _summaryByAlgoMaskHp,
1281     _summaryByAlgoMaskNHp,
1282     _summaryPt09Hp,
1283     _summaryPt09NHp,
1284 ]
1285 _summaryPlotsSeeds = [
1286     _summarySeeds,
1287     _summarySeedsN,
1288 ]
1289 _packedCandidatePlots = [
1290     _packedCandidateFlow,
1291     _packedCandidateKinematics,
1292     _packedCandidateVertex,
1293     _packedCandidateImpactParameter1,
1294     _packedCandidateImpactParameter2,
1295     _packedCandidateCovarianceMatrix1,
1296     _packedCandidateCovarianceMatrix2,
1297     _packedCandidateHits,
1298     _packedCandidateHitsHitPattern,
1299     _packedCandidateLayers,
1300 ]
1301 plotter = Plotter()
1302 plotterExt = Plotter()
1303 def _appendTrackingPlots(lastDirName, name, algoPlots, onlyForPileup=False, onlyForElectron=False, onlyForConversion=False, onlyForBHadron=False, seeding=False, building=False, rawSummary=False, highPuritySummary=True):
1304     folders = _trackingFolders(lastDirName)
1305     # to keep backward compatibility, this set of plots has empty name
1306     limiters = dict(onlyForPileup=onlyForPileup, onlyForElectron=onlyForElectron, onlyForConversion=onlyForConversion, onlyForBHadron=onlyForBHadron)
1307     commonForTPF = dict(purpose=PlotPurpose.TrackingIteration, fallbackRefFiles=[
1308         _trackingRefFileFallbackSLHC_Phase1PU140
1309     ], **limiters)
1310     common = dict(fallbackDqmSubFolders=[
1311         _trackingSubFoldersFallbackSLHC_Phase1PU140,
1312         _trackingSubFoldersFallbackFromPV, _trackingSubFoldersFallbackConversion,
1313         _trackingSubFoldersFallbackPreSplitting])
1314     plotter.append(name, folders, TrackingPlotFolder(*algoPlots, **commonForTPF), **common)
1315     extendedPlots = []
1316     if building:
1317         extendedPlots.extend(_buildingExtendedPlots)
1318     extendedPlots.extend(_extendedPlots)
1319     plotterExt.append(name, folders, TrackingPlotFolder(*extendedPlots, **commonForTPF), **common)
1320 
1321     summaryName = ""
1322     if name != "":
1323         summaryName += name+"_"
1324     summaryName += "summary"
1325     summaryPlots = []
1326     if rawSummary:
1327         summaryPlots.extend([_summaryRaw, _summaryRawN])
1328     summaryPlots.extend(_summaryPlots)
1329 
1330     common = dict(loopSubFolders=False, purpose=PlotPurpose.TrackingSummary, page="summary",
1331                   #numberOfEventsHistogram=_trackingNumberOfEventsHistogram, # FIXME
1332                   **limiters)
1333     plotter.append(summaryName, folders,
1334                    PlotFolder(*summaryPlots, section=name, **common))
1335     if highPuritySummary:
1336         plotter.append(summaryName+"_highPurity", folders,
1337                        PlotFolder(*_summaryPlotsHp, section=name+"_highPurity" if name != "" else "highPurity", **common),
1338                        fallbackNames=[summaryName]) # backward compatibility for release validation, the HP plots used to be in the same directory with all-track plots
1339     if seeding:
1340         plotter.append(summaryName+"_seeds", folders,
1341                        PlotFolder(*_summaryPlotsSeeds, section=name+"_seeds", **common))
1342 
1343     plotter.appendTable(summaryName, folders, TrackingSummaryTable(section=name))
1344     plotter.appendTable(summaryName, folders, TrackingSummaryTable(section=name+"Pt09", collection=TrackingSummaryTable.GeneralTracksPt09))
1345     if highPuritySummary:
1346         sectionName = name+"_highPurity" if name != "" else "highPurity"
1347         plotter.appendTable(summaryName+"_highPurity", folders, TrackingSummaryTable(section=sectionName, collection=TrackingSummaryTable.HighPurity))
1348         plotter.appendTable(summaryName+"_highPurity", folders, TrackingSummaryTable(section=sectionName+"Pt09", collection=TrackingSummaryTable.HighPurityPt09))
1349     if name == "":
1350         plotter.appendTable(summaryName, folders, TrackingSummaryTable(section="btvLike", collection=TrackingSummaryTable.BTVLike))
1351         plotter.appendTable(summaryName, folders, TrackingSummaryTable(section="ak4PFJets", collection=TrackingSummaryTable.AK4PFJets))
1352 _appendTrackingPlots("Track", "", _simBasedPlots+_recoBasedPlots)
1353 _appendTrackingPlots("TrackTPPtLess09", "tpPtLess09", _simBasedPlots)
1354 _appendTrackingPlots("TrackTPEtaGreater2p7", "tpEtaGreater2p7", _simBasedPlots+_recoBasedPlots)
1355 _appendTrackingPlots("TrackAllTPEffic", "allTPEffic", _simBasedPlots, onlyForPileup=True)
1356 _appendTrackingPlots("TrackFromPV", "fromPV", _simBasedPlots+_recoBasedPlots, onlyForPileup=True)
1357 _appendTrackingPlots("TrackFromPVAllTP", "fromPVAllTP", _simBasedPlots+_recoBasedPlots, onlyForPileup=True)
1358 _appendTrackingPlots("TrackFromPVAllTP2", "fromPVAllTP2", _simBasedPlots+_recoBasedPlots, onlyForPileup=True)
1359 _appendTrackingPlots("TrackSeeding", "seeding", _seedingBuildingPlots, seeding=True)
1360 _appendTrackingPlots("TrackBuilding", "building", _seedingBuildingPlots, building=True)
1361 _appendTrackingPlots("TrackConversion", "conversion", _simBasedPlots+_recoBasedPlots, onlyForConversion=True, rawSummary=True, highPuritySummary=False)
1362 _appendTrackingPlots("TrackGsf", "gsf", _simBasedPlots+_recoBasedPlots, onlyForElectron=True, rawSummary=True, highPuritySummary=False)
1363 _appendTrackingPlots("TrackBHadron", "bhadron", _simBasedPlots+_recoBasedPlots, onlyForBHadron=True)
1364 _appendTrackingPlots("TrackDisplaced", "displaced", _simBasedPlots+_recoBasedPlots)
1365 # Pixel tracks
1366 def _appendPixelTrackingPlots(lastDirName, name):
1367     _common = dict(purpose=PlotPurpose.Pixel, page="pixel")
1368     _folders = _trackingFolders(lastDirName)
1369 
1370     plotter.append(name, _folders, TrackingPlotFolder(*(_simBasedPlots+_recoBasedPlots), **_common))
1371     plotterExt.append(name, _folders, TrackingPlotFolder(*_extendedPlots, **_common))
1372 
1373     plotter.append(name+"_summary",  _folders, PlotFolder(_summaryRaw, _summaryRawN, loopSubFolders=False, purpose=PlotPurpose.TrackingSummary, page="summary", section=name))
1374     plotter.append(name+"_summary",  _folders, PlotFolder(_summaryRaw, _summaryRawN, loopSubFolders=False, purpose=PlotPurpose.TrackingSummary, page="summary", section=name+"Pt09"))
1375     plotter.appendTable(name+"_summary", _folders, TrackingSummaryTable(section=name, collection=TrackingSummaryTable.Pixel))
1376     plotter.appendTable(name+"_summary", _folders, TrackingSummaryTable(section=name+"Pt09", collection=TrackingSummaryTable.PixelPt09))
1377 _appendPixelTrackingPlots("PixelTrack", "pixel")
1378 _appendPixelTrackingPlots("PixelTrackFromPV", "pixelFromPV")
1379 _appendPixelTrackingPlots("PixelTrackFromPVAllTP", "pixelFromPVAllTP")
1380 _appendPixelTrackingPlots("PixelTrackBHadron", "pixelbhadron")
1381 _appendPixelTrackingPlots("HIPixelTrack", "hiPixel")
1382 
1383 # MiniAOD
1384 plotter.append("packedCandidate", _trackingFolders("PackedCandidate"),
1385                PlotFolder(*_packedCandidatePlots, loopSubFolders=False,
1386                           purpose=PlotPurpose.MiniAOD, page="miniaod", section="PackedCandidate"))
1387 plotter.append("packedCandidateLostTracks", _trackingFolders("PackedCandidate/lostTracks"),
1388                PlotFolder(*_packedCandidatePlots, loopSubFolders=False,
1389                           purpose=PlotPurpose.MiniAOD, page="miniaod", section="PackedCandidate (lostTracks)"))
1390 
1391 # HLT
1392 _hltFolder = [
1393     "DQMData/Run 1/HLT/Run summary/Tracking/ValidationWRTtp",
1394 ]
1395 plotterHLT = Plotter()
1396 plotterHLTExt = Plotter()
1397 _common = dict(purpose=PlotPurpose.HLT, page="hlt")
1398 plotterHLT.append("hlt", _hltFolder, TrackingPlotFolder(*(_simBasedPlots+_recoBasedPlots), **_common))
1399 plotterHLTExt.append("hlt", _hltFolder, TrackingPlotFolder(*_extendedPlots, **_common))
1400 
1401 # Timing
1402 class Iteration:
1403     def __init__(self, name, clusterMasking=None, seeding=None, building=None, fit=None, selection=None, other=[]):
1404         self._name = name
1405 
1406         def _set(param, name, modules):
1407             if param is not None:
1408                 setattr(self, name, param)
1409             else:
1410                 setattr(self, name, modules)
1411 
1412         _set(clusterMasking, "_clusterMasking", [self._name+"Clusters"])
1413         # it's fine to include e.g. quadruplets here also for pair
1414         # steps, as non-existing modules are just ignored
1415         _set(seeding, "_seeding", [self._name+"SeedingLayers", self._name+"TrackingRegions", self._name+"HitDoublets", self._name+"HitTriplets", self._name+"HitQuadruplets", self._name+"Seeds"])
1416         trackCandidates = self._name+"TrackCandidates"
1417         _set(building, "_building", [trackCandidates+"MkFitSeeds", trackCandidates+"MkFit", trackCandidates])
1418         _set(fit, "_fit", [self._name+"Tracks"])
1419         _set(selection, "_selection", [self._name])
1420         self._other = other
1421 
1422     def name(self):
1423         return self._name
1424 
1425     def all(self):
1426         return self._clusterMasking+self._seeding+self._building+self._fit+self._selection+self._other
1427 
1428     def clusterMasking(self):
1429         return self._clusterMasking
1430 
1431     def seeding(self):
1432         return self._seeding
1433 
1434     def building(self):
1435         return self._building
1436 
1437     def fit(self):
1438         return self._fit
1439 
1440     def selection(self):
1441         return self._selection
1442 
1443     def other(self):
1444         return self._other
1445 
1446     def modules(self):
1447         return [("ClusterMask", self.clusterMasking()),
1448                 ("Seeding", self.seeding()),
1449                 ("Building", self.building()),
1450                 ("Fit", self.fit()),
1451                 ("Selection", self.selection()),
1452                 ("Other", self.other())]
1453 
1454 
1455 _iterations = [
1456     Iteration("initialStepPreSplitting", clusterMasking=[],
1457               seeding=["initialStepSeedLayersPreSplitting",
1458                        "initialStepTrackingRegionsPreSplitting",
1459                        "initialStepHitDoubletsPreSplitting",
1460                        "initialStepHitTripletsPreSplitting",
1461                        "initialStepHitQuadrupletsPreSplitting",
1462                        "initialStepSeedsPreSplitting"],
1463               building=["initialStepTrackCandidatesPreSplitting",
1464                         "initialStepTrackCandidatesMkFitSeedsPreSplitting",
1465                         "initialStepTrackCandidatesMkFitPreSplitting"],
1466               fit=["initialStepTracksPreSplitting"],
1467               other=["firstStepPrimaryVerticesPreSplitting",
1468                      "initialStepTrackRefsForJetsPreSplitting",
1469                      "caloTowerForTrkPreSplitting",
1470                      "ak4CaloJetsForTrkPreSplitting",
1471                      "jetsForCoreTrackingPreSplitting",
1472                      "siPixelClusters",
1473                      "siPixelRecHits",
1474                      "MeasurementTrackerEvent",
1475                      "siPixelClusterShapeCache",
1476                      "mkFitSiPixelHitsPreSplitting",
1477                      "mkFitSiStripHits",
1478                      "mkFitEventOfHitsPreSplitting"]),
1479     Iteration("initialStep", clusterMasking=[],
1480               selection=["initialStepClassifier1",
1481                          "initialStepClassifier2",
1482                          "initialStepClassifier3",
1483                          "initialStep",
1484                          "initialStepSelector"],
1485               other=["firstStepPrimaryVerticesUnsorted",
1486                      "initialStepTrackRefsForJets",
1487                      "caloTowerForTrk",
1488                      "ak4CaloJetsForTrk",
1489                      "firstStepPrimaryVertices",
1490                      "mkFitSiPixelHits",
1491                      "mkFitEventOfHits"]),
1492     Iteration("highPtTripletStep",
1493               selection=["highPtTripletStepClassifier1",
1494                          "highPtTripletStepClassifier2",
1495                          "highPtTripletStepClassifier3",
1496                          "highPtTripletStep",
1497                          "highPtTripletStepSelector"]),
1498     Iteration("detachedQuadStep",
1499               selection=["detachedQuadStepClassifier1",
1500                          "detachedQuadStepClassifier2",
1501                          "detachedQuadStep",
1502                          "detachedQuadStepSelector"]),
1503     Iteration("detachedTripletStep",
1504               selection=["detachedTripletStepClassifier1",
1505                          "detachedTripletStepClassifier2",
1506                          "detachedTripletStep",
1507                          "detachedTripletStepSelector"]),
1508     Iteration("lowPtQuadStep",
1509               selection=["lowPtQuadStepClassifier1",
1510                          "lowPtQuadStepClassifier2",
1511                          "lowPtQuadStep",
1512                          "lowPtQuadStepSelector"]),
1513     Iteration("lowPtTripletStep",
1514               selection=["lowPtTripletStepClassifier1",
1515                          "lowPtTripletStepClassifier2",
1516                          "lowPtTripletStep",
1517                          "lowPtTripletStepSelector"]),
1518     Iteration("pixelPairStep",
1519               seeding=["pixelPairStepSeedLayers",
1520                        "pixelPairStepSeedLayersB",
1521                        "pixelPairStepSeedLayersC",
1522                        "pixelPairStepTrackingRegions",
1523                        "pixelPairStepTrackingRegionsB",
1524                        "pixelPairStepTrackingRegionsC",
1525                        "pixelPairStepTrackingRegionsSeedLayersB",
1526                        "pixelPairStepHitDoublets",
1527                        "pixelPairStepHitDoubletsB",
1528                        "pixelPairStepHitDoubletsC",
1529                        "pixelPairStepSeedsA",
1530                        "pixelPairStepSeedsB",
1531                        "pixelPairStepSeedsC",
1532                        "pixelPairStepSeeds",],
1533               selection=["pixelPairStep",
1534                          "pixelPairStepSelector"]),
1535     Iteration("mixedTripletStep",
1536               seeding=["mixedTripletStepSeedLayersA",
1537                        "mixedTripletStepSeedLayersB",
1538                        "mixedTripletStepTrackingRegionsA",
1539                        "mixedTripletStepTrackingRegionsB",
1540                        "mixedTripletStepHitDoubletsA",
1541                        "mixedTripletStepHitDoubletsB",
1542                        "mixedTripletStepHitTripletsA",
1543                        "mixedTripletStepHitTripletsB",
1544                        "mixedTripletStepSeedsA",
1545                        "mixedTripletStepSeedsB",
1546                        "mixedTripletStepSeeds"],
1547               selection=["mixedTripletStepClassifier1",
1548                          "mixedTripletStepClassifier2",
1549                          "mixedTripletStep",
1550                          "mixedTripletStepSelector"]),
1551     Iteration("pixelLessStep",
1552               selection=["pixelLessStepClassifier1",
1553                          "pixelLessStepClassifier2",
1554                          "pixelLessStep",
1555                          "pixelLessStepSelector"]),
1556     Iteration("tobTecStep",
1557               seeding=["tobTecStepSeedLayersTripl",
1558                        "tobTecStepSeedLayersPair",
1559                        "tobTecStepTrackingRegionsTripl",
1560                        "tobTecStepTrackingRegionsPair",
1561                        "tobTecStepHitDoubletsTripl",
1562                        "tobTecStepHitDoubletsPair",
1563                        "tobTecStepHitTripletsTripl",
1564                        "tobTecStepSeedsTripl",
1565                        "tobTecStepSeedsPair",
1566                        "tobTecStepSeeds"],
1567               selection=["tobTecStepClassifier1",
1568                          "tobTecStepClassifier2",
1569                          "tobTecStep",
1570                          "tobTecStepSelector"]),
1571     Iteration("displacedGeneralStep",
1572               seeding=["displacedGeneralStepSeedLayers",
1573                        "displacedGeneralStepTrackingRegions",
1574                        "displacedGeneralStepHitDoublets",
1575                        "displacedGeneralStepHitTriplets",
1576                        "displacedGeneralStepSeeds"],
1577               selection=["displacedGeneralStepClassifier1",
1578                          "displacedGeneralStepClassifier2",
1579                          "displacedGeneralStep",
1580                          "displacedGeneralStepSelector"]),
1581     Iteration("jetCoreRegionalStep",
1582               clusterMasking=[],
1583               other=["jetsForCoreTracking",
1584                      "firstStepGoodPrimaryVertices",
1585                      ]),
1586     Iteration("muonSeededSteps",
1587               clusterMasking=[],
1588               seeding=["muonSeededSeedsInOut",
1589                        "muonSeededSeedsOutIn"],
1590               building=["muonSeededTrackCandidatesInOut",
1591                         "muonSeededTrackCandidatesOutIn"],
1592               fit=["muonSeededTracksInOut",
1593                    "muonSeededTracksOutIn"],
1594               selection=["muonSeededTracksInOutClassifier",
1595                          "muonSeededTracksInOutSelector",
1596                          "muonSeededTracksOutIntClassifier",
1597                          "muonSeededTracksOutIntSelector"],
1598 #              other=["earlyMuons"]
1599           ),
1600     Iteration("displacedRegionalStep",
1601               seeding=["displacedRegionalStepSeedLayersTripl",
1602                        "displacedRegionalStepSeedLayersPair",
1603                        "displacedRegionalStepTrackingRegionsTripl",
1604                        "displacedRegionalStepTrackingRegionsPair",
1605                        "displacedRegionalStepHitDoubletsTripl",
1606                        "displacedRegionalStepHitDoubletsPair",
1607                        "displacedRegionalStepHitTripletsTripl",
1608                        "displacedRegionalStepSeedsTripl",
1609                        "displacedRegionalStepSeedsPair",
1610                        "displacedRegionalStepSeeds"],
1611               selection=["displacedRegionalStepClassifier1",
1612                          "displacedRegionalStepClassifier2",
1613                          "displacedRegionalStep",
1614                          "displacedRegionalStepSelector"]),
1615     Iteration("duplicateMerge",
1616               clusterMasking=[], seeding=[],
1617               building=["duplicateTrackCandidates"],
1618               fit=["mergedDuplicateTracks"],
1619               selection=["duplicateTrackClassifier"]),
1620     Iteration("generalTracks",
1621               clusterMasking=[], seeding=[], building=[], fit=[], selection=[],
1622               other=["preDuplicateMergingGeneralTracks",
1623                      "generalTracks"]),
1624     Iteration("ConvStep",
1625               clusterMasking=["convClusters"],
1626               seeding=["convLayerPairs",
1627                        "photonConvTrajSeedFromSingleLeg"],
1628               building=["convTrackCandidates"],
1629               fit=["convStepTracks"],
1630               selection=["convStepSelector"]),
1631     Iteration("Other", clusterMasking=[], seeding=[], building=[], fit=[], selection=[],
1632               other=["trackerClusterCheckPreSplitting",
1633                      "trackerClusterCheck"]),
1634 ]
1635 
1636 def _iterModuleMap(includeConvStep=True, onlyConvStep=False):
1637     iterations = _iterations
1638     if not includeConvStep:
1639         iterations = [i for i in iterations if i.name() != "ConvStep"]
1640     if onlyConvStep:
1641         iterations = [i for i in iterations if i.name() == "ConvStep"]
1642     return collections.OrderedDict([(i.name(), i.all()) for i in iterations])
1643 def _stepModuleMap():
1644     def getProp(prop):
1645         ret = []
1646         for i in _iterations:
1647             if i.name() == "ConvStep":
1648                 continue
1649             ret.extend(getattr(i, prop)())
1650         return ret
1651 
1652     return collections.OrderedDict([
1653         ("ClusterMask", getProp("clusterMasking")),
1654         ("Seeding", getProp("seeding")),
1655         ("Building", getProp("building")),
1656         ("Fitting", getProp("fit")),
1657         ("Selection", getProp("selection")),
1658         ("Other", getProp("other"))
1659     ])
1660 
1661 class TimePerEventPlot:
1662     def __init__(self, name, timeHisto):
1663         self._name = name
1664         self._timeHisto = timeHisto
1665         self._eventsHisto = "path time_real"
1666         self._cache = {}
1667 
1668     def __str__(self):
1669         return self._name
1670 
1671     def _create(self, tdirectory):
1672         timeTh1 = plotting._getOrCreateObject(tdirectory, self._timeHisto)
1673         if timeTh1 is None:
1674             return None
1675 
1676         eventsTh1 = plotting._getOrCreateObject(tdirectory, self._eventsHisto)
1677         if eventsTh1 is None:
1678             return None
1679         nevents = eventsTh1.GetEntries()
1680         if nevents == 0:
1681             return None
1682 
1683         ret = timeTh1.Clone(self._name)
1684         xaxis = ret.GetXaxis()
1685         for i in range(1, ret.GetNbinsX()+1):
1686             ret.SetBinContent(i, ret.GetBinContent(i)/nevents)
1687             ret.SetBinError(i, ret.GetBinError(i)/nevents)
1688             xaxis.SetBinLabel(i, xaxis.GetBinLabel(i).replace(" (unscheduled)", ""))
1689         return ret
1690 
1691     def create(self, tdirectory):
1692         path = tdirectory.GetPath()
1693         if path not in self._cache:
1694             self._cache[path] = self._create(tdirectory)
1695         return self._cache[path]
1696 
1697 class TimePerTrackPlot:
1698     def __init__(self, name, timeHisto, selectedTracks=False):
1699         self._name = name
1700         self._timeHisto = timeHisto
1701         self._selectedTracks = selectedTracks
1702 
1703     def __str__(self):
1704         return self._name
1705 
1706     def _getDirectory(self, tfile):
1707         for dirName in _trackingFolders():
1708             tdir = tfile.Get(dirName)
1709             if tdir != None:
1710                 return tdir
1711         return None
1712 
1713     def create(self, tdirectory):
1714         timeTh1 = plotting._getOrCreateObject(tdirectory, self._timeHisto)
1715         if timeTh1 is None:
1716             return None
1717 
1718         # this is bit of a hack, but as long as it is needed only
1719         # here, I won't invest in better solution
1720         tfile = tdirectory.GetFile()
1721         trkDir = self._getDirectory(tfile)
1722         if trkDir is None:
1723             return None
1724 
1725         iterMap = copy.copy(_collLabelMapHp)
1726         del iterMap["generalTracks"]
1727         del iterMap["jetCoreRegionalStep"] # this is expensive per track on purpose
1728         if self._selectedTracks:
1729             renameBin = lambda bl: _summaryBinRename(bl, highPurity=True, byOriginalAlgo=False, byAlgoMask=True, ptCut=False, seeds=False)
1730         else:
1731             renameBin = lambda bl: _summaryBinRename(bl, highPurity=False, byOriginalAlgo=False, byAlgoMask=False, ptCut=False, seeds=False)
1732         recoAB = AggregateBins("tmp", "num_reco_coll", mapping=iterMap,ignoreMissingBins=True, renameBin=renameBin)
1733         h_reco_per_iter = recoAB.create(trkDir)
1734         if h_reco_per_iter is None:
1735             return None
1736         values = {}
1737         for i in range(1, h_reco_per_iter.GetNbinsX()+1):
1738             values[h_reco_per_iter.GetXaxis().GetBinLabel(i)] = h_reco_per_iter.GetBinContent(i)
1739 
1740 
1741         result = []
1742         for i in range(1, timeTh1.GetNbinsX()+1):
1743             iterName = timeTh1.GetXaxis().GetBinLabel(i)
1744             if iterName in values:
1745                 ntrk = values[iterName]
1746                 result.append( (iterName,
1747                                 timeTh1.GetBinContent(i)/ntrk if ntrk > 0 else 0,
1748                                 timeTh1.GetBinError(i)/ntrk if ntrk > 0 else 0) )
1749 
1750         if len(result) == 0:
1751             return None
1752 
1753         res = ROOT.TH1F(self._name, self._name, len(result), 0, len(result))
1754         for i, (label, value, error) in enumerate(result):
1755             res.GetXaxis().SetBinLabel(i+1, label)
1756             res.SetBinContent(i+1, value)
1757             res.SetBinError(i+1, error)
1758 
1759         return res
1760 
1761 class TrackingIterationOrder:
1762     def __init__(self):
1763         self._cache = {}
1764 
1765     def _findOrder(self, f):
1766         h = f.Get(_trackingIterationOrderHistogram)
1767         if not h:
1768             return None
1769         xaxis = h.GetXaxis()
1770         def _edit(s):
1771             # remove "Tracks" from the track producer name to get the iteration name
1772             # muonSeeded iterations do not have "Step" in the producer name, so add it here
1773             return s.replace("Tracks", "").replace("muonSeeded", "muonSeededStep")
1774         return [_edit(xaxis.GetBinLabel(i)) for i in range(1, h.GetNbinsX()+1)]
1775 
1776     def __call__(self, tdirectory, labels):
1777         ret = list(range(0, len(labels)))
1778         f = tdirectory.GetFile()
1779         if not f:
1780             return ret
1781 
1782         if not f.GetName() in self._cache:
1783             r = self._findOrder(f)
1784             if r is None:
1785                 return ret
1786             self._cache[f.GetName()] = r
1787         order = self._cache[f.GetName()]
1788 
1789         # O(N^2) I know, but we're talking about O(10) elements...
1790         orderIndices = []
1791         for l in order:
1792             try:
1793                 orderIndices.append(labels.index(l))
1794             except ValueError:
1795                 pass
1796         ret = []
1797         for i, l in enumerate(labels):
1798             if l in order:
1799                 try:
1800                     found = orderIndices.index(i)
1801                     if found == 0:
1802                         ret.append(i)
1803                     else:
1804                         ret.append(orderIndices[0])
1805                 except ValueError:
1806                     ret.append(orderIndices[0])
1807                 orderIndices.pop(0)
1808             else:
1809                 ret.append(i)
1810         return ret
1811 
1812 _time_per_event_cpu = TimePerEventPlot("timePerEvent", "module_time_thread_total")
1813 _time_per_event_real = TimePerEventPlot("timePerEvent", "module_time_real_total")
1814 
1815 class TrackingTimingTable:
1816     def __init__(self):
1817         self._purpose = PlotPurpose.Timing
1818         self._page = "timing"
1819         self._section = "timing"
1820 
1821     def getPurpose(self):
1822         return self._purpose
1823 
1824     def getPage(self):
1825         return self._page
1826 
1827     def getSection(self, dqmSubFolder):
1828         return self._section
1829 
1830     def _getValues(self, tdirectory, histo):
1831         h = tdirectory.Get(histo._timeHisto)
1832         totalReco = None
1833         if h:
1834             totalReco = "%.1f" % h.Integral()
1835 
1836         creator = AggregateBins("iteration", histo, _iterModuleMap(includeConvStep=False), ignoreMissingBins=True)
1837         h = creator.create(tdirectory)
1838         totalTracking = None
1839         if h:
1840             totalTracking = "%.1f" % h.Integral()
1841 
1842         creator = AggregateBins("iteration", histo, _iterModuleMap(onlyConvStep=True), ignoreMissingBins=True)
1843         h = creator.create(tdirectory)
1844         totalConvStep = None
1845         if h:
1846             totalConvStep = "%.1f" % h.Integral()
1847 
1848         return [
1849             totalReco,
1850             totalTracking,
1851             totalConvStep,
1852         ]
1853 
1854     def create(self, tdirectory):
1855         cpuValues = self._getValues(tdirectory, _time_per_event_cpu)
1856         realValues = self._getValues(tdirectory, _time_per_event_real)
1857 
1858         return cpuValues + realValues
1859 
1860     def headers(self):
1861         return [
1862             "Average reco CPU time / event (ms)",
1863             "Average tracking (w/o convStep) CPU time / event (ms)",
1864             "Average convStep CPU time / event (ms)",
1865             "Average reco real time / event (ms)",
1866             "Average tracking (w/o convStep) real time / event (ms)",
1867             "Average convStep real time / event (ms)",
1868         ]
1869 
1870 _common = {
1871     "drawStyle": "P",
1872     "xbinlabelsize": 10,
1873     "xbinlabeloption": "d"
1874 }
1875 
1876 _iteration_reorder = TrackingIterationOrder()
1877 _time_per_iter_cpu = AggregateBins("iteration", _time_per_event_cpu, _iterModuleMap(), ignoreMissingBins=True, reorder=_iteration_reorder)
1878 _time_per_iter_real = AggregateBins("iteration", _time_per_event_real, _iterModuleMap(), ignoreMissingBins=True, reorder=_iteration_reorder)
1879 
1880 _timing_summaryCPU = PlotGroup("summaryCPU", [
1881     Plot(_time_per_iter_cpu,
1882          ytitle="Average CPU time (ms)", title="Average CPU time / event", legendDx=-0.4, **_common),
1883     Plot(AggregateBins("iteration_fraction", _time_per_event_cpu, _iterModuleMap(), ignoreMissingBins=True, reorder=_iteration_reorder),
1884          ytitle="Fraction", title="", normalizeToUnitArea=True, **_common),
1885     #
1886     Plot(AggregateBins("step", _time_per_event_cpu, _stepModuleMap(), ignoreMissingBins=True),
1887          ytitle="Average CPU time (ms)", title="Average CPU time / event", **_common),
1888     Plot(AggregateBins("step_fraction", _time_per_event_cpu, _stepModuleMap(), ignoreMissingBins=True),
1889          ytitle="Fraction", title="", normalizeToUnitArea=True, **_common),
1890     #
1891     Plot(TimePerTrackPlot("iteration_track", _time_per_iter_cpu, selectedTracks=False),
1892          ytitle="Average CPU time / built track (ms)", title="Average CPU time / built track", **_common),
1893     Plot(TimePerTrackPlot("iteration_trackhp", _time_per_iter_cpu, selectedTracks=True),
1894          ytitle="Average CPU time / selected track (ms)", title="Average CPU time / selected HP track by algoMask", **_common),
1895     ],
1896 )
1897 _timing_summaryReal = PlotGroup("summaryReal", [
1898     Plot(_time_per_iter_real,
1899          ytitle="Average real time (ms)", title="Average real time / event", legendDx=-0.4, **_common),
1900     Plot(AggregateBins("iteration_fraction", _time_per_event_real, _iterModuleMap(), ignoreMissingBins=True, reorder=_iteration_reorder),
1901          ytitle="Fraction", title="", normalizeToUnitArea=True, **_common),
1902     #
1903     Plot(AggregateBins("step", _time_per_event_real, _stepModuleMap(), ignoreMissingBins=True),
1904          ytitle="Average real time (ms)", title="Average real time / event", **_common),
1905     Plot(AggregateBins("step_fraction", _time_per_event_real, _stepModuleMap(), ignoreMissingBins=True),
1906          ytitle="Fraction", title="", normalizeToUnitArea=True, **_common),
1907     #
1908     Plot(TimePerTrackPlot("iteration_track", _time_per_iter_real, selectedTracks=False),
1909          ytitle="Average real time / built track (ms)", title="Average real time / built track", **_common),
1910     Plot(TimePerTrackPlot("iteration_trackhp", _time_per_iter_real, selectedTracks=True),
1911          ytitle="Average real time / selected track (ms)", title="Average real time / selected HP track by algoMask", **_common),
1912     ],
1913 )
1914 
1915 _timing_iterationsCPU = PlotGroup("iterationsCPU", [
1916     Plot(AggregateBins(i.name(), _time_per_event_cpu, collections.OrderedDict(i.modules()), ignoreMissingBins=True),
1917          ytitle="Average CPU time (ms)", title=i.name(), **_common)
1918     for i in _iterations
1919 ],
1920                                ncols=4, legend=False
1921 )
1922 _timing_iterationsReal = PlotGroup("iterationsReal", [
1923     Plot(AggregateBins(i.name(), _time_per_event_real, collections.OrderedDict(i.modules()), ignoreMissingBins=True),
1924          ytitle="Average real time (ms)", title=i.name(), **_common)
1925     for i in _iterations
1926 ],
1927                                ncols=4, legend=False
1928 )
1929 
1930 # TODO: to be updated to new FastTimerService format later
1931 #_pixelTiming = PlotGroup("pixelTiming", [
1932 #    Plot(AggregateBins("pixel", "reconstruction_step_module_average", {"pixelTracks": ["pixelTracks"]}), ytitle="Average processing time [ms]", title="Average processing time / event", drawStyle="HIST")
1933 #])
1934 
1935 _timeFolders = [
1936 #    "DQMData/Run 1/DQM/Run summary/TimerService/process RECO paths/path reconstruction_step",
1937     "DQMData/Run 1/DQM/Run summary/TimerService/process RECO paths/path prevalidation_step", # because of unscheduled, it's actually prevalidation_step that has all the tracking modules?
1938 ]
1939 timePlotter = Plotter()
1940 timePlotter.append("timing", _timeFolders, PlotFolder(
1941     _timing_summaryCPU,
1942     _timing_iterationsCPU,
1943     _timing_summaryReal,
1944     _timing_iterationsReal,
1945     # _pixelTiming,
1946     loopSubFolders=False, purpose=PlotPurpose.Timing, page="timing"
1947 ))
1948 timePlotter.appendTable("timing", _timeFolders, TrackingTimingTable())
1949 
1950 _common = {"stat": True, "normalizeToUnitArea": True, "drawStyle": "hist"}
1951 _tplifetime = PlotGroup("tplifetime", [
1952     Plot("TPlip", xtitle="TP lip", **_common),
1953     Plot("TPtip", xtitle="TP tip", **_common),
1954 ])
1955 
1956 tpPlotter = Plotter()
1957 tpPlotter.append("tp", [
1958     "DQMData/Run 1/Tracking/Run summary/TrackingMCTruth/TrackingParticle",
1959     "DQMData/Tracking/TrackingMCTruth/TrackingParticle",
1960 ], PlotFolder(
1961     _tplifetime,
1962 ))