diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY new file mode 100644 index 0000000000000000000000000000000000000000..c30d4e85586e3b0c74824f92ac4bb15bee90cd9d --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY @@ -0,0 +1 @@ +MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/CMakeLists.txt b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..265dd90eace72a9fbd6688e51f859ae897c82211 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/CMakeLists.txt @@ -0,0 +1,22 @@ +################################################################################ +# Package: LRTMuonPhysValMonitoring +################################################################################ + +# Declare the package name: +atlas_subdir( LRTMuonPhysValMonitoring ) + +# External dependencies: +find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) + +# Component(s) in the package: +atlas_add_component( LRTMuonPhysValMonitoring + src/*.cxx + src/components/*.cxx + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} AtlasHepMCLib GaudiKernel AthenaMonitoringLib xAODBase xAODCore xAODEventInfo xAODMuon xAODTracking xAODTrigMuon xAODTrigger xAODTruth MuonHistUtils IsolationSelectionLib FourMomUtils MuonCombinedToolInterfaces TrkToolInterfaces TrkValHistUtils TrigDecisionToolLib MuonAnalysisInterfacesLib ) + +# Install files from the package: +atlas_install_scripts( macros/MuonValidation_*.py macros/MuonValidation_*.sh) +atlas_install_python_modules( python/*py POST_BUILD_CMD ${ATLAS_FLAKE8} ) +atlas_install_runtime( scripts/*py POST_BUILD_CMD ${ATLAS_FLAKE8} ) + diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/AtlasStyle.C b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/AtlasStyle.C new file mode 100644 index 0000000000000000000000000000000000000000..cad2041c41a62505f8f4e6aa66e49f750c6999d0 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/AtlasStyle.C @@ -0,0 +1,89 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// +// ATLAS Style, based on a style file from BaBar +// +#include "TStyle.h" +TStyle* AtlasStyle(); + +void SetAtlasStyle() { + std::cout << "\nApplying ATLAS style settings...\n" << std::endl; + TStyle* atlasStyle = AtlasStyle(); + gROOT->SetStyle("ATLAS"); + gROOT->ForceStyle(); +} + +TStyle* AtlasStyle() { + TStyle* atlasStyle = new TStyle("ATLAS", "Atlas style"); + + // use plain black on white colors + Int_t icol = 0; // WHITE + atlasStyle->SetFrameBorderMode(icol); + atlasStyle->SetFrameFillColor(icol); + atlasStyle->SetCanvasBorderMode(icol); + atlasStyle->SetCanvasColor(icol); + atlasStyle->SetPadBorderMode(icol); + atlasStyle->SetPadColor(icol); + atlasStyle->SetStatColor(icol); + // atlasStyle->SetFillColor(icol); // don't use: white fill color for *all* objects + + // set the paper & margin sizes + atlasStyle->SetPaperSize(20, 26); + + // set margin sizes + atlasStyle->SetPadTopMargin(0.05); + atlasStyle->SetPadRightMargin(0.05); + atlasStyle->SetPadBottomMargin(0.16); + atlasStyle->SetPadLeftMargin(0.16); + + // set title offsets (for axis label) + atlasStyle->SetTitleXOffset(1.4); + atlasStyle->SetTitleYOffset(1.4); + + // use large fonts + // Int_t font=72; // Helvetica italics + Int_t font = 42; // Helvetica + Double_t tsize = 0.05; + atlasStyle->SetTextFont(font); + + atlasStyle->SetTextSize(tsize); + atlasStyle->SetLabelFont(font, "x"); + atlasStyle->SetTitleFont(font, "x"); + atlasStyle->SetLabelFont(font, "y"); + atlasStyle->SetTitleFont(font, "y"); + atlasStyle->SetLabelFont(font, "z"); + atlasStyle->SetTitleFont(font, "z"); + + atlasStyle->SetLabelSize(tsize, "x"); + atlasStyle->SetTitleSize(tsize, "x"); + atlasStyle->SetLabelSize(tsize, "y"); + atlasStyle->SetTitleSize(tsize, "y"); + atlasStyle->SetLabelSize(tsize, "z"); + atlasStyle->SetTitleSize(tsize, "z"); + + // use bold lines and markers + atlasStyle->SetMarkerStyle(20); + atlasStyle->SetMarkerSize(1.2); + atlasStyle->SetHistLineWidth(2.); + atlasStyle->SetLineStyleString(2, "[12 12]"); // postscript dashes + + // get rid of X error bars + // atlasStyle->SetErrorX(0.001); + // get rid of error bar caps + atlasStyle->SetEndErrorSize(0.); + + // do not display any of the standard histogram decorations + atlasStyle->SetOptTitle(0); + // atlasStyle->SetOptStat(1111); + atlasStyle->SetOptStat(0); + // atlasStyle->SetOptFit(1111); + atlasStyle->SetOptFit(0); + + // put tick marks on top and RHS of plots + atlasStyle->SetPadTickX(1); + atlasStyle->SetPadTickY(1); + + return atlasStyle; +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/CreateMuonValidationSlides.README b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/CreateMuonValidationSlides.README new file mode 100644 index 0000000000000000000000000000000000000000..56c9b9fc162cc2adda733ed5a5227fa5b202ef43 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/CreateMuonValidationSlides.README @@ -0,0 +1,49 @@ +Dan Mori <dmori at cern.ch> + +This is how to use the macros in MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/macros to create Beamer LaTeX slides with muon validation histograms. This assumes that the validation will be done using a test sample and reference sample for comparison and that you already have the ROOT files containing the physval plots for each sample. + +eg. REFFILE=19.0.3.3.run1.root +eg. TESTFILE=19.1.1.1.run1.root + +Since not all histograms can be created in the validation code, a few macros need to be run first to create them. + +---------------------------------- +Efficiency and Reco Fraction Plots +---------------------------------- +Run the following for each file to add efficiency and reco fraction plots: + +python CreateEffAndRecoFracPlots.py $PHYSVAL_FILE + +-------------------------- +Resolution and Scale Plots +-------------------------- +If DoBinnedResolutionPlots is enabled in PhysValMuon_jobOptions.py, run the following for each file to add resolution and pt scale plots: + +python CreateResolutionPlots.py $PHYSVAL_FILE + +----------------------------- +Create Muon Validation Slides +----------------------------- +CreateMuonValidation Slides uses Beamer (LaTeX) to create slides for a presentation using selected plots from the test and reference physval files. All plots will also contain a ratio plot of the test and reference histograms. + +** This macro requires Python 2.7 or greater. ** +Athena version 19 or greater will setup Python 2.7 automatically. + +Configuration +------------- +First, open up the config.py file and edit the info as required. From here, you can edit the title page info, such as title, date, author, as well as input the sample datasets, Athena versions used, description of the samples, summary slide items, and which plots go on which page. Comments can be added to each slide as well. + +e.g. +title = 'Muon Validation of 19.1.1.1 compared to 19.0.3.3' +subtitle = 'No Pileup, Run 1 Configuration' +date = r'\today' + +Running the macro +----------------- +python CreateMuonValidationSlides.py -r $REFFILE -t $TESTFILE -d OUTPUT_DIRECTORY -c + +-t FILE: test file +-r FILE: reference file +-d DIR: directory where the LaTeX files, plots and final pdf will be put. This is by default set to './beamer' +-c: compile LaTeX file +-n: no title page for the slides diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_AddGaussianFitToPulls.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_AddGaussianFitToPulls.py new file mode 100644 index 0000000000000000000000000000000000000000..8494d418814bbaba055c3e9eaae0d98ccfa88830 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_AddGaussianFitToPulls.py @@ -0,0 +1,75 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +#author: Dan Mori +#Add gaussian curve to pull plots +#if plotdir argument given, will output pdfs in that directory of all pull plots +#usage: python PullFitMacro.py physval_file.root [plotdir] + +import ROOT +import sys +import os +import itertools + +#--------------------------------------------------------------------------- + +def AddGaussian( infile, HistDir, HistName ): + hist = infile.GetDirectory(HistDir).Get(HistName) + if hist.GetEntries() < 10: + print( 'INFO Skipping Fit. NumEntries = {0}: '.format(hist.GetEntries()) + HistName ) + return + gaus2 = ROOT.TF1( "gaus2", "gaus", -2, 2 ) + gaus5 = ROOT.TF1( "gaus", "gaus", -5, 5 ) + if int(hist.Fit(gaus2,"RQ")) != 0: + print( 'WARNING fit failed for ' + HistName ) + return + hist.GetListOfFunctions().Add(gaus5) + f1 = hist.GetFunction("gaus") + f1.SetParameters( hist.GetFunction("gaus2").GetParameters() ) + hist.GetListOfFunctions().Remove( gaus2 ) + f1.SetLineColor(ROOT.kRed) + print('INFO Overwriting histogram: ' + HistDir + '/' + HistName ) + hist.GetDirectory().WriteTObject( hist, HistName, "Overwrite" ) + +#--------------------------------------------------------------------------- +def main( args ): + if len( args ) > 1: + filename = args[1] + else: + print( 'Usage: python {0} filename'.format( args[0] ) ) + return + + if not os.path.exists( filename ): + print ( 'File not found: ' + filename ) + return + + infile = ROOT.TFile.Open( filename, 'update' ) + + MuonTypes = [ 'All', 'Prompt', 'InFlight', 'NonIsolated' ] + PullTypes = [ '', 'ID', 'MS' ] + Variables = [ 'phi', 'theta', 'qOverP', 'd0', 'z0' ] + + for MuonType in MuonTypes: + if not infile.Get( 'Muons/' + MuonType ): + print( 'INFO TDirectory not found: Muons/' + MuonType ) + continue + AuthDir = infile.Get( 'Muons/{0}/matched'.format( MuonType ) ) + Authors = [ i.GetName() for i in AuthDir.GetListOfKeys() if AuthDir.Get( i.GetName() ).InheritsFrom( 'TDirectory' ) ] + for Author in Authors: + DirName = 'Muons/{0}/matched/{1}/Pulls'.format( MuonType, Author ) + Dir = infile.Get( DirName ) + if not Dir: + print( 'INFO TDirectory not found: ' + DirName ) + continue + for PullType, var in itertools.product( PullTypes, Variables ): + HistName = '_'.join( DirName.split('/') ) + '_Pull{0}_'.format(PullType) + var + if not Dir.Get( HistName ): + print( 'INFO Histogram not found: ' + HistName ) + continue + AddGaussian( infile, DirName, HistName ) + infile.Close() + +#--------------------------------------------------------------------------- + +if __name__ == "__main__": + ROOT.gROOT.SetBatch() + main( sys.argv ) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateEffAndRecoFracPlots.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateEffAndRecoFracPlots.py new file mode 100755 index 0000000000000000000000000000000000000000..fcf26af973befdbc8ecdc49f4fc3fab22db1d459 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateEffAndRecoFracPlots.py @@ -0,0 +1,382 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +#Written by Dan Mori +#Create efficiency plots for each author by dividing matched/author pt by truth/all pt + +#Usage: python CreateEffAndRecoFracPlots.py filename [doAverage] + +#Added flag doAverage to add TF1 of line showing overall efficiency/reco fraction + +import ROOT +import os +import sys +import itertools +from array import array +ROOT.gROOT.SetBatch( True ) + +doProjX=1 +doProjY=0 + +#-------------------------------------------------------------------------- +def SetBinomialError( ratio, den ): + if 'TH2' in ratio.IsA().GetName(): + for j in range(1,ratio.GetNbinsY()+1): + for i in range(1,ratio.GetNbinsX()+1): + n = den.Integral(i,i,j,j) + p = ratio.GetBinContent(i,j) + if n <= 0 or p>=1: + ratio.SetBinError( i, j, 0 ) + continue + else: + ratio.SetBinError( i, j, (p*(1-p)/n)**0.5 ) + elif 'TH1' in ratio.IsA().GetName(): + for i in range(1,ratio.GetNbinsX()+1): + n = den.Integral(i,i) + p = ratio.GetBinContent(i) + if n <= 0 or p>=1: + ratio.SetBinError( i, 0 ) + continue + else: + ratio.SetBinError( i, (p*(1.-p)/n)**0.5 ) + else: + print( 'WARNING ' + ratio.GetName() + 'is not a TH1 or TH2' ) + +#-------------------------------------------------------------------------- +#create histograms that require dividing one histogram by another +#works for both efficiency and reco fraction plots, set by plottype variable + +def CreateRatioPlot( infile, numHist, denHist, var, projXorY=doProjY, x1=None, x2=None, xtitle = '', plottype = '', doAverage = False ): + #require plottype variable for setting plot title, etc + #plottype = 'eff' or 'RecoFrac' to create efficiency or reco fraction histogram + if plottype == 'eff': + typeName = 'efficiency' + elif plottype == 'RecoFrac': + typeName = 'Reco Fraction' + elif plottype == 'purity': + typeName = 'purity' + else: + print('plottype must be one of the following: \'eff\', \'RecoFrac\', \'purity\'' ) + return + + PlotNamePrefix = numHist.GetName()[:numHist.GetName().find('_kinematics')] + '_' + typeName.replace(' ','') + + #create ratio hist for given eta range + if (x1 != None and x2 != None): + if '_' in var: + if projXorY==doProjX: + xvar=var.split('_')[1] + yvar=var.split('_')[0] + else: + xvar=var.split('_')[0] + yvar=var.split('_')[1] + #PlotName = PlotNamePrefix + '_' + var.split('_')[1] + '_etaRange_{0}_{1}'.format(x1,x2).replace('-','m').replace('.','p') + #PlotTitle = var.split('_',1)[1].capitalize() + ' ' + typeName + PlotName = PlotNamePrefix + '_' + yvar + '_'+xvar+'Range_{0}_{1}'.format(x1,x2).replace('-','m').replace('.','p') + PlotTitle = yvar.capitalize() + ' ' + typeName + + if x1>=0 and x2>0: + if projXorY==doProjX: + ibin1 = numHist.GetYaxis().FindBin(x1) + ibin2 = numHist.GetYaxis().FindBin(x2) + num = numHist.ProjectionX('num_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + den = denHist.ProjectionX('den_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + else: + ibin1 = numHist.GetXaxis().FindBin(x1) + ibin2 = numHist.GetXaxis().FindBin(x2) + num = numHist.ProjectionY('num_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + den = denHist.ProjectionY('den_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + + if yvar=='eta': + if projXorY==doProjX: + ibin1 = numHist.GetYaxis().FindBin(-1*x2) + ibin2 = numHist.GetYaxis().FindBin(-1*x1) + num2 = numHist.ProjectionX('num2_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + den2 = denHist.ProjectionX('den2_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + else: + ibin1 = numHist.GetXaxis().FindBin(-1*x2) + ibin2 = numHist.GetXaxis().FindBin(-1*x1) + num2 = numHist.ProjectionY('num2_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + den2 = denHist.ProjectionY('den2_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + num.Add(num2) + den.Add(den2) + PlotTitle = PlotTitle + ' ({0}<|eta|<{1})'.format(x1,x2) + del num2, den2 + else: + if yvar=='pt': + PlotTitle = PlotTitle + ' ({0}<pt<{1})'.format(x1,x2) + # else: + # if projXorY==doProjX: + # ibin1 = numHist.GetYaxis().FindBin(x1) + # ibin2 = numHist.GetYaxis().FindBin(x2) + # num = numHist.ProjectionX('num_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + # den = denHist.ProjectionX('den_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + # #PlotTitle = PlotTitle + ' (pt>{0})'.format(eta1) + # PlotTitle = PlotTitle + ' ({0}<{2}<{1})'.format(x1,x2,yvar) + # PlotName = PlotNamePrefix + '_' + var.split('_')[1] + '_ptMin{0}'.format(x1).replace('-','m').replace('.','p') + # else: + # ibin1 = numHist.GetXaxis().FindBin(x1) + # ibin2 = numHist.GetXaxis().FindBin(x2) + # num = numHist.ProjectionY('num_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + # den = denHist.ProjectionY('den_'+xvar+"_"+yvar+"Range",ibin1,ibin2) + # PlotTitle = PlotTitle + ' ({0}<{2}<{1})'.format(x1,x2,yvar) + else: + PlotTitle = var.capitalize() + ' ' + typeName + PlotName = PlotNamePrefix + '_' + var + num = numHist.Clone() + den = denHist.Clone() + + #create variable bin histogram for pt to group high bins together + if ('_pt' in var and projXorY==doProjY) or var=='pt': + #rebin the initial pt hist that is in bins of 1 GeV + ptBins = [ 0, 5, 10, 15, 20, 25, 30, 40, 50, 65, 80, 100, 200 ] + #ptBins = [ 0, 2,3,4,5,6, 8, 15 ] + numRebinned = ROOT.TH1D( 'num_'+var, '', len(ptBins)-1, array( 'f', ptBins ) ) + denRebinned = ROOT.TH1D( 'den_'+var, '', len(ptBins)-1, array( 'f', ptBins ) ) + for i in range( 1, numHist.GetNbinsX() + 1 ): + numRebinned.Fill( num.GetXaxis().GetBinCenter(i), num.GetBinContent(i) ) + denRebinned.Fill( den.GetXaxis().GetBinCenter(i), den.GetBinContent(i) ) + #rebin eta and phi + else: + if 'TH1' in den.IsA().GetName(): + numRebinned = num.Clone() + denRebinned = den.Clone() + numRebinned.Rebin(2) + denRebinned.Rebin(2) + else: + return + + ## @@@ for eff turn-on curve: + # num.GetXaxis().SetRangeUser(0,15) + # den.GetXaxis().SetRangeUser(0,15) + + ratio = numRebinned.Clone( PlotName ) + ratio.Divide( numRebinned, denRebinned, 1, 1 ) + ratio.SetTitle( PlotTitle ) + SetBinomialError( ratio, denRebinned ) #root binomial error is different - custom done + + # Define x and y-axis name from histogram name (var) + if 'TH2' in ratio.IsA().GetName(): + if '_' in var: + ratio.GetXaxis().SetTitle( var.split('_')[0] ) + ratio.GetYaxis().SetTitle( var.split('_')[1] ) + ratio.GetZaxis().SetTitle( typeName.lower() ) + else: + print 'WARNING Could not get axes name from histogram name' + elif 'TH1' in ratio.IsA().GetName(): + ymax = ratio.GetBinContent( ratio.GetMaximumBin() ) + ratio.GetBinError( ratio.GetMaximumBin() ) + ratio.GetYaxis().SetRangeUser(0, ymax*1.2 ) + ratio.GetYaxis().SetTitle( typeName.lower() ) + if xtitle == '': + xtitle = var + ratio.GetXaxis().SetTitle( xtitle ) + + if doAverage and den.Integral() > 0 and num.Integral() > 0: + tot_eff = ROOT.TF1( 'aveline', "[0]", ratio.GetXaxis().GetBinLowEdge(1), ratio.GetXaxis().GetBinUpEdge( ratio.GetNbinsX() ) ) + ratio.GetListOfFunctions().Add( tot_eff ) + f1 = ratio.GetFunction( "aveline" ) + f1.SetParameter( 0, num.Integral()/den.Integral() ) + f1.SetLineColor( ROOT.kRed ) + #f1.SetBit(ROOT.TF1.kNotDraw) + + PlotDirName = PlotNamePrefix.replace('__','_').split('_') + if not infile.GetDirectory( '/'.join( PlotDirName ) ): + PlotDir = infile.Get( '/'.join( PlotDirName[:-1] ) ).mkdir( PlotDirName[-1] ) + else: + PlotDir = infile.Get( '/'.join( PlotDirName ) ) + PlotDirName = '/'.join( PlotDirName ) + + if not infile.GetDirectory(PlotDirName).WriteTObject( ratio, PlotName, "Overwrite" ): + print('WARNING failed to write histogram to file: ' + PlotDirName + '/' + PlotName ) + del ratio, num, den + +#-------------------------------------------------------------------------- +def main( argv ): + """ + Main function to be executed when starting the code. + """ + + if len( argv ) < 2: + print( 'No filename given' ) + print( 'Usage: python '+argv[0]+' physval_filename [doAverage]' ) + exit(1) + + filename = argv[1] + if not os.path.exists( filename ): + print ( 'File not found: ' + filename ) + exit(1) + + if len(argv) > 2 and argv[2] == 'doAverage': + doAverage = True + else: + doAverage = False + + infile = ROOT.TFile.Open( filename, 'update' ) + + muonTypesEff = [ 'All', 'Prompt', 'InFlight', 'NonIsolated' ] + muonTypesReco = [ 'Prompt', 'InFlight', 'NonIsolated', 'Rest' ] + Variables = [ 'pt', 'eta', 'phi', 'eta_phi', 'eta_pt' ] + + Xtitles = { + 'pt' : 'p_{T} [GeV]', + 'eta' : '|#eta|', + 'phi' : '#phi', + 'eta_phi' : '#phi', + 'eta_pt' : 'p_{T} [GeV]' } + + #Efficiency plots + Authors = [] + for muType in muonTypesEff: + if not infile.Get( 'Muons/' + muType ): + print( 'INFO TDirectory not found: Muons/' + muType ) + continue + #get list of authors from matched dir + AuthDir = infile.Get( 'Muons/{0}/matched'.format( muType ) ) + if Authors == []: + Authors = [ i.GetName() for i in AuthDir.GetListOfKeys() if AuthDir.Get( i.GetName() ).InheritsFrom( 'TDirectory' ) ] + for author in Authors: + truthDirName = 'Muons/{0}/truth/all'.format( muType ) + matchDirName = 'Muons/{0}/matched/{1}/kinematics'.format( muType, author ) + truthDir = infile.GetDirectory( truthDirName ) + matchDir = infile.GetDirectory( matchDirName ) + if not truthDir: + print( 'WARNING Directory not found: '+truthDirName ) + continue + if not matchDir: + print( 'WARNING Directory not found: '+matchDirName ) + continue + for var in Variables: + truthHistName = truthDirName.replace('/','_') + '_' + var + truthHist = truthDir.Get( truthHistName ) + matchHistName = matchDirName.replace('/','_') + '_' + var + matchHist = matchDir.Get( matchHistName ) + if not truthHist: + print( 'WARNING histogram not found: '+truthHistName ) + continue + if not matchHist: + print( 'WARNING histogram not found: '+matchHistName ) + continue + CreateRatioPlot( infile, matchHist, truthHist, var, xtitle = muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + if var == 'eta_phi' or var == 'eta_pt': + CreateRatioPlot( infile, matchHist, truthHist, var, doProjY, 0, 2.5, muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjY, 0, 0.1, muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjY, 0.1, 1.05, muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjY, 1.05, 2.0, muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjY, 2.0, 2.5, muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjY, 2.5, 2.7, muType+' Muon '+Xtitles[var], plottype = 'eff', doAverage = doAverage ) + if var == 'eta_pt' and author == 'CaloTag' : + CreateRatioPlot( infile, matchHist, truthHist, var, doProjX, 10, 1000, muType+' Muon '+Xtitles['eta'], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjX, 15, 1000, muType+' Muon '+Xtitles['eta'], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjX, 20, 1000, muType+' Muon '+Xtitles['eta'], plottype = 'eff', doAverage = doAverage ) + CreateRatioPlot( infile, matchHist, truthHist, var, doProjX, 25, 1000, muType+' Muon '+Xtitles['eta'], plottype = 'eff', doAverage = doAverage ) + #Reco Fraction plots + for muType in muonTypesReco: + if not infile.Get( 'Muons/' + muType ): + print( 'INFO TDirectory not found: Muons/' + muType ) + continue + #get list of authors from matched dir + AuthDir = infile.Get( 'Muons/{0}/matched'.format( muType ) ) + if Authors == []: + Authors = [ i.GetName() for i in AuthDir.GetListOfKeys() if AuthDir.Get( i.GetName() ).InheritsFrom( 'TDirectory' ) ] + for author in Authors: + typedir = 'Muons/{0}/reco/{1}/kinematics'.format( muType, author ) + alldir = 'Muons/All/reco/{0}/kinematics'.format( author ) + typeRecoDir = infile.Get( typedir ) + allRecoDir = infile.Get( alldir ) + if not typeRecoDir: + print( 'INFO TDirectory not found: '+typedir ) + continue + if not allRecoDir: + print( 'INFO TDirectory not found: '+alldir ) + continue + for var in Variables: + typeplot = typedir.replace('/','_') + '_' + var + allplot = alldir.replace('/','_') + '_' + var + typeRecoHist = typeRecoDir.Get( typeplot ) + allRecoHist = allRecoDir.Get( allplot ) + if not typeRecoHist: + print( 'WARNING plot not found: ' + typeplot ) + continue + if not allRecoHist: + print( 'WARNING plot not found: ' + allplot ) + continue + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, xtitle = muType + ' Muon ' + Xtitles[var], plottype = 'RecoFrac', doAverage = doAverage ) + + #Purity plots (matched/reco) + ### for muType in muonTypesReco: + muType = 'All' + if not infile.Get( 'Muons/' + muType ): + print( 'INFO TDirectory not found: Muons/' + muType ) + else: + #get list of authors from matched dir + AuthDir = infile.Get( 'Muons/{0}/matched'.format( muType ) ) + if Authors == []: + Authors = [ i.GetName() for i in AuthDir.GetListOfKeys() if AuthDir.Get( i.GetName() ).InheritsFrom( 'TDirectory' ) ] + for author in Authors: + typedir = 'Muons/{0}/matched/{1}/kinematicsReco'.format( muType, author ) + alldir = 'Muons/{0}/reco/{1}/kinematics'.format( muType, author ) + typeRecoDir = infile.Get( typedir ) + allRecoDir = infile.Get( alldir ) + if not typeRecoDir: + print( 'INFO TDirectory not found: '+typedir ) + continue + if not allRecoDir: + print( 'INFO TDirectory not found: '+alldir ) + continue + for var in Variables: + typeplot = typedir.replace('/','_') + '_' + var + allplot = alldir.replace('/','_') + '_' + var + typeRecoHist = typeRecoDir.Get( typeplot ) + allRecoHist = allRecoDir.Get( allplot ) + if not typeRecoHist: + print( 'WARNING plot not found: ' + typeplot ) + continue + if not allRecoHist: + print( 'WARNING plot not found: ' + allplot ) + continue + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, xtitle = muType + ' Muon ' + Xtitles[var], plottype = 'purity', doAverage = doAverage ) + if var == 'eta_pt': ## purity vs eta in pt ranges + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjX, 4, 500, muType+' Muon '+Xtitles['pt'], plottype = 'purity', doAverage = doAverage ) + if var == 'eta_pt' and author == 'CaloTag' : ## purity vs eta in pt ranges + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjX, 10, 500, muType+' Muon '+Xtitles['pt'], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjX, 15, 500, muType+' Muon '+Xtitles['pt'], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjX, 20, 500, muType+' Muon '+Xtitles['pt'], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjX, 25, 500, muType+' Muon '+Xtitles['pt'], plottype = 'purity', doAverage = doAverage ) + if (var == 'eta_phi' or var == 'eta_pt') and author is not 'CaloTag' : + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjY, 0, 0.1, muType+' Muon '+Xtitles[var], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjY, 0.1, 1.05, muType+' Muon '+Xtitles[var], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjY, 1.05, 2.0, muType+' Muon '+Xtitles[var], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjY, 2.0, 2.5, muType+' Muon '+Xtitles[var], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjY, 0, 2.5, muType+' Muon '+Xtitles[var], plottype = 'purity', doAverage = doAverage ) + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, doProjY, 2.5, 2.7, muType+' Muon '+Xtitles[var], plottype = 'purity', doAverage = doAverage ) + + #unmatched muon reco fraction + muType = 'UnmatchedRecoMuons' + typedir = 'Muons/{0}/kinematics'.format( muType ) + allnames = [ i for i in Authors if i == 'AllMuons' or i == 'AllAuthors' ] + if len(allnames) == 0: + return + alldir = 'Muons/All/reco/{0}/kinematics'.format( allnames[0] ) + if not infile.GetDirectory( typedir ): + print( 'INFO directory not found: ' + typedir ) + elif not infile.GetDirectory( alldir ): + print( 'INFO directory not found: ' + alldir ) + else: + for var in Variables: + typeplot = 'Muons_{0}__kinematics_{1}'.format( muType, var ) + allplot = alldir.replace('/','_') + '_{0}'.format( var ) + #print('Working on Muons_{0}__{1}'.format(muType,var)) + typeRecoHist = infile.GetDirectory( typedir ).Get( typeplot ) + allRecoHist = infile.GetDirectory( alldir ).Get( allplot ) + if typeRecoHist and allRecoHist: + CreateRatioPlot( infile, typeRecoHist, allRecoHist, var, xtitle = 'Unmatched Reco Muon '+Xtitles[var], plottype = 'RecoFrac', doAverage = doAverage ) + infile.Close() + +#=============================================================================== + +if __name__ == "__main__": + """ + Here the code should appear that is executed when running the plotter directly + (and not import it in another python file via 'import Plotter') + """ + # start main program + main( sys.argv ) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreatePullProfiles.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreatePullProfiles.py new file mode 100644 index 0000000000000000000000000000000000000000..861d81378f37cac5a4c5e3c167b40de7f9ce3886 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreatePullProfiles.py @@ -0,0 +1,80 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +import sys +import os +from array import array +import itertools +import ROOT +from MuonValidation_CreateResolutionProfiles import * + +#--------------------------------------------------------------------------- + +#create profile plots for pull parameters vs pt from 2D histograms +def CreateProfile( infile, HistDir, HistName, Var, doAverage = False ): + hist = infile.Get(HistDir).Get(HistName) + if not hist: + return + prof_ave, prof_std, projHists = GetProfilesFromTH2( hist, doAverage = doAverage ) + + prof_ave.SetName( hist.GetName().replace( '_vs_', '_ProfMean_vs_' ) ) + prof_ave.SetTitle( Var + ' Pull vs pt (Mean)' ) + prof_ave.SetXTitle( 'Transverse Momentum [GeV]' ) + prof_ave.SetYTitle( Var + ' Pull Mean' ) + + prof_std.SetName( hist.GetName().replace( '_vs_', '_ProfStDev_vs_' ) ) + prof_std.SetTitle( Var + ' Pull vs pt (StDev)' ) + prof_std.SetXTitle( 'Transverse Momentum [GeV]' ) + prof_std.SetYTitle( Var + ' Pull StdDev' ) + + if not infile.Get( HistDir ).WriteTObject( prof_ave, prof_ave.GetName(), "Overwrite" ): + print( 'WARNING Failed to write histogram to file: ' + HistDir + '/' + prof_ave.GetName() ) + if not infile.Get( HistDir ).WriteTObject( prof_std, prof_std.GetName(), "Overwrite" ): + print( 'WARNING Failed to write histogram to file: ' + HistDir + '/' + prof_std.GetName() ) + del prof_ave, prof_std + +#--------------------------------------------------------------------------- + +def main( args ): + doAverage = False + if len( args ) > 1: + filename = args[1] + if len(args) > 2 and args[2] == 'doAverage': + doAverage = True + else: + print( 'Usage: python {0} filename [doAverage]'.format( args[0] ) ) + return + + if not os.path.exists( filename ): + print ( 'File not found: ' + filename ) + return + + infile = ROOT.TFile.Open( filename, 'update' ) + + MuonTypes = [ 'All', 'Prompt' ] #, 'InFlight', 'NonIsolated' ] + Variables = [ 'phi', 'theta', 'qOverP', 'd0', 'z0' ] + + for MuonType in MuonTypes: + if not infile.Get( 'Muons/' + MuonType ): + print( 'INFO TDirectory not found: Muons/' + MuonType ) + continue + AuthDir = infile.Get( 'Muons/{0}/matched'.format( MuonType ) ) + Authors = [ i.GetName() for i in AuthDir.GetListOfKeys() if AuthDir.Get( i.GetName() ).InheritsFrom( 'TDirectory' ) ] + for Author in Authors: + DirName = 'Muons/{0}/matched/{1}/Pulls'.format( MuonType, Author ) + Dir = infile.Get( DirName ) + if not Dir: + print( 'INFO TDirectory not found: ' + DirName ) + continue + for var in Variables: + HistName = '_'.join( DirName.split('/') ) + '_Pull_{0}_vs_pt'.format(var) + if not Dir.Get( HistName ): + print( 'INFO Histogram not found: ' + HistName ) + continue + CreateProfile( infile, DirName, HistName, var, doAverage = doAverage ) + infile.Close() + +#--------------------------------------------------------------------------- + +if __name__ == "__main__": + ROOT.gROOT.SetBatch() + main( sys.argv ) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateResolutionProfiles.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateResolutionProfiles.py new file mode 100755 index 0000000000000000000000000000000000000000..49b81976d90faec78e2288c782ffd63e5df4af62 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateResolutionProfiles.py @@ -0,0 +1,227 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +#Dan Mori <dmori@cern.ch> +#This macro creates muon resolution profiles from 2D histograms +#Usage: python CreateResolutionProfiles.py filename [doAverage doBinned] +#Adding the flag doAverage adds a TF1 showing the overall pT scale/resolution to the profiles +#Adding the flag doBinned creates resolution plots for each pt, eta, phi bin for prompt muons + +import sys +import os +from array import array +import itertools +from math import sqrt +import ROOT +from ROOT import * + +#--------------------------------------------------------------------------- + +def SetYrange( hist ): + #adjust y range so negative bins will show + ymax = hist.GetBinContent( hist.GetMaximumBin() ) + hist.GetBinError( hist.GetMaximumBin() ) + ymin = hist.GetBinContent( hist.GetMinimumBin() ) - hist.GetBinError( hist.GetMinimumBin() ) + #c = 0.2*( ymax - ymin ) + #ymax += c + #ymin -= c + ymax += 0.2*ymax + ymin -= 0.2*ymax + hist.GetYaxis().SetRangeUser( ymin, ymax ) + +#--------------------------------------------------------------------------- +def GetProfilesFromTH2( hist, doAverage ): + binedges = [ hist.GetXaxis().GetBinLowEdge(1) ] + binedges += [ hist.GetXaxis().GetBinUpEdge(i) for i in range( 1, hist.GetNbinsX()+1 ) ] + if hist.GetXaxis().GetBinUpEdge(hist.GetNbinsX()) == 1000 and hist.GetBinContent(hist.GetNbinsX()) < 3: #remove last bin (200-1000) if nothing there + binedges = binedges[:-1] + nBins = len(binedges) - 1 + + prof_ave = ROOT.TH1D( 'ave', 'ave', nBins, array( 'f', binedges ) ) + prof_std = ROOT.TH1D( 'std', 'std', nBins, array( 'f', binedges ) ) + binnedRes = {} + for i in range( 1, nBins + 1 ): + h = hist.ProjectionY( hist.GetName()+'_p_y', i, i ) + n = h.GetEntries() + if n<20: + continue + ## fit range + xmin = h.GetMean()-3*h.GetRMS() + xmax = h.GetMean()+3*h.GetRMS() + h.GetXaxis().SetRangeUser(xmin,xmax) + print '>>> ' , h.GetName() + mean, meanErr, sigma, sigmaErr, frame = fit(h, -0.5, 0.5) ## call the fit method + prof_ave.SetBinContent( i, mean ) + prof_ave.SetBinError( i, meanErr ) + prof_std.SetBinContent( i, sigma ) + prof_std.SetBinError( i, sigmaErr ) + name = '{0}_{1}'.format( binedges[i-1], binedges[i] ) + binnedRes[name] = frame.Clone(name) + #del h, fit + SetYrange( prof_ave ) + SetYrange( prof_std ) + return prof_ave,prof_std,binnedRes +#--------------------------------------------------------------------------- +#--------------------------------------------------------------------------- + +# Simple fit method ................................................ +# F = f1 * Gauss(mean,sigma) + (1-f1) Gauss(mean,sigma) x Exp(tau) +# .................................................................. + +def fit(h, emin,emax): + x = RooRealVar('x','x',emin,emax); + if (h.GetEntries()<20): + return 0,0,0,0,x.frame() + mean = RooRealVar('mean','mean',-0.001,-0.01,0.01); + sigma = RooRealVar('sigma','#sigma',0.02, 0.01, 0.3); + Gauss = RooGaussian('Gauss','Gauss',x,mean,sigma); + f1 = RooRealVar('f1','f1',0.8,0.,1.); + + GaussModel = RooGaussModel('GaussModel','Gauss',x,mean,sigma) + tau = RooRealVar('tau','tau',0.02,0.,1.) + tailmodel = RooDecay('tailmodel','ExpxGaus',x,tau,GaussModel,RooDecay.DoubleSided); + model = RooAddPdf('model','G1+E2',Gauss,tailmodel,f1) + + hdata = RooDataHist('hdata','hist', RooArgList(x), h); + model.fitTo(hdata,RooFit.PrintLevel(-1),RooFit.Verbose(kFALSE)); + frame = x.frame(); + + hdata.plotOn(frame) + model.plotOn(frame,RooFit.LineColor(ROOT.kRed)) + model.plotOn(frame,RooFit.Components('tailmodel'),RooFit.DrawOption('F'),RooFit.FillColor(ROOT.kOrange),RooFit.MoveToBack()) + return mean.getVal(), mean.getError(), sigma.getVal(), sigma.getError(), frame +#--------------------------------------------------------------------------- +#--------------------------------------------------------------------------- + +#create pt res and scale profiles vs pt, eta, phi from 2D histograms +def CreateProfile( infile, HistDir, HistName, Var, MuonType, doAverage = False, doBinned = False ): + hist = infile.Get(HistDir).Get(HistName) + if hist.IsA().InheritsFrom(ROOT.TProfile.Class()): + return + xtitle = MuonType + ' Muon ' + if 'pT' in Var: + xtitle += 'pT [GeV]' + else: + xtitle += Var + + prof_ave, prof_std, binnedRes = GetProfilesFromTH2( hist, doAverage = doAverage ) + + prof_ave.SetName( HistName.replace( 'pT_vs', 'PtScale_vs' ) ) + prof_ave.SetTitle( 'pT Scale vs ' + Var ) + prof_ave.SetXTitle( xtitle ) + prof_ave.SetYTitle( 'pT scale' ) + + prof_std.SetName( HistName.replace( 'pT_vs', 'PtResol_vs' ) ) + prof_std.SetTitle( 'pT Resolution vs ' + Var ) + prof_std.SetXTitle( xtitle ) + prof_std.SetYTitle( 'pT resolution' ) + + if not infile.Get( HistDir ).WriteTObject( prof_ave, prof_ave.GetName(), "Overwrite" ): + # print( 'INFO Writing histogram to file: ' + HistDir + '/' + prof_ave.GetName() ) + print( 'WARNING failed to write histogram to file: ' + HistDir + '/' + prof_ave.GetName() ) + if not infile.Get( HistDir ).WriteTObject( prof_std, prof_std.GetName(), "Overwrite" ): + # print( 'INFO Writing histogram to file: ' + HistDir + '/' + prof_std.GetName() ) + print( 'WARNING failed to write histogram to file: ' + HistDir + '/' + prof_std.GetName() ) + + #create binned res plots + bindirname = Var.lower() + 'Bins' + bindirpath = HistDir + '/' + bindirname + bindir = infile.GetDirectory( bindirpath ) + if not bindir: + bindir = infile.GetDirectory( HistDir ).mkdir( bindirname ) + + if doBinned: + canv = ROOT.TCanvas("canv","",800,800); + canv.Divide(3,3) + ipad = 0 + icanv = 0 + storePlots = 'resPlots/'+os.path.split(infile.GetName())[1].replace('.root','') + if not os.path.exists(storePlots): + os.makedirs(storePlots) + print('Creating directory: '+storePlots) + + for x1,name,plot in sorted([ (float(name.split('_')[0]), name, plot) for name, plot in binnedRes.iteritems() ]): + plot.SetName( 'bin_' + name.replace('-','m') ) + plot.SetTitle( 'pT Resolution {0} < {1} < {2}'.format( name.split('_')[0], Var, name.split('_')[1] ) ) + plot.SetYTitle( 'Entries' ) + t=ROOT.TCanvas() +# if not bindir.WriteTObject( plot, plot.GetName(), "Overwrite" ): +# print('WARNING failed to write histogram to file: ' + bindirpath + '/' + plot.GetName() ) + ipad+=1 + if ipad>9: + canv.cd() + canv.SaveAs(storePlots+'/'+HistDir.replace('/','_')+'_PtResFits_{0}_bins_{1}.pdf'.format(Var,icanv)) + canv.Clear() + canv.Divide(3,3) + icanv+=1 + ipad=1 + canv.cd(ipad) + t = ROOT.TLatex() + t.SetNDC(); t.SetTextColor(1); + tit = name.replace('m','-').replace('_','<'+Var+'<') + mu = mu_err = sigma = sigma_err = 0 + canv.cd(ipad) + plot.Draw() + t.DrawLatex(0.2,0.96,plot.GetTitle()) + resultMeanLab ='#mu = {0:0.2g} #pm {1:0.2g}'.format( mu, mu_err ) + resultSigmaLab ='#sigma = {0:0.2g} #pm {1:0.2g}'.format( sigma, sigma_err ) + t.DrawLatex(0.2,0.85,'#splitline{'+resultMeanLab+'}{'+resultSigmaLab+'}') + + canv.cd() + canv.SaveAs(storePlots+'/'+HistDir.replace('/','_')+'_PtResFits_{0}_bins_{1}.pdf'.format(Var,icanv)) + canv.Close() + + del prof_ave, prof_std, binnedRes +#--------------------------------------------------------------------------- + +def main( args ): + if len( args ) > 1: + filename = args[1] + else: + print( 'Usage: python {0} filename [doAverage doBinned]'.format( args[0] ) ) + return + + if not os.path.exists( filename ): + print ( 'File not found: ' + filename ) + return + + doAverage = False + doBinned = True + if len(args) > 2: + doAverage = bool( 'doAverage' in args[2:] ) + doBinned = bool( 'doBinned' in args[2:] ) + + print( 'Opening file: ' + filename ) + infile = ROOT.TFile.Open( filename, 'update' ) + + MuonTypes = [ 'Prompt' ] + BinVars = [ 'pT','lowpT','highpT','eta', 'phi' ] + + for MuonType in MuonTypes: + if not infile.Get( 'Muons/' + MuonType ): + print( 'INFO TDirectory not found: Muons/' + MuonType ) + continue + AuthDir = infile.Get( 'Muons/{0}/matched'.format( MuonType ) ) + Authors = [ i.GetName() for i in AuthDir.GetListOfKeys() if AuthDir.Get( i.GetName() ).InheritsFrom( 'TDirectory' ) ] + for Author in Authors: + if Author=='MSTrackParticles' or Author=='CaloTag' or Author=='AllMuons' or Author=='Tight' or Author=='Loose' or Author=='VeryLoose': + continue + HistDir = 'Muons/{0}/matched/{1}/resolution'.format( MuonType, Author ) + FileDir = infile.Get( HistDir ) + if not FileDir: + print( 'INFO TDirectory not found: ' + HistDir ) + continue + for Var in BinVars: + resTypes= [ '','ID','MS' ] + for resType in resTypes: + HistName = '_'.join( HistDir.split('/') ) + '_Res{0}_pT_vs_{1}'.format( resType, Var ) + if not FileDir.Get( HistName ): + #print( 'INFO Histogram not found: ' + HistName ) + continue + CreateProfile( infile, HistDir, HistName, Var, MuonType, doAverage = doAverage, doBinned = doBinned ) + + infile.Close() + +#--------------------------------------------------------------------------- + +if __name__ == "__main__": + ROOT.gROOT.SetBatch() + main( sys.argv ) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateSlides.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateSlides.py new file mode 100644 index 0000000000000000000000000000000000000000..333b0c6ce3b366357348c232d33d326a52a94610 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateSlides.py @@ -0,0 +1,310 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +#author: Dan Mori < dmori@cern.ch > +#including code by Felix Socher <Felix.Socher@cern.ch> +import ROOT +import math +import sys +import os +import argparse +from commands import getstatusoutput +from MuonValidation_CreateSlides_config import * + +############################################################################# + +def CreateEmptyPlot( filename ): + can = ROOT.TCanvas("","",860,900) + can.SaveAs( filename ) + +############################################################################# + +def SetBounds( refHist, testHist ): + maximum = max(refHist.GetMaximum(), testHist.GetMaximum()) + maximum = maximum + 0.1*abs(maximum) + minimum = min(refHist.GetMinimum(), testHist.GetMinimum()) + minimum = minimum - 0.1*abs(minimum) + refHist.SetMinimum(minimum) + refHist.SetMaximum(maximum) + return refHist + +############################################################################# + +def MakeComparisonPlot( refHist, testHist, plotName, path, doNorm = False, doRatio = True ): + labelsize = 0.14 + titlesize = 0.18 + + #check that test histogram exist + if not refHist: + print('WARNING Ref Histogram not found: '+plotName) + + if not testHist: + print('WARNING Test histogram not found: '+plotName) + print(' Creating empty plot') + CreateEmptyPlot( path+'/'+plotName+'.png' ) + return + + #if doNorm set, scale hists to area = 1 + if refHist: + refint = refHist.Integral() + else: + refint = 0 + testint = testHist.Integral() + + if doNorm: + if refint != 0: + refHist.Scale( 1./refint ) + elif refHist: + print( 'WARNING empty ref plot ' + plotName ) + + if testint != 0: + testHist.Scale( 1./testint ) + else: + print( 'WARNING empty test plot ' + plotName ) + + canvas = ROOT.TCanvas( "", "", 860, 900 ) + canvas.SetLeftMargin( 0 ) + padMain = ROOT.TPad( 'padMain', 'padMain', 0, 0.3, 1, 1 ) + padMain.SetBottomMargin( 0 ) + padMain.Draw() + + if doRatio: + padRatio = ROOT.TPad( 'padRatio', 'padRatio', 0, 0, 1, 0.3 ) + padRatio.SetTopMargin( 0 ) + padRatio.SetBottomMargin( 0.4 ) + padRatio.Draw() + ROOT.TLine() + padMain.cd() + if 'cone' in plotName: + padMain.SetLogy() + + leg = ROOT.TLegend( 0.82, 0.77, 0.96, .96 ) + leg.SetFillColor( ROOT.kWhite ) + leg.SetTextSizePixels(20) + + testHist.SetMarkerColor(ROOT.kRed) + testHist.SetLineColor(ROOT.kRed) + leg.AddEntry(testHist, "test",'P') + + testHist.GetYaxis().SetTitleOffset( 1.4 ) + testHist.GetYaxis().SetTitleSize( labelsize*0.4 ) + testHist.SetLabelSize( labelsize*0.4, 'Y' ) + + for i in testHist.GetListOfFunctions(): + testHist.GetFunction(i.GetName()).SetBit(ROOT.TF1.kNotDraw) + testHist.Draw("PE") + if refint > 0: + for i in refHist.GetListOfFunctions(): + refHist.GetFunction(i.GetName()).SetBit(ROOT.TF1.kNotDraw) + + refHist.SetMarkerColor(ROOT.kBlack) + refHist.SetLineColor(ROOT.kBlack) + leg.AddEntry(refHist, "ref", 'P') + if 'cone' not in plotName: + refHist = SetBounds(refHist, testHist) + + refHist.Draw("PESAME") + testHist.Draw("PESAME") + leg.Draw() + + # #ks & chi^2 values + # if refint > 0 and testint > 0: + # ks = testHist.KolmogorovTest( refHist, 'WW' ) + # kstext = ROOT.TLatex( 0.18, .955, 'KS = %0.3f'%(ks)) + # kstext.SetNDC(ROOT.kTRUE) + # kstext.SetTextSize(0.055) + # kstext.Draw() + # chi = testHist.Chi2Test( refHist, 'WW' ) + # #print(chi) + # chitext = ROOT.TLatex( 0.4, .955, 'p(#chi^{2}) = %0.3f'%(chi)) + # chitext.SetNDC(ROOT.kTRUE) + # chitext.SetTextSize(0.055) + # chitext.Draw() + + if refint == 0 or testint == 0: + print( 'WARNING No ratio plot available: '+ plotName ) + elif not doRatio: + print( 'INFO skipping ratio plot for '+ plotName ) + else: + padRatio.cd() + ratioHist = testHist.Clone() + ratioHist.Divide( refHist ) + ratioHist.SetMarkerColor( ROOT.kBlack ) + ratioHist.SetMaximum(1.2) + ratioHist.SetMinimum(0.8) + ratioHist.SetLineColor( ROOT.kBlack ) + ratioHist.GetYaxis().SetTitle( "test / ref" ) + xtitle = ratioHist.GetXaxis().GetTitle() + if 'Transverse Momentum' in xtitle: + ratioHist.GetXaxis().SetTitle(xtitle.replace('Transverse Momentum', 'pT')) + + ratioHist.GetXaxis().SetTitleSize( titlesize ) + ratioHist.GetYaxis().SetTitleSize( labelsize ) + ratioHist.SetLabelSize( labelsize, 'XY' ) + ratioHist.GetXaxis().SetTitleOffset( 1.0 ) + ratioHist.GetYaxis().SetTitleOffset( .4 ) + ratioHist.Draw("PE") + + lineRatio = ROOT.TLine( ratioHist.GetXaxis().GetXmin(), 1, + ratioHist.GetXaxis().GetXmax(), 1 ) + lineRatio.SetLineColor( ROOT.kRed ) + lineRatio.SetLineWidth( 2 ) + lineRatio.Draw("same") + + canvas.cd() + canvas.SaveAs( path + '/' + plotName + '.png' ) + del canvas, padRatio, padMain + +############################################################################# + +def main(): + #parse options + parser = argparse.ArgumentParser( description = 'Create Muon Validation Slides in LaTeX Beamer' ) + parser.add_argument( '-r', '--reference', help = 'reference sample ROOT file' ) + parser.add_argument( '-t', '--test', required=True, help = 'test sample ROOT file' ) + parser.add_argument( '-d', '--directory', default = 'beamer', help = 'directory to put new files' ) + parser.add_argument( '-n', '--notitlepage', action = 'store_true', help = 'set to remove title page' ) + parser.add_argument( '-c', '--compile', action= 'store_true', help = 'compile beamer file' ) + args = parser.parse_args() + args.directory = os.path.dirname( args.directory + '/' ) + outdir = args.directory + '/plots' + if not os.path.isdir( outdir ): + os.makedirs( outdir ) + + #read files + testfile = ROOT.TFile.Open( args.test, 'read' ) + reffile = ROOT.TFile.Open( args.reference, 'read' ) + + ##### save histograms ##### + + specialTypes = [ 'RecoFrac', 'PtRes', 'Res_pT_vs', 'PtScale', 'Eff' ] + for PlotList in PlotPages.values(): + for PlotPath in PlotList: + HistDir, HistName = os.path.split( PlotPath ) + if testfile.GetDirectory( HistDir ): + testhist = testfile.GetDirectory( HistDir ).Get( HistName ) + else: + testhist = False + if reffile.GetDirectory( HistDir ): + refhist = reffile.GetDirectory( HistDir ).Get( HistName ) + else: + refhist = False + + doNorm = not sum([ HistName.__contains__(i) for i in specialTypes ]) + #doRatio = not (plot.__contains__('PtRes') or plot.__contains__('PtScale')) + MakeComparisonPlot( refhist, testhist, HistName, outdir, doNorm = doNorm, doRatio = True ) + + testfile.Close() + reffile.Close() + ##### create Beamer file ##### + + endl = '\n' + output = r'\documentclass{beamer}' + endl + output += r'\definecolor{links}{HTML}{0000FF}' + endl + output += r'\hypersetup{colorlinks=true,urlcolor=links}' + endl + output += r'\usepackage[latin1]{inputenc}' + endl + output += r'\usetheme{Warsaw}' + endl*2 + output += r'\definecolor{LightBlue}{cmyk}{0.248,0.0609,0,0.098}' + endl + output += r'\setbeamercolor{author in head/foot}{fg=white, bg=blue}'+endl + output += r'\setbeamercolor{title in head/foot}{fg=white, bg=LightBlue}'+endl + output += r'\makeatother' + endl + output += r'\setbeamertemplate{footline}{' + endl + output += r'\leavevmode' + endl + output += r'\hbox{%' + endl + + ht = 2.4 + dp = 1.1 + output += r'\begin{beamercolorbox}[wd=0.4\paperwidth,ht=%0.3fex,dp=%0.3fex,center]{author in head/foot}'%( ht, dp ) + r'%' + endl + output += r' \usebeamerfont{author in head/foot}\insertshortauthor' + endl + + output += r'\end{beamercolorbox}%' + endl + output += r'\begin{beamercolorbox}[wd=0.5\paperwidth,ht=%0.3fex,dp=%0.3fex,center]{title in head/foot}'%( ht, dp ) + r'%' + endl + output += r' \usebeamerfont{author in head/foot}\insertshorttitle' + endl + output += r'\end{beamercolorbox}%' + endl + output += r'\begin{beamercolorbox}[wd=0.1\paperwidth,ht=%0.3fex,dp=%0.3fex,center]{author in head/foot}'%( ht, dp ) + r'%' + endl + output += r' \insertframenumber{}/\inserttotalframenumber' + endl + output += r'\end{beamercolorbox}}%' + endl + output += r'\vskip0pt}' + endl*2 + + output += r'\makeatletter' + endl + output += r'\setbeamertemplate{navigation symbols}{}' + endl*2 + output += r'\setbeamerfont{footline}{size=\fontsize{10}{11}\selectfont}' + endl + + output += r'\setbeamersize{text margin left=0.5cm}' + endl + output += r'\setbeamersize{text margin right=0.5cm}' + endl + + output += r'\title[%s]{%s}'%(ShortTitle, Title) + endl + output += r'\subtitle{%s}'%(Subtitle) + endl + output += r'\author[%s]{%s}'%(ShortAuthor, Author) + endl + output += r'\institute[%s]{%s}'%(ShortInstitute, Institute) + endl + output += r'\date{%s}'%(Date) + endl + output += r'\begin{document}' + endl*2 + output += r'%%%%%%%%%%%%%%%%%%%% BEGIN DOCUMENT %%%%%%%%%%%%%%%%%%%%' + endl*2 + if not args.notitlepage: + output += r'{\setbeamertemplate{footline}{}' + endl + output += r'\begin{frame} \titlepage \end{frame} }' + endl + output += r'\addtocounter{framenumber}{-1}' + endl*2 + + #intro slide + output += r'\begin{frame}' + endl + output += r'\frametitle{Introduction}' + endl + output += 'Reference:' + endl*2 + output += '{0}: {1}'.format(RefVersion, RefDescription) + endl*2 + output += RefDataset + endl*2 + output += r'\vspace{12pt}' + endl + output += 'Test:' + endl*2 + output += '{0}: {1}'.format(TestVersion, TestDescription) + endl*2 + output += TestDataset + endl*2 + output += r'\vspace{12pt}' + Intro + endl + output += r'\end{frame}' + endl*2 + + for page in PlotPages: + plotlist = PlotPages[page] + output += r'\begin{frame}' + endl + output += r'\frametitle{%s}'%(page) + endl + output += r'\hspace*{-4pt}\makebox[\linewidth][c]{' + endl + output += r'\begin{tabular}{c%s}'%(r'@{\hspace{1pt}}c'*(len(plotlist)-1)) + endl + for n, plotpath in enumerate(plotlist): + output += r'\includegraphics[width=%0.2f\textwidth]{%s/%s.png}'%( 0.35, outdir.replace( args.directory+'/', '' ), os.path.split(plotpath)[1] ) + if n+1 < len(plotlist): + output += ' &' + output += endl + output += r'\end{tabular} }' + endl + if page in PlotComments: + output += PlotComments[page] + endl + output += r'\end{frame}' + endl*2 + + #summary slide + if len(Summary) > 0: + output += r'\begin{frame}' + endl + output += 'Summary' + endl + output += r'\begin{itemize}' + endl + + for item in Summary: + output += r'\item %s'%(item) + endl + + output += r'\end{itemize}' + endl + output += r'\end{frame}' + endl + output += r'\end{document}' + + with open( args.directory + '/' + texfile, 'w' ) as f: + f.write( output ) + + badEnvVars = [ 'TEXMFCNF', 'TEXINPUTS', 'TEXMFHOME' ] #Athena sets these vars but LaTeX doesn't like them + for i in badEnvVars: + os.unsetenv(i) + if args.compile: + stat, out = getstatusoutput( 'cd %s; pdflatex -halt-on-error %s; pdflatex -halt-on-error %s'%( args.directory, texfile, texfile ) ) + if stat != 0: + print out + + +######################### Executable Area ######################### + +if __name__ == "__main__": + if sys.version_info < (2,7): + print( 'INFO This program requires Python version 2.7 or greater' ) + exit(1) + + #ROOT.gROOT.Macro("rootlogon.C") + ROOT.gROOT.SetBatch() + main() diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateSlides_config.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateSlides_config.py new file mode 100644 index 0000000000000000000000000000000000000000..729c02bf2581087a836d5e50449c2792ec58eb6d --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_CreateSlides_config.py @@ -0,0 +1,183 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +#by Dan Mori +#config file for CreateMuonValidationSlides.py +#all strings here are for LaTeX + +from collections import OrderedDict + +texfile = 'muon_validation.tex' #The output pdf file name will be the same + +#dataset info +RefVersion = 'ttbar' +TestVersion = 'Zprime' +RefDataset = 'r6059' +TestDataset = 'r6059' +RefDescription = '' +TestDescription = '' + +#titlepage info +Title = 'Muon Validation of {0}'.format( TestVersion, RefVersion ) +Subtitle = '' +Author = 'Me' +ShortAuthor = 'Me' +Institute = 'CERN' +ShortInstitute = 'CERN' +Date = r'\today' + +ShortTitle = r'\textcolor{red}{Test: %s} \textcolor{black}{Ref: %s}'%( TestVersion, RefVersion ) #this will be in the footline of each slide - shows versions of test/ref in red/black + +#intro slide +Intro = ''#'Everything looks good' + +#summary slide +Summary = [] +#Summary = [ +# 'item 1', +# 'item 2', +# 'item 3' ] + +############################################################################# +#list of plots to go into each page. the dict key is the title for each page +#each plot should be entered as path/to/hist/histname +#The pages will appear in the order given here +#macro is setup to handle 2 or 3 plots per page only + +PlotPages = OrderedDict() +PlotComments = {} + +#kinematics +PlotPages[ r'Kinematics - $p_T$, $\eta$, $\phi$' ] = [ + 'Muons/All/reco/AllMuons/kinematics/Muons_All_reco_AllMuons_kinematics_pt', + 'Muons/All/reco/AllMuons/kinematics/Muons_All_reco_AllMuons_kinematics_eta', + 'Muons/All/reco/AllMuons/kinematics/Muons_All_reco_AllMuons_kinematics_phi' ] +#PlotComments[ r'Kinematics - $p_T$, $\eta$, $\phi$' ] = 'PUT COMMENTS HERE IF YOU WANT' + +PlotPages[ r'Kinematics - $d_0$, $z_0$' ] = [ + 'Muons/All/reco/AllMuons/parameters/Muons_All_reco_AllMuons_parameters_d0', + 'Muons/All/reco/AllMuons/parameters/Muons_All_reco_AllMuons_parameters_z0' ] +#PlotComments[ r'Kinematics - $d_0$, $z_0$' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#layers +PlotPages[ 'Precision Layers' ] = [ + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_nprecLayers', + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_nphiLayers' ] +#PlotComments[ 'Precision Layers' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#hits +PlotPages[ 'Precision Hits - Inner' ] = [ + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_innersmallhits', + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_innerlargehits' ] +#PlotComments[ 'Precision Hits - Inner' ] = 'PUT COMMENTS HERE IF YOU WANT' + +PlotPages[ 'Precision Hits - Middle' ] = [ + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_middlesmallhits', + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_middlelargehits' ] +#PlotComments[ 'Precision Hits - Middle' ] = 'PUT COMMENTS HERE IF YOU WANT' + +PlotPages[ 'Precision Hits - Outer' ] = [ + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_outersmallhits', + 'Muons/All/reco/AllMuons/hits/Muons_All_reco_AllMuons_hits_outerlargehits' ] +#PlotComments[ 'Precision Hits - Outer' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#isolation +PlotPages[ r'Isolation - $p_T$-cone / $p_T$' ] = [ + 'Muons/All/reco/AllMuons/isolation/Muons_All_reco_AllMuons_isolation_ptcone20rel', + 'Muons/All/reco/AllMuons/isolation/Muons_All_reco_AllMuons_isolation_ptcone30rel', + 'Muons/All/reco/AllMuons/isolation/Muons_All_reco_AllMuons_isolation_ptcone40rel' ] +#PlotComments[ r'Isolation - $p_T$-cone / $p_T$' ] = 'PUT COMMENTS HERE IF YOU WANT' + +PlotPages[ r'Isolation - $E_T$-cone / $p_T$' ] = [ + 'Muons/All/reco/AllMuons/isolation/Muons_All_reco_AllMuons_isolation_etcone20rel', + 'Muons/All/reco/AllMuons/isolation/Muons_All_reco_AllMuons_isolation_etcone30rel', + 'Muons/All/reco/AllMuons/isolation/Muons_All_reco_AllMuons_isolation_etcone40rel' ] +#PlotComments[ r'Isolation - $E_T$-cone / $p_T$' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#chi^2 +PlotPages[ 'Track Fit Quality' ] = [ + 'Muons/All/reco/AllMuons/parameters/Muons_All_reco_AllMuons_parameters_tchi2', + 'Muons/All/reco/AllMuons/parameters/Muons_All_reco_AllMuons_parameters_chi2ndof' ] +#PlotComments[ 'Track Fit Quality' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#Resolution +PlotPages[ 'Resolution (Combined)' ] = [ + 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_Res_PtResol_vs_pT', + 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_Res_PtResol_vs_eta', + 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_Res_PtResol_vs_phi' ] +#PlotComments[ 'Resolution (Combined)' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# PlotPages[ 'Resolution (ID)' ] = [ +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResID_PtResol_vs_pT', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResID_PtResol_vs_eta', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResID_PtResol_vs_phi' ] +# #PlotComments[ 'Resolution (ID)' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# PlotPages[ 'Resolution (MS)' ] = [ +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResMS_PtResol_vs_pT', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResMS_PtResol_vs_eta', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResMS_PtResol_vs_phi' ] +# #PlotComments[ 'Resolution (MS)' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#Momentum scale +PlotPages[ r'$p_T$ Scale (Combined)' ] = [ + 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_Res_PtScale_vs_pT', + 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_Res_PtScale_vs_eta', + 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_Res_PtScale_vs_phi' ] +#PlotComments[ r'$p_T$ Scale (Combined)' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# PlotPages[ r'$p_T$ Scale (ID)' ] = [ +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResID_PtScale_vs_pT', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResID_PtScale_vs_eta', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResID_PtScale_vs_phi' ] +# #PlotComments[ r'$p_T$ Scale (ID)' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# PlotPages[ r'$p_T$ Scale (MS)' ] = [ +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResMS_PtScale_vs_pT', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResMS_PtScale_vs_eta', +# 'Muons/Prompt/matched/MuidCo/resolution/Muons_Prompt_matched_MuidCo_resolution_ResMS_PtScale_vs_phi' ] +# #PlotComments[ r'$p_T$ Scale (MS)' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#Pulls +PlotPages[ r'Track Pull Plots - $q/P$, $\theta$, $\phi$' ] = [ + 'Muons/All/matched/AllMuons/Pulls/Muons_All_matched_AllMuons_Pulls_Pull_qOverP', + 'Muons/All/matched/AllMuons/Pulls/Muons_All_matched_AllMuons_Pulls_Pull_theta', + 'Muons/All/matched/AllMuons/Pulls/Muons_All_matched_AllMuons_Pulls_Pull_phi' ] +#PlotComments[ r'Track Pull Plots - $q/P$, $\theta$, $\phi$' ] = 'PUT COMMENTS HERE IF YOU WANT' + +PlotPages[ r'Track Pull Plots - $d_0$, $z_0$' ] = [ + 'Muons/All/matched/AllMuons/Pulls/Muons_All_matched_AllMuons_Pulls_Pull_d0', + 'Muons/All/matched/AllMuons/Pulls/Muons_All_matched_AllMuons_Pulls_Pull_z0' ] +#PlotComments[ r'Track Pull Plots - $d_0$, $z_0$' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# #Efficiency +PlotPages[ 'Efficiency' ] = [ + 'Muons/All/matched/AllMuons/efficiency/Muons_All_matched_AllMuons_efficiency_pt', + 'Muons/All/matched/AllMuons/efficiency/Muons_All_matched_AllMuons_efficiency_eta', + 'Muons/All/matched/AllMuons/efficiency/Muons_All_matched_AllMuons_efficiency_phi' ] +#PlotComments[ 'Efficiency' ] = 'PUT COMMENTS HERE IF YOU WANT' + +#Purity +PlotPages[ 'Purity' ] = [ + 'Muons/All/matched/AllMuons/purity/Muons_All_matched_AllMuons_purity_pt', + 'Muons/All/matched/AllMuons/purity/Muons_All_matched_AllMuons_purity_eta', + 'Muons/All/matched/AllMuons/purity/Muons_All_matched_AllMuons_purity_phi' ] +#PlotComments[ 'Purity' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# #Reco fraction +# PlotPages[ 'Reco Fraction - Inflight Muons' ] = [ +# 'Muons/InFlight/reco/AllMuons/RecoFraction/Muons_InFlight_reco_AllMuons_RecoFraction_pt', +# 'Muons/InFlight/reco/AllMuons/RecoFraction/Muons_InFlight_reco_AllMuons_RecoFraction_eta', +# 'Muons/InFlight/reco/AllMuons/RecoFraction/Muons_InFlight_reco_AllMuons_RecoFraction_phi' ] +# #PlotComments[ 'Reco Fraction - Inflight Muons' ] = 'PUT COMMENTS HERE IF YOU WANT' + +# PlotPages[ 'Reco Fraction - NonIsolated Muons' ] = [ +# 'Muons/NonIsolated/reco/AllMuons/RecoFraction/Muons_NonIsolated_reco_AllMuons_RecoFraction_pt', +# 'Muons/NonIsolated/reco/AllMuons/RecoFraction/Muons_NonIsolated_reco_AllMuons_RecoFraction_eta', +# 'Muons/NonIsolated/reco/AllMuons/RecoFraction/Muons_NonIsolated_reco_AllMuons_RecoFraction_phi' ] +# # PlotComments[ 'Reco Fraction - NonIsolated Muons' ] = 'PUT COMMENTS HERE IF YOU WANT' + +PlotPages[ 'Reco Fraction - Unmatched All Authors' ] = [ + 'Muons/UnmatchedRecoMuons/RecoFraction/Muons_UnmatchedRecoMuons__RecoFraction_pt', + 'Muons/UnmatchedRecoMuons/RecoFraction/Muons_UnmatchedRecoMuons__RecoFraction_eta', + 'Muons/UnmatchedRecoMuons/RecoFraction/Muons_UnmatchedRecoMuons__RecoFraction_phi' ] +#PlotComments[ 'Reco Fraction - Unmatched All Authors' ] = 'PUT COMMENTS HERE IF YOU WANT' diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_runPostProcessMacrosRtt.sh b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_runPostProcessMacrosRtt.sh new file mode 100755 index 0000000000000000000000000000000000000000..565a85d1ffcbf7fdda280b6a031068fab8206784 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/MuonValidation_runPostProcessMacrosRtt.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +if [ $# -lt 1 ]; then + echo "Please give input file!" + exit +fi + +inputfile=$1 + +cp $inputfile $inputfile.temp.root +tmpfile=$inputfile.temp.root + +## Settings doAverage option will add a TF1 function of a horizontal line +# showing overall efficiency, resolution, scale, etc. + +## Creates efficiency and other ratio plots +#MuonValidation_CreateEffAndRecoFracPlots.py $tmpfile #doAverage + +## Creates pt resolution and pt scale plots. doBinned option makes res plots for each bin in 2D hists +MuonValidation_CreateResolutionProfiles.py $tmpfile #doAverage doBinned + +## Creates profiles of pull plots over pt +#MuonValidation_CreatePullProfiles.py $tmpfile #doAverage + +## Normalizes all plots to unity (for comparisons). MUST RUN AFTER EFFICIENCY MACROS!!! OTHERWISE EFFICIENCY WILL BE WRONG!!!! +# normalizator.py $tmpfile + +echo "Created $tmpfile." diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/normalizator.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/normalizator.py new file mode 100755 index 0000000000000000000000000000000000000000..285935dd1c503da888f849fd79639d3ba04145a6 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/normalizator.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +#This script normalizes all histograms (except TH2, efficiencies and TProfiles) in a given root file. +import ROOT +from ROOT import TFile, TH1 +import sys +import argparse +import re +import os +import math + + +def browseDir( dir ): + #print dir.GetPath().split(':', 1)[-1] + path = dir.GetPath().split(':/', 1)[-1] + pathdir = dir #.GetDirectory(path) + #print pathdir.GetPath() + keylist = dir.GetListOfKeys() + + for key in keylist: + obj = key.ReadObj() + + #2D histograms cannot be compared, tprofiles and efficiencies should not be normalized; skip + if obj.IsA().InheritsFrom(ROOT.TH2.Class()) or obj.IsA().InheritsFrom(ROOT.TProfile.Class()) or "fficiency" in obj.GetName() or 'RecoFraction' in obj.GetName() or 'purity' in obj.GetName() or "PtResol" in obj.GetName() or "PtScale" in obj.GetName() or "Prof" in obj.GetName() or "Fit" in obj.GetName(): + continue + + if obj.IsA().InheritsFrom(ROOT.TH1.Class()) : + #normalize + #print '----- ', obj.GetName() + ii = 1.*obj.Integral() + hname = obj.GetName() + if ii>0: + obj.Scale(1./ii) + #print ' ',hname + pathdir.WriteTObject( obj , hname , "WriteDelete" ) + continue + + if obj.IsA().InheritsFrom(ROOT.TDirectory.Class()): + #print obj.GetName() + browseDir(obj) + + + +#====================================================================== +def main( argv ): + """ + Main function to be executed when starting the code. + """ + + if len( argv ) < 2: + print( 'No filename given' ) + print( 'Usage: python '+argv[0]+' physval_filename' ) + exit(1) + + filename = argv[1] + if not os.path.exists( filename ): + print ( 'File not found: ' + filename ) + exit(1) + + try: + infile = ROOT.TFile.Open( filename, 'update' ) + except: + print( 'Cannot open file: {0}'.format( filename ) ) + exit(1) + + ROOT.gROOT.SetBatch() + + infile.cd("Muons") + topDir = infile.GetDirectory("Muons") + + browseDir(topDir) + infile.Close() + +#====================================================================== + +if __name__ == "__main__": + """ + Here the code should appear that is executed when running the plotter directly + (and not import it in another python file via 'import Plotter') + """ + + # start main program + main( sys.argv ) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/rootlogon.C b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/rootlogon.C new file mode 100644 index 0000000000000000000000000000000000000000..fd7500de0bf625483cade95dc4e2a4baeb5aa19c --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/rootlogon.C @@ -0,0 +1,12 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +{ + gROOT->ProcessLine("#include \"AtlasStyle.C\""); + // gROOT->ProcessLine("#include \"AtlasUtils.C\""); + TStyle* atlasStyle = AtlasStyle(); + gROOT->SetStyle("ATLAS"); + gROOT->ForceStyle(); + gStyle->SetPalette(1, 0); +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/runPostProcessMacrosLocal.sh b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/runPostProcessMacrosLocal.sh new file mode 100755 index 0000000000000000000000000000000000000000..9092c60aa22e3862144ea25836fe377176d580c1 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/runPostProcessMacrosLocal.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ $# -lt 1 ]; then + echo "Please give input file!" + exit +fi + +inputfilename=`basename $1 .root` +tmpfile=$(dirname $1)/$(basename $1 .root).PROC.root +cp $1 $tmpfile + +## Settings doAverage option will add a TF1 function of a horizontal line +# showing overall efficiency, resolution, scale, etc. + +## Creates efficiency and other ratio plots +python CreateEffAndRecoFracPlots.py $tmpfile #doAverage + +## Creates pt resolution and pt scale plots. doBinned option makes res plots for each bin in 2D hists +python CreateResolutionProfiles.py $tmpfile #doAverage doBinned + +## Creates profiles of pull plots over pt +python CreatePullProfiles.py $tmpfile #doAverage + +## Normalizes all plots to unity (for comparisons). MUST RUN AFTER EFFICIENCY MACROS!!! OTHERWISE EFFICIENCY WILL BE WRONG!!!! +python normalizator.py $tmpfile + +echo "Created $tmpfile." diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/validator.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/validator.py new file mode 100644 index 0000000000000000000000000000000000000000..8bae6b3aea5ed32cac5e1a495b84640fbe14564c --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/macros/validator.py @@ -0,0 +1,330 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +"""This script compares two given root files and saves plots where they differ +as pdfs. + +author: Felix Socher <Felix.Socher@cern.ch>""" + + +import ROOT +from ROOT import * +import sys +import argparse +import re +import os +import math + +LABELS = [] + +def GoToDirectory(directory): + cwd = os.getcwd() + print os.getcwd() + newdir = cwd + "/" + directory + if not os.path.isdir( newdir ): + print "Creating folder " + newdir + os.makedirs( newdir ) + os.chdir(newdir) + + +def SameHist(refHist, testHist): + chi2 = 0 + for x in range(refHist.GetNbinsX()): + for y in range(refHist.GetNbinsY()): + for z in range(refHist.GetNbinsZ()): + if refHist.GetBinContent(x,y,z) != testHist.GetBinContent(x,y,z): return False + return True + +def SimilarHist(refHist, testHist): + for x in range(refHist.GetNbinsX()): + for y in range(refHist.GetNbinsY()): + for z in range(refHist.GetNbinsZ()): + if abs(refHist.GetBinContent(x,y,z) - testHist.GetBinContent(x,y,z)) > 0.01: return False + return True + + + + +class Validator(object): + """docstring for Validator""" + def __init__(self, structDirs, exclude, compareFunc, normalization): + super(Validator, self).__init__() + self.structDirs = structDirs + #self.excludedStrings = exclude.split("|") + #print self.excludedStrings + self.CompareFunc = compareFunc + self.DoNormalization = normalization + + def CompareFiles(self, fileNames, dirName): + openedFiles = [ TFile.Open(f) for f in fileNames ] + self.CompareDirectories(openedFiles, dirName) + + def CompareDirectories(self, dirs, dirName): + if (self.structDirs): GoToDirectory(dirName) + refDir = dirs[0] + newRefDir = refDir.GetDirectory(dirName) + for testDir in dirs: + if testDir == refDir: continue + if not testDir: + print 'ERROR --------- test dir not found: ', dirName, testDir + return + + newTestDirs = [ testDir.GetDirectory(dirName) for testDir in dirs ] + + theDir = newRefDir + # if not newRefDir: + # print 'ERROR --------- reference dir not found: ', dirName + # theDir = newTestDir + + for key in theDir.GetListOfKeys(): + + obj = key.ReadObj() + + #2D histograms cannot be compared; skip + if obj.IsA().InheritsFrom(ROOT.TH2.Class()): + continue + + if obj.IsA().InheritsFrom(ROOT.TH1.Class()): + print key.GetName() + #testHist = newTestDir.Get(key.GetName()) + testHists = [ newTestDir.Get(key.GetName()) for newTestDir in newTestDirs ] + self.CompareHistograms( testHists, newRefDir.GetPath()) + elif obj.IsA().InheritsFrom(ROOT.TDirectory.Class()): + self.CompareDirectories( newTestDirs, obj.GetName()) + if (self.structDirs): os.chdir("..") + + def CompareHistograms(self, hists, path): + # print self.excludedStrings, refHist.GetName() + # if any(exString in refHist.GetName() for exString in self.excludedStrings): + # print "Skipped " + path + "/" + refHist.GetName() + # return + #@@@if self.CompareFunc(refHist, testHist): print path + refHist.GetName() + " looks ok" + #else: + #self.MakeComparisonPlot(refHist, testHist, path) + self.MakeComparisonPlot(hists, path) + + #def MakeComparisonPlot(self,refHist, testHist, path): + def MakeComparisonPlot(self, hists, path): + def SetBounds(hists, ymin=0, ymax=0): + if (ymin==0 and ymax==0): + ymin = min( [ h.GetMinimum() for h in hists ] ) + ymax = min( [ h.GetMaximum() for h in hists ] ) + if ymin>0 and ymax>0: + ymin = 0 + else: + ymin = ymin - 0.15*abs(ymin) + ymax = ymax+ 0.15*ymax + # if ymin<0 and ymax>0: + # if ymax>0 and abs(minimum)>ymax: + # ymax = -minimum + hists[0].SetMinimum(ymin) + hists[0].SetMaximum(ymax) + return hists[0] + ################################## end SetBounds + + # try: + # refHist.Scale(1.0/refHist.Integral()) + # testHist.Scale(1.0/testHist.Integral()) + # except: + # return + canvas = ROOT.TCanvas( "", "", 900, 900 ) + padMain = ROOT.TPad( 'padMain', 'padMain', 0, 0.3, 1, 1 ) + padMain.SetBottomMargin( 0.02 ) + padMain.Draw() + #padMain.SetLogy(1) #@@@ + padRatio = ROOT.TPad( 'padRatio', 'padRatio', 0, 0, 1, 0.3 ) + padRatio.SetTopMargin( 0.01 ) + padRatio.SetBottomMargin( 0.25 ) + padRatio.Draw() + ROOT.TLine() + padMain.cd() + + leg = ROOT.TLegend(0.82,0.78,0.96,0.94) + #leg = ROOT.TLegend(0.52,0.76,0.96,0.94) + #leg.SetFillColor(ROOT.kWhite) + leg.SetFillStyle(0) + leg.SetBorderSize(0) + leg.SetTextFont(43) + leg.SetTextSizePixels(32) + + refHist = hists[0] + refHist.SetLineColor(17) + #refHist.SetFillColor(30) + + ## @@@ Legend!!! + #leg.AddEntry(hists[0], 'ref', 'lp') + #leg.AddEntry(hists[1], 'test', 'lp') + #if len(hists)>2: + # for i in range(2,len(hists)): + # leg.AddEntry(hists[i], 'test{0}'.format(i), 'lp') + for i in range(0,len(hists)): + leg.AddEntry(hists[i], LABELS[i], 'lp') + + if self.DoNormalization and not "_Eff_" in refHist.GetName() and not "_eff" in refHist.GetName() and not "_Eff" in refHist.GetName(): + for h in hists: + n = h.Integral() + if n>0: + h.Scale(1./n) + + refHist = SetBounds(hists) + + ref_textsize = 32./(padMain.GetWh()*padMain.GetAbsHNDC()) + refHist.GetYaxis().SetLabelSize( ref_textsize ) + refHist.GetXaxis().SetLabelSize( 0 ) + refHist.GetXaxis().SetTitleSize( 0 ) + refHist.GetYaxis().SetTitleSize( 1.3*ref_textsize ) + refHist.GetYaxis().SetTitleOffset(1) + refHist.GetYaxis().SetTitleColor( kAzure ) + + # testHist.GetYaxis().SetTextFont(43) + # testHist.GetYaxis().SetTextSizePixels(20) + refHist.SetMarkerSize(0) + refHist.SetLineColor(ROOT.kRed) + #refHist.GetYaxis().SetRangeUser(0.00001,refHist.GetMaximum()*5) ##@@@ + + #testHist.Rebin(2) + #refHist.Rebin(2); + histmax = refHist + histmax.DrawCopy('e') + # for h in hists: + # if h.GetMaximum() > refHist.GetMaximum(): + # histmax = h + # if histmax == refHist: + # histmax.DrawCopy("e") + # else: + # histmax.DrawCopy("ehist") + nh=0 + for h in hists: + if h is not histmax: + if h==refHist: + h.DrawCopy('histsame') + else: + nh=nh+1 + if nh>1: + h.SetMarkerStyle(0) + h.SetMarkerColor(0) + h.SetLineColor(8) # green + h.SetLineStyle(ROOT.kDashed) + h.DrawCopy('ehistsame') + # if refHist.GetMaximum()>histmax.GetMaximum(): + # refHist.DrawCopy("e") + # testHist.DrawCopy("ehistsame") + # refHist.DrawCopy("ehistsame") + # else: + # testHist.DrawCopy("ehist") + # refHist.DrawCopy("ehistsame") + + leg.Draw() + padRatio.cd() + + for h in hists: + if h is refHist: continue + ratioHist = h.Clone() + ratioHist.Divide(refHist) + ratioHist = SetBounds( [ratioHist, ratioHist], 0.84,1.16) # 0.941,1.059 + for i in range(ratioHist.GetNbinsX()): + nref = refHist.GetBinContent(i) + ntest = h.GetBinContent(i) + if nref == 0 or ntest == 0: + ratioHist.SetBinError(i, 0) + else: + #error = nref/ntest*math.sqrt((refHist.GetBinError(i)/nref)**2 + (testHist.GetBinError(i)/ntest)**2) + error = nref/ntest* max(refHist.GetBinError(i)/nref, h.GetBinError(i)/ntest) + ratioHist.SetBinError(i, error) + + ratioHist_textsize = 32./(padRatio.GetWh()*padRatio.GetAbsHNDC()) + ratioHist.GetYaxis().SetLabelSize( ratioHist_textsize ) + ratioHist.GetXaxis().SetLabelSize( ratioHist_textsize ) + ratioHist.GetXaxis().SetTitleSize( 1.2*ratioHist_textsize ) + ratioHist.GetXaxis().SetTitleOffset(0.75) + ratioHist.GetXaxis().SetTitleColor(kAzure) + ratioHist.GetYaxis().SetTitleSize( ratioHist_textsize ) + ratioHist.GetYaxis().SetTitleOffset(0.6) + + + ratioHist.SetLineColor(ROOT.kBlack) + ratioHist.SetMarkerStyle(24) + ratioHist.SetYTitle("test / ref") + if h == hists[1]: + ratioHist.DrawCopy("p") + lineRatio = ROOT.TLine( ratioHist.GetXaxis().GetXmin(), 1, + ratioHist.GetXaxis().GetXmax(), 1 ) + lineRatio.SetLineColor( ROOT.kRed ) + lineRatio.SetLineWidth( 2 ) + lineRatio.Draw("same") + else: + ratioHist.SetMarkerStyle(25) + ratioHist.SetMarkerColor(8) + ratioHist.SetLineColor(8) + ratioHist.DrawCopy("psame") + + npath = "" + if not self.structDirs: + npath = path[path.find(":/")+2:] + "/" + npath = re.sub(r"[:,./]", "_", npath+"/") + + canvas.cd() + t = ROOT.TLatex(); + t.SetNDC() + t.SetTextColor(1) + t.SetTextSize(0.03); + t.DrawLatex(0.,0.97,refHist.GetName()) #@@@ + + canvas.SaveAs(npath + refHist.GetName() + ".pdf") + canvas.Close() + +#====================================================================== +def main( argv ): + """ + Main function to be executed when starting the code. + """ + + parser = argparse.ArgumentParser( description = 'Distribution Plotter' ) + parser.add_argument( '-s', '--structDirs', default = True, action = "store_true", help = ' if true, it creates directories following the same structure as in the root file to store the pdf plots') + parser.add_argument( '-r', '--reference', help = 'The reference' ) + parser.add_argument( '-t', '--test', help = 'The test' ) + parser.add_argument( '-t2', '--test2', default ='', help = 'The additional test' ) + parser.add_argument( '-d', '--directory', default = "/", help = 'Print cutflow fror systematic variations' ) + parser.add_argument( '-e', '--exclude', default = "_bin_", help = 'histograms whose names contain the provided strings are not examined') + parser.add_argument( '-n', '--normalize', default = False, action = "store_true", help = 'normalize histograms with larger stats for better comparison') + parser.add_argument( '-l', '--labels', default ='', help = 'Add text to legend for ref/test/test2, split with commas' ) + + args = parser.parse_args() + + + #ROOT.gROOT.Macro("rootlogon.C") + ROOT.gROOT.SetBatch() + #ROOT.gROOT.LoadMacro("./AtlasUtils.C") + ROOT.gROOT.LoadMacro("./AtlasStyle.C") + ROOT.TH1.SetDefaultSumw2(ROOT.kTRUE) + + SetAtlasStyle() + + LABELS = [] + if args.labels is '': + LABELS = [ 'Ref','Test' ] + if args.test2 is not '': + LABELS.append( 'Test2' ) + else: + LABELS = args.labels.split(",") + #print LABELS + + # if you want to pass labels to legend directly from the file name...: + #LABELS.append( args.test.split('.')[2]+' '+args.test.split('.')[3] ) + # + + validator = Validator( args.structDirs, args.exclude, SameHist, args.normalize ) + if args.test2 == '': + allFiles = [ os.path.abspath(args.reference), os.path.abspath(args.test) ] + else: + allFiles = [ os.path.abspath(args.reference), os.path.abspath(args.test), os.path.abspath(args.test2) ] + #====================================================================== + +if __name__ == "__main__": + """ + Here the code should appear that is executed when running the plotter directly + (and not import it in another python file via 'import Plotter') + """ + + # start main program + main( sys.argv[1:] ) + diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/python/LRTMuonPhysValConfig.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/python/LRTMuonPhysValConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..2ed2fc77f19e10fabc4034156ca7585a5acad7a2 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/python/LRTMuonPhysValConfig.py @@ -0,0 +1,74 @@ +# +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +# + +'''@file LRTMuonPhysValConfig.py +@author N. Pettersson +@date 2022-07-13 +@brief Main CA-based python configuration for LRTMuonPhysValMonitoring +''' + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + +def PhysValLRTMuonCfg(flags, container='', **kwargs): + acc = ComponentAccumulator() + + kwargs.setdefault("IsData", not flags.Input.isMC) + kwargs.setdefault("SlowMuonContainerName", "") + + kwargs.setdefault("SelectMuonWorkingPoints", [0, 1, 2]) + kwargs.setdefault("SelectMuonAuthors", [1, 2 , 4, 5, 6, 8, 10]) + selectMuonCat = [0, 1] + if not flags.Input.isMC: + selectMuonCat = [0, 1, 4] + kwargs.setdefault("SelectMuonCategories", selectMuonCat) + from IsolationSelection.IsolationSelectionConfig import MuonPhysValIsolationSelCfg + kwargs.setdefault("IsoTool", acc.popToolsAndMerge(MuonPhysValIsolationSelCfg(flags))) + from InDetConfig.InDetTrackSelectorToolConfig import MuonCombinedInDetDetailedTrackSelectorToolCfg + kwargs.setdefault("TrackSelector",acc.popToolsAndMerge(MuonCombinedInDetDetailedTrackSelectorToolCfg(flags))) + from MuonSelectorTools.MuonSelectorToolsConfig import MuonSelectionToolCfg + kwargs.setdefault("MuonSelector", acc.popToolsAndMerge(MuonSelectionToolCfg(flags))) + from MuonConfig.MuonRecToolsConfig import MuonEDMPrinterToolCfg + edmprinter = acc.popToolsAndMerge(MuonEDMPrinterToolCfg(flags)) + kwargs.setdefault("MuonPrinter", CompFactory.Rec.MuonPrintingTool(MuonStationPrinter=edmprinter)) + kwargs.setdefault("EnableLumi", False) + from AthenaCommon.Constants import WARNING + kwargs.setdefault("OutputLevel", WARNING) + kwargs.setdefault("DetailLevel", 10) + + acc.setPrivateTools(CompFactory.LRTMuonPhysValMonitoring.LRTMuonPhysValMonitoringTool("lrtmuphysval", **kwargs)) + return acc + + +def PhysValLRTMuonTriggerCfg(flags, container='', **kwargs): + acc = ComponentAccumulator() + + selectHLTMuonItems = [ + ["HLT_mu20","L1_MU20"], + ["HLT_mu20_iloose_L1MU15","L1_MU15"], + ["HLT_mu24","L1_MU20"], + ["HLT_mu24_iloose_L1MU15","L1_MU15"], + ["HLT_mu24_imedium","L1_MU20"], + ["HLT_mu26","L1_MU20"], + ["HLT_mu26_imedium","L1_MU20"], + ["HLT_mu50","L1_MU20"] + ] + + selectL1MuonItems = [ + "L1_MU4", + "L1_MU6", + "L1_MU10", + "L1_MU11", + "L1_MU15", + "L1_MU20", + ] + + kwargs.setdefault("SelectHLTMuonItems", selectHLTMuonItems) + kwargs.setdefault("SelectL1MuonItems", selectL1MuonItems) + from TrigDecisionTool.TrigDecisionToolConfig import TrigDecisionToolCfg + kwargs.setdefault("TrigDecTool", acc.getPrimaryAndMerge(TrigDecisionToolCfg(flags))) + + acc.setPrivateTools(acc.popToolsAndMerge( + PhysValLRTMuonCfg(flags, container, **kwargs))) + return acc diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/scripts/runLRTMuonPhysVal.py b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/scripts/runLRTMuonPhysVal.py new file mode 100755 index 0000000000000000000000000000000000000000..fd4564905f7d577662a1eeee33b5903ed7018073 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/scripts/runLRTMuonPhysVal.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + +from glob import glob + +def GetCustomAthArgs(): + from argparse import ArgumentParser + parser = ArgumentParser(description='Parser for LRTMuonPhysVal configuration') + parser.add_argument("--filesInput", required=True) + parser.add_argument("--outputFile", help='Name of output file',default="M_output.root") + return parser.parse_args() + +# Parse the arguments +MyArgs = GetCustomAthArgs() + +from AthenaConfiguration.AllConfigFlags import initConfigFlags +flags = initConfigFlags() +flags.Input.Files = [] +for path in MyArgs.filesInput.split(','): + flags.Input.Files += glob(path) +flags.PhysVal.OutputFileName = MyArgs.outputFile + +from AthenaConfiguration.MainServicesConfig import MainServicesCfg +acc = MainServicesCfg(flags) +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +acc.merge(PoolReadCfg(flags)) + +flags.lock() + +#LRTMuons +#from LRTMuonPhysValMonitoring.LRTMuonPhysValConfig import PhysValLRTMuonCfg +#from PhysValMonitoring.PhysValMonitoringConfig import PhysValMonitoringCfg +#acc.merge(PhysValMonitoringCfg(flags, tools=[acc.popToolsAndMerge(PhysValLRTMuonCfg(flags))])) + + + + +acc.printConfig(withDetails=True) + +# Execute and finish +sc = acc.run(maxEvents=-1) + +# Success should be 0 +import sys +sys.exit(not sc.isSuccess()) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/LRTMuonPhysValMonitoringTool.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/LRTMuonPhysValMonitoringTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..fc16596b757f6d302b04a5dddeba66e1b53a9af2 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/LRTMuonPhysValMonitoringTool.cxx @@ -0,0 +1,1695 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +*/ + +// LRTMuonPhysValMonitoringTool.cxx +// Implementation file for class LRTMuonPhysValMonitoringTool +/////////////////////////////////////////////////////////////////// + +// PhysVal includes +#include "LRTMuonPhysValMonitoringTool.h" + + + +#include "GaudiKernel/IToolSvc.h" +#include "MuonHistUtils/MuonEnumDefs.h" + +#include "xAODBase/IParticleHelpers.h" +#include "xAODCore/ShallowCopy.h" +#include "xAODMuon/MuonAuxContainer.h" +#include "xAODMuon/MuonContainer.h" +#include "xAODMuon/SlowMuonAuxContainer.h" +#include "xAODMuon/SlowMuonContainer.h" +#include "xAODTrigMuon/L2CombinedMuonContainer.h" +#include "xAODTrigMuon/L2StandAloneMuonContainer.h" +#include "xAODTrigger/MuonRoI.h" +#include "xAODTrigger/MuonRoIContainer.h" + +#include "xAODTruth/TruthVertexAuxContainer.h" +#include "xAODTruth/TruthVertexContainer.h" +#include "FourMomUtils/xAODP4Helpers.h" +#include "TruthUtils/HepMCHelpers.h" + +#include "TString.h" +#include <cmath> +#include <limits> + + +namespace{ + using TrackLink = ElementLink<xAOD::TrackParticleContainer>; + using MuonLink = ElementLink<xAOD::MuonContainer>; + using MuonSegmentLink = ElementLink<xAOD::MuonSegmentContainer>; + using TruthLink = ElementLink<xAOD::TruthParticleContainer>; + + constexpr int comm_bit = (1<<xAOD::Muon::Commissioning); +} +using namespace xAOD::P4Helpers; + +namespace LRTMuonPhysValMonitoring { + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// + + // utilities + float getMatchingProbability(const xAOD::TrackParticle& trackParticle) { + float result(std::numeric_limits<float>::quiet_NaN()); + if (trackParticle.isAvailable<float>("truthMatchProbability")) { result = trackParticle.auxdata<float>("truthMatchProbability"); } + return result; + } + + // Constructors + //////////////// + + LRTMuonPhysValMonitoringTool::LRTMuonPhysValMonitoringTool(const std::string& type, const std::string& name, const IInterface* parent) : + ManagedMonitorToolBase(type, name, parent), + m_counterBits(), + m_muonItems(), + m_L1Seed() { + } + + // Athena algtool's Hooks + //////////////////////////// + StatusCode LRTMuonPhysValMonitoringTool::initialize() { + ATH_MSG_INFO("Initializing " << name() << "..."); + ATH_CHECK(ManagedMonitorToolBase::initialize()); + + if (!m_slowMuonsName.empty()) m_muonsName = m_slowMuonsName; + + for (unsigned int i = 0; i < m_selectHLTMuonItems.size(); i++) { + if (m_selectHLTMuonItems[i][0] == "" || m_selectHLTMuonItems[i][1] == "") continue; + m_muonItems.emplace_back(m_selectHLTMuonItems[i][0]); + m_L1Seed.emplace_back(m_selectHLTMuonItems[i][1]); + } + + // setup flags + if (m_doTrigMuonValidation == false) { + m_doTrigMuonL1Validation = false; + m_doTrigMuonL2Validation = false; + m_doTrigMuonEFValidation = false; + } + ATH_CHECK(m_trigDec.retrieve(DisableTool{!m_doTrigMuonValidation})); + + ATH_CHECK(m_eventInfo.initialize()); + ATH_CHECK(m_muonSelectionTool.retrieve()); + ATH_CHECK(m_trackSelector.retrieve()); + ATH_CHECK(m_isoTool.retrieve()); + + return StatusCode::SUCCESS; + } + StatusCode LRTMuonPhysValMonitoringTool::bookHistograms() { + ATH_MSG_INFO("Booking hists " << name() << "..."); + + if (m_selectMuonWPs.size() == 1 && m_selectMuonWPs[0] < 0) m_selectMuonWPs.clear(); + + if (m_selectMuonAuthors.size() == 1 && m_selectMuonAuthors[0] == 0) m_selectMuonAuthors.clear(); + + static const std::map<int,std::string> theMuonCategories = { + {ALL, "All"}, + {PROMPT, "Prompt"}, + {INFLIGHT, "InFlight"}, + {NONISO, "NonIsolated"}, + {REST, "Rest"} + }; + + for (const auto& category : m_selectMuonCategories) m_selectMuonCategoriesStr.emplace_back(theMuonCategories.at(category)); + + // no such muons in case of SlowMuon reco + bool separateSAFMuons = m_slowMuonsName.empty(); + + std::string muonContainerName = m_muonsName; + for (const auto& category : m_selectMuonCategoriesStr) { + std::string categoryPath = m_muonsName + "/" + category + "/"; + m_muonValidationPlots.emplace_back(std::make_unique<MuonValidationPlots>( + nullptr, categoryPath, m_selectMuonWPs, m_selectMuonAuthors, m_isData, + (category == theMuonCategories.at(ALL) ? false : m_doBinnedResolutionPlots.value()), separateSAFMuons, m_doMuonTree)); + if (!m_slowMuonsName.empty()) m_slowMuonValidationPlots.emplace_back(std::make_unique<SlowMuonValidationPlots>(nullptr, categoryPath, m_isData)); + if (m_doTrigMuonValidation) { + if (category == "All") { + m_TriggerMuonValidationPlots.emplace_back(std::make_unique<TriggerMuonValidationPlots>( + nullptr, categoryPath, m_selectMuonAuthors, m_isData, m_doTrigMuonL1Validation, m_doTrigMuonL2Validation, + m_doTrigMuonEFValidation, m_selectHLTMuonItems, m_L1MuonItems)); + } + } + if (!m_muonTracksName.empty()) { + m_muonMSTrackValidationPlots.emplace_back(std::make_unique<MuonTrackValidationPlots>(nullptr, categoryPath, "MSTrackParticles", m_isData)); + if (!m_isData) + m_oUnmatchedRecoMuonTrackPlots = std::make_unique<Muon::RecoMuonTrackPlotOrganizer>(nullptr, muonContainerName + "/UnmatchedRecoMuonTracks/"); + } + if (!m_muonExtrapolatedTracksName.empty()) + m_muonMETrackValidationPlots.emplace_back(std::make_unique<MuonTrackValidationPlots>(nullptr, categoryPath, "METrackParticles", m_isData)); + if (!m_muonMSOnlyExtrapolatedTracksName.empty()) + m_muonMSOnlyMETrackValidationPlots.emplace_back( + std::make_unique<MuonTrackValidationPlots>(nullptr, categoryPath, "MSOnlyMETrackParticles", m_isData)); + + if (!m_tracksName.empty()) { + m_muonIDTrackValidationPlots.emplace_back(std::make_unique<MuonTrackValidationPlots>(nullptr, categoryPath, "IDTrackParticles", m_isData)); + m_muonIDSelectedTrackValidationPlots.emplace_back( + std::make_unique<MuonTrackValidationPlots>(nullptr, categoryPath, "IDSelectedTrackParticles", m_isData)); + } + if (!m_fwdtracksName.empty()) + m_muonIDForwardTrackValidationPlots.emplace_back( + std::make_unique<MuonTrackValidationPlots>(nullptr, categoryPath, "IDForwardTrackParticles", m_isData)); + + if (!m_muonSegmentsName.empty()) { + if (category != theMuonCategories.at(ALL)) continue; // cannot identify the truth origin of segments... + m_muonSegmentValidationPlots.emplace_back(std::make_unique<MuonSegmentValidationPlots>(nullptr, categoryPath, m_isData)); + if (!m_isData) + m_oUnmatchedRecoMuonSegmentPlots.reset( + new Muon::MuonSegmentPlots(nullptr, Form("%s/UnmatchedRecoMuonSegments/", muonContainerName.c_str()))); + } + } + + if (!m_isData) { + m_oUnmatchedRecoMuonPlots = std::make_unique<Muon::RecoMuonPlotOrganizer>(nullptr, muonContainerName +"/UnmatchedRecoMuons/"); + m_oUnmatchedTruthMuonPlots = std::make_unique<Muon::TruthMuonPlotOrganizer>(nullptr, muonContainerName +"/UnmatchedTruthMuons/"); + } + + for (const auto& plots : m_muonValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_slowMuonValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_TriggerMuonValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_muonIDTrackValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_muonIDSelectedTrackValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_muonIDForwardTrackValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_muonMSTrackValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_muonMETrackValidationPlots) bookValidationPlots(*plots).ignore(); + for (const auto& plots : m_muonMSOnlyMETrackValidationPlots) bookValidationPlots(*plots).ignore(); + if (!m_isData) { + bookValidationPlots(*m_oUnmatchedRecoMuonPlots).ignore(); + bookValidationPlots(*m_oUnmatchedTruthMuonPlots).ignore(); + if (m_oUnmatchedRecoMuonTrackPlots) bookValidationPlots(*m_oUnmatchedRecoMuonTrackPlots).ignore(); + for (const auto& plots : m_muonSegmentValidationPlots) bookValidationPlots(*plots).ignore(); + if (m_oUnmatchedRecoMuonSegmentPlots) bookValidationPlots(*m_oUnmatchedRecoMuonSegmentPlots).ignore(); + } + // book overview hists + m_h_overview_Z_mass = new TH1F(Form("%s_Overview_Z_mass", muonContainerName.c_str()), "", 20, 76, 106); + ATH_CHECK(regHist(m_h_overview_Z_mass, Form("%s/Overview", muonContainerName.c_str()), all)); + m_h_overview_Z_mass_ME = new TH1F(Form("%s_Overview_Z_mass_ME", muonContainerName.c_str()), "", 20, 76, 106); + ATH_CHECK(regHist(m_h_overview_Z_mass_ME, Form("%s/Overview", muonContainerName.c_str()), all)); + m_h_overview_Z_mass_ID = new TH1F(Form("%s_Overview_Z_mass_ID", muonContainerName.c_str()), "", 20, 76, 106); + ATH_CHECK(regHist(m_h_overview_Z_mass_ID, Form("%s/Overview", muonContainerName.c_str()), all)); + + m_h_overview_nObjects.clear(); + m_h_overview_nObjects.emplace_back(new TH1F(Form("%s_Overview_N_perevent_truth_muons", muonContainerName.c_str()), + "Number of truth Muons per event", 20, -0.5, 19.5)); + m_h_overview_nObjects.emplace_back( + new TH1F(Form("%s_Overview_N_perevent_muons", muonContainerName.c_str()), "Number of Muons per event", 20, -0.5, 19.5)); + m_h_overview_nObjects.emplace_back( + new TH1F(Form("%s_Overview_N_perevent_tracks", muonContainerName.c_str()), "Number of Tracks per event", 50, -0.5, 49.5)); + m_h_overview_nObjects.emplace_back(new TH1F(Form("%s_Overview_N_perevent_truth_segments", muonContainerName.c_str()), + "Number of truth Segments per event", 200, -0.5, 199.5)); + m_h_overview_nObjects.emplace_back( + new TH1F(Form("%s_Overview_N_perevent_segments", muonContainerName.c_str()), "Number of Segments per event", 200, -0.5, 199.5)); + for (const auto& hist : m_h_overview_nObjects) { + if (hist) ATH_CHECK(regHist(hist, Form("%s/Overview", muonContainerName.c_str()), all)); + } + + m_h_overview_reco_category = + new TH1F(Form("%s_Overview_reco_category", muonContainerName.c_str()), "", 4, 0, 4); // prompt/in-flight/non-isolated/other + for (int i = 1; i < 4; i++) { // skip 'All' + m_h_overview_reco_category->GetXaxis()->SetBinLabel(i, theMuonCategories.at(i).c_str()); + } + m_h_overview_reco_category->GetXaxis()->SetBinLabel(4, "Other"); // of some other origin or fakes + ATH_CHECK(regHist(m_h_overview_reco_category, Form("%s/Overview", muonContainerName.c_str()), all)); + + int nAuth = xAOD::Muon::NumberOfMuonAuthors; + for (int i = 1; i < 4; i++) { + m_h_overview_reco_authors.emplace_back(new TH1F((m_muonsName + "_" + theMuonCategories.at(i) + "_reco_authors").c_str(), + (muonContainerName + "_" + theMuonCategories.at(i) + "_reco_authors").c_str(), + nAuth + 1, -0.5, nAuth + 0.5)); + } + m_h_overview_reco_authors.emplace_back(new TH1F((m_muonsName + "_Overview_Other_reco_authors").c_str(), + (muonContainerName + "_Other_reco_authors").c_str(), nAuth + 1, -0.5, nAuth + 0.5)); + + for (const auto& hist : m_h_overview_reco_authors) { + if (hist) ATH_CHECK(regHist(hist, Form("%s/Overview", muonContainerName.c_str()), all)); + } + + return StatusCode::SUCCESS; + }//bookHistograms + + StatusCode LRTMuonPhysValMonitoringTool::bookValidationPlots(PlotBase& valPlots) { + valPlots.initialize(); + std::vector<HistData> hists = valPlots.retrieveBookedHistograms(); + + for (auto& hist : hists) { + TString sHistName = hist.first->GetName(); + ATH_MSG_VERBOSE("Initializing " << hist.first << " " << sHistName << " " << hist.second << "..."); + + // check for histograms that are useless and skip regHist: + if (sHistName.Contains("momentumPulls")) { + if (sHistName.Contains(Muon::EnumDefs::toString(xAOD::Muon::MuidSA))) continue; // empty for standalone muons + if (!(sHistName.Contains("Prompt") && (sHistName.Contains("AllMuons") || sHistName.Contains("SiAssocForward")))) + continue; // don't need binned eloss plots for separate muon types, keep only for Prompt AllMuons + } + if ((sHistName.Contains("resolution") || sHistName.Contains("pulls")) && !sHistName.Contains("Prompt")) + continue; // don't need resolution plots except for prompt muons + if (sHistName.Contains("trigger") && sHistName.Contains("wrt") && sHistName.Contains("Features")) continue; + modifyHistogram(hist.first); + ATH_CHECK(regHist(hist.first, hist.second, all)); + } + + // register trees + std::vector<TreeData> trees = valPlots.retrieveBookedTrees(); + for (auto& tree : trees) { + std::string sTreeName = tree.first->GetName(); + ATH_MSG_VERBOSE("Initializing " << tree.first << " " << sTreeName << " " << tree.second << "..."); + ATH_CHECK(regTree(tree.first, tree.second, all)); + } + + return StatusCode::SUCCESS; + } + + StatusCode LRTMuonPhysValMonitoringTool::fillHistograms() { + ATH_MSG_DEBUG("Filling hists " << name() << "..."); + m_vMatchedTruthMuons.clear(); + m_vMatchedMuons.clear(); + m_vMatchedSlowMuons.clear(); + m_vMatchedMuonTracks.clear(); + m_vMatchedMuonSegments.clear(); + m_vZmumuIDTracks.clear(); + m_vZmumuMETracks.clear(); + m_vZmumuMuons.clear(); + m_vEFMuons.clear(); + m_vEFMuonsSelected.clear(); + m_vL2SAMuons.clear(); + m_vL2SAMuonsSelected.clear(); + m_vL2CBMuons.clear(); + m_vL2CBMuonsSelected.clear(); + m_vRecoMuons.clear(); + m_vRecoMuons_EffDen.clear(); + m_vRecoMuons_EffDen_CB.clear(); + m_vRecoMuons_EffDen_MS.clear(); + + SG::ReadHandle<xAOD::EventInfo> eventInfoHandle(m_eventInfo); + if (!eventInfoHandle.isValid()) { + ATH_MSG_WARNING("Could not retrieve EventInfo, returning"); + return StatusCode::SUCCESS; + } + const xAOD::EventInfo* eventInfo = eventInfoHandle.cptr(); + m_isData = !eventInfo->eventType(xAOD::EventInfo::IS_SIMULATION); + float beamSpotWeight = eventInfo->beamSpotWeight(); + + const xAOD::TruthParticleContainer* TruthMuons(nullptr); + + if (!m_isData) { + TruthMuons = evtStore()->tryConstRetrieve<xAOD::TruthParticleContainer>(m_muonsTruthName); + if (!TruthMuons) { + ATH_MSG_ERROR("Couldn't retrieve TruthMuons container with key: " << m_muonsTruthName); + return StatusCode::FAILURE; + } + ATH_MSG_DEBUG("Retrieved truth muons " << TruthMuons->size()); + m_h_overview_nObjects[0]->Fill(TruthMuons->size(), beamSpotWeight); + } + + const xAOD::MuonContainer* Muons = nullptr; + const xAOD::SlowMuonContainer* SlowMuons = nullptr; + if (!m_slowMuonsName.empty()) { + SlowMuons = getContainer<xAOD::SlowMuonContainer>(m_slowMuonsName); + if (!SlowMuons) { + ATH_MSG_WARNING("Couldn't retrieve SlowMuons container with key: " << m_slowMuonsName); + return StatusCode::SUCCESS; + } + ATH_MSG_DEBUG("Retrieved slow muons " << SlowMuons->size()); + m_h_overview_nObjects[1]->Fill(SlowMuons->size(), beamSpotWeight); + } else { + Muons = getContainer<xAOD::MuonContainer>(m_muonsName); + if (!Muons) { return StatusCode::SUCCESS; } + ATH_MSG_DEBUG("Retrieved muons " << Muons->size()); + m_h_overview_nObjects[1]->Fill(Muons->size(), beamSpotWeight); + } + + /////////////////////////////////////////////////////////////////////// @@@ + // @@@ Temp hack to get the MuonSpectrometerTrackParticle (@MS Entry, not extrapolated), needed for eloss plots + // Remove when the link to the real MuonSpectrometerTrackParticle appears in the xAOD muon + if (evtStore()->contains<xAOD::TrackParticleContainer>("MuonSpectrometerTrackParticles")) { + m_MSTracks = getContainer<xAOD::TrackParticleContainer>("MuonSpectrometerTrackParticles"); + if (!m_MSTracks) { + ATH_MSG_WARNING("Couldn't retrieve MS Tracks container"); + return StatusCode::SUCCESS; + } else + ATH_MSG_DEBUG("Retrieved muon tracks " << m_MSTracks->size()); + } else + ATH_MSG_DEBUG("Couldn't find MS Tracks container"); + + /////////////////////////////////////////////////////////////////////// @@@ + + // Do resonance selection + std::vector<std::pair<const xAOD::Muon*, const xAOD::Muon*> > pairs; + if (Muons) { + // Use iterator loop to avoid double counting + for (xAOD::MuonContainer::const_iterator mu1_itr = Muons->begin(); mu1_itr != Muons->end(); ++mu1_itr) { + const xAOD::Muon* mu1 = (*mu1_itr); + if (!m_selectComissioning && mu1->allAuthors() & comm_bit) continue; + for (xAOD::MuonContainer::const_iterator mu2_itr = Muons->begin(); mu2_itr != mu1_itr; ++mu2_itr) { + const xAOD::Muon* mu2 = (*mu2_itr); + if (!m_selectComissioning && mu2->allAuthors() & comm_bit) continue; + if (mu1->charge() * mu2->charge() >= 0) continue; + pairs.emplace_back(std::make_pair(mu1, mu2)); + } + } + } + + float dMmin {1e10}, mZ{0.}; + for (std::pair<const xAOD::Muon*, const xAOD::Muon*>& x : pairs) { + // select best Z + const TLorentzVector mu1{x.first->p4()}, mu2{x.second->p4()}; + const float M = (mu1 + mu2).M(); + if (M < 66000. || M > 116000.) continue; + + // choose the Z candidate closest to the Z pole - if multiple exist + float dM = std::abs(M - 91187.); + if (dM > dMmin) continue; + dMmin = dM; + mZ = M; + + m_vZmumuMuons.clear(); + m_vZmumuMuons.emplace_back(x.first); + m_vZmumuMuons.emplace_back(x.second); + } + + if (m_vZmumuMuons.size() == 2) { + m_h_overview_Z_mass->Fill(mZ / 1000., beamSpotWeight); + + const xAOD::TrackParticle* metr1 = m_vZmumuMuons[0]->trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle); + const xAOD::TrackParticle* metr2 = m_vZmumuMuons[1]->trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle); + if (metr1 && metr2) { + const TLorentzVector mu1ME{metr1->p4()}, mu2ME{metr2->p4()}; + m_h_overview_Z_mass_ME->Fill((mu1ME + mu2ME).M() / 1000., beamSpotWeight); + if (m_isData) { + m_vZmumuMETracks.clear(); + m_vZmumuMETracks.emplace_back(metr1); + m_vZmumuMETracks.emplace_back(metr2); + } + } + + const xAOD::TrackParticle* tr1 = m_vZmumuMuons[0]->trackParticle(xAOD::Muon::InnerDetectorTrackParticle); + const xAOD::TrackParticle* tr2 = m_vZmumuMuons[1]->trackParticle(xAOD::Muon::InnerDetectorTrackParticle); + if (tr1 && tr2) { + const TLorentzVector mu1ID{tr1->p4()}, mu2ID{tr2->p4()}; + m_h_overview_Z_mass_ID->Fill((mu1ID + mu2ID).M() / 1000., beamSpotWeight); + if (m_isData) { + m_vZmumuIDTracks.clear(); + m_vZmumuIDTracks.emplace_back(tr1); + m_vZmumuIDTracks.emplace_back(tr2); + } + } + } + + if (!m_isData) { + for (const auto& truthMu : *TruthMuons) handleTruthMuon(truthMu, beamSpotWeight); + } + + if (SlowMuons) { + for (const auto& smu : *SlowMuons) { + if (!smu) continue; + const MuonLink link = smu->muonLink(); + if (!link.isValid()) continue; + handleMuon(*link, smu, beamSpotWeight); + } + } else if (Muons) { + for (const auto& mu : *Muons) handleMuon(mu, nullptr, beamSpotWeight); + } + + if (m_doMuonTree) { handleMuonTrees(eventInfo, m_isData); } + + if (!m_tracksName.empty()) { + auto IDTracks = getContainer<xAOD::TrackParticleContainer>(m_tracksName); + if (!IDTracks) return StatusCode::FAILURE; + ATH_MSG_DEBUG("handling " << IDTracks->size() << " " << m_tracksName); + for (const auto& tp : *IDTracks) handleMuonTrack(tp, xAOD::Muon::InnerDetectorTrackParticle, beamSpotWeight); + } + if (!m_fwdtracksName.empty()) { + auto FwdIDTracks = getContainer<xAOD::TrackParticleContainer>(m_fwdtracksName); + if (!FwdIDTracks) return StatusCode::FAILURE; + ATH_MSG_DEBUG("handling " << FwdIDTracks->size() << " " << m_fwdtracksName); + for (const auto& tp : *FwdIDTracks) handleMuonTrack(tp, xAOD::Muon::InnerDetectorTrackParticle, beamSpotWeight); + } + if (!m_muonTracksName.empty()) { + auto MuonTracks = getContainer<xAOD::TrackParticleContainer>(m_muonTracksName); + if (!MuonTracks) return StatusCode::FAILURE; + ATH_MSG_DEBUG("handling " << MuonTracks->size() << " " << m_muonTracksName); + m_h_overview_nObjects[2]->Fill(MuonTracks->size(), beamSpotWeight); + for (const auto& tp : *MuonTracks) handleMuonTrack(tp, xAOD::Muon::MuonSpectrometerTrackParticle, beamSpotWeight); + } + if (!m_muonExtrapolatedTracksName.empty()) { + auto MuonExtrapolatedTracks = getContainer<xAOD::TrackParticleContainer>(m_muonExtrapolatedTracksName); + if (!MuonExtrapolatedTracks) return StatusCode::FAILURE; + ATH_MSG_DEBUG("handling " << MuonExtrapolatedTracks->size() << " " << m_muonExtrapolatedTracksName); + for (const auto& tp : *MuonExtrapolatedTracks) + handleMuonTrack(tp, xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle, beamSpotWeight); + } + + if (!m_muonMSOnlyExtrapolatedTracksName.empty() && + evtStore()->contains<xAOD::TrackParticleContainer>(m_muonMSOnlyExtrapolatedTracksName)) { + auto MSOnlyMuonExtrapolatedTracks = getContainer<xAOD::TrackParticleContainer>(m_muonMSOnlyExtrapolatedTracksName); + if (!MSOnlyMuonExtrapolatedTracks) return StatusCode::FAILURE; + ATH_MSG_DEBUG("handling " << MSOnlyMuonExtrapolatedTracks->size() << " " << m_muonMSOnlyExtrapolatedTracksName); + for (const auto& tp : *MSOnlyMuonExtrapolatedTracks) + handleMuonTrack(tp, xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle, beamSpotWeight); + } + + if (!m_muonSegmentsName.empty()) { + const xAOD::MuonSegmentContainer* TruthMuonSegments(nullptr); + if (!m_isData) { + TruthMuonSegments = getContainer<xAOD::MuonSegmentContainer>(m_muonSegmentsTruthName); + if (!TruthMuonSegments) { return StatusCode::SUCCESS; } + m_h_overview_nObjects[3]->Fill(TruthMuonSegments->size(), beamSpotWeight); + ATH_MSG_DEBUG("handling " << TruthMuonSegments->size() << " " << m_muonSegmentsTruthName); + for (const auto& truthMuSeg : *TruthMuonSegments) handleTruthMuonSegment(truthMuSeg, TruthMuons, beamSpotWeight); + } + + const xAOD::MuonSegmentContainer* MuonSegments = getContainer<xAOD::MuonSegmentContainer>(m_muonSegmentsName); + if (!MuonSegments) { return StatusCode::SUCCESS; } + m_h_overview_nObjects[4]->Fill(MuonSegments->size(), beamSpotWeight); + ATH_MSG_DEBUG("handling " << MuonSegments->size() << " " << m_muonSegmentsName); + for (const auto& muSeg : *MuonSegments) handleMuonSegment(muSeg, beamSpotWeight); + } + + //@@@@@@@@@@@@@@@@ TRIGGER MONITORING IMPLEMENTATION @@@@@@@@@@@@@@@@@ + if (m_doTrigMuonValidation) { + auto chainGroups = m_trigDec->getChainGroup("HLT_.*mu.*"); + for (auto& trig : chainGroups->getListOfTriggers()) { + if (m_trigDec->isPassed(trig, TrigDefs::EF_passedRaw)) { + ATH_MSG_DEBUG("Chain " << trig << " is passed: YES"); + } else + ATH_MSG_DEBUG("Chain " << trig << " is passed: NO"); + } + auto L1chainGroups = m_trigDec->getChainGroup("L1_MU.*"); + for (auto& L1trig : L1chainGroups->getListOfTriggers()) { + if (m_trigDec->isPassed(L1trig, TrigDefs::EF_passedRaw)) + ATH_MSG_DEBUG("Chain " << L1trig << " is passed: YES"); + else + ATH_MSG_DEBUG("Chain " << L1trig << " is passed: NO"); + } + for (auto mu : m_vRecoMuons) { + if (passesAcceptanceCuts(mu) && std::abs(mu->eta()) < 2.4) { + if (mu->author() == 1) { + m_vRecoMuons_EffDen_CB.emplace_back(mu); + ATH_MSG_DEBUG("##### m_vRecoMuons_EffDen_CB pt:" << mu->pt() << " phi:" << mu->phi() << " eta:" << mu->eta()); + } else if (mu->author() == 5) { + m_vRecoMuons_EffDen_MS.emplace_back(mu); + ATH_MSG_DEBUG("##### m_vRecoMuons_EffDen_MS pt:" << mu->pt() << " phi:" << mu->phi() << " eta:" << mu->eta()); + } + } + } + + //@@@@@ L1 @@@@@ + if (m_doTrigMuonL1Validation) { + const xAOD::MuonRoIContainer* L1TrigMuons = getContainer<xAOD::MuonRoIContainer>(m_muonL1TrigName); + if (!L1TrigMuons) { return StatusCode::SUCCESS; } + ATH_MSG_DEBUG("Retrieved L1 triggered muons " << L1TrigMuons->size()); + for (const auto& TrigL1mu : *L1TrigMuons) handleMuonL1Trigger(TrigL1mu); + } + + //@@@@@ L2 @@@@@ + if (m_doTrigMuonL2Validation) { + //@@@@@ L2SA @@@@@ + const xAOD::L2StandAloneMuonContainer* L2SAMuons = getContainer<xAOD::L2StandAloneMuonContainer>(m_muonL2SAName); + if (!L2SAMuons) { return StatusCode::SUCCESS; } + ATH_MSG_DEBUG("Retrieved L2 StandAlone triggered muons " << L2SAMuons->size()); + if (L2SAMuons->size() != 0) { + for (const auto& L2SAmu : *L2SAMuons) { + ATH_MSG_DEBUG("Muon L2SA Trigger: pt " << L2SAmu->pt() << " phi " << L2SAmu->phi() << " eta " << L2SAmu->eta() + << " roiWord " << L2SAmu->roiWord() << " sAddress " << L2SAmu->sAddress()); + m_vL2SAMuons.emplace_back(L2SAmu); + } + for (const auto& mu : m_vL2SAMuons) { + if (mu->pt() != 0.) { + m_vL2SAMuonsSelected.emplace_back(mu); + break; + } + } + for (unsigned int i = 0; i < m_vL2SAMuons.size(); i++) { + unsigned int cont = 0; + for (unsigned int j = 0; j < m_vL2SAMuonsSelected.size(); j++) { + if (((m_vL2SAMuons.at(i)->pt()) != 0.) && ((deltaR(m_vL2SAMuonsSelected.at(j), m_vL2SAMuons.at(i))) > 0.1)) + cont++; + if (cont == m_vL2SAMuonsSelected.size()) { + m_vL2SAMuonsSelected.emplace_back(m_vL2SAMuons.at(i)); + break; + } + } + } + for (unsigned int i = 0; i < m_vL2SAMuonsSelected.size(); i++) { handleMuonL2Trigger(m_vL2SAMuonsSelected.at(i)); } + L2SATriggerResolution(); + } + for (const auto& muonItem : m_muonItems) { + std::vector<Trig::Feature<xAOD::L2StandAloneMuonContainer> > vec_muons; + TString muonItem_str = (TString)muonItem; + if (muonItem_str.Contains("_OR_")) { + muonItem_str.ReplaceAll("_OR_", " "); + TString delim = " "; + std::vector<TString> v_subchains; + SplitString(muonItem_str, delim, v_subchains); + for (int i = 0; i < (int)v_subchains.size(); i++) { + Trig::FeatureContainer fc1 = m_trigDec->features((std::string)v_subchains.at(i)); + std::vector<Trig::Feature<xAOD::L2StandAloneMuonContainer> > vec_muons_1 = + fc1.get<xAOD::L2StandAloneMuonContainer>(); + for (const auto& mufeat : vec_muons_1) { vec_muons.emplace_back(mufeat); } + } + } else { + Trig::FeatureContainer fc = m_trigDec->features(muonItem); + vec_muons = fc.get<xAOD::L2StandAloneMuonContainer>(); + } + ATH_MSG_DEBUG("Size of vector Trig::Feature<xAOD::L2StandAloneMuonContainer> for chain " << muonItem << " = " + << vec_muons.size()); + for (const auto& mufeat : vec_muons) { + ATH_MSG_DEBUG(muonItem << " vec_muons.size() = " << vec_muons.size() + << " mufeat.cptr()->size() = " << mufeat.cptr()->size()); + for (unsigned int i = 0; i < mufeat.cptr()->size(); i++) { + ATH_MSG_DEBUG("#####" << muonItem << " L2SA feature pt: " << (*mufeat.cptr())[i]->pt() + << " eta: " << (*mufeat.cptr())[i]->eta() << " phi: " << (*mufeat.cptr())[i]->phi()); + } + } + } + + //@@@@@ L2CB @@@@@ + const xAOD::L2CombinedMuonContainer* L2CBMuons = getContainer<xAOD::L2CombinedMuonContainer>(m_muonL2CBName); + if (!L2CBMuons) { return StatusCode::SUCCESS; } + ATH_MSG_DEBUG("Retrieved L2 Combined triggered muons " << L2CBMuons->size()); + if (L2CBMuons->size() != 0) { + for (const auto& L2CBmu : *L2CBMuons) { + ATH_MSG_DEBUG("Muon L2CB Trigger: pt " << L2CBmu->pt() << " phi " << L2CBmu->phi() << " eta " << L2CBmu->eta()); + m_vL2CBMuons.emplace_back(L2CBmu); + } + for (unsigned int i = 0; i < m_vL2CBMuons.size(); i++) { + if ((m_vL2CBMuons.at(i)->pt()) != 0.) { + m_vL2CBMuonsSelected.emplace_back(m_vL2CBMuons.at(i)); + break; + } + } + for (unsigned int i = 0; i < m_vL2CBMuons.size(); i++) { + unsigned int cont = 0; + for (unsigned int j = 0; j < m_vL2CBMuonsSelected.size(); j++) { + if (((m_vL2CBMuons.at(i)->pt()) != 0.) && ((deltaR(m_vL2CBMuonsSelected.at(j), m_vL2CBMuons.at(i))) > 0.1)) + cont++; + if (cont == m_vL2CBMuonsSelected.size()) { + m_vL2CBMuonsSelected.emplace_back(m_vL2CBMuons.at(i)); + break; + } + } + } + for (unsigned int i = 0; i < m_vL2CBMuonsSelected.size(); i++) { handleMuonL2Trigger(m_vL2CBMuonsSelected.at(i)); } + L2CBTriggerResolution(); + } + for (const auto& muonItem : m_muonItems) { + std::vector<Trig::Feature<xAOD::L2CombinedMuonContainer> > vec_muons; + TString muonItem_str = (TString)muonItem; + if (muonItem_str.Contains("_OR_")) { + muonItem_str.ReplaceAll("_OR_", " "); + TString delim = " "; + std::vector<TString> v_subchains; + SplitString(muonItem_str, delim, v_subchains); + for (int i = 0; i < (int)v_subchains.size(); i++) { + Trig::FeatureContainer fc1 = m_trigDec->features((std::string)v_subchains.at(i)); + std::vector<Trig::Feature<xAOD::L2CombinedMuonContainer> > vec_muons_1 = + fc1.get<xAOD::L2CombinedMuonContainer>(); + for (const auto& mufeat : vec_muons_1) { vec_muons.emplace_back(mufeat); } + } + } else { + Trig::FeatureContainer fc = m_trigDec->features(muonItem); + vec_muons = fc.get<xAOD::L2CombinedMuonContainer>(); + } + ATH_MSG_DEBUG("Size of vector Trig::Feature<xAOD::L2CombinedMuonContainer> for chain " << muonItem << " = " + << vec_muons.size()); + for (const auto& mufeat : vec_muons) { + ATH_MSG_DEBUG(muonItem << " vec_muons.size() = " << vec_muons.size() + << " mufeat.cptr()->size() = " << mufeat.cptr()->size()); + for (unsigned int i = 0; i < mufeat.cptr()->size(); i++) { + ATH_MSG_DEBUG("#####" << muonItem << " L2CB feature pt: " << (*mufeat.cptr())[i]->pt() + << " eta: " << (*mufeat.cptr())[i]->eta() << " phi: " << (*mufeat.cptr())[i]->phi()); + } + } + } + } // close if(m_doTrigMuonL2Validation) + + //@@@@@ EF @@@@@ + if (m_doTrigMuonEFValidation) { + const xAOD::MuonContainer* EFCombTrigMuons = getContainer<xAOD::MuonContainer>(m_muonEFCombTrigName); + const xAOD::MuonRoIContainer* L1TrigMuons = getContainer<xAOD::MuonRoIContainer>(m_muonL1TrigName); + if (!EFCombTrigMuons) { return StatusCode::SUCCESS; } + ATH_MSG_DEBUG("Retrieved EF triggered muons " << EFCombTrigMuons->size()); + if (EFCombTrigMuons->size() != 0) { + for (const auto& Trigmu : *EFCombTrigMuons) { + ATH_MSG_DEBUG("Muon EF Trigger: pt " << Trigmu->pt() << " phi " << Trigmu->phi() << " eta " << Trigmu->eta() + << " author" << Trigmu->author()); + m_vEFMuons.emplace_back(Trigmu); + } + m_vEFMuonsSelected.emplace_back(m_vEFMuons.at(0)); + for (unsigned int i = 0; i < m_vEFMuons.size(); i++) { + unsigned int cont = 0; + for (unsigned int j = 0; j < m_vEFMuonsSelected.size(); j++) { + if (((deltaR(m_vEFMuonsSelected.at(j), m_vEFMuons.at(i))) > 0.1) || + ((m_vEFMuons.at(i)->author() - m_vEFMuonsSelected.at(j)->author()) != 0)) + cont++; + if (cont == m_vEFMuonsSelected.size()) { + m_vEFMuonsSelected.emplace_back(m_vEFMuons.at(i)); + break; + } + } + } + for (unsigned int i = 0; i < m_vEFMuonsSelected.size(); i++) { handleMuonTrigger(m_vEFMuonsSelected.at(i)); } + EFTriggerResolution(); + } + if (!m_isData) { + for (const auto& truthMu : *TruthMuons) { + ATH_MSG_DEBUG("TRUTH:: pt=" << truthMu->pt() << " eta=" << truthMu->eta() << " phi=" << truthMu->phi()); + } + } + // handleMuonTrigger_ResoWRTTruth(m_vEFMuonsSelected,) + //@@@@@ chains efficiency @@@@@ + for (const auto& muonItem : m_muonItems) { + m_vRecoMuons_EffDen = m_vRecoMuons_EffDen_CB; + m_SelectedAuthor = 1; + if ((muonItem.find("msonly") != std::string::npos)) { + m_vRecoMuons_EffDen = m_vRecoMuons_EffDen_MS; + m_SelectedAuthor = 5; + } + std::vector<Trig::Feature<xAOD::MuonContainer> > vec_muons; + TString muonItem_str = (TString)muonItem; + if (muonItem_str.Contains("_OR_")) { + muonItem_str.ReplaceAll("_OR_", " "); + TString delim = " "; + std::vector<TString> v_subchains; + SplitString(muonItem_str, delim, v_subchains); + for (int i = 0; i < (int)v_subchains.size(); i++) { + Trig::FeatureContainer fc1 = m_trigDec->features((std::string)v_subchains.at(i)); + std::vector<Trig::Feature<xAOD::MuonContainer> > vec_muons_1 = fc1.get<xAOD::MuonContainer>(); + for (const auto& mufeat : vec_muons_1) { vec_muons.emplace_back(mufeat); } + } + } else { + Trig::FeatureContainer fc = m_trigDec->features(muonItem); + vec_muons = fc.get<xAOD::MuonContainer>(); + } + ATH_MSG_DEBUG("Size of vector Trig::Feature<xAOD::MuonContainer> for chain " << muonItem << " = " << vec_muons.size()); + for (const auto& mufeat : vec_muons) { + ATH_MSG_DEBUG(muonItem << " vec_muons.size() = " << vec_muons.size() + << " mufeat.cptr()->size() = " << mufeat.cptr()->size()); + for (unsigned int i = 0; i < mufeat.cptr()->size(); i++) { + ATH_MSG_DEBUG("#####" << muonItem << " EF feature pt: " << (*mufeat.cptr())[i]->pt() + << " eta: " << (*mufeat.cptr())[i]->eta() << " phi: " << (*mufeat.cptr())[i]->phi() + << " author: " << (*mufeat.cptr())[i]->author()); + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + if (((*mufeat.cptr())[i]->author()) == m_SelectedAuthor) + m_TriggerMuonValidationPlots[j]->fillFeatPlots(*(*mufeat.cptr())[i], muonItem); + } // if categ=ALL + } // categories + } // mufeat.cptr + } // mufeat + for (unsigned int k = 0; k < m_vRecoMuons_EffDen.size(); k++) { + bool break_flag = false; + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + m_TriggerMuonValidationPlots[j]->fillDenEff(*m_vRecoMuons_EffDen.at(k), muonItem); + } + } + for (const auto& mufeat : vec_muons) { + for (unsigned int i = 0; i < mufeat.cptr()->size(); i++) { + if ((((*mufeat.cptr())[i]->author()) == m_SelectedAuthor) && + (deltaR((*mufeat.cptr())[i], m_vRecoMuons_EffDen.at(k)) < 0.1)) { + break_flag = true; + ATH_MSG_DEBUG(" $$$ match Reco_EffDen " + << muonItem << " pt: " << m_vRecoMuons_EffDen.at(k)->pt() << " eta: " + << m_vRecoMuons_EffDen.at(k)->eta() << " phi: " << m_vRecoMuons_EffDen.at(k)->phi() + << " author: " << m_vRecoMuons_EffDen.at(k)->author()); + ATH_MSG_DEBUG(" $$$ match EF MuidCo feature " + << muonItem << " pt: " << (*mufeat.cptr())[i]->pt() + << " eta: " << (*mufeat.cptr())[i]->eta() << " phi: " << (*mufeat.cptr())[i]->phi() + << " author: " << (*mufeat.cptr())[i]->author() << " rel_p " + << (std::abs(((*mufeat.cptr())[i]->pt() - m_vRecoMuons_EffDen.at(k)->pt()) / + (m_vRecoMuons_EffDen.at(k)->pt())))); + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + m_TriggerMuonValidationPlots[j]->fillNumEff(*m_vRecoMuons_EffDen.at(k), muonItem); + // if (muonItem=="HLT_2mu10") m_TriggerMuonValidationPlots[j]->fill( + // *(*mufeat.cptr())[i],*m_vRecoMuons_EffDen.at(k)); + + } // if categ=ALL + } // categories + break; + } // if(Delta_R) + } // mufeat + if (break_flag) break; + } // vec_muons + } // m_vRecoMuons_EffDen + } // m_muonItems + //@@@@@ L1 items efficiency @@@@@ + for (const auto& L1MuonItem : m_L1MuonItems) { + m_vRecoMuons_EffDen = m_vRecoMuons_EffDen_CB; + m_SelectedAuthor = 1; + float treshold = 0.; + if (L1MuonItem == "L1_MU4") treshold = 4000; + else if (L1MuonItem == "L1_MU6") treshold = 6000; + else if (L1MuonItem == "L1_MU10") treshold = 10000; + else if (L1MuonItem == "L1_MU11") treshold = 11000; + else if (L1MuonItem == "L1_MU15") treshold = 15000; + else if (L1MuonItem == "L1_MU20") treshold = 20000; + for (const auto& TrigL1mu : *L1TrigMuons) { + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + if ((TrigL1mu->thrValue()) >= treshold) + m_TriggerMuonValidationPlots[j]->fillFeatPlots(*TrigL1mu, L1MuonItem); + } // if categ=ALL + } // categories + } // L1TrigMuons + for (unsigned int k = 0; k < m_vRecoMuons_EffDen.size(); k++) { + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + m_TriggerMuonValidationPlots[j]->fillDenL1Eff(*m_vRecoMuons_EffDen.at(k), L1MuonItem); + } + } + for (const auto& TrigL1mu : *L1TrigMuons) { + if (((TrigL1mu->thrValue()) >= treshold) && + (sqrt(pow(m_vRecoMuons_EffDen.at(k)->eta() - TrigL1mu->eta(), 2.) + + pow(m_vRecoMuons_EffDen.at(k)->phi() - TrigL1mu->phi(), 2.)) < 0.2)) { + ATH_MSG_DEBUG(" $$$ match Reco_EffDen " + << L1MuonItem << " pt: " << m_vRecoMuons_EffDen.at(k)->pt() << " eta: " + << m_vRecoMuons_EffDen.at(k)->eta() << " phi: " << m_vRecoMuons_EffDen.at(k)->phi() + << " author: " << m_vRecoMuons_EffDen.at(k)->author()); + ATH_MSG_DEBUG(" $$$ L1 feature " << L1MuonItem << " pt: " << TrigL1mu->thrValue() + << " eta: " << TrigL1mu->eta() << " phi: " << TrigL1mu->phi()); + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + m_TriggerMuonValidationPlots[j]->fillNumL1Eff(*m_vRecoMuons_EffDen.at(k), L1MuonItem); + } // if categ=ALL + } // categories + break; + } // if(Delta_R) + } // L1TrigMuons + } // m_vRecoMuons_EffDen + } + //@@@@@ chains efficiency w.r.t. L1 @@@@@ + for (unsigned int m = 0; m < m_muonItems.size(); m++) { + std::vector<Trig::Feature<xAOD::MuonContainer> > vec_muons; + TString muonItem_str = (TString)m_muonItems[m]; + if (muonItem_str.Contains("_OR_")) { + muonItem_str.ReplaceAll("_OR_", " "); + TString delim = " "; + std::vector<TString> v_subchains; + SplitString(muonItem_str, delim, v_subchains); + for (int i = 0; i < (int)v_subchains.size(); i++) { + Trig::FeatureContainer fc1 = m_trigDec->features((std::string)v_subchains.at(i)); + std::vector<Trig::Feature<xAOD::MuonContainer> > vec_muons_1 = fc1.get<xAOD::MuonContainer>(); + for (const auto& mufeat : vec_muons_1) { vec_muons.emplace_back(mufeat); } + } + } else { + Trig::FeatureContainer fc = m_trigDec->features(m_muonItems[m]); + vec_muons = fc.get<xAOD::MuonContainer>(); + } + m_vRecoMuons_EffDen = m_vRecoMuons_EffDen_CB; + m_SelectedAuthor = 1; + if ((m_muonItems[m].find("msonly") != std::string::npos)) { + m_vRecoMuons_EffDen = m_vRecoMuons_EffDen_MS; + m_SelectedAuthor = 5; + } + float treshold = 0.; + if (m_L1Seed[m] == "L1_MU4") treshold = 4000; + if (m_L1Seed[m] == "L1_MU6") treshold = 6000; + if (m_L1Seed[m] == "L1_MU10") treshold = 10000; + if (m_L1Seed[m] == "L1_MU11") treshold = 11000; + if (m_L1Seed[m] == "L1_MU15") treshold = 15000; + if (m_L1Seed[m] == "L1_MU20") treshold = 20000; + for (unsigned int k = 0; k < m_vRecoMuons_EffDen.size(); k++) { + bool break_flag = false; + for (const auto& TrigL1mu : *L1TrigMuons) { + if (((TrigL1mu->thrValue()) >= treshold) && + (sqrt(pow(m_vRecoMuons_EffDen.at(k)->eta() - TrigL1mu->eta(), 2.) + + pow(m_vRecoMuons_EffDen.at(k)->phi() - TrigL1mu->phi(), 2.)) < 0.2)) { + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + m_TriggerMuonValidationPlots[j]->fillDenRELEff(*m_vRecoMuons_EffDen.at(k), m_muonItems[m]); + } // if categ=ALL + } // categories + for (const auto& mufeat : vec_muons) { + for (unsigned int i = 0; i < mufeat.cptr()->size(); i++) { + if ((((*mufeat.cptr())[i]->author()) == m_SelectedAuthor) && + (deltaR((*mufeat.cptr())[i], m_vRecoMuons_EffDen.at(k)) < 0.1)) { + break_flag = true; + for (unsigned int j = 0; j < m_selectMuonCategories.size(); j++) { + if (m_selectMuonCategories[j] == ALL) { + m_TriggerMuonValidationPlots[j]->fillNumRELEff(*m_vRecoMuons_EffDen.at(k), + m_muonItems[m]); + } // if categ=ALL + } // categories + break; + } // if(Delta_R) + } // mufeat + if (break_flag) break; + } // vec_muons + break; + } // if(Delta_R) + } // L1TrigMuons + } // m_vRecoMuons_EffDen + } // m_muonItems.size() + } // m_doTrigMuonEFValidation + } + return StatusCode::SUCCESS; + }//fillHistgrams + + void LRTMuonPhysValMonitoringTool::handleTruthMuonSegment(const xAOD::MuonSegment* truthMuSeg, + const xAOD::TruthParticleContainer* /*muonTruthContainer*/, float weight) { + const xAOD::MuonSegment* muSeg = findRecoMuonSegment(truthMuSeg); + ////if (msgLvl(MSG::DEBUG)) printTruthMuonDebug(truthMu, mu); + + unsigned int thisMuonCategory = ALL; // getMuonSegmentTruthCategory(truthMuSeg, muonTruthContainer) @@@ Does not work... + + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL || m_selectMuonCategories[i] == thisMuonCategory) { + m_muonSegmentValidationPlots[i]->fill(truthMuSeg, muSeg, + weight); // if no reco muon segment is found a protection inside + // MuonSegmentValidationPlots will ensure, its plots won't be filled + } + } + } + + void LRTMuonPhysValMonitoringTool::handleMuonSegment(const xAOD::MuonSegment* muSeg, float weight) { + if (!muSeg) { + ATH_MSG_WARNING("No muon segment found"); + return; + } + if (std::find(std::begin(m_vMatchedMuonSegments), std::end(m_vMatchedMuonSegments), muSeg) != std::end(m_vMatchedMuonSegments)) + return; + if (!m_isData) m_oUnmatchedRecoMuonSegmentPlots->fill(*muSeg, weight); + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + m_muonSegmentValidationPlots[i]->fill(muSeg, weight); + break; + } + } + } + + void LRTMuonPhysValMonitoringTool::handleMuon(const xAOD::Muon* mu, const xAOD::SlowMuon* smu, float weight) { + if (!mu) return; + if (!m_selectComissioning && mu->allAuthors() & comm_bit) return; + + if (msgLvl(MSG::DEBUG)) printMuonDebug(mu); + + // make deep copy of muon and decorate with quality + std::unique_ptr<xAOD::Muon> mu_c; + try { + mu_c = getCorrectedMuon(*mu); + } catch (const SG::ExcBadAuxVar&) { + ATH_MSG_ERROR("Cannot retrieve aux-item - rejecting muon"); + return; + } + + if (m_isData) { + MUCATEGORY thisMuonCategory = ALL; + // for events with a Zmumu candidate, separate Z muons from the rest: + if (m_vZmumuMuons.size() > 0) { + thisMuonCategory = REST; + if (std::find(m_vZmumuMuons.begin(), m_vZmumuMuons.end(), mu) != m_vZmumuMuons.end()) { thisMuonCategory = PROMPT; } + } + // fill plots + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL or m_selectMuonCategories[i] == thisMuonCategory) { + if (mu_c){ + // histos + m_muonValidationPlots[i]->fill(*mu_c, weight); + if (smu) m_slowMuonValidationPlots[i]->fill(*smu, *mu_c, weight); + // tree branches + m_muonValidationPlots[i]->fillTreeBranches(*mu_c); + } + } + } + } + + /////////////////////////////////////////////////////// + // SELECT MUON MEDIUM QUALITY FOR TRIGGER VALIDATION + xAOD::Muon::Quality my_quality = m_muonSelectionTool->getQuality(*mu_c); + if (my_quality <= xAOD::Muon::Medium && m_isoTool->accept(*mu_c)) m_vRecoMuons.emplace_back(mu); + /////////////////////////////////////////////////////// + + if (smu) { + if (std::find(std::begin(m_vMatchedSlowMuons), std::end(m_vMatchedSlowMuons), smu) != std::end(m_vMatchedSlowMuons)) { return; } + } else { + if (std::find(std::begin(m_vMatchedMuons), std::end(m_vMatchedMuons), mu) != std::end(m_vMatchedMuons)) { return; } + } + + // unmatched reco muons (not matched with any kind of truth particle, fakes) + if (!m_isData) m_oUnmatchedRecoMuonPlots->fill(*mu_c, weight); + + m_h_overview_reco_category->Fill("Other", weight); + m_h_overview_reco_authors[3]->Fill(mu->author(), weight); + + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + if (mu_c){// histos + m_muonValidationPlots[i]->fill(*mu_c); + if (smu) m_slowMuonValidationPlots[i]->fill(*smu, *mu_c, weight); + // tree branches + m_muonValidationPlots[i]->fillTreeBranches(*mu_c); + break; + } + } + } + } + + void LRTMuonPhysValMonitoringTool::handleTruthMuon(const xAOD::TruthParticle* truthMu, float weight) { + const xAOD::SlowMuon* smu = nullptr; + const xAOD::Muon* mu = nullptr; + if (!m_slowMuonsName.empty()) { + smu = findRecoSlowMuon(truthMu); + if (smu) { + const MuonLink muLink = smu->muonLink(); + if (muLink.isValid()) mu = *muLink; + + if (!mu) { + ATH_MSG_WARNING("Found SlowMuon without valid muon link"); + smu = nullptr; + } + } + } else { + mu = findRecoMuon(truthMu); + } + + if (msgLvl(MSG::DEBUG)) printTruthMuonDebug(truthMu, mu); + if (!passesAcceptanceCuts(truthMu)) return; + + std::unique_ptr<xAOD::Muon> mu_c; + if (mu) { + try { + mu_c = getCorrectedMuon(*mu); + } catch (const SG::ExcBadAuxVar&) { + ATH_MSG_ERROR("Cannot retrieve aux-item - rejecting muon"); + return; + } + } + + unsigned int thisMuonCategory = getMuonTruthCategory(truthMu); + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL || m_selectMuonCategories[i] == thisMuonCategory) { + // histos + m_muonValidationPlots[i]->fill( + truthMu, mu_c.get(), m_MSTracks, + weight); // if no muon is found a protection inside MuonValidationPlots will ensure, its plots won't be filled + if (!m_slowMuonsName.empty()) m_slowMuonValidationPlots[i]->fill(truthMu, smu, mu_c.get(), weight); + // tree branches + m_muonValidationPlots[i]->fillTreeBranches(truthMu, mu_c.get(), m_MSTracks); + } + } + if (mu_c) { + m_h_overview_reco_category->Fill(thisMuonCategory - 1, weight); + m_h_overview_reco_authors[thisMuonCategory - 1]->Fill(mu_c->author(), weight); + } else if (!m_isData) + m_oUnmatchedTruthMuonPlots->fill(*truthMu, weight); + } + + // This method MUST be called after all muon object (reco, truth) related variables (usually, vectors or arrays of vectors) of branches + // of tree are already initialized. The method fills the event related branches (basic types like int, float, double, etc), fills the + // TTree object and at the end resets all branch variables for the next event. + void LRTMuonPhysValMonitoringTool::handleMuonTrees(const xAOD::EventInfo* eventInfo, bool isData) { + ATH_MSG_DEBUG("Filling MuonTree " << name() << "..."); + + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + m_muonValidationPlots[i]->fillTree(eventInfo, isData); + + ATH_MSG_DEBUG("MuonTree is filled for muon category = " << m_selectMuonCategories[i] << " with event # " + << eventInfo->eventNumber()); + } + } + + void LRTMuonPhysValMonitoringTool::handleMuonTrack(const xAOD::TrackParticle* tp, xAOD::Muon::TrackParticleType type, float weight) { + if (!tp) { + ATH_MSG_WARNING("No track particle found"); + return; + } + + // if ID track, check that it passes standard combined mu reco selections + bool passesMuonTrackSel = false; + if (type == xAOD::Muon::InnerDetectorTrackParticle) { passesMuonTrackSel = m_trackSelector->decision(*tp); } + + if (m_isData) { + if (type == xAOD::Muon::InnerDetectorTrackParticle) { + MUCATEGORY thisTrkCategory = ALL; + // for events with a Zmumu candidate, separate Z muon tracks from the rest: + if (m_vZmumuIDTracks.size() > 0) { + thisTrkCategory = REST; + for (const auto& zmu : m_vZmumuIDTracks) { + if (deltaR(zmu, tp) < 0.01) { + thisTrkCategory = PROMPT; + break; + } + } + } + + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL || m_selectMuonCategories[i] == thisTrkCategory) { + m_muonIDTrackValidationPlots[i]->fill(*tp, weight); + if (passesMuonTrackSel) m_muonIDSelectedTrackValidationPlots[i]->fill(*tp, weight); + } + } + } else if (type == xAOD::Muon::MuonSpectrometerTrackParticle) + m_muonMSTrackValidationPlots[ALL]->fill(*tp, weight); + else if (type == xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle) + m_muonMETrackValidationPlots[ALL]->fill(*tp, weight); + else if (type == xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle) + m_muonMSOnlyMETrackValidationPlots[ALL]->fill(*tp, weight); + + return; + } + + TruthLink truthLink; + if (tp->isAvailable<TruthLink>("truthParticleLink")) { truthLink = tp->auxdata<TruthLink>("truthParticleLink"); } + + // int truthType = tp->isAvailable<int>("truthType")? tp->auxdata< int >("truthType") :0; + // float truthMatchProb = getMatchingProbability(*tp); + + if (!truthLink.isValid()) { + ATH_MSG_DEBUG("No truth link available"); + if (type == xAOD::Muon::InnerDetectorTrackParticle) return; + if (!passesAcceptanceCuts(tp)) return; + + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + // ID track plots for any track + // if (type==xAOD::Muon::InnerDetectorTrackParticle) { + // m_muonIDTrackValidationPlots[i]->fill(*tp); + // if (passesMuonTrackSel) m_muonIDSelectedTrackValidationPlots[i]->fill(*tp); + // } else + if (type == xAOD::Muon::MuonSpectrometerTrackParticle) { + if (!m_isData) m_oUnmatchedRecoMuonTrackPlots->fill(*tp, weight); + m_muonMSTrackValidationPlots[i]->fill(*tp, weight); + } else if (type == xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle) { + m_muonMETrackValidationPlots[i]->fill(*tp, weight); + } else if (type == xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle) { + m_muonMSOnlyMETrackValidationPlots[i]->fill(*tp, weight); + } + break; + } + } + } // end if no valid truth link + else { // here: valid truth link and truthType + + if (type == + xAOD::Muon::InnerDetectorTrackParticle) { // don't fill histograms for any ID track, only for muons; buys a lot of time + if ((*truthLink)->absPdgId() != 13 || !MC::isStable(*truthLink)) return; // not a muon + if ((*truthLink)->barcode() == 0 || HepMC::is_simulation_particle((*truthLink))) return; // must have valid barcode + } + + if (!passesAcceptanceCuts(*truthLink)) return; + unsigned int thisMuonCategory = getMuonTruthCategory(tp); + + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL || m_selectMuonCategories[i] == thisMuonCategory) { + if (type == xAOD::Muon::InnerDetectorTrackParticle) { + if (!m_fwdtracksName.empty() && std::abs((*truthLink)->eta()) > 2.5) + m_muonIDForwardTrackValidationPlots[i]->fill(*truthLink, tp, weight); + else if (!m_tracksName.empty()) { + m_muonIDTrackValidationPlots[i]->fill(*truthLink, tp, weight); + if (passesMuonTrackSel) m_muonIDSelectedTrackValidationPlots[i]->fill(*truthLink, tp, weight); + } + } else if (type == xAOD::Muon::MuonSpectrometerTrackParticle) { + m_muonMSTrackValidationPlots[i]->fill(*truthLink, tp, weight); + } else if (type == xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle) { + m_muonMETrackValidationPlots[i]->fill(*truthLink, tp, weight); + } else if (type == xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle) { + m_muonMSOnlyMETrackValidationPlots[i]->fill(*truthLink, tp, weight); + } + } + } + } + + return; + } + + void LRTMuonPhysValMonitoringTool::handleMuonL1Trigger(const xAOD::MuonRoI* TrigL1mu) { + ATH_MSG_DEBUG("MuonRoI L1 Trigger: ptThr " << TrigL1mu->thrValue() << " phi " << TrigL1mu->phi() << " eta " << TrigL1mu->eta()); + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + m_TriggerMuonValidationPlots[i]->fill(*TrigL1mu); + break; + } + } + } + + void LRTMuonPhysValMonitoringTool::handleMuonL2Trigger(const xAOD::L2StandAloneMuon* L2SAMu) { + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + m_TriggerMuonValidationPlots[i]->fill(*L2SAMu); + break; + } + } + ATH_MSG_DEBUG(" ==> Geometrical selection of Muon L2SA Trigger : pt " << L2SAMu->pt() << " phi " << L2SAMu->phi() << " eta " + << L2SAMu->eta() << " roiWord " << L2SAMu->roiWord() + << " sAddress " << L2SAMu->sAddress()); + } + + void LRTMuonPhysValMonitoringTool::L2SATriggerResolution() { + int k_L2SAMu_MinDeltaR = -1; + float MinDeltaR = 0.; + ATH_MSG_DEBUG(" m_vL2SAMuons.size()" << m_vL2SAMuons.size()); + for (unsigned int i = 0; i < m_vRecoMuons.size(); i++) { + ATH_MSG_DEBUG(":: TEST: listing all Recomu pt=" << m_vRecoMuons.at(i)->pt() << " eta=" << m_vRecoMuons.at(i)->eta() << " phi=" + << m_vRecoMuons.at(i)->phi() << " auth=" << m_vRecoMuons.at(i)->author()); + } + for (unsigned int i = 0; i < m_vRecoMuons.size(); i++) { + if ((m_vRecoMuons.at(i)->author() != 1) || (std::abs(m_vRecoMuons.at(i)->eta()) > 2.4)) continue; + ATH_MSG_DEBUG(":::: TEST: Recomu pt=" << m_vRecoMuons.at(i)->pt() << " eta=" << m_vRecoMuons.at(i)->eta() + << " phi=" << m_vRecoMuons.at(i)->phi() << " auth=" << m_vRecoMuons.at(i)->author()); + k_L2SAMu_MinDeltaR = -1; + MinDeltaR = 1000; + ATH_MSG_DEBUG("==============>>>> k_L2SAMu_MinDeltaR=" << k_L2SAMu_MinDeltaR << " MinDeltaR" << MinDeltaR); + for (unsigned int k = 0; k < m_vL2SAMuons.size(); k++) { + ATH_MSG_DEBUG(" :::::::: TEST: L2SA pt=" << m_vL2SAMuons.at(k)->pt() << " eta=" << m_vL2SAMuons.at(k)->eta() + << " phi=" << m_vL2SAMuons.at(k)->phi() + << " DeltaR=" << deltaR(m_vRecoMuons.at(i), m_vL2SAMuons.at(k))); + if ((deltaR(m_vRecoMuons.at(i), m_vL2SAMuons.at(k)) < 0.1 && + (deltaR(m_vRecoMuons.at(i), m_vL2SAMuons.at(k)) < MinDeltaR))) { + k_L2SAMu_MinDeltaR = k; + MinDeltaR = deltaR(m_vRecoMuons.at(i), m_vL2SAMuons.at(k)); + ATH_MSG_DEBUG("==============>>>> taken!!!! k_L2SAMu_MinDeltaR=" << k_L2SAMu_MinDeltaR << " MinDeltaR" + << MinDeltaR); + } + } + if (k_L2SAMu_MinDeltaR == -1) continue; + for (unsigned int c = 0; c < m_selectMuonCategories.size(); c++) { + if (m_selectMuonCategories[c] == ALL) { + m_TriggerMuonValidationPlots[c]->fill(*m_vL2SAMuons.at(k_L2SAMu_MinDeltaR), *m_vRecoMuons.at(i)); /////work in progress + } + } + } + } + + void LRTMuonPhysValMonitoringTool::handleMuonL2Trigger(const xAOD::L2CombinedMuon* L2CBMu) { + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + m_TriggerMuonValidationPlots[i]->fill(*L2CBMu); + break; + } + } + ATH_MSG_DEBUG(" ==> Geometrical selection of Muon L2CB Trigger : pt " << L2CBMu->pt() << " phi " << L2CBMu->phi() << " eta " + << L2CBMu->eta()); + } + + void LRTMuonPhysValMonitoringTool::L2CBTriggerResolution() { + int k_L2CBMu_MinDeltaR = -1; + float MinDeltaR = 0.; + ATH_MSG_DEBUG(" m_vL2CBMuons.size()" << m_vL2CBMuons.size()); + for (unsigned int i = 0; i < m_vRecoMuons.size(); i++) { + ATH_MSG_DEBUG(":: TEST: listing all Recomu pt=" << m_vRecoMuons.at(i)->pt() << " eta=" << m_vRecoMuons.at(i)->eta() << " phi=" + << m_vRecoMuons.at(i)->phi() << " auth=" << m_vRecoMuons.at(i)->author()); + } + for (unsigned int i = 0; i < m_vRecoMuons.size(); i++) { + if ((m_vRecoMuons.at(i)->author() != 1) || (std::abs(m_vRecoMuons.at(i)->eta()) > 2.4)) continue; + ATH_MSG_DEBUG(":::: TEST: Recomu pt=" << m_vRecoMuons.at(i)->pt() << " eta=" << m_vRecoMuons.at(i)->eta() + << " phi=" << m_vRecoMuons.at(i)->phi() << " auth=" << m_vRecoMuons.at(i)->author()); + k_L2CBMu_MinDeltaR = -1; + MinDeltaR = 1000; + ATH_MSG_DEBUG("==============>>>> k_L2CBMu_MinDeltaR=" << k_L2CBMu_MinDeltaR << " MinDeltaR" << MinDeltaR); + for (unsigned int k = 0; k < m_vL2CBMuons.size(); k++) { + ATH_MSG_DEBUG(" :::::::: TEST: L2CB pt=" << m_vL2CBMuons.at(k)->pt() << " eta=" << m_vL2CBMuons.at(k)->eta() + << " phi=" << m_vL2CBMuons.at(k)->phi() + << " DeltaR=" << deltaR(m_vRecoMuons.at(i), m_vL2CBMuons.at(k))); + if ((deltaR(m_vRecoMuons.at(i), m_vL2CBMuons.at(k)) < 0.1 && + (deltaR(m_vRecoMuons.at(i), m_vL2CBMuons.at(k)) < MinDeltaR))) { + k_L2CBMu_MinDeltaR = k; + MinDeltaR = deltaR(m_vRecoMuons.at(i), m_vL2CBMuons.at(k)); + ATH_MSG_DEBUG("==============>>>> taken!!!! k_L2CBMu_MinDeltaR=" << k_L2CBMu_MinDeltaR << " MinDeltaR" + << MinDeltaR); + } + } + if (k_L2CBMu_MinDeltaR == -1) continue; + for (unsigned int c = 0; c < m_selectMuonCategories.size(); c++) { + if (m_selectMuonCategories[c] == ALL) { + m_TriggerMuonValidationPlots[c]->fill(*m_vL2CBMuons.at(k_L2CBMu_MinDeltaR), *m_vRecoMuons.at(i)); /////work in progress + } + } + } + } + + void LRTMuonPhysValMonitoringTool::handleMuonTrigger(const xAOD::Muon* EFMu) { + for (unsigned int i = 0; i < m_selectMuonCategories.size(); i++) { + if (m_selectMuonCategories[i] == ALL) { + m_TriggerMuonValidationPlots[i]->fill(*EFMu); + break; + } + } + ATH_MSG_DEBUG("==> Geometrical selection of EF Trigger muons: pt " << EFMu->pt() << " phi " << EFMu->phi() << " eta " << EFMu->eta() + << " author " << EFMu->author()); + } + + void LRTMuonPhysValMonitoringTool::EFTriggerResolution() { + int k_EFMu_MinDeltaR = -1; + float MinDeltaR = 0.; + std::vector<int> vAvailableAuthors; + vAvailableAuthors.clear(); + vAvailableAuthors.emplace_back(m_vEFMuons[0]->author()); + unsigned int iter = 0; + for (unsigned int k = 0; k < m_vEFMuons.size(); k++) { + iter = 0; + for (unsigned int l = 0; l < vAvailableAuthors.size(); l++) { + if (m_vEFMuons[k]->author() != vAvailableAuthors[l]) iter++; + } + if (iter == vAvailableAuthors.size()) vAvailableAuthors.emplace_back(m_vEFMuons[k]->author()); + } + ATH_MSG_DEBUG(" m_vEFMuons.size()" << m_vEFMuons.size()); + for (unsigned int i = 0; i < m_vRecoMuons.size(); i++) { + ATH_MSG_DEBUG(":: TEST: listing all Recomu pt=" << m_vRecoMuons.at(i)->pt() << " eta=" << m_vRecoMuons.at(i)->eta() << " phi=" + << m_vRecoMuons.at(i)->phi() << " auth=" << m_vRecoMuons.at(i)->author()); + } + for (unsigned int i = 0; i < m_vRecoMuons.size(); i++) { + if ((m_vRecoMuons.at(i)->author() != 1) || (std::abs(m_vRecoMuons.at(i)->eta()) > 2.4)) continue; + ATH_MSG_DEBUG(":::: TEST: Recomu pt=" << m_vRecoMuons.at(i)->pt() << " eta=" << m_vRecoMuons.at(i)->eta() + << " phi=" << m_vRecoMuons.at(i)->phi() << " auth=" << m_vRecoMuons.at(i)->author()); + for (unsigned int l = 0; l < vAvailableAuthors.size(); l++) { + k_EFMu_MinDeltaR = -1; + MinDeltaR = 1000; + for (unsigned int k = 0; k < m_vEFMuons.size(); k++) { + ATH_MSG_DEBUG(" :::::::: TEST: EF pt=" << m_vEFMuons.at(k)->pt() << " eta=" << m_vEFMuons.at(k)->eta() + << " phi=" << m_vEFMuons.at(k)->phi() + << " DeltaR=" << deltaR(m_vRecoMuons.at(i), m_vEFMuons.at(k)) + << " author=" << m_vEFMuons.at(k)->author()); + if (m_vEFMuons.at(k)->author() == vAvailableAuthors.at(l) && + (deltaR(m_vRecoMuons.at(i), m_vEFMuons.at(k)) < 0.1 && + (deltaR(m_vRecoMuons.at(i), m_vEFMuons.at(k)) < MinDeltaR))) { + k_EFMu_MinDeltaR = k; + MinDeltaR = deltaR(m_vRecoMuons.at(i), m_vEFMuons.at(k)); + } + } + if (k_EFMu_MinDeltaR == -1) continue; + for (unsigned int c = 0; c < m_selectMuonCategories.size(); c++) { + if (m_selectMuonCategories[c] == ALL) { + m_TriggerMuonValidationPlots[c]->fill(*m_vEFMuons.at(k_EFMu_MinDeltaR), *m_vRecoMuons.at(i)); + } + } + } + } + } + + void LRTMuonPhysValMonitoringTool::printMuonDebug(const xAOD::Muon* mu) { + const xAOD::TrackParticle* tp = mu->primaryTrackParticle(); + TruthLink truthLink; + if (tp) { + if (!tp->isAvailable<TruthLink>("truthParticleLink")) + ATH_MSG_VERBOSE("No truth link found"); + else + truthLink = tp->auxdata<TruthLink>("truthParticleLink"); + } + ATH_MSG_DEBUG("Muon: pt " << mu->pt() << " eta " << mu->eta() << " link " << truthLink.isValid()); + } + + const xAOD::Muon* LRTMuonPhysValMonitoringTool::findRecoMuon(const xAOD::TruthParticle* truthMu) { + static const SG::AuxElement::ConstAccessor<MuonLink> acc_muon("recoMuonLink"); + if (!acc_muon.isAvailable(*truthMu)) return nullptr; + MuonLink link = acc_muon(*truthMu); + if (!link.isValid()) return nullptr; + const xAOD::Muon* reco_mu = (*link); + if (!m_selectComissioning && reco_mu->allAuthors() & comm_bit) return nullptr; + m_vMatchedMuons.emplace_back(reco_mu); + return reco_mu; + } + + const xAOD::SlowMuon* LRTMuonPhysValMonitoringTool::findRecoSlowMuon(const xAOD::TruthParticle* truthMu) { + if (m_slowMuonsName.empty()) return nullptr; + + const xAOD::SlowMuonContainer* SlowMuons = nullptr; + SlowMuons = getContainer<xAOD::SlowMuonContainer>(m_slowMuonsName); + for (const auto& smu : *SlowMuons) { + const MuonLink muLink = smu->muonLink(); + if (!muLink.isValid()) continue; + float DR = deltaR(*muLink , truthMu); + if (DR < 0.005) { + m_vMatchedSlowMuons.emplace_back(smu); + return smu; + } + } + + return nullptr; + } + + void LRTMuonPhysValMonitoringTool::printTruthMuonDebug(const xAOD::TruthParticle* truthMu, const xAOD::Muon* mu) { + ATH_MSG_DEBUG("Truth muon: " << truthMu->pt() << " eta " << truthMu->eta()); + if (!mu) return; + ATH_MSG_DEBUG("Reco muon: " << mu->pt() << " eta " << mu->eta()); + } + + StatusCode LRTMuonPhysValMonitoringTool::procHistograms() { + ATH_MSG_INFO("Finalising hists " << name() << "..."); + for (const auto& plots : m_muonValidationPlots) plots->finalize(); + for (const auto& plots : m_TriggerMuonValidationPlots) plots->finalize(); + if (!m_isData) { + m_oUnmatchedRecoMuonPlots->finalize(); + m_oUnmatchedTruthMuonPlots->finalize(); + } + + for (const auto& plots : m_muonMSTrackValidationPlots) plots->finalize(); + for (const auto& plots : m_muonMETrackValidationPlots) plots->finalize(); + for (const auto& plots : m_muonMSOnlyMETrackValidationPlots) plots->finalize(); + for (const auto& plots : m_muonIDTrackValidationPlots) plots->finalize(); + for (const auto& plots : m_muonIDSelectedTrackValidationPlots) plots->finalize(); + for (const auto& plots : m_muonIDForwardTrackValidationPlots) plots->finalize(); + if (!m_isData) + if (m_oUnmatchedRecoMuonTrackPlots) m_oUnmatchedRecoMuonTrackPlots->finalize(); + + for (const auto& plots : m_muonSegmentValidationPlots) plots->finalize(); + if (!m_isData) + if (m_oUnmatchedRecoMuonSegmentPlots) m_oUnmatchedRecoMuonSegmentPlots->finalize(); + + if (m_doMuonTree) { + for (const auto& plots : m_muonValidationPlots) { + if (plots->getMuonTree()) { plots->getMuonTree()->getTree()->Write(); } + } + } + + return StatusCode::SUCCESS; + }//ProcHistgrams + + const xAOD::MuonSegment* LRTMuonPhysValMonitoringTool::findRecoMuonSegment(const xAOD::MuonSegment* truthMuSeg) { + if (!truthMuSeg->isAvailable<MuonSegmentLink>("recoSegmentLink")) { + ATH_MSG_DEBUG("recoSegmentLink not found"); + return nullptr; + } + MuonSegmentLink link = truthMuSeg->auxdata<MuonSegmentLink>("recoSegmentLink"); + if (!link.isValid()) { + ATH_MSG_DEBUG("recoSegmentLink not valid"); + return nullptr; + } + m_vMatchedMuonSegments.emplace_back(*link); + return (*link); + } + + TH1F* LRTMuonPhysValMonitoringTool::findHistogram(const std::vector<HistData>& hists, const std::string& hnameTag, + const std::string& hdirTag, const std::string& hNewName) { + TH1F* h = nullptr; + for (const auto& hist : hists) { + if (hist.second.find(hdirTag) != std::string::npos || hdirTag.empty()) { + std::string histname = hist.first->GetName(); + if (histname.find(hnameTag) != std::string::npos) { + h = (TH1F*)hist.first->Clone(hNewName.c_str()); + return h; + } + } + } + return h; + } + + LRTMuonPhysValMonitoringTool::MUCATEGORY LRTMuonPhysValMonitoringTool::getMuonSegmentTruthCategory( + const xAOD::MuonSegment* truthMuSeg, const xAOD::TruthParticleContainer* muonTruthContainer) { + TruthLink truthLink; + if (truthMuSeg->isAvailable<TruthLink>("truthParticleLink")) { + truthLink = truthMuSeg->auxdata<TruthLink>("truthParticleLink"); + if (truthLink.isValid()) { + int theBarcode = (*truthLink)->barcode(); + if (std::abs((*truthLink)->pdgId()) != 13) return REST; + + for (const auto& muTruthPart : *muonTruthContainer) { + if (muTruthPart->barcode() == theBarcode) { return getMuonTruthCategory(muTruthPart); } + } + } + } else + ATH_MSG_WARNING("No truth link available for muon truth segment"); + + return REST; + } + + LRTMuonPhysValMonitoringTool::MUCATEGORY LRTMuonPhysValMonitoringTool::getMuonTruthCategory(const xAOD::IParticle* mu) { + int truthType = mu->auxdata<int>("truthType"); + if (truthType == 6) + return PROMPT; + else if (truthType == 8 && (mu->auxdata<int>("truthOrigin") == 34 || mu->auxdata<int>("truthOrigin") == 35)) + return INFLIGHT; + else if (truthType == 7) + return NONISO; + return REST; + } + + std::unique_ptr<xAOD::Muon> LRTMuonPhysValMonitoringTool::getCorrectedMuon(const xAOD::Muon& mu) { + std::unique_ptr<xAOD::Muon> mu_c; + if (mu.m() <= 0) return mu_c; + mu_c = std::make_unique<xAOD::Muon>(); + mu_c->makePrivateStore(mu); + + // add decorations too fool the muon selector tool + const xAOD::TrackParticle* idtrk{mu_c->trackParticle(xAOD::Muon::InnerDetectorTrackParticle)}; + const xAOD::TrackParticle* metrk{mu_c->trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle)}; + if (idtrk && metrk) { + mu_c->auxdecor<float>("InnerDetectorPt") = idtrk->pt(); + mu_c->auxdecor<float>("MuonSpectrometerPt") = metrk->pt(); + } + m_muonSelectionTool->setQuality(*mu_c); + m_muonSelectionTool->setPassesHighPtCuts(*mu_c); + m_muonSelectionTool->setPassesIDCuts(*mu_c); + return mu_c; + } + + void LRTMuonPhysValMonitoringTool::modifyHistogram(TH1* hist) { + std::string histname = hist->GetName(); + + if (histname.find("trigger_L1_pt") != std::string::npos) { // if (histname=="Muons_All_trigger_L1_pt"){ + hist->SetTitle("L1Trigger Muons pt treshold"); + hist->GetXaxis()->SetTitle("L1Trigger Muons pt treshold [GeV]"); + hist->GetXaxis()->Set(30, -0.5, 29.5); + } + if (histname.find("trigger_L1_eta_pt") != std::string::npos) { // if (histname=="Muons_All_trigger_L1_eta_pt") { + hist->SetTitle("L1Trigger Muons pt treshold vs eta"); + hist->GetYaxis()->Set(90, -0.5, 29.5); + hist->GetYaxis()->SetTitle("L1Trigger Muons pt treshold [GeV]"); + } + + if (histname.find("trigger") != std::string::npos && + ((histname.find("Denom_pt") != std::string::npos) || (histname.find("Numer_pt") != std::string::npos) || + (histname.find("Features_pt") != std::string::npos))) + hist->GetXaxis()->Set(200, 0., 200.); + + if (histname.find("hits") != std::string::npos) { + if (histname.find("etaLayer2") != std::string::npos) + hist->GetXaxis()->Set(15, -0.5, 14.5); + else if (histname.find("etaLayer") != std::string::npos) + hist->GetXaxis()->Set(11, -0.5, 10.5); + } + + ////////////// + bool is2D = !(histname.find("_vs_") == std::string::npos); + ////////////// + + if (histname.find("METrackParticles") != std::string::npos) { + if (histname.find("Res_eta") != std::string::npos) { + if (is2D) + hist->GetYaxis()->Set(50, -0.025, 0.025); + else + hist->GetXaxis()->Set(50, -0.025, 0.025); + } else if (histname.find("Res_phi") != std::string::npos) { + if (is2D) + hist->GetYaxis()->Set(50, -0.02, 0.02); + else + hist->GetXaxis()->Set(50, -0.02, 0.02); + } + } else if (histname.find("MSTrackParticles") != std::string::npos) { + if (histname.find("Res_eta") != std::string::npos) { + if (is2D) + hist->GetYaxis()->Set(50, -0.025, 0.025); + else + hist->GetXaxis()->Set(50, -0.025, 0.025); + } else if (histname.find("Res_phi") != std::string::npos) { + if (is2D) + hist->GetYaxis()->Set(50, -0.05, 0.05); + else + hist->GetXaxis()->Set(50, -0.05, 0.05); + } + } else { + if (histname.find("Res_eta") != std::string::npos) { + if (is2D) + hist->GetYaxis()->Set(50, -0.005, 0.005); + else + hist->GetXaxis()->Set(50, -0.005, 0.005); + } else if (histname.find("Res_phi") != std::string::npos) { + if (is2D) + hist->GetYaxis()->Set(50, -0.002, 0.002); + else + hist->GetXaxis()->Set(50, -0.002, 0.002); + } + } + + if (histname.find("trigger") != std::string::npos) { + // RESO EF - MC + if ((!m_isData) && histname.find("MuidCo") != std::string::npos && + (histname.find("BARREL") != std::string::npos || histname.find("WHOLE_DETECT") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.04, 0.04); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.04, 0.04); } + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.0005, 0.0005); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.0005, 0.0005); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.0002, 0.0002); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.0002, 0.0002); } + } + if ((!m_isData) && histname.find("MuidCo") != std::string::npos && (histname.find("ENDCAPS") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.05, 0.05); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.05, 0.05); } + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.001, 0.001); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.001, 0.001); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.0003, 0.0003); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.0003, 0.0003); } + } + if ((!m_isData) && histname.find("MuidSA") != std::string::npos) { + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.03, 0.03); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.03, 0.03); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.03, 0.03); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.03, 0.03); } + } + if ((!m_isData) && histname.find("MuidSA") != std::string::npos && (histname.find("BARREL") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.15, 0.15); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.15, 0.15); } + } + if ((!m_isData) && histname.find("MuidSA") != std::string::npos && + (histname.find("ENDCAPS") != std::string::npos || histname.find("WHOLE_DETECT") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.2, 0.2); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.2, 0.2); } + } + + // RESO EF - DATA + if ((m_isData) && histname.find("MuidCo") != std::string::npos && + (histname.find("BARREL") != std::string::npos || histname.find("WHOLE_DETECT") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.06, 0.06); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.06, 0.06); } + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.001, 0.001); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.001, 0.001); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.0005, 0.0005); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.0005, 0.0005); } + } + if ((m_isData) && histname.find("MuidCo") != std::string::npos && (histname.find("ENDCAPS") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.1, 0.1); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.1, 0.1); } + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.0015, 0.0015); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.0015, 0.0015); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.0005, 0.0005); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.0005, 0.0005); } + } + if ((m_isData) && histname.find("MuidSA") != std::string::npos) { + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.03, 0.03); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.03, 0.03); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.03, 0.03); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.03, 0.03); } + } + if ((m_isData) && histname.find("MuidSA") != std::string::npos && (histname.find("BARREL") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.3, 0.3); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.3, 0.3); } + } + if ((m_isData) && histname.find("MuidSA") != std::string::npos && + (histname.find("ENDCAPS") != std::string::npos || histname.find("WHOLE_DETECT") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.5, 0.5); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.5, 0.5); } + } + + // LEVEL2 + if ((histname.find("L2_StandAlone") != std::string::npos)) { + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.03, 0.03); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.03, 0.03); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.03, 0.03); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.03, 0.03); } + } + if ((histname.find("L2_StandAlone") != std::string::npos) && (histname.find("BARREL") != std::string::npos)) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.3, 0.3); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.3, 0.3); } + } + if ((histname.find("L2_StandAlone") != std::string::npos) && + ((histname.find("ENDCAPS") != std::string::npos) || (histname.find("WHOLE_DETECT") != std::string::npos))) { + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.5, 0.5); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.5, 0.5); } + } + + if ((histname.find("L2_Combined") != std::string::npos)) { + if (histname.find("Res_eta") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.002, 0.002); + } + if (histname.find("Res_eta_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.002, 0.002); } + + if (histname.find("Res_phi") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.001, 0.001); + } + if (histname.find("Res_phi_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.001, 0.001); } + if (histname.find("Res_pT") != std::string::npos && histname.find("_vs_") == std::string::npos) { + hist->GetXaxis()->Set(100, -0.2, 0.2); + } + if (histname.find("Res_pT_vs_") != std::string::npos) { hist->GetYaxis()->Set(100, -0.2, 0.2); } + } + } + } + + bool LRTMuonPhysValMonitoringTool::passesAcceptanceCuts(const xAOD::IParticle* prt) { + if (prt->pt() < 2000.) return false; + if (std::abs(prt->eta()) > 2.7) return false; + return true; + } + + void LRTMuonPhysValMonitoringTool::SplitString(TString x, const TString& delim, std::vector<TString>& v) { + v.clear(); + int stringLength = x.Length(); + int delimLength = delim.Length(); + + int stop = 1; + TString temp = "---"; + while (stop != -1) { + stop = x.First(delim); + + if (stop != -1) { + temp = x(0, stop); + TSubString newString = x(stop + delimLength, stringLength); + x = newString; + stringLength = x.Length(); + } else { + stringLength = x.Length(); + temp = x(0, stringLength); + } + + v.emplace_back(temp); + } + } + +} // namespace LRTMonitoring diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/LRTMuonPhysValMonitoringTool.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/LRTMuonPhysValMonitoringTool.h new file mode 100644 index 0000000000000000000000000000000000000000..b6da17fa5d5b1078457f59ea958e31d5cd610f4c --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/LRTMuonPhysValMonitoringTool.h @@ -0,0 +1,230 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// LRTMuonPhysValMonitoringTool.cxx +// Implementation file for class LRTMuonPhysValMonitoringTool +/////////////////////////////////////////////////////////////////// + +#ifndef LRTMUONPHYSVALMONITORING_LRTMUONPHYSVALMONITORINGTOOL_H +#define LRTMUONPHYSVALMONITORING_LRTMUONPHYSVALMONITORINGTOOL_H + + + +#include "AthenaMonitoring/ManagedMonitorToolBase.h" +#include "GaudiKernel/ServiceHandle.h" +#include "IsolationSelection/IIsolationSelectionTool.h" +#include "MuonAnalysisInterfaces/IMuonSelectionTool.h" +#include "MuonCombinedToolInterfaces/IMuonPrintingTool.h" + + +#include "StoreGate/ReadHandleKey.h" +#include "TrigDecisionTool/TrigDecisionTool.h" + +#include "TrkToolInterfaces/ITrackSelectorTool.h" +#include "xAODEventInfo/EventInfo.h" +#include "xAODMuon/Muon.h" //typedef +#include "xAODMuon/MuonSegment.h" //typedef +#include "xAODMuon/SlowMuon.h" //typedef +#include "xAODTrigMuon/L2CombinedMuon.h" //typedef + +#include "xAODTrigMuon/L2StandAloneMuon.h" //typedef +#include "xAODTruth/TruthParticle.h" //typedef +#include "xAODTruth/TruthParticleContainer.h" //typedef + +#include "MuonSegmentValidationPlots.h" //needed for unique_ptr access to deleter +#include "MuonHistUtils/MuonSegmentPlots.h" //needed for unique_ptr access to deleter +#include "MuonValidationPlots.h" //needed for unique_ptr access to deleter +#include "MuonHistUtils/RecoMuonPlotOrganizer.h" //needed for unique_ptr access to deleter +#include "MuonHistUtils/TruthMuonPlotOrganizer.h" //needed for unique_ptr access to deleter +#include "TrkValHistUtils/PlotBase.h" //for PlotBase, also for typedef of HistData +#include "SlowMuonValidationPlots.h" //needed for unique_ptr access to deleter +#include "MuonTrackValidationPlots.h" //needed for unique_ptr access to deleter +#include "TriggerMuonValidationPlots.h" //needed for unique_ptr access to deleter + +#include <string> +#include <vector> +#include <memory> + +class TString; +class TH1F; + + + +namespace LRTMuonPhysValMonitoring { + + class LRTMuonPhysValMonitoringTool : public ManagedMonitorToolBase { + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// + public: + // Copy constructor: + + /// Constructor with parameters: + LRTMuonPhysValMonitoringTool(const std::string& type, const std::string& name, const IInterface* parent); + + /// Destructor: + virtual ~LRTMuonPhysValMonitoringTool() = default; + + // Athena algtool's Hooks + virtual StatusCode initialize() override; + virtual StatusCode bookHistograms() override; + virtual StatusCode fillHistograms() override; + virtual StatusCode procHistograms() override; + + /////////////////////////////////////////////////////////////////// + // Private data: + /////////////////////////////////////////////////////////////////// + private: + enum MUCATEGORY { ALL = 0, PROMPT, INFLIGHT, NONISO, REST }; + + void handleMuon(const xAOD::Muon* mu, const xAOD::SlowMuon* smu = nullptr, float weight = 1.0); + void handleSlowMuon(const xAOD::SlowMuon* smu, float weight = 1.0); + void handleTruthMuon(const xAOD::TruthParticle* truthMu, float weight = 1.0); + void handleMuonTrack(const xAOD::TrackParticle* tp, xAOD::Muon::TrackParticleType type, float weight = 1.0); + void handleMuonSegment(const xAOD::MuonSegment* muSeg, float weight = 1.0); + void handleTruthMuonSegment(const xAOD::MuonSegment* truthMuSeg, const xAOD::TruthParticleContainer* muonTruthContainer, + float weight = 1.0); + + void handleMuonTrees(const xAOD::EventInfo* eventInfo, bool isData); + + void handleMuonL1Trigger(const xAOD::MuonRoI* TrigL1mu); + void handleMuonL2Trigger(const xAOD::L2StandAloneMuon* L2SAMu); + void handleMuonL2Trigger(const xAOD::L2CombinedMuon* L2CBMu); + void handleMuonTrigger(const xAOD::Muon* mu); + void L2SATriggerResolution(); + void L2CBTriggerResolution(); + void EFTriggerResolution(); + + void printMuonDebug(const xAOD::Muon* mu); + void printTruthMuonDebug(const xAOD::TruthParticle* truthMu, const xAOD::Muon* mu); + + StatusCode bookValidationPlots(PlotBase& valPlots); + const xAOD::Muon* findRecoMuon(const xAOD::TruthParticle* truthMu); + const xAOD::SlowMuon* findRecoSlowMuon(const xAOD::TruthParticle* truthMu); + const xAOD::MuonSegment* findRecoMuonSegment(const xAOD::MuonSegment* truthMuSeg); + std::unique_ptr<xAOD::Muon> getCorrectedMuon(const xAOD::Muon& mu); + + const xAOD::TrackParticleContainer* m_MSTracks{nullptr}; + std::map<std::string, int> m_counterBits; + std::vector<std::string> m_muonItems; + std::vector<std::string> m_L1Seed; + int m_SelectedAuthor{0}; + + TH1F* findHistogram(const std::vector<HistData>& hists, const std::string& hnameTag, const std::string& hdirTag, + const std::string& hNewName); + void modifyHistogram(TH1* hist); + + Gaudi::Property<std::string> m_tracksName{this, "TrackContainerName", "InDetTrackParticles"}; + Gaudi::Property<std::string> m_fwdtracksName{this, "FwdTrackContainerName", ""}; + Gaudi::Property<std::string> m_muonsName{this, "MuonContainerName", "MuonsLRT"}; + Gaudi::Property<std::string> m_slowMuonsName{this, "SlowMuonContainerName", "SlowMuons"}; + Gaudi::Property<std::string> m_muonsTruthName{this, "MuonTruthParticleContainerName", "MuonTruthParticles"}; + Gaudi::Property<std::string> m_muonTracksName{this, "MuonTrackContainerName", "MuonSpectrometerTrackParticles"}; + Gaudi::Property<std::string> m_muonExtrapolatedTracksName{this, "MuonExtrapolatedTrackContainerName", + "ExtrapolatedMuonTrackParticles"}; + Gaudi::Property<std::string> m_muonMSOnlyExtrapolatedTracksName{this, "MuonOnlyExtrapolatedTrackContainerName", + "MSOnlyExtrapolatedMuonTrackParticles"}; + Gaudi::Property<std::string> m_muonSegmentsName{this, "MuonSegmentContainerName", "MuonSegments"}; + Gaudi::Property<std::string> m_muonSegmentsTruthName{this, "MuonTruthSegmentContainerName", "MuonTruthSegments"}; + Gaudi::Property<std::string> m_muonL1TrigName{this, "L1TrigMuonContainerName", "LVL1MuonRoIs"}; + Gaudi::Property<std::string> m_muonL2SAName{this, "L2SAMuonContainerName", "HLT_xAOD__L2StandAloneMuonContainer_MuonL2SAInfo"}; + Gaudi::Property<std::string> m_muonL2CBName{this, "L2CBMuonContainerName", "HLT_xAOD__L2CombinedMuonContainer_MuonL2CBInfo"}; + Gaudi::Property<std::string> m_muonEFCombTrigName{this, "EFCombTrigMuonContainerName", "HLT_xAOD__MuonContainer_MuonEFInfo"}; + + Gaudi::Property<std::vector<int>> m_selectMuonWPs{ + this, "SelectMuonWorkingPoints", {xAOD::Muon::Loose, xAOD::Muon::Medium, xAOD::Muon::Tight}}; + Gaudi::Property<std::vector<unsigned int>> m_selectMuonAuthors{ + this, + "SelectMuonAuthors", + {xAOD::Muon::MuidCo, xAOD::Muon::MuTagIMO, xAOD::Muon::MuidSA, xAOD::Muon::MuGirl, xAOD::Muon::CaloTag, xAOD::Muon::CaloScore}}; + /// Flag to tell whether muons with the comissioning author will be selected or not + Gaudi::Property<bool> m_selectComissioning{this, "SelectComissioningMuons", false}; + Gaudi::Property<std::vector<std::vector<std::string>>> m_selectHLTMuonItems{this, "SelectHLTMuonItems", {}}; + Gaudi::Property<std::vector<std::string>> m_L1MuonItems{this, "SelectL1MuonItems", {}}; + Gaudi::Property<std::vector<unsigned int>> m_selectMuonCategories{ + this, + "SelectMuonCategories", + {MUCATEGORY::ALL, MUCATEGORY::PROMPT, MUCATEGORY::INFLIGHT, MUCATEGORY::NONISO, MUCATEGORY::REST}}; + + Gaudi::Property<bool> m_doBinnedResolutionPlots{this, "DoBinnedResolutionPlots", true}; + Gaudi::Property<bool> m_doTrigMuonValidation{this, "DoTrigMuonValidation", false}; + Gaudi::Property<bool> m_doTrigMuonL1Validation{this, "DoTrigMuonL1Validation", false}; + Gaudi::Property<bool> m_doTrigMuonL2Validation{this, "DoTrigMuonL2Validation", false}; + Gaudi::Property<bool> m_doTrigMuonEFValidation{this, "DoTrigMuonEFValidation", false}; + Gaudi::Property<bool> m_doMuonTree{this, "DoMuonTree", false}; + Gaudi::Property<bool> m_isData{this, "IsData", false}; + + SG::ReadHandleKey<xAOD::EventInfo> m_eventInfo{this, "EventInfo", "EventInfo", "event info"}; + + // Tools + ToolHandle<CP::IMuonSelectionTool> m_muonSelectionTool{this, "MuonSelector", "CP::MuonSelectionTool/MuonSelectionTool"}; + ToolHandle<Rec::IMuonPrintingTool> m_muonPrinter{this, "MuonPrinter", "Rec::MuonPrintingTool/MuonPrintingTool"}; + ToolHandle<Trig::TrigDecisionTool> m_trigDec{this, "TrigDecTool", "Trig::TrigDecisionTool/TrigDecisionTool"}; + ToolHandle<Trk::ITrackSelectorTool> m_trackSelector{this, "TrackSelector", "InDet::InDetDetailedTrackSelectorTool/MuonCombinedInDetDetailedTrackSelectorTool"}; + ToolHandle<CP::IIsolationSelectionTool> m_isoTool{this, "IsoTool", ""}; + + std::vector<std::string> m_selectMuonCategoriesStr; + LRTMuonPhysValMonitoringTool::MUCATEGORY getMuonSegmentTruthCategory(const xAOD::MuonSegment* truthMuSeg, + const xAOD::TruthParticleContainer* muonTruthContainer); + LRTMuonPhysValMonitoringTool::MUCATEGORY getMuonTruthCategory(const xAOD::IParticle* prt); + bool passesAcceptanceCuts(const xAOD::IParticle* prt); + void SplitString(TString x, const TString& delim, std::vector<TString>& v); + + // Hists + std::vector<std::unique_ptr<MuonValidationPlots>> m_muonValidationPlots; + std::vector<std::unique_ptr<TriggerMuonValidationPlots>> m_TriggerMuonValidationPlots; + std::vector<std::unique_ptr<MuonTrackValidationPlots>> m_muonMSTrackValidationPlots; + std::vector<std::unique_ptr<MuonTrackValidationPlots>> m_muonMETrackValidationPlots; + std::vector<std::unique_ptr<MuonTrackValidationPlots>> m_muonMSOnlyMETrackValidationPlots; + std::vector<std::unique_ptr<MuonTrackValidationPlots>> m_muonIDTrackValidationPlots; + std::vector<std::unique_ptr<MuonTrackValidationPlots>> m_muonIDSelectedTrackValidationPlots; + std::vector<std::unique_ptr<MuonTrackValidationPlots>> m_muonIDForwardTrackValidationPlots; + std::vector<std::unique_ptr<MuonSegmentValidationPlots>> m_muonSegmentValidationPlots; + std::unique_ptr<Muon::RecoMuonPlotOrganizer> m_oUnmatchedRecoMuonPlots; + std::unique_ptr<Muon::TruthMuonPlotOrganizer> m_oUnmatchedTruthMuonPlots; + std::unique_ptr<Muon::RecoMuonTrackPlotOrganizer> m_oUnmatchedRecoMuonTrackPlots; + std::unique_ptr<Muon::MuonSegmentPlots> m_oUnmatchedRecoMuonSegmentPlots; + + std::vector<std::unique_ptr<SlowMuonValidationPlots>> m_slowMuonValidationPlots; + + // overview hists + std::vector<TH1F*> m_h_overview_nObjects; + TH1F* m_h_overview_reco_category{nullptr}; + std::vector<TH1F*> m_h_overview_reco_authors; + + TH1F* m_h_overview_Z_mass{nullptr}; + TH1F* m_h_overview_Z_mass_ME{nullptr}; + TH1F* m_h_overview_Z_mass_ID{nullptr}; + + std::vector<const xAOD::TruthParticle*> m_vMatchedTruthMuons; + std::vector<const xAOD::Muon*> m_vMatchedMuons; + std::vector<const xAOD::SlowMuon*> m_vMatchedSlowMuons; + std::vector<const xAOD::TrackParticle*> m_vMatchedMuonTracks; + std::vector<const xAOD::MuonSegment*> m_vMatchedMuonSegments; + std::vector<const xAOD::TrackParticle*> m_vZmumuIDTracks; + std::vector<const xAOD::TrackParticle*> m_vZmumuMETracks; + std::vector<const xAOD::Muon*> m_vZmumuMuons; + std::vector<const xAOD::Muon*> m_vEFMuons; + std::vector<const xAOD::Muon*> m_vEFMuonsSelected; + std::vector<const xAOD::L2StandAloneMuon*> m_vL2SAMuons; + std::vector<const xAOD::L2StandAloneMuon*> m_vL2SAMuonsSelected; + std::vector<const xAOD::L2CombinedMuon*> m_vL2CBMuons; + std::vector<const xAOD::L2CombinedMuon*> m_vL2CBMuonsSelected; + std::vector<const xAOD::Muon*> m_vRecoMuons; + std::vector<const xAOD::Muon*> m_vRecoMuons_EffDen_CB; + std::vector<const xAOD::Muon*> m_vRecoMuons_EffDen_MS; + std::vector<const xAOD::Muon*> m_vRecoMuons_EffDen; + + template <class T> const T* getContainer(const std::string& containerName); + }; + + template <class T> const T* LRTMuonPhysValMonitoringTool::getContainer(const std::string& containerName) { + const T* ptr = evtStore()->retrieve<const T>(containerName); + if (!ptr) { ATH_MSG_WARNING("Container '" << containerName << "' could not be retrieved"); } + return ptr; + } + +} // namespace LRTMuonPhysValMonitoring + +#endif //> !LRTMUONPHYSVALMONITORING_LRTMUONPHYSVALMONITORINGTOOL_H diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonSegmentValidationPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonSegmentValidationPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b78f8fe560e6df70339e5229ba35de5f66bdfc20 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonSegmentValidationPlots.cxx @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "MuonSegmentValidationPlots.h" + +MuonSegmentValidationPlots::MuonSegmentValidationPlots(PlotBase* pParent, const std::string& sDir, bool isData) : + PlotBase(pParent, sDir) { + m_oRecoSegmPlots = std::make_unique<Muon::MuonSegmentPlots>(this, "reco/MuonSegments/"); + if (!isData) { + m_oMatchedMuonSegmPlots = std::make_unique<Muon::MuonSegmentPlots>(this, "matched/MuonSegments/"); + m_oMatchedMuonSegmDiffPlots = std::make_unique<Muon::MuonSegmentTruthRelatedPlots>(this, "matched/MuonSegments/"); + m_oTruthMuonSegmPlots = std::make_unique<Muon::MuonSegmentPlots>(this, "truth/MuonSegments/"); + } +} + +MuonSegmentValidationPlots::~MuonSegmentValidationPlots() = default; + +void MuonSegmentValidationPlots::fill(const xAOD::MuonSegment* truthMuSeg, const xAOD::MuonSegment* muSeg, float weight) { + if (truthMuSeg) m_oTruthMuonSegmPlots->fill(*truthMuSeg, weight); + if (muSeg) m_oRecoSegmPlots->fill(*muSeg, weight); + + if ((truthMuSeg) && (muSeg)) { + m_oMatchedMuonSegmPlots->fill(*truthMuSeg, weight); + m_oMatchedMuonSegmDiffPlots->fill(*truthMuSeg, *muSeg, weight); + } +} + +void MuonSegmentValidationPlots::fill(const xAOD::MuonSegment* muSeg, float weight) { m_oRecoSegmPlots->fill(*muSeg, weight); } diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonSegmentValidationPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonSegmentValidationPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..5a93e16dc291b7270f88c6ffe18acfd35d0cef0c --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonSegmentValidationPlots.h @@ -0,0 +1,27 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_MUONSEGMENTVALIDATIONPLOTS_H +#define MUONPHYSVALMONITORING_MUONSEGMENTVALIDATIONPLOTS_H + +#include "MuonHistUtils/MuonSegmentPlots.h" +#include "MuonHistUtils/MuonSegmentTruthRelatedPlots.h" + +class MuonSegmentValidationPlots : public PlotBase { +public: + MuonSegmentValidationPlots(PlotBase* pParent, const std::string& sDir, bool isData); + ~MuonSegmentValidationPlots(); + + // Reco only information + std::unique_ptr<Muon::MuonSegmentPlots> m_oRecoSegmPlots{}; + // Truth related plots + std::unique_ptr<Muon::MuonSegmentPlots> m_oMatchedMuonSegmPlots{}; + std::unique_ptr<Muon::MuonSegmentTruthRelatedPlots> m_oMatchedMuonSegmDiffPlots{}; + std::unique_ptr<Muon::MuonSegmentPlots> m_oTruthMuonSegmPlots{}; + + void fill(const xAOD::MuonSegment* truthMuSeg, const xAOD::MuonSegment* muSeg, float weight = 1.0); + void fill(const xAOD::MuonSegment* muSeg, float weight = 1.0); +}; + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonTrackValidationPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonTrackValidationPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..5d39b437669bf95cbf6320dd4b366b67d777b07f --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonTrackValidationPlots.cxx @@ -0,0 +1,38 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "MuonTrackValidationPlots.h" + +MuonTrackValidationPlots::MuonTrackValidationPlots(PlotBase* pParent, const std::string& sDir, const std::string& sTrackType, bool isData) : + PlotBase(pParent, sDir), m_sTrackType(sTrackType) { + std::vector<int> selectedRecoPlots(0); + selectedRecoPlots.push_back(Muon::TRK_PARAM); + selectedRecoPlots.push_back(Muon::TRK_RECOINFO); + selectedRecoPlots.push_back(Muon::TRK_IMPACT); + if (sTrackType.find("ID") != std::string::npos) + selectedRecoPlots.push_back(Muon::TRK_IDHITS); + else + selectedRecoPlots.push_back(Muon::TRK_MSHITS); + m_oRecoMuonTrackPlots = std::make_unique<Muon::RecoMuonTrackPlotOrganizer>(this, "reco/" + sTrackType, selectedRecoPlots); + + if (!isData) { + std::vector<int> selectedMatchedPlots(0); + selectedMatchedPlots.push_back(Muon::TRK_MATCHEDTRUE); + selectedMatchedPlots.push_back(Muon::TRK_MATCHEDRECO); + selectedMatchedPlots.push_back(Muon::TRK_DEFPARAMPULLS); + selectedMatchedPlots.push_back(Muon::MUON_RESOL); + m_oMatchedMuonTrackPlots = std::make_unique<Muon::TruthRelatedMuonPlotOrganizer>(this, "matched/" + sTrackType, true, selectedMatchedPlots); + } +} + +MuonTrackValidationPlots::~MuonTrackValidationPlots() = default; + +void MuonTrackValidationPlots::fill(const xAOD::TrackParticle& muTP, float weight) { m_oRecoMuonTrackPlots->fill(muTP, weight); } + +void MuonTrackValidationPlots::fill(const xAOD::TruthParticle* truthMu, const xAOD::TrackParticle* muTP, float weight) { + if (muTP) { + m_oRecoMuonTrackPlots->fill(*muTP, weight); + if (truthMu) { m_oMatchedMuonTrackPlots->fill(*truthMu, *muTP, weight); } + } +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonTrackValidationPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonTrackValidationPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..1d6dbe9afe45c1585ba99b78588b882e257f5f5e --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonTrackValidationPlots.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_MUONTRACKVALIDATIONPLOTS_H +#define MUONPHYSVALMONITORING_MUONTRACKVALIDATIONPLOTS_H + +#include "MuonHistUtils/RecoMuonTrackPlotOrganizer.h" +#include "MuonHistUtils/TruthRelatedMuonPlotOrganizer.h" +#include "TrkValHistUtils/PlotBase.h" +#include "xAODTracking/TrackParticle.h" +#include "xAODTruth/TruthParticle.h" + +class MuonTrackValidationPlots : public PlotBase { +public: + MuonTrackValidationPlots(PlotBase* pParent, const std::string& sDir, const std::string& sTrackType, bool isData = false); + ~MuonTrackValidationPlots(); + + // Reco only information + std::unique_ptr<Muon::RecoMuonTrackPlotOrganizer> m_oRecoMuonTrackPlots{}; + // Truth related plots + std::unique_ptr<Muon::TruthRelatedMuonPlotOrganizer> m_oMatchedMuonTrackPlots{}; + + void fill(const xAOD::TrackParticle& muTP, float weight = 1.0); + void fill(const xAOD::TruthParticle* truthMu, const xAOD::TrackParticle* muTP, float weight = 1.0); + +private: + std::string m_sTrackType; +}; + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonValidationPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonValidationPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..823913adb42b31c49804e964bb70962df26646ae --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonValidationPlots.cxx @@ -0,0 +1,227 @@ +/* + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration +*/ + +#include "MuonValidationPlots.h" + +#include <utility> + +#include "MuonHistUtils/MuonEnumDefs.h" + +typedef ElementLink<xAOD::TrackParticleContainer> TrackLink; +typedef ElementLink<xAOD::MuonContainer> MuonLink; + +MuonValidationPlots::MuonValidationPlots(PlotBase* pParent, const std::string& sDir, std::vector<int> wps, + std::vector<unsigned int> authors, bool isData, bool doBinnedResolutionPlots, + bool doSeparateSAFMuons, bool doMuonTree) : + PlotBase(pParent, sDir), + m_selectedWPs(std::move(wps)), + m_selectedAuthors(std::move(authors)), + m_truthSelections(2, ""), + m_oTruthRelatedMuonPlots(nullptr), + m_isData(isData), + m_doSeparateSAFMuons(doSeparateSAFMuons), + m_MuonTree(nullptr) { + if (!m_isData) { + m_truthSelections[0] = "all"; // no selection on truth muons (minimum selection is |eta|<2.5, pt>5 GeV, defined in + // MuonPhysValMonitoringTool::handleTruthMuon() + m_truthSelections[1] = "MSAcceptance"; // truth muons in MS acceptance (at least 4 associated hits in the MS) + + // histogram classes for all muons + for (const auto& truthSelection : m_truthSelections) { + m_oTruthMuonPlots.emplace_back(new Muon::TruthMuonPlotOrganizer(this, "truth/" + truthSelection)); + } + m_oTruthRelatedMuonPlots.reset( + new Muon::TruthRelatedMuonPlotOrganizer(this, "matched/AllMuons", doBinnedResolutionPlots)); + } + + std::vector<int> allPlotCategories(0); + std::vector<int> selectedPlotCategories(0); + for (unsigned int i = 0; i < Muon::MAX_RECOPLOTCLASS; i++) { + allPlotCategories.emplace_back(i); + if (i != Muon::MUON_CHARGEPARAM) selectedPlotCategories.emplace_back(i); + } + + // histogram classes for all muons + m_oRecoMuonPlots.reset(new Muon::RecoMuonPlotOrganizer(this, "reco/AllMuons", allPlotCategories)); + + // define a histogram class for each of the selected muon qualities + for (unsigned int i = 0; i < m_selectedWPs.size(); i++) { + std::string sQuality = Muon::EnumDefs::toString((xAOD::Muon::Quality)m_selectedWPs[i]); + m_oRecoMuonPlots_perQuality.emplace_back(new Muon::RecoMuonPlotOrganizer( + this, "reco/" + sQuality, (sQuality == "Medium" || sQuality == "Tight") ? allPlotCategories : selectedPlotCategories)); + + if (!m_isData) { + bool doBinnedPlots = false; + if (sQuality == "Medium") doBinnedPlots = true; + m_oTruthRelatedMuonPlots_perQuality.emplace_back( + new Muon::TruthRelatedMuonPlotOrganizer(this, "matched/" + sQuality, doBinnedPlots)); + } + } + + // define a histogram class for each of the selected muon authors (+one inclusive for all authors) + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + std::string sAuthor = Muon::EnumDefs::toString((xAOD::Muon::Author)m_selectedAuthors[i]); + if (sAuthor == "CaloTag") sAuthor = "CaloTagTight"; + m_oRecoMuonPlots_perAuthor.emplace_back( + new Muon::RecoMuonPlotOrganizer(this, "reco/" + sAuthor, (sAuthor == "MuidCo") ? allPlotCategories : selectedPlotCategories)); + if (!m_isData) + m_oTruthRelatedMuonPlots_perAuthor.emplace_back( + new Muon::TruthRelatedMuonPlotOrganizer(this, "matched/" + sAuthor, doBinnedResolutionPlots)); + } + + // define histogram class for loose CaloTag and append to author plots, not very nice workaround though + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + if ((xAOD::Muon::Author)m_selectedAuthors[i] == xAOD::Muon::CaloTag) { // found CaloTag in list, also do CaloTagLoose + m_oRecoMuonPlots_perAuthor.emplace_back(new Muon::RecoMuonPlotOrganizer(this, "reco/CaloTagLoose", selectedPlotCategories)); + if (!m_isData) + m_oTruthRelatedMuonPlots_perAuthor.emplace_back( + new Muon::TruthRelatedMuonPlotOrganizer(this, "matched/CaloTagLoose", doBinnedResolutionPlots)); + } + } + + // define histogram class for SiliconAssociatedForwardMuons + if (m_doSeparateSAFMuons) { + m_oRecoMuonPlots_SiAssocFwrdMu.emplace_back(new Muon::RecoMuonPlotOrganizer(this, "reco/SiAssocForward", selectedPlotCategories)); + if (!m_isData) + m_oTruthRelatedMuonPlots_SiAssocFwrdMu.emplace_back( + new Muon::TruthRelatedMuonPlotOrganizer(this, "matched/SiAssocForward", doBinnedResolutionPlots)); + } + + if (doMuonTree) m_MuonTree.reset(new Muon::MuonTree(this, "", !m_isData)); +} + +MuonValidationPlots::~MuonValidationPlots() =default; + +void MuonValidationPlots::fillRecoMuonPlots(const xAOD::Muon& mu, float weight) { + // fill hists for all muons + m_oRecoMuonPlots->fill(mu, weight); + // fill separate hists for each muon quality + xAOD::Muon::Quality muqual = mu.quality(); + for (unsigned int i = 0; i < m_selectedWPs.size(); i++) { + if (muqual <= (xAOD::Muon::Quality)m_selectedWPs[i]) { m_oRecoMuonPlots_perQuality[i]->fill(mu, weight); } + } + // fill separate hists for each author + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + if (mu.isAuthor((xAOD::Muon::Author)m_selectedAuthors[i])) { + if ((xAOD::Muon::Author)m_selectedAuthors[i] == (xAOD::Muon::CaloTag)) { + int ipar = 0; + if (mu.parameter(ipar, xAOD::Muon::CaloMuonIDTag)) { ; } + if (ipar < 11) continue; + } + + // filter SiliconAssociatedForwardMuons + if (mu.muonType() != (xAOD::Muon::MuonType)xAOD::Muon::SiliconAssociatedForwardMuon || !m_doSeparateSAFMuons) + m_oRecoMuonPlots_perAuthor[i]->fill(mu, weight); + } + } + // fill SiliconAssociatedForwardMuons + for (unsigned int i = 0; i < m_oTruthRelatedMuonPlots_SiAssocFwrdMu.size(); i++) { + if (mu.muonType() == (xAOD::Muon::MuonType)xAOD::Muon::SiliconAssociatedForwardMuon) + m_oRecoMuonPlots_SiAssocFwrdMu[i]->fill(mu, weight); + } + // fill CaloTagLoose (one additional plot in plot list) + unsigned int counter = m_selectedAuthors.size(); + if (counter + 1 == m_oRecoMuonPlots_perAuthor.size()) { + if (mu.isAuthor(xAOD::Muon::CaloTag)) m_oRecoMuonPlots_perAuthor[counter]->fill(mu, weight); + } +} + +void MuonValidationPlots::fillTruthMuonPlots(const xAOD::TruthParticle& truthMu, float weight) { + m_oTruthMuonPlots[0]->fill(truthMu, weight); // no selections + if (isGoodTruthTrack(truthMu)) { // in MS acceptance (minimum precision hits) + m_oTruthMuonPlots[1]->fill(truthMu, weight); + } +} + +void MuonValidationPlots::fill(const xAOD::Muon& mu, float weight) { fillRecoMuonPlots(mu, weight); } + +void MuonValidationPlots::fill(const xAOD::TruthParticle& truthMu, float weight) { fillTruthMuonPlots(truthMu, weight); } + +void MuonValidationPlots::fill(const xAOD::TruthParticle* truthMu, const xAOD::Muon* mu, const xAOD::TrackParticleContainer* MSTracks, + float weight) { + if (truthMu) fillTruthMuonPlots(*truthMu, weight); + if (mu) fillRecoMuonPlots(*mu, weight); + + if ((mu) && (truthMu)) { + // plots for all + m_oTruthRelatedMuonPlots->fill(*truthMu, *mu, MSTracks, weight); + // fill SiliconAssociatedForwardMuons + for (unsigned int i = 0; i < m_oTruthRelatedMuonPlots_SiAssocFwrdMu.size(); i++) { + if (mu->muonType() == xAOD::Muon::SiliconAssociatedForwardMuon || !m_doSeparateSAFMuons) + m_oTruthRelatedMuonPlots_SiAssocFwrdMu[i]->fill(*truthMu, *mu, MSTracks, weight); + } + + // plots per quality + xAOD::Muon::Quality muqual = mu->quality(); + for (unsigned int i = 0; i < m_selectedWPs.size(); i++) { + if (muqual <= (xAOD::Muon::Quality)m_selectedWPs[i]) { + m_oTruthRelatedMuonPlots_perQuality[i]->fill(*truthMu, *mu, MSTracks, weight); + } + } + // plots per author + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + if (mu->isAuthor((xAOD::Muon::Author)m_selectedAuthors[i])) { + if ((xAOD::Muon::Author)m_selectedAuthors[i] == xAOD::Muon::CaloTag) { + int ipar = 0; + if (mu->parameter(ipar, xAOD::Muon::CaloMuonIDTag)) { ; } + if (ipar < 11) continue; + } + // filter SilicionAssociatedForwardMuons + if (mu->muonType() != xAOD::Muon::SiliconAssociatedForwardMuon || !m_doSeparateSAFMuons) + m_oTruthRelatedMuonPlots_perAuthor[i]->fill(*truthMu, *mu, MSTracks, weight); + } + } + // fill CaloTagLoose (one additional plot in plot list) + unsigned int counter = m_selectedAuthors.size(); + if (counter + 1 == m_oRecoMuonPlots_perAuthor.size()) { + if (mu->isAuthor(xAOD::Muon::CaloTag)) m_oTruthRelatedMuonPlots_perAuthor[counter]->fill(*truthMu, *mu, MSTracks, weight); + } + } +} + +Muon::MuonTree* MuonValidationPlots::getMuonTree() { return m_MuonTree.get(); } + +void MuonValidationPlots::fillTreeBranches(const xAOD::Muon& mu) { + if (m_MuonTree) m_MuonTree->fillRecoMuonBranches(mu); +} + +void MuonValidationPlots::fillTreeBranches(const xAOD::TruthParticle& truthMu) { + if (m_MuonTree) m_MuonTree->fillTruthMuonBranches(truthMu, isGoodTruthTrack(truthMu)); +} + +void MuonValidationPlots::fillTreeBranches(const xAOD::TruthParticle* truthMu, const xAOD::Muon* mu, + const xAOD::TrackParticleContainer* MSTracks) { + if (!m_MuonTree) return; + if (mu) m_MuonTree->fillRecoMuonBranches(*mu); + if (truthMu) m_MuonTree->fillTruthMuonBranches(*truthMu, isGoodTruthTrack(*truthMu)); + + if (truthMu && mu) { m_MuonTree->fillTruthMuonBranches(*truthMu, *mu, MSTracks, isGoodTruthTrack(*truthMu)); } +} + +void MuonValidationPlots::fillTree(const xAOD::EventInfo* eventInfo, bool isData) { + if (!m_MuonTree) return; + m_MuonTree->fillEventBranches(eventInfo, isData); + m_MuonTree->getTree()->Fill(); + m_MuonTree->postFillTreeActions(); +} + +bool MuonValidationPlots::isGoodTruthTrack(const xAOD::TruthParticle& truthMu) { + static const std::array<std::string,6> hitTypes{"innerSmallHits", "innerLargeHits", "middleSmallHits", + "middleLargeHits", "outerSmallHits", "outerLargeHits"}; // MDT + CSC + int minPrecHits = 5; + + int nPrecHits = 0; + bool hasEnoughPrecHits = false; + + for (const auto& hitTypeItr : hitTypes) { + if (truthMu.isAvailable<uint8_t>(hitTypeItr)) { + nPrecHits += truthMu.auxdata<uint8_t>(hitTypeItr); + if (nPrecHits >= minPrecHits) { + hasEnoughPrecHits = true; + break; + } + } + } + return (hasEnoughPrecHits); +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonValidationPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonValidationPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..fb48b8e862c373bf8539396250b9235655a38c55 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/MuonValidationPlots.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_MUONVALIDATIONPLOTS_H +#define MUONPHYSVALMONITORING_MUONVALIDATIONPLOTS_H + +#include "MuonHistUtils/MuonTree.h" +#include "MuonHistUtils/RecoMuonPlotOrganizer.h" +#include "MuonHistUtils/TruthMuonPlotOrganizer.h" +#include "MuonHistUtils/TruthRelatedMuonPlotOrganizer.h" +#include "xAODEventInfo/EventInfo.h" +#include "xAODMuon/Muon.h" +#include "xAODMuon/MuonContainer.h" +#include "xAODTruth/TruthParticle.h" + +class MuonValidationPlots : public PlotBase { +public: + MuonValidationPlots(PlotBase* pParent, const std::string& sDir, std::vector<int> wps, std::vector<unsigned int> authors, bool isData, + bool doBinnedResolutionPlots, bool doSplitSAFMuons, bool doMuonTree = false); + + virtual ~MuonValidationPlots(); + void fill(const xAOD::Muon& mu, float weight = 1.0); + bool isGoodTruthTrack(const xAOD::TruthParticle& truthMu); + void fill(const xAOD::TruthParticle& truthMu, float weight = 1.0); + void fill(const xAOD::TruthParticle* truthMu, const xAOD::Muon* mu, const xAOD::TrackParticleContainer* MSTracks, float weight = 1.0); + Muon::MuonTree* getMuonTree(); + void fillTreeBranches(const xAOD::Muon& mu); + void fillTreeBranches(const xAOD::TruthParticle& truthMu); + void fillTreeBranches(const xAOD::TruthParticle* truthMu, const xAOD::Muon* mu, const xAOD::TrackParticleContainer* MSTracks); + void fillTree(const xAOD::EventInfo* eventInfo, bool isData); + + std::vector<int> m_selectedWPs; + std::vector<unsigned int> m_selectedAuthors; + std::vector<std::string> m_truthSelections; + + std::unique_ptr<Muon::RecoMuonPlotOrganizer> m_oRecoMuonPlots; + std::unique_ptr<Muon::TruthRelatedMuonPlotOrganizer> m_oTruthRelatedMuonPlots; + std::vector<std::unique_ptr<Muon::RecoMuonPlotOrganizer>> m_oRecoMuonPlots_perQuality; + std::vector<std::unique_ptr<Muon::RecoMuonPlotOrganizer>> m_oRecoMuonPlots_perAuthor; + std::vector<std::unique_ptr<Muon::TruthRelatedMuonPlotOrganizer>> m_oTruthRelatedMuonPlots_perQuality; + std::vector<std::unique_ptr<Muon::TruthRelatedMuonPlotOrganizer>> m_oTruthRelatedMuonPlots_perAuthor; + std::vector<std::unique_ptr<Muon::TruthMuonPlotOrganizer>> m_oTruthMuonPlots; + + std::vector<std::unique_ptr<Muon::TruthRelatedMuonPlotOrganizer>> m_oTruthRelatedMuonPlots_SiAssocFwrdMu; + std::vector<std::unique_ptr<Muon::RecoMuonPlotOrganizer>> m_oRecoMuonPlots_SiAssocFwrdMu; + +private: + void fillRecoMuonPlots(const xAOD::Muon& mu, float weight = 1.0); + void fillTruthMuonPlots(const xAOD::TruthParticle& truthMu, float weight = 1.0); + + bool m_isData; + bool m_doSeparateSAFMuons; + + std::unique_ptr<Muon::MuonTree> m_MuonTree; +}; + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/ResoTriggerMuonPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/ResoTriggerMuonPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..38f492da4791a98cde55e8d1cdaed8e6ab25872d --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/ResoTriggerMuonPlots.cxx @@ -0,0 +1,143 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ResoTriggerMuonPlots.h" +#include "FourMomUtils/xAODP4Helpers.h" + +#include <utility> + +using namespace xAOD::P4Helpers; + + +ResoTriggerMuonPlots::ResoTriggerMuonPlots(PlotBase* pParent, const std::string& sDir, std::string sType) : + PlotBase(pParent, sDir), + m_sType(std::move(sType)) { + m_pt_slices = {"0", "25", "55", "100"}; + m_etaBins = {-3., -2.5, -2.4, -1.918, -1.623, -1.348, -1.2329, -1.1479, -1.05, -0.908, -0.791, + -0.652, -0.476, -0.324, -0.132, 0, 0.132, 0.324, 0.476, 0.652, 0.791, 0.908, + 1.05, 1.1479, 1.2329, 1.348, 1.623, 1.918, 2.4, 2.5, 3.}; + + Res_pT = Book1D("Res" + m_sType + "_pT", "Res" + m_sType + "_pT;(1/pT-1/RECOpT)/(1/RECOpT);Entries", 200, -0.25, 0.25); + Res_eta = Book1D("Res" + m_sType + "_eta", "Res" + m_sType + "_eta;eta-RECOeta;Entries", 200, -0.02, 0.02); + Res_phi = Book1D("Res" + m_sType + "_phi", "Res" + m_sType + "_phi;phi-RECOphi;Entries", 200, -0.005, 0.005); + + Res_pT_vs_pT = Book2D("Res" + m_sType + "_pT_vs_pT", "Res" + m_sType + "_pT vs pT;pT [GeV];(1/pT-1/RECOpT)/(1/RECOpT)", 150, 0., + 150., 100, -0.25, 0.25); + Res_eta_vs_pT = + Book2D("Res" + m_sType + "_eta_vs_pT", "Res" + m_sType + "_eta vs pT;pT [GeV];eta-RECOeta", 150, 0., 150., 200, -0.02, 0.02); + Res_phi_vs_pT = + Book2D("Res" + m_sType + "_phi_vs_pT", "Res" + m_sType + "_phi vs pT;pT [GeV];phi-RECOphi", 150, 0., 150., 200, -0.005, 0.005); + Res_pT_vs_eta.clear(); + Res_pT_vs_phi.clear(); + Res_phi_vs_phi.clear(); + Res_eta_vs_eta.clear(); + + for (unsigned int i = 0; i < m_pt_slices.size() - 1; i++) { + Res_pT_vs_eta.push_back(Book2D("Res" + m_sType + "_pT_vs_eta_from" + m_pt_slices[i] + "_to" + m_pt_slices[i + 1] + "GeV", + "Res" + m_sType + "_pT vs eta from " + m_pt_slices[i] + " GeV to " + m_pt_slices[i + 1] + + " GeV; eta;(1/pT-1/RECOpT)/(1/RECOpT)", + m_etaBins.size() - 1, &m_etaBins[0], 100, -0.25, 0.25)); + Res_pT_vs_phi.push_back(Book2D("Res" + m_sType + "_pT_vs_phi_from" + m_pt_slices[i] + "_to" + m_pt_slices[i + 1] + "GeV", + "Res" + m_sType + "_pT vs phi from " + m_pt_slices[i] + " GeV to " + m_pt_slices[i + 1] + + " GeV;phi;(1/pT-1/RECOpT)/(1/RECOpT)", + 96, -M_PI, M_PI, 100, -0.25, 0.25)); + Res_phi_vs_phi.push_back(Book2D("Res" + m_sType + "_phi_vs_phi_from" + m_pt_slices[i] + "_to" + m_pt_slices[i + 1] + "GeV", + "Res" + m_sType + "_phi vs phi from " + m_pt_slices[i] + " GeV to " + m_pt_slices[i + 1] + + " GeV;phi;(1/pT-1/RECOpT)/(1/RECOpT)", + 96, -M_PI, M_PI, 100, -0.25, 0.25)); + Res_eta_vs_eta.push_back( + Book2D("Res" + m_sType + "_eta_vs_eta_from" + m_pt_slices[i] + "_to" + m_pt_slices[i + 1] + "GeV", + "Res" + m_sType + "_eta vs eta from " + m_pt_slices[i] + " GeV to " + m_pt_slices[i + 1] + " GeV;eta;eta-RECOeta", + m_etaBins.size() - 1, &m_etaBins[0], 100, -0.25, 0.25)); + } +} + +void ResoTriggerMuonPlots::fill(const xAOD::Muon& Trigmu, const xAOD::Muon& Recomu) { + // fill plots Res_pt,eta,phi + float pt = 0.001 * Recomu.pt(); + float eta = Recomu.eta(); + float phi = Recomu.phi(); + // float respt = (Trigmu.pt() - Recomu.pt())/Recomu.pt(); + float respt = (1. / Trigmu.pt() - 1. / Recomu.pt()) / (1. / Recomu.pt()); + + const float d_phi = deltaPhi(Trigmu.phi(), phi); + const float d_eta = Trigmu.eta() - eta; + Res_pT->Fill(respt); + Res_eta->Fill(d_eta); + Res_phi->Fill(d_phi); + + Res_pT_vs_pT->Fill(pt, respt); + Res_eta_vs_pT->Fill(pt, d_eta); + Res_phi_vs_pT->Fill(pt, d_phi); + + for (unsigned int i = 0; i < m_pt_slices.size() - 1; i++) { + float pt_min = atof(m_pt_slices[i].c_str()); + float pt_max = atof(m_pt_slices[i + 1].c_str()); + if (pt >= pt_min && pt < pt_max) { + Res_pT_vs_eta[i]->Fill(eta, respt); + Res_pT_vs_phi[i]->Fill(phi, respt); + Res_phi_vs_phi[i]->Fill(phi, d_phi); + Res_eta_vs_eta[i]->Fill(eta, d_eta); + } + } +} + +void ResoTriggerMuonPlots::fill(const xAOD::L2StandAloneMuon& L2SAmu, const xAOD::Muon& Recomu) { + float pt = 0.001 * Recomu.pt(); + float eta = Recomu.eta(); + float phi = Recomu.phi(); + float respt = 0; + if (L2SAmu.pt() > 0.) respt = (1. / (1000. * L2SAmu.pt()) - 1. / Recomu.pt()) / (1. / Recomu.pt()); + if (L2SAmu.pt() < 0.) respt = (1. / (-1000. * L2SAmu.pt()) - 1. / Recomu.pt()) / (1. / Recomu.pt()); + + const float d_eta = L2SAmu.eta() - eta; + const float d_phi = deltaPhi(L2SAmu.phi(), phi); + Res_pT->Fill(respt); + Res_eta->Fill(d_eta); + Res_phi->Fill(d_phi); + + Res_pT_vs_pT->Fill(pt, respt); + Res_eta_vs_pT->Fill(pt, d_eta); + Res_phi_vs_pT->Fill(pt, d_phi); + + for (unsigned int i = 0; i < m_pt_slices.size() - 1; i++) { + float pt_min = atof(m_pt_slices[i].c_str()); + float pt_max = atof(m_pt_slices[i + 1].c_str()); + if (pt >= pt_min && pt < pt_max) { + Res_phi_vs_phi[i]->Fill(phi, d_phi); + Res_eta_vs_eta[i]->Fill(eta, d_eta); + Res_pT_vs_eta[i]->Fill(eta, respt); + Res_pT_vs_phi[i]->Fill(phi, respt); + } + } +} + +void ResoTriggerMuonPlots::fill(const xAOD::L2CombinedMuon& L2CBmu, const xAOD::Muon& Recomu) { + float pt = 0.001 * Recomu.pt(); + float eta = Recomu.eta(); + float phi = Recomu.phi(); + float respt = (1. / (L2CBmu.pt()) - 1. / Recomu.pt()) / (1. / Recomu.pt()); + ; + + const float d_phi = deltaPhi(L2CBmu.phi() , phi); + const float d_eta = L2CBmu.eta() - eta; + Res_pT->Fill(respt); + Res_eta->Fill(d_eta); + Res_phi->Fill(d_phi); + + Res_pT_vs_pT->Fill(pt, respt); + Res_eta_vs_pT->Fill(pt, d_eta); + Res_phi_vs_pT->Fill(pt, d_phi); + + for (unsigned int i = 0; i < m_pt_slices.size() - 1; i++) { + float pt_min = atof(m_pt_slices[i].c_str()); + float pt_max = atof(m_pt_slices[i + 1].c_str()); + if (pt >= pt_min && pt < pt_max) { + Res_phi_vs_phi[i]->Fill(phi, d_phi); + Res_eta_vs_eta[i]->Fill(eta, d_eta); + Res_pT_vs_eta[i]->Fill(eta, respt); + Res_pT_vs_phi[i]->Fill(phi, respt); + } + } +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/ResoTriggerMuonPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/ResoTriggerMuonPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..1d71301b616f2202824f42a5279274d3040ee8b0 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/ResoTriggerMuonPlots.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_RESOTRIGGERMUONPLOTS_H +#define MUONPHYSVALMONITORING_RESOTRIGGERMUONPLOTS_H + +#include "TrkValHistUtils/PlotBase.h" +#include "xAODMuon/Muon.h" +#include "xAODTrigMuon/L2CombinedMuon.h" +#include "xAODTrigMuon/L2StandAloneMuon.h" + + + +class ResoTriggerMuonPlots : public PlotBase { +public: + ResoTriggerMuonPlots(PlotBase* pParent, const std::string& sDir, std::string sType = ""); + void fill(const xAOD::Muon& Trigmu, const xAOD::Muon& Recomu); + void fill(const xAOD::L2StandAloneMuon& L2SAmu, const xAOD::Muon& Recomu); + void fill(const xAOD::L2CombinedMuon& L2CBmu, const xAOD::Muon& Recomu); + + TH1* Res_pT{nullptr}; + TH1* Res_eta{nullptr}; + TH1* Res_phi{nullptr}; + TH2* Res_pT_vs_pT{nullptr}; + TH2* Res_eta_vs_pT{nullptr}; + TH2* Res_phi_vs_pT{nullptr}; + std::vector<TH2*> Res_pT_vs_eta; + std::vector<TH2*> Res_pT_vs_phi; + std::vector<TH2*> Res_eta_vs_eta; + std::vector<TH2*> Res_phi_vs_phi; + +private: + std::string m_sType; + std::vector<std::string> m_pt_slices; + std::vector<double> m_etaBins; +}; + + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/SlowMuonValidationPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/SlowMuonValidationPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..49ce5af46d9ca4c2783b5f43c1adc92305f74282 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/SlowMuonValidationPlots.cxx @@ -0,0 +1,31 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SlowMuonValidationPlots.h" + +#include <iostream> + +#include "MuonHistUtils/MuonEnumDefs.h" + +typedef ElementLink<xAOD::MuonContainer> MuonLink; + +SlowMuonValidationPlots::SlowMuonValidationPlots(PlotBase* pParent, const std::string& sDir, bool isData) : + PlotBase(pParent, sDir), m_isData(isData) { + // histogram classes for all muons + m_oSlowMuonRecoPlots = std::make_unique<Muon::SlowMuonParamPlots>(this, "reco/AllMuons/parameters/"); + if (!m_isData) m_oSlowMuonMatchedPlots = std::make_unique< Muon::SlowMuonParamPlots>(this, "matched/AllMuons/parameters/"); +} + +SlowMuonValidationPlots::~SlowMuonValidationPlots() = default; + +void SlowMuonValidationPlots::fill(const xAOD::SlowMuon& smu, const xAOD::Muon& mu, float weight) { fillRecoMuonPlots(smu, mu, weight); } +void SlowMuonValidationPlots::fill(const xAOD::TruthParticle* truthMu, const xAOD::SlowMuon* smu, const xAOD::Muon* mu, float weight) { + if (smu) fillRecoMuonPlots(*smu, *mu, weight); + if ((smu) && (truthMu)) { m_oSlowMuonMatchedPlots->fill(*smu, weight); } +} + +void SlowMuonValidationPlots::fillRecoMuonPlots(const xAOD::SlowMuon& smu, const xAOD::Muon& /*mu*/, float weight) { + // fill hists for all muons + m_oSlowMuonRecoPlots->fill(smu, weight); +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/SlowMuonValidationPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/SlowMuonValidationPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..cc83bcfb11fa13664a2238d3e4f1dfc6742c4483 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/SlowMuonValidationPlots.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_SLOWMUONVALIDATIONPLOTS_H +#define MUONPHYSVALMONITORING_SLOWMUONVALIDATIONPLOTS_H + +#include "MuonHistUtils/SlowMuonParamPlots.h" +#include "xAODMuon/SlowMuon.h" +#include "xAODTruth/TruthParticle.h" + +class SlowMuonValidationPlots : public PlotBase { +public: + SlowMuonValidationPlots(PlotBase* pParent, const std::string& sDir, bool isData); + + virtual ~SlowMuonValidationPlots(); + void fill(const xAOD::SlowMuon& smu, const xAOD::Muon& mu, float weight = 1.0); + void fill(const xAOD::TruthParticle* truthMu, const xAOD::SlowMuon* smu, const xAOD::Muon* mu, float weight = 1.0); + + std::unique_ptr<Muon::SlowMuonParamPlots> m_oSlowMuonRecoPlots{}; + std::unique_ptr<Muon::SlowMuonParamPlots> m_oSlowMuonMatchedPlots{}; + +private: + void fillRecoMuonPlots(const xAOD::SlowMuon& smu, const xAOD::Muon& mu, float weight = 1.0); + void fillMatchedMuonPlots(const xAOD::SlowMuon& smu, const xAOD::Muon& mu, float weight = 1.0); + + bool m_isData; +}; + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerEfficiencyPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerEfficiencyPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e1dae3128ad97eead041e499a3f4cc862485cc84 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerEfficiencyPlots.cxx @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TriggerEfficiencyPlots.h" + +TriggerEfficiencyPlots::TriggerEfficiencyPlots(PlotBase* pParent, const std::string& sDir) : + PlotBase(pParent, sDir), + m_pDenomPlots(this, "Denom/", "Muons"), + m_pNumPlots(this, "Numer/", "Muons"), + m_pFeatPlots(this, "Features/", "Muons"), + m_pDenomPlots_threshold(this, "DenomT/", "Muons"), + m_pNumPlots_threshold(this, "NumerT/", "Muons"), + m_pFeatPlots_threshold(this, "FeaturesT/", "Muons") {} + +void TriggerEfficiencyPlots::fillNumerator(const xAOD::Muon& mu, float Treshold) { + m_pNumPlots.fill(mu); + if (mu.pt() > Treshold) m_pNumPlots_threshold.fill(mu); +} + +void TriggerEfficiencyPlots::fillDenominator(const xAOD::Muon& mu, float Treshold) { + m_pDenomPlots.fill(mu); + if (mu.pt() > Treshold) m_pDenomPlots_threshold.fill(mu); +} + +void TriggerEfficiencyPlots::fillFeatures(const xAOD::Muon& mu, float Treshold) { + m_pFeatPlots.fill(mu); + if (mu.pt() > Treshold) m_pFeatPlots_threshold.fill(mu); +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerEfficiencyPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerEfficiencyPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..709c6fa2fe5a4677f0f2551d4b37939dfcf94163 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerEfficiencyPlots.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_TRIGGEREFFICIENCYPLOTS_H +#define MUONPHYSVALMONITORING_TRIGGEREFFICIENCYPLOTS_H + +#include "TrkValHistUtils/ParamPlots.h" +#include "TrkValHistUtils/PlotBase.h" +#include "xAODMuon/Muon.h" + +/// class holding Pt plots for Inner Detector RTT Validation and implementing fill methods +class TriggerEfficiencyPlots : public PlotBase { +public: + TriggerEfficiencyPlots(PlotBase* pParent, const std::string& dirName); + void fillNumerator(const xAOD::Muon& mu, float Treshold); + void fillDenominator(const xAOD::Muon& mu, float Treshold); + void fillFeatures(const xAOD::Muon& mu, float Treshold); + + Trk::ParamPlots m_pDenomPlots; + Trk::ParamPlots m_pNumPlots; + Trk::ParamPlots m_pFeatPlots; + + Trk::ParamPlots m_pDenomPlots_threshold; + Trk::ParamPlots m_pNumPlots_threshold; + Trk::ParamPlots m_pFeatPlots_threshold; +}; + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerMuonValidationPlots.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerMuonValidationPlots.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3ceaa5d22bf022f0164f6b54155d2fbfe440ffcd --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerMuonValidationPlots.cxx @@ -0,0 +1,294 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TriggerMuonValidationPlots.h" + +#include <utility> + +#include "MuonHistUtils/MuonEnumDefs.h" +TriggerMuonValidationPlots::TriggerMuonValidationPlots(PlotBase* pParent, const std::string& sDir, std::vector<unsigned int> authors, + bool /*isData*/, bool doTrigMuonL1Validation, bool doTrigMuonL2Validation, + bool doTrigMuonEFValidation, std::vector<std::vector<std::string>> ChainSeed, + std::vector<std::string> L1MuonItems) : + PlotBase(pParent, sDir), + m_selectedAuthors(std::move(authors)), + m_doTrigMuonL1Validation(doTrigMuonL1Validation), + m_doTrigMuonL2Validation(doTrigMuonL2Validation), + m_doTrigMuonEFValidation(doTrigMuonEFValidation), + m_ChainSeed(std::move(ChainSeed)), + m_L1MuonItems(std::move(L1MuonItems)) { + for (unsigned int i = 0; i < m_ChainSeed.size(); i++) { + m_chains.push_back(m_ChainSeed[i][0]); + m_seeds.push_back(m_ChainSeed[i][1]); + } + + if (m_doTrigMuonL1Validation) m_oL1TriggerMuonPlots = std::make_unique<L1TriggerMuonPlots>(this, "trigger/L1"); + if (m_doTrigMuonL2Validation) { + m_oL2TriggerMuonPlots.push_back(std::make_unique<HLTriggerMuonPlots>(this, "trigger/L2/StandAlone")); + m_oL2TriggerMuonPlots.push_back(std::make_unique<HLTriggerMuonPlots>(this, "trigger/L2/Combined")); + m_oL2TriggerMuonBarrelResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/L2/StandAlone/Resolution/BARREL/", "")); + m_oL2TriggerMuonBarrelResolutionPlots.push_back(std::make_unique<ResoTriggerMuonPlots>(this, "trigger/L2/Combined/Resolution/BARREL/", "")); + m_oL2TriggerMuonEndcapsResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/L2/StandAlone/Resolution/ENDCAPS/", "")); + m_oL2TriggerMuonEndcapsResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/L2/Combined/Resolution/ENDCAPS/", "")); + m_oL2TriggerMuonResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/L2/StandAlone/Resolution/WHOLE_DETECT/", "")); + m_oL2TriggerMuonResolutionPlots.push_back(std::make_unique<ResoTriggerMuonPlots>(this, "trigger/L2/Combined/Resolution/WHOLE_DETECT/", "")); + } + + // define a histogram class for each of the selected muon authors + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + std::string sAuthor = Muon::EnumDefs::toString((xAOD::Muon::Author)m_selectedAuthors[i]); + if (m_doTrigMuonEFValidation) m_oEFTriggerMuonPlots.push_back(std::make_unique<HLTriggerMuonPlots>(this, "trigger/EF/" + sAuthor)); + if (m_doTrigMuonEFValidation) + m_oEFTriggerMuonBarrelResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/EF/" + sAuthor + "/Resolution/BARREL/", "")); + if (m_doTrigMuonEFValidation) + m_oEFTriggerMuonEndcapsResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/EF/" + sAuthor + "/Resolution/ENDCAPS/", "")); + if (m_doTrigMuonEFValidation) + m_oEFTriggerMuonResolutionPlots.push_back( + std::make_unique<ResoTriggerMuonPlots>(this, "trigger/EF/" + sAuthor + "/Resolution/WHOLE_DETECT/", "")); + } + + for (unsigned int i = 0; i < m_L1MuonItems.size(); i++) { + if (m_doTrigMuonEFValidation) + m_oL1TriggerChainBarrelEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_L1MuonItems[i] + "_Efficiency/BARREL/")); + if (m_doTrigMuonEFValidation) + m_oL1TriggerChainEndcapsEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_L1MuonItems[i] + "_Efficiency/ENDCAPS/")); + if (m_doTrigMuonEFValidation) + m_oL1TriggerChainEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_L1MuonItems[i] + "_Efficiency/WHOLE_DETECT/")); + } + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_doTrigMuonEFValidation) + m_oEFTriggerChainBarrelEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_chains[i] + "_Efficiency/BARREL/")); + if (m_doTrigMuonEFValidation) + m_oEFTriggerChainEndcapsEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_chains[i] + "_Efficiency/ENDCAPS/")); + if (m_doTrigMuonEFValidation) + m_oEFTriggerChainEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_chains[i] + "_Efficiency/WHOLE_DETECT/")); + } + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_doTrigMuonEFValidation) + m_oEFTriggerChainBarrelRELEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_chains[i] + "_wrt_" + m_seeds[i] + "_Efficiency/BARREL/")); + if (m_doTrigMuonEFValidation) + m_oEFTriggerChainEndcapsRELEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_chains[i] + "_wrt_" + m_seeds[i] + "_Efficiency/ENDCAPS/")); + if (m_doTrigMuonEFValidation) + m_oEFTriggerChainRELEfficiencyPlots.push_back( + std::make_unique<TriggerEfficiencyPlots>(this, "trigger/" + m_chains[i] + "_wrt_" + m_seeds[i] + "_Efficiency/WHOLE_DETECT/")); + } + PlateauTreshold = 0.; +} + +TriggerMuonValidationPlots::~TriggerMuonValidationPlots() = default; + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::MuonRoI& TrigL1mu) { m_oL1TriggerMuonPlots->fill(TrigL1mu); } + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::L2StandAloneMuon& L2SAmu) { m_oL2TriggerMuonPlots[0]->fill(L2SAmu); } + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::L2CombinedMuon& L2CBmu) { m_oL2TriggerMuonPlots[1]->fill(L2CBmu); } + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::Muon& Trigmu) { + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + if (Trigmu.isAuthor((xAOD::Muon::Author)m_selectedAuthors[i])) { + // if (Trigmu.isAuthor( (xAOD::Muon::Author)m_selectedAuthors[i] ) || m_selectedAuthors[i]==xAOD::Muon::NumberOfMuonAuthors) { + m_oEFTriggerMuonPlots[i]->fill(Trigmu); + } + } +} + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::Muon& Trigmu, const xAOD::Muon& Recomu) { + for (unsigned int i = 0; i < m_selectedAuthors.size(); i++) { + if (Trigmu.isAuthor((xAOD::Muon::Author)m_selectedAuthors[i])) { + // if (Trigmu.isAuthor( (xAOD::Muon::Author)m_selectedAuthors[i] ) || m_selectedAuthors[i]==xAOD::Muon::NumberOfMuonAuthors) { + m_oEFTriggerMuonResolutionPlots[i]->fill(Trigmu, Recomu); + if (std::abs(Recomu.eta()) < 1.05) m_oEFTriggerMuonBarrelResolutionPlots[i]->fill(Trigmu, Recomu); + if (std::abs(Recomu.eta()) > 1.05) m_oEFTriggerMuonEndcapsResolutionPlots[i]->fill(Trigmu, Recomu); + } + } +} + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::L2StandAloneMuon& L2SAmu, const xAOD::Muon& Recomu) { + m_oL2TriggerMuonResolutionPlots[0]->fill(L2SAmu, Recomu); + if (std::abs(Recomu.eta()) < 1.05) m_oL2TriggerMuonBarrelResolutionPlots[0]->fill(L2SAmu, Recomu); + if (std::abs(Recomu.eta()) > 1.05) m_oL2TriggerMuonEndcapsResolutionPlots[0]->fill(L2SAmu, Recomu); +} + +void TriggerMuonValidationPlots::fillTriggerMuonPlots(const xAOD::L2CombinedMuon& L2CBmu, const xAOD::Muon& Recomu) { + m_oL2TriggerMuonResolutionPlots[1]->fill(L2CBmu, Recomu); + if (std::abs(Recomu.eta()) < 1.05) m_oL2TriggerMuonBarrelResolutionPlots[1]->fill(L2CBmu, Recomu); + if (std::abs(Recomu.eta()) > 1.05) m_oL2TriggerMuonEndcapsResolutionPlots[1]->fill(L2CBmu, Recomu); +} + +void TriggerMuonValidationPlots::fill(const xAOD::Muon& Trigmu) { fillTriggerMuonPlots(Trigmu); } + +void TriggerMuonValidationPlots::fill(const xAOD::Muon& Trigmu, const xAOD::Muon& Recomu) { fillTriggerMuonPlots(Trigmu, Recomu); } + +void TriggerMuonValidationPlots::fill(const xAOD::L2StandAloneMuon& L2SAmu, const xAOD::Muon& Recomu) { + fillTriggerMuonPlots(L2SAmu, Recomu); +} + +void TriggerMuonValidationPlots::fill(const xAOD::L2CombinedMuon& L2CBmu, const xAOD::Muon& Recomu) { + fillTriggerMuonPlots(L2CBmu, Recomu); +} + +void TriggerMuonValidationPlots::fill(const xAOD::MuonRoI& TrigL1mu) { fillTriggerMuonPlots(TrigL1mu); } + +void TriggerMuonValidationPlots::fill(const xAOD::L2StandAloneMuon& L2SAmu) { fillTriggerMuonPlots(L2SAmu); } + +void TriggerMuonValidationPlots::fill(const xAOD::L2CombinedMuon& L2CBmu) { fillTriggerMuonPlots(L2CBmu); } + +void TriggerMuonValidationPlots::fillNumEff(const xAOD::Muon& mu, const std::string& selectedChain) { + float PlateauTreshold = findTrigTreshold(selectedChain); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_chains[i] == selectedChain) { + m_oEFTriggerChainEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) m_oEFTriggerChainBarrelEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) m_oEFTriggerChainEndcapsEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + } + } +} + +void TriggerMuonValidationPlots::fillDenEff(const xAOD::Muon& mu, const std::string& selectedChain) { + float PlateauTreshold = findTrigTreshold(selectedChain); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_chains[i] == selectedChain) { + m_oEFTriggerChainEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) + m_oEFTriggerChainBarrelEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) + m_oEFTriggerChainEndcapsEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + } + } +} + +void TriggerMuonValidationPlots::fillFeatPlots(const xAOD::Muon& mu, const std::string& selectedChain) { + float PlateauTreshold = findTrigTreshold(selectedChain); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_chains[i] == selectedChain) { + m_oEFTriggerChainEfficiencyPlots[i]->fillFeatures(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) m_oEFTriggerChainBarrelEfficiencyPlots[i]->fillFeatures(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) m_oEFTriggerChainEndcapsEfficiencyPlots[i]->fillFeatures(mu, PlateauTreshold); + } + } +} + +void TriggerMuonValidationPlots::fillNumL1Eff(const xAOD::Muon& mu, const std::string& selectedL1MuonItem) { + float PlateauTreshold = findTrigTreshold(selectedL1MuonItem); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_L1MuonItems.size(); i++) { + if (m_L1MuonItems[i] == selectedL1MuonItem) { + m_oL1TriggerChainEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) m_oL1TriggerChainBarrelEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) m_oL1TriggerChainEndcapsEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + } + } +} + +void TriggerMuonValidationPlots::fillDenL1Eff(const xAOD::Muon& mu, const std::string& selectedL1MuonItem) { + float PlateauTreshold = findTrigTreshold(selectedL1MuonItem); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_L1MuonItems.size(); i++) { + if (m_L1MuonItems[i] == selectedL1MuonItem) { + m_oL1TriggerChainEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) + m_oL1TriggerChainBarrelEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) + m_oL1TriggerChainEndcapsEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + } + } +} +void TriggerMuonValidationPlots::fillFeatPlots(const xAOD::MuonRoI& TrigL1mu, const std::string& selectedL1MuonItem) { + float PlateauTreshold = findTrigTreshold(selectedL1MuonItem); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + xAOD::MuonContainer* ROIinMuons = new xAOD::MuonContainer; + xAOD::MuonAuxContainer* ROIinMuonsAux = new xAOD::MuonAuxContainer; + ROIinMuons->setStore(ROIinMuonsAux); + xAOD::Muon* myROI = new xAOD::Muon(); + ROIinMuons->push_back(myROI); + myROI->setP4(TrigL1mu.thrValue(), TrigL1mu.eta(), TrigL1mu.phi()); + + for (unsigned int i = 0; i < m_L1MuonItems.size(); i++) { + if (m_L1MuonItems[i] == selectedL1MuonItem) { + m_oL1TriggerChainEfficiencyPlots[i]->fillFeatures(*myROI, PlateauTreshold); + if (((TrigL1mu.eta()) > -1.05) && ((TrigL1mu.eta()) < 1.05)) + m_oL1TriggerChainBarrelEfficiencyPlots[i]->fillFeatures(*myROI, PlateauTreshold); + if (((TrigL1mu.eta()) < -1.05) || ((TrigL1mu.eta()) > 1.05)) + m_oL1TriggerChainEndcapsEfficiencyPlots[i]->fillFeatures(*myROI, PlateauTreshold); + } + } + delete ROIinMuons; + delete ROIinMuonsAux; +} + +void TriggerMuonValidationPlots::fillDenRELEff(const xAOD::Muon& mu, const std::string& selectedChain) { + float PlateauTreshold = findTrigTreshold(selectedChain); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_chains[i] == selectedChain) { + m_oEFTriggerChainRELEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) + m_oEFTriggerChainBarrelRELEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) + m_oEFTriggerChainEndcapsRELEfficiencyPlots[i]->fillDenominator(mu, PlateauTreshold); + } + } +} + +void TriggerMuonValidationPlots::fillNumRELEff(const xAOD::Muon& mu, const std::string& selectedChain) { + float PlateauTreshold = findTrigTreshold(selectedChain); + PlateauTreshold = PlateauTreshold * 1000. * 1.05; + for (unsigned int i = 0; i < m_chains.size(); i++) { + if (m_chains[i] == selectedChain) { + m_oEFTriggerChainRELEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + if (((mu.eta()) > -1.05) && ((mu.eta()) < 1.05)) + m_oEFTriggerChainBarrelRELEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + if (((mu.eta()) < -1.05) || ((mu.eta()) > 1.05)) + m_oEFTriggerChainEndcapsRELEfficiencyPlots[i]->fillNumerator(mu, PlateauTreshold); + } + } +} + +float TriggerMuonValidationPlots::findTrigTreshold(const TString& chain) { + float PlateauTreshold; + std::string str(chain); + TString temp; + if (str.find("HLT_") != std::string::npos) { + for (unsigned int l = 0; l < str.size(); l++) { + if (isdigit(str[l])) { + for (unsigned int a = l; a < str.size(); a++) { + // if (str[a]=='_') break; + if ((isdigit(str[a])) == 0) break; + temp += str[a]; + } + break; + } + } + } + if (str.find("L1_MU") != std::string::npos) { + for (unsigned int l = 0; l < str.size(); l++) { + if ((str[l]) == 'U') { + for (unsigned int a = l + 1; a < str.size(); a++) { + // if (str[a]=='_') break; + temp += str[a]; + } + break; + } + } + } + PlateauTreshold = temp.Atof(); + return PlateauTreshold; +} diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerMuonValidationPlots.h b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerMuonValidationPlots.h new file mode 100644 index 0000000000000000000000000000000000000000..ed0606bb8f2ae1b11ec6e7b10af08e6f2b91d7d0 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/TriggerMuonValidationPlots.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MUONPHYSVALMONITORING_TRIGGERMUONVALIDATIONPLOTS_H +#define MUONPHYSVALMONITORING_TRIGGERMUONVALIDATIONPLOTS_H + +#include "MuonHistUtils/HLTriggerMuonPlots.h" +#include "MuonHistUtils/L1TriggerMuonPlots.h" +#include "ResoTriggerMuonPlots.h" +#include "TriggerEfficiencyPlots.h" +#include "xAODMuon/Muon.h" +#include "xAODMuon/MuonAuxContainer.h" +#include "xAODMuon/MuonContainer.h" +#include "xAODTrigMuon/L2CombinedMuon.h" +#include "xAODTrigMuon/L2StandAloneMuon.h" +#include "xAODTrigger/MuonRoI.h" + +class TriggerMuonValidationPlots : public PlotBase { +public: + TriggerMuonValidationPlots(PlotBase* pParent, const std::string& sDir, std::vector<unsigned int> authors, bool isData, + bool doTrigMuonL1Validation, bool doTrigMuonL2Validation, bool doTrigMuonEFValidation, + std::vector<std::vector<std::string>> ChainSeed, std::vector<std::string> L1MuonItems); + + float PlateauTreshold; + virtual ~TriggerMuonValidationPlots(); + void fill(const xAOD::MuonRoI& TrigL1mu); + void fill(const xAOD::L2StandAloneMuon& L2SAmu); + void fill(const xAOD::L2CombinedMuon& L2CBmu); + void fill(const xAOD::Muon& Trigmu); + void fill(const xAOD::Muon& Trigmu, const xAOD::Muon& Recomu); + void fill(const xAOD::L2StandAloneMuon& L2SAmu, const xAOD::Muon& Recomu); + void fill(const xAOD::L2CombinedMuon& L2CBmu, const xAOD::Muon& Recomu); + void fillNumEff(const xAOD::Muon& Trigmu, const std::string& selectedChain); + void fillDenEff(const xAOD::Muon& Trigmu, const std::string& selectedChain); + void fillNumL1Eff(const xAOD::Muon& Trigmu, const std::string& selectedChain); + void fillDenL1Eff(const xAOD::Muon& Trigmu, const std::string& selectedChain); + void fillFeatPlots(const xAOD::Muon& Trigmu, const std::string& selectedChain); + void fillFeatPlots(const xAOD::MuonRoI& TrigL1mu, const std::string& selectedChain); + void fillDenRELEff(const xAOD::Muon& Trigmu, const std::string& selectedChain); + void fillNumRELEff(const xAOD::Muon& Trigmu, const std::string& selectedChain); + + std::vector<unsigned int> m_selectedAuthors; + std::vector<std::string> m_chains; + std::vector<std::string> m_seeds; + std::unique_ptr<L1TriggerMuonPlots> m_oL1TriggerMuonPlots{}; + std::vector<std::unique_ptr<HLTriggerMuonPlots>> m_oEFTriggerMuonPlots; + std::vector<std::unique_ptr<HLTriggerMuonPlots>> m_oL2TriggerMuonPlots; + std::vector<std::unique_ptr<ResoTriggerMuonPlots>> m_oEFTriggerMuonBarrelResolutionPlots; + std::vector<std::unique_ptr<ResoTriggerMuonPlots>> m_oEFTriggerMuonEndcapsResolutionPlots; + std::vector<std::unique_ptr<ResoTriggerMuonPlots>> m_oEFTriggerMuonResolutionPlots; + std::vector<std::unique_ptr<ResoTriggerMuonPlots>> m_oL2TriggerMuonBarrelResolutionPlots; + std::vector<std::unique_ptr<ResoTriggerMuonPlots>> m_oL2TriggerMuonEndcapsResolutionPlots; + std::vector<std::unique_ptr<ResoTriggerMuonPlots>> m_oL2TriggerMuonResolutionPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oL1TriggerChainEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oL1TriggerChainBarrelEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oL1TriggerChainEndcapsEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oEFTriggerChainEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oEFTriggerChainBarrelEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oEFTriggerChainEndcapsEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oEFTriggerChainRELEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oEFTriggerChainBarrelRELEfficiencyPlots; + std::vector<std::unique_ptr<TriggerEfficiencyPlots>> m_oEFTriggerChainEndcapsRELEfficiencyPlots; + +private: + void fillTriggerMuonPlots(const xAOD::Muon& Trigmu); + void fillTriggerMuonPlots(const xAOD::Muon& Trigmu, const xAOD::Muon& Recomu); + void fillTriggerMuonPlots(const xAOD::L2StandAloneMuon& L2SAmu, const xAOD::Muon& Recomu); + void fillTriggerMuonPlots(const xAOD::L2CombinedMuon& L2CBmu, const xAOD::Muon& Recomu); + void fillTriggerMuonPlots(const xAOD::MuonRoI& TrigL1mu); + void fillTriggerMuonPlots(const xAOD::L2StandAloneMuon& L2SAmu); + void fillTriggerMuonPlots(const xAOD::L2CombinedMuon& L2CBmu); + float findTrigTreshold(const TString& chain); + + bool m_doTrigMuonL1Validation; + bool m_doTrigMuonL2Validation; + bool m_doTrigMuonEFValidation; + std::vector<std::vector<std::string>> m_ChainSeed; + std::vector<std::string> m_L1MuonItems; +}; + +#endif diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/components/LRTMuonPhysValMon_entries.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/components/LRTMuonPhysValMon_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c2a35c584235d049eeaf812eee05db273a32ea32 --- /dev/null +++ b/MuonSpectrometer/MuonValidation/MuonDQA/LRTMuonPhysValMonitoring/src/components/LRTMuonPhysValMon_entries.cxx @@ -0,0 +1,3 @@ +#include "../LRTMuonPhysValMonitoringTool.h" + +DECLARE_COMPONENT(LRTMuonPhysValMonitoring::LRTMuonPhysValMonitoringTool) diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/scripts/runMuonPhysVal.py b/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/scripts/runMuonPhysVal.py index 06f851926f2a432d27b6748d94aaf2e1d289120d..6cb0e8773337df770c37eb1d08bb9b1efa46394a 100755 --- a/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/scripts/runMuonPhysVal.py +++ b/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/scripts/runMuonPhysVal.py @@ -31,6 +31,13 @@ from MuonPhysValMonitoring.MuonPhysValConfig import PhysValMuonCfg from PhysValMonitoring.PhysValMonitoringConfig import PhysValMonitoringCfg acc.merge(PhysValMonitoringCfg(flags, tools=[acc.popToolsAndMerge(PhysValMuonCfg(flags))])) +#LRTMuons +#from LRTMuonPhysValMonitoring.LRTMuonPhysValConfig import PhysValLRTMuonCfg +#from PhysValMonitoring.PhysValMonitoringConfig import PhysValMonitoringCfg +#acc.merge(PhysValMonitoringCfg(flags, tools=[acc.popToolsAndMerge(PhysValLRTMuonCfg(flags))])) + + + acc.printConfig(withDetails=True) # Execute and finish diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.cxx b/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.cxx index 0faec05dd5ffa98dd6757cb7b73e0caa87e6191b..4eb10fcbec489f0eaff59afcb5fefab8b0c47cde 100644 --- a/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.cxx +++ b/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.cxx @@ -98,6 +98,9 @@ namespace MuonPhysValMonitoring { return StatusCode::SUCCESS; } + + + StatusCode MuonPhysValMonitoringTool::bookHistograms() { ATH_MSG_INFO("Booking hists " << name() << "..."); @@ -121,9 +124,11 @@ namespace MuonPhysValMonitoring { std::string muonContainerName = m_muonsName; for (const auto& category : m_selectMuonCategoriesStr) { std::string categoryPath = m_muonsName + "/" + category + "/"; + m_muonValidationPlots.emplace_back(std::make_unique<MuonValidationPlots>( nullptr, categoryPath, m_selectMuonWPs, m_selectMuonAuthors, m_isData, (category == theMuonCategories.at(ALL) ? false : m_doBinnedResolutionPlots.value()), separateSAFMuons, m_doMuonTree)); + if (!m_slowMuonsName.empty()) m_slowMuonValidationPlots.emplace_back(std::make_unique<SlowMuonValidationPlots>(nullptr, categoryPath, m_isData)); if (m_doTrigMuonValidation) { if (category == "All") { @@ -227,7 +232,7 @@ namespace MuonPhysValMonitoring { } return StatusCode::SUCCESS; - } + }//bookHistograms*/ StatusCode MuonPhysValMonitoringTool::bookValidationPlots(PlotBase& valPlots) { valPlots.initialize(); @@ -847,7 +852,7 @@ namespace MuonPhysValMonitoring { } // m_doTrigMuonEFValidation } return StatusCode::SUCCESS; - } + }//fillHistograms()*/ void MuonPhysValMonitoringTool::handleTruthMuonSegment(const xAOD::MuonSegment* truthMuSeg, const xAOD::TruthParticleContainer* /*muonTruthContainer*/, float weight) { @@ -1356,7 +1361,7 @@ namespace MuonPhysValMonitoring { } return StatusCode::SUCCESS; - } + }//procHistograms*/ const xAOD::MuonSegment* MuonPhysValMonitoringTool::findRecoMuonSegment(const xAOD::MuonSegment* truthMuSeg) { if (!truthMuSeg->isAvailable<MuonSegmentLink>("recoSegmentLink")) { @@ -1439,6 +1444,20 @@ namespace MuonPhysValMonitoring { void MuonPhysValMonitoringTool::modifyHistogram(TH1* hist) { std::string histname = hist->GetName(); + if (histname.find("parameters_z0") != std::string::npos) { + hist->GetXaxis()->Set(80, -200., 200.); + } + + if (histname.find("parameters_d0") != std::string::npos) { + hist->GetXaxis()->Set(80, -1., 1.); + hist->GetYaxis()->SetTitle("Entries / 0.025 mm"); + + } + if (histname.find("parameters_d0_small") != std::string::npos) { + hist->GetXaxis()->Set(80, -0.1, 0.1); + hist->GetYaxis()->SetTitle("Entries / 0.0025 mm"); + } + if (histname.find("trigger_L1_pt") != std::string::npos) { // if (histname=="Muons_All_trigger_L1_pt"){ hist->SetTitle("L1Trigger Muons pt treshold"); hist->GetXaxis()->SetTitle("L1Trigger Muons pt treshold [GeV]"); diff --git a/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.h b/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.h index 1efd3269436125821c9d4f095baa62fb90070b05..c996ad9ee0dbd4d26c6dfc3f64ab2b113106f5be 100644 --- a/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.h +++ b/MuonSpectrometer/MuonValidation/MuonDQA/MuonPhysValMonitoring/src/MuonPhysValMonitoringTool.h @@ -119,6 +119,7 @@ namespace MuonPhysValMonitoring { Gaudi::Property<std::string> m_tracksName{this, "TrackContainerName", "InDetTrackParticles"}; Gaudi::Property<std::string> m_fwdtracksName{this, "FwdTrackContainerName", ""}; Gaudi::Property<std::string> m_muonsName{this, "MuonContainerName", "Muons"}; + //Gaudi::Property<std::string> m_muonsName{this, "MuonContainerName", "MuonsLRT"}; Gaudi::Property<std::string> m_slowMuonsName{this, "SlowMuonContainerName", "SlowMuons"}; Gaudi::Property<std::string> m_muonsTruthName{this, "MuonTruthParticleContainerName", "MuonTruthParticles"}; Gaudi::Property<std::string> m_muonTracksName{this, "MuonTrackContainerName", "MuonSpectrometerTrackParticles"}; diff --git a/PhysicsAnalysis/PhysicsValidation/PhysValMonitoring/share/PhysValLRTMuon_jobOptions.py b/PhysicsAnalysis/PhysicsValidation/PhysValMonitoring/share/PhysValLRTMuon_jobOptions.py new file mode 100644 index 0000000000000000000000000000000000000000..e22014250ee05ded2f9dd91684be0c4261dc45c5 --- /dev/null +++ b/PhysicsAnalysis/PhysicsValidation/PhysValMonitoring/share/PhysValLRTMuon_jobOptions.py @@ -0,0 +1,92 @@ +from AthenaCommon.CfgGetter import getPublicTool +getPublicTool("MuonCombinedInDetDetailedTrackSelectorTool") + +algseq = CfgMgr.AthSequencer("AthAlgSeq") + +from PyUtils.MetaReader import read_metadata +from AthenaCommon.AppMgr import ServiceMgr as svcMgr +try: + input_file = svcMgr.EventSelector.InputCollections[0] +except AttributeError: + from AthenaCommon.AthenaCommonFlags import athenaCommonFlags + input_file = athenaCommonFlags.FilesInput()[0] +metadata = read_metadata(input_file) +metadata = metadata[input_file] # promote all keys one level up + +isDAOD_PHYSVAL=False +for class_name, name in metadata['metadata_items'].items(): + if name == 'EventStreamInfo': + if "DAOD_PHYSVAL" in class_name : + print ("Running on DAOD_PHYSVAL - will not add TTVA decorations.") + isDAOD_PHYSVAL=True + +if not isDAOD_PHYSVAL: + from IsolationAlgs.IsoUpdatedTrackCones import GetUpdatedIsoTrackCones + if not hasattr(algseq,"IsolationBuilderNonprompt_All_MaxWeight500"): + ToolSvc += CfgMgr.InDet__InDetUsedInFitTrackDecoratorTool( name = algseq.name()+"_InDetUsedInFitDecoratorTool_forIso", + AMVFVerticesDecoName = 'TTVA_AMVFVertices', + AMVFWeightsDecoName = 'TTVA_AMVFWeights', + TrackContainer = 'InDetTrackParticles', + VertexContainer = 'PrimaryVertices' ) + algseq += CfgMgr.InDet__InDetUsedInVertexFitTrackDecorator(name = algseq.name()+"_InDetUsedInFitDecorator_forIso", + UsedInFitDecoratorTool = getattr(ToolSvc, algseq.name()+"_InDetUsedInFitDecoratorTool_forIso") ) + algseq += GetUpdatedIsoTrackCones() + +from LRTMuonPhysValMonitoring.LRTMuonPhysValMonitoringConf import LRTMuonPhysValMonitoring__LRTMuonPhysValMonitoringTool +from RecExConfig.RecFlags import rec as recFlags + +tool1 = LRTMuonPhysValMonitoring__LRTMuonPhysValMonitoringTool( name = 'lrtmuphysval' ) +tool1.IsData = not recFlags.doTruth() + +#add if you need any of the following containers +#tool1.FwdTrackContainerName='InDetForwardTrackParticles' +tool1.SlowMuonContainerName = '' + +tool1.SelectHLTMuonItems = [ + ["HLT_mu20","L1_MU20"], + ["HLT_mu20_iloose_L1MU15","L1_MU15"], + ["HLT_mu24","L1_MU20"], + ["HLT_mu24_iloose_L1MU15","L1_MU15"], + ["HLT_mu24_imedium","L1_MU20"], + ["HLT_mu26","L1_MU20"], + ["HLT_mu26_imedium","L1_MU20"], + ["HLT_mu50","L1_MU20"] +] + +tool1.SelectL1MuonItems = [ + "L1_MU4", + "L1_MU6", + "L1_MU10", + "L1_MU11", + "L1_MU15", + "L1_MU20" +] + +#Select Muon Working Points... (empty: all, -1: None, 0: Tight, 1: Medium, 2: Loose, 3: VeryLoose) +tool1.SelectMuonWorkingPoints = [0, 1, 2 ] + +#Select Muon Authors... (empty: all authors, 0: None, 1: combined, 2: STACO, 4: MuTagIMO, 5: Standalone, 6: MuGirl, 8: CaloTag, 10: CaloScore) +#tool1.SelectMuonAuthors = [ 1, 2, 4, 5, 6, 8, 10 ] +tool1.SelectMuonAuthors = [ 1 ] + +#Select Muon Categories... (origin of muons, empty: all categories, 0: ALL, 1: PROMPT, 2: IN-FLIGHT, 3: NON-ISOLATED, 4: REST) +#tool1.SelectMuonCategories = [ 0, 1 ] # lighter version, good for official validation tasks overriden when in data mode +tool1.SelectMuonCategories = [ 0 ] # lighter version, good for official validation tasks overriden when in data mode + +if not recFlags.doTruth(): + tool1.SelectMuonCategories = [0, 1, 4] + +from IsolationSelection.IsolationSelectionConf import CP__IsolationSelectionTool +IsolationTool = CP__IsolationSelectionTool( "IsolationSelectionTool", + MuonWP = "PflowTight_FixedRad") +ToolSvc += IsolationTool +tool1.IsoTool = IsolationTool +tool1.EnableLumi = False +tool1.OutputLevel = WARNING +tool1.DetailLevel = 10 + +#Flag for saving a ROOT TTree in an output ntuple... default value is False --> no TTree is saved +#tool1.DoMuonTree = True + +monMan = CfgMgr.AthenaMonManager("PhysValMonManager") +monMan.AthenaMonTools += [ tool1 ] diff --git a/Tracking/TrkValidation/TrkValHistUtils/Root/ImpactPlots.cxx b/Tracking/TrkValidation/TrkValHistUtils/Root/ImpactPlots.cxx index 225d8bcf25c2496bb4524c55b7f432db442b8be3..f760233244dd09fa21a4f356f3b03be7aecf4271 100644 --- a/Tracking/TrkValidation/TrkValHistUtils/Root/ImpactPlots.cxx +++ b/Tracking/TrkValidation/TrkValHistUtils/Root/ImpactPlots.cxx @@ -16,9 +16,9 @@ namespace Trk { void ImpactPlots::initializePlots() { - z0 = Book1D("z0", "z0;Signed Impact Parameter z0 (mm);Entries / 5 mm", 80, -200, 200); + z0 = Book1D("z0", "z0;Signed Impact Parameter z0 (mm);Entries / 5 mm", 120, -300, 300); // z0sig = Book1D("z0sig","z0sig,;Signed Impact Parameter Significance; Entries / 0.1", 100, 0, 10); - d0 = Book1D("d0", "d0;Signed Impact Parameter d0 (mm);Entries / 0.025 mm", 80, -1, 1); + d0 = Book1D("d0", "d0;Signed Impact Parameter d0 (mm);Entries / 2.5 mm", 240, -300, 300); // d0sig = Book1D("d0sig","d0sig,;Signed Impact Parameter Significance; Entries / 0.1", 100, 0, 10); d0_small = Book1D("d0_small", "d0;Signed Impact Parameter d0 (mm);Entries / 0.0025 mm", 80, -0.1, 0.1); }