diff --git a/PhysicsAnalysis/NtupleDumper/scripts/analyzeRun.py b/PhysicsAnalysis/NtupleDumper/scripts/analyzeRun.py index fcee52fbc227a9746d5b45d285295ccfeae95736..8a47857614ebb70589ed7cb5ab6ca20aef91c878 100755 --- a/PhysicsAnalysis/NtupleDumper/scripts/analyzeRun.py +++ b/PhysicsAnalysis/NtupleDumper/scripts/analyzeRun.py @@ -56,8 +56,10 @@ if __name__ == "__main__": Configurable.configurableRun3Behavior = True dataDir=f"/eos/experiment/faser/rec/2022/{ptag}/{runno:06d}" - files=sorted(glob.glob(f"{dataDir}/Faser-Physics*")) - fileListInitial=files[num*filesPerJob:(num+1)*filesPerJob] + if inputIsMC: dataDir=f"/eos/experiment/faser/sim/mdc/foresee/{ui.runnum}/rec/r0009/" + files=sorted(glob.glob(f"{dataDir}/Faser*")) + if num==-1: num=len(files) + fileListInitial=files[0:num]#[num*filesPerJob:(num+1)*filesPerJob] fileList=[] for fName in fileListInitial: try: @@ -66,7 +68,7 @@ if __name__ == "__main__": except OSError: print("Warning bad file: ",fName) - log.info(f"Analyzing Run {runno} files {num*filesPerJob} to {(num+1)*filesPerJob} (num={num})") + log.info(f"Analyzing Run {runno} files {0} to {num} (num={num})") log.info(f"Got {len(fileList)} files out of {len(fileListInitial)}") outName=f"Data-tuple-{runno:06d}-{num:05d}-{filesPerJob}.root" @@ -76,7 +78,7 @@ if __name__ == "__main__": ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersionS ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig - ConfigFlags.Input.isMC = False # Needed to bypass autoconfig + ConfigFlags.Input.isMC = inputIsMC # Needed to bypass autoconfig ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # FASER geometry ConfigFlags.Common.isOnline = False ConfigFlags.GeoModel.Align.Dynamic = False @@ -98,11 +100,12 @@ if __name__ == "__main__": acc.addService(AthenaEventLoopMgr) # # Hack to avoid problem with our use of MC databases when isMC = False - replicaSvc = acc.getService("DBReplicaSvc") - replicaSvc.COOLSQLiteVetoPattern = "" - replicaSvc.UseCOOLSQLite = True - replicaSvc.UseCOOLFrontier = False - replicaSvc.UseGeomSQLite = True + if not inputIsMC: + replicaSvc = acc.getService("DBReplicaSvc") + replicaSvc.COOLSQLiteVetoPattern = "" + replicaSvc.UseCOOLSQLite = True + replicaSvc.UseCOOLFrontier = False + replicaSvc.UseGeomSQLite = True # Timing #acc.merge(MergeRecoTimingObjCfg(ConfigFlags)) @@ -119,7 +122,7 @@ if __name__ == "__main__": # ConfigFlags.dump() # Execute and finish - sc = acc.run(maxEvents=-1) + sc = acc.run(maxEvents=ui.events) # Success should be 0 sys.exit(not sc.isSuccess()) diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx index 9614de99c394407659689aea08630ed141cdbbb9..1369684d16f1071c2b5eab6e5853b87459d0e06a 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx @@ -136,6 +136,8 @@ StatusCode NtupleDumperAlg::initialize() } m_tree = new TTree("nt", "NtupleDumper tree"); + + //META INFORMATION m_tree->Branch("run", &m_run_number, "run/I"); m_tree->Branch("eventID", &m_event_number, "eventID/I"); m_tree->Branch("eventTime", &m_event_time, "eventTime/I"); @@ -156,6 +158,7 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("inputBits", &m_inputBits, "inputBits/I"); m_tree->Branch("inputBitsNext", &m_inputBitsNext, "inputBitsNext/I"); + //WAVEFORMS addWaveBranches("VetoNu",2,4); addWaveBranches("VetoSt1",2,6); addWaveBranches("VetoSt2",1,14); @@ -172,6 +175,7 @@ StatusCode NtupleDumperAlg::initialize() addBranch("Preshower_total_nMIP", &m_preshower_total_nMIP); addBranch("Preshower_total_E_dep", &m_preshower_total_E_dep); + //TRACKER addBranch("nClusters0",&m_station0Clusters); addBranch("nClusters1",&m_station1Clusters); addBranch("nClusters2",&m_station2Clusters); @@ -192,6 +196,7 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("TrackSegment_py", &m_trackseg_py); m_tree->Branch("TrackSegment_pz", &m_trackseg_pz); + //TrackCollection m_tree->Branch("longTracks", &m_longTracks, "longTracks/I"); m_tree->Branch("Track_Chi2", &m_Chi2); m_tree->Branch("Track_nDoF", &m_DoF); @@ -212,11 +217,13 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("Track_charge", &m_charge); m_tree->Branch("Track_nLayers", &m_nLayers); + //Which Stations were hit? m_tree->Branch("Track_InStation0",&m_nHit0); m_tree->Branch("Track_InStation1",&m_nHit1); m_tree->Branch("Track_InStation2",&m_nHit2); m_tree->Branch("Track_InStation3",&m_nHit3); + //Extrapolated Track Info m_tree->Branch("Track_X_atVetoNu", &m_xVetoNu); m_tree->Branch("Track_Y_atVetoNu", &m_yVetoNu); m_tree->Branch("Track_ThetaX_atVetoNu", &m_thetaxVetoNu); @@ -252,15 +259,20 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("Track_ThetaX_atCalo", &m_thetaxCalo); m_tree->Branch("Track_ThetaY_atCalo", &m_thetayCalo); + //TRUTH m_tree->Branch("t_pdg", &m_t_pdg); m_tree->Branch("t_barcode", &m_t_barcode); m_tree->Branch("t_truthHitRatio", &m_t_truthHitRatio); + m_tree->Branch("t_prodVtx_x", &m_t_prodVtx_x); m_tree->Branch("t_prodVtx_y", &m_t_prodVtx_y); m_tree->Branch("t_prodVtx_z", &m_t_prodVtx_z); + m_tree->Branch("t_decayVtx_x", &m_t_decayVtx_x); m_tree->Branch("t_decayVtx_y", &m_t_decayVtx_y); m_tree->Branch("t_decayVtx_z", &m_t_decayVtx_z); + + //Truth track info m_tree->Branch("t_px", &m_t_px); m_tree->Branch("t_py", &m_t_py); m_tree->Branch("t_pz", &m_t_pz); diff --git a/Tracker/TrackerRecAlgs/PairVertex/CMakeLists.txt b/Tracker/TrackerRecAlgs/PairVertex/CMakeLists.txt index ff270bb69c9defc70b31e5e50f8dbc93ffa3992f..07e4fc4065838c8e54104fdbb25625c4b0bb2d21 100644 --- a/Tracker/TrackerRecAlgs/PairVertex/CMakeLists.txt +++ b/Tracker/TrackerRecAlgs/PairVertex/CMakeLists.txt @@ -9,6 +9,7 @@ atlas_add_component( FaserActsGeometryLib TrackerSimEvent TrackerIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack xAODFaserWaveform ScintIdentifier FaserCaloIdentifier + FaserActsKalmanFilterLib ) atlas_install_python_modules(python/*.py) diff --git a/Tracker/TrackerRecAlgs/PairVertex/scripts/EfficiencyPlotter.py b/Tracker/TrackerRecAlgs/PairVertex/scripts/EfficiencyPlotter.py new file mode 100644 index 0000000000000000000000000000000000000000..8fc57cc162617b2d5c5b5b1bd6035329d95ea096 --- /dev/null +++ b/Tracker/TrackerRecAlgs/PairVertex/scripts/EfficiencyPlotter.py @@ -0,0 +1,53 @@ +from PlotHelper import * +from Utilities import * + +#Efficiency Plotters Seperate from General Plotter system. Maybe put this in its own script +def CutEfficiencyArrays(lmbda,dcutN=[],dcutD=[],lcutN=[],lcutD=[],title=None,bins=15,hmin=0,hmax=10000): + Func = lmbda # (Returns 1 value) + narray=[] + darray=[] + for event in t: + if ApplyAllCuts(event,dcutN,lcutN): narray+=[Func(event)] + if ApplyAllCuts(event,dcutD,lcutD): darray+=[Func(event)] + + PlotRootRatio([narray,darray],title=f"{user_input} {title}",bins=bins,hmin=hmin,hmax=hmax) + +def FiducialEff_vs_Rho2(): + l= lambda event: (event.vertexPos[0]**2)+(event.vertexPos[1]**2) + CutEfficiencyArrays(l,title='BothDFiducial vs TRho^2',bins=20,hmin=0,hmax=10000,lcutN=[lambda event: event.truthd0_IsFiducial[0] and event.truthd1_IsFiducial[0]]) + +def FiducialEff_vs_VertexZ(): + l= lambda event: event.vertexPos[2] + CutEfficiencyArrays(l,title='BothDFiducial vs TVertexZ',bins=20,hmin=-1600,hmax=0,lcutN=[lambda event: event.truthd0_IsFiducial[0] and event.truthd1_IsFiducial[0]]) + +EfficiencyDict={ + 'FiducialEff_vs_Rho2':{ + 'lambda': lambda event: (event.vertexPos[0]**2)+(event.vertexPos[1]**2), + 'kwargs':{'title':'BothDFiducial vs TRho^2', + 'bins':20,'hmin':0,'hmax':10000, + 'lcutN':[lambda event: event.truthd0_IsFiducial[0] and event.truthd1_IsFiducial[0]]} + }, + 'FiducialEff_vs_Rho2':{ + 'lambda': lambda event: event.vertexPos[2], + 'kwargs':{'title':'BothDFiducial vs TVertexZ', + 'bins':20,'hmin':-1600,'hmax':0, + 'lcutN':[lambda event: event.truthd0_IsFiducial[0] and event.truthd1_IsFiducial[0]]} + } +} + +def DoEfficiencyPlots(): + for k in EfficiencyDict.keys(): + print(k) + CutEfficiencyArrays(EfficiencyDict[k]['lambda'],**EfficiencyDict[k]['kwargs']) + +#EXECUTE +if __name__ == "__main__": + DP_fnames=['Ntuple_Aee_100MeV_1Em5_']# Ntuple_Aee_10MeV_1Em5_ Ntuple_Amm_316MeV_2Em6_ Ntuple_Aee_10MeV_1Em4_ + for f in DP_fnames: + user_input=f + t = TChain("events") + nfiles = 0 + nfiles += t.Add("/eos/home-s/sshively/CALYPZONE/run/BackUp2/"+user_input+".root") + print(f) + + DoEfficiencyPlots() \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/PairVertex/scripts/PairVertexReader.py b/Tracker/TrackerRecAlgs/PairVertex/scripts/PairVertexReader.py index 2468be886114912fa36555c88abaad99e8e77076..f585d0e61a539b8015ca4897b51f5a231c9804ac 100644 --- a/Tracker/TrackerRecAlgs/PairVertex/scripts/PairVertexReader.py +++ b/Tracker/TrackerRecAlgs/PairVertex/scripts/PairVertexReader.py @@ -1,587 +1,249 @@ #!/usr/bin/env python +from PlotHelper import * +from Utilities import * -# Set up (Py)ROOT. -from ROOT import TChain, TH2F, TH1F -print("Root loaded.") -import matplotlib.pyplot as plt -print("MPL loaded.") -from operator import lt,eq,ne,gt -from numpy import nan, seterr, inf,arctan,log10,logspace, histogram2d, meshgrid, ones_like,array -from numpy import sum as npsum -import numpy as np -from math import sqrt -from cmcrameri import cm -print("Other stuff loaded.") -seterr(all='ignore') -missingattr=[] - -#attr: [>,<,==,!=] if none --> skip -CUTDICT={ - 'TrackCount':[None,None,2,None], - 'VetoNu0_integral':[None,None,0,None], - 'VetoNu1_integral':[None,None,0,None], - 'VetoSt10_integral':[None,None,0,None], - 'VetoSt11_integral':[None,None,0,None], - 'VetoSt20_integral':[None,None,0,None], - 'nlayersHit':[6,None,None,None], - 'playersHit':[6,None,None,None], - 'niftHit':[None,None,0,None], - 'piftHit':[None,None,0,None], - 'pDoF':[0,None,None,None], - 'nDoF':[0,None,None,None], - 'Preshower0_integral':[0,None,None,None], - 'Preshower1_integral':[0,None,None,None] - } - -#CUT DICTIONARIES/LISTS -LAMBDACUTS=[ - lambda event : len(event.Tracks[0])==2, - lambda event : event.Tracks[0][0]==-1*event.Tracks[0][1], - lambda event : event.Timing0_integral+event.Timing1_integral+event.Timing2_integral+event.Timing3_integral>0, - lambda event : event.Calo0_integral+event.Calo1_integral+event.Calo2_integral+event.Calo3_integral>0, - lambda event : event.nChi2/event.nDoF <10 and event.pChi2/event.pDoF <10, - lambda event : sqrt((event.pMom[0]**2)+(event.pMom[1]**2)+(event.pMom[2]**2))>1] - -FIDUCIALCUT=[lambda event : event.vertexPos[2]>-1585 and event.vertexPos[2]<-45] - -BADCUT=list(LAMBDACUTS) -#BADCUT[4]=lambda event : event.nChi2/event.nDoF >10 and event.pChi2/event.pDoF >10 -#BADCUT[] - -HITCUT= [lambda event : all([abs(i)<200 for i in [event.pPos_S1L0[0],event.pPos_S1L0[1],event.nPos_S1L0[0],event.nPos_S1L0[1]]])] - - -#UTILITY -def configHitMap(arrayx,arrayy=[],xlabel="X (mm)",ylabel="Y (mm)",xlim=None,ylim=None,title=None,show=False): - plt.hist2d(arrayx, arrayy, bins=(50, 50), cmap=cm.imola) - plt.colorbar() - plt.xlabel(xlabel) - plt.ylabel(ylabel) - if xlim: plt.xlim(xlim) - if ylim: plt.ylim(ylim)#-100,100 - #plt.text(50,-185,"COUNTS: {}".format(len(arrayx))) - if title: plt.title(title) - if show: plt.show() - -def configHitMap2(arrays,bins=(50,50),xlabel="X (mm)",ylabel="Y (mm)",xlim=None,ylim=None,title=None,show=False): - arrayx=arrays[0] - arrayy=arrays[1] - plt.hist2d(arrayx, arrayy, bins=bins, cmap=cm.imola) - plt.colorbar() - plt.xlabel(xlabel) - plt.ylabel(ylabel) - if xlim: plt.xlim(xlim) - if ylim: plt.ylim(ylim)#-100,100 - #plt.text(50,-185,"COUNTS: {}".format(len(arrayx))) - if title: plt.title(title) - if show: plt.show() - -def configBasicHist(arr,bins=25,xscale='linear',yscale='linear',title=None,xlabel=None,legend=False,kwargs={}): - if len(arr)==0: - print("Empty array.") - return - if 'log' in xscale: - minx,maxx = (min(arr),max(arr)) - if minx==maxx: - maxx+=1 - bins=1 - bins = logspace(start=log10(minx), stop=log10(maxx), num=bins) - if xscale=='symlog': - bins = [0]+list(logspace(start=log10(1), stop=log10(maxx), num=24)) - if minx>1: bins = logspace(start=log10(minx), stop=log10(maxx), num=25) - - n, bins, patches = plt.hist(arr,bins=bins,align="left",histtype=u'step',**kwargs) - plt.xscale(xscale) - #plt.xticks([i for i in range(0,21)]) - if xlabel: plt.xlabel(xlabel) - plt.yscale(yscale) - plt.ylabel('Number of Events') - if legend: plt.legend() - if title:plt.title(title) +#Q/P METHODS +def GetPBounds(dcuts=[],lcuts=[]): + TotalTracks=0 + PArray=[] + for event in t: + if ApplyAllCuts(event,dcuts,lcuts): + TotalTracks+=event.TrackCount + PArray+=list(event.tracksTruthPmag) + Ilims=[int(i*TotalTracks/10) for i in range(11)] + PArray.sort() + Plims=[0]+[PArray[i] for i in Ilims] + return Plims + +#Q/P P bounds entered manually because storing them was weird in dictionary generation +PH = [191909.7203710638, 248751.19099289246] +PHr=0.02 +def MakeNewQPDicts(Plims=None): + newdict=dict() + basename='AllTracksQP' + dictbase={ + 'array':[], + 'lambda': GetAllTrackQPReco, + 'plotterfunc': configBasicHist, + 'plotkwargs' :{'bins':100,'kwargs':{'range':[-1*PHr,PHr]}}} #[2*-10**-3,2*10**-3] - return n,bins - -def configMultiHist(arrlist,bins=25,xscale='linear',yscale='linear',title=None,xlabel=None,label=[],legend=True,kwargs={}): - megarr=[] - for a in arrlist: megarr+=a - if 'log' in xscale: - minx,maxx = (min(megarr),max(megarr)) - if minx==maxx: - maxx+=1 - bins=1 - bins = logspace(start=log10(minx), stop=log10(maxx), num=bins) - if xscale=='symlog': - bins = [0]+list(logspace(start=log10(1), stop=log10(maxx), num=24)) - if minx>1: bins = logspace(start=log10(minx), stop=log10(maxx), num=25) - - for iarr in range(len(arrlist)): - arr=arrlist[iarr] - labelused='' - if len(megarr)==0: - print(f"Empty array.") - else: - - if len(label)==len(arrlist): labelused=label[iarr] - else: - print("Insufficient labels given.") - plt.hist(arr,bins=bins,align="left",histtype=u'step',label=labelused,**kwargs) - - plt.xscale(xscale) - plt.yscale(yscale) - if xlabel: plt.xlabel(xlabel) - plt.ylabel('Number of Events') - if legend: plt.legend() - if title:plt.title(title) - -def sortList(tlist): - tlist.sort(key = lambda x: x[4], reverse=True) - return tlist - -def plotLEGO(xarr,yarr): - hist = TH2F("hist","Ndiff",20,-10,10,20,-10,10) - print("Fill start.") - for i in range(len(xarr)): - hist.Fill(xarr[i],yarr[i]) - - print("Fill done.") - hist.Draw("LEGO") #colz - input() - -def getQPNSorted(event,highestrank=1,lowestrank=3): #Get sorted array containing [q,px,py,pz,p-mag], ranked by p-mag - trackQPN=[] # [(q,px,py,pz,p)] - for i in range(highestrank-1,lowestrank): - #Momenum is in MeV by default, so we convert to GeV since 1 MeV = 10^-3 GeV - pmag = sqrt((event.Tracks[4][i]**2)+(event.Tracks[5][i]**2)+(event.Tracks[6][i]**2)) - trackQPN+=[(event.Tracks[0][i],event.Tracks[4][i]*(10**-3),event.Tracks[5][i]*(10**-3),event.Tracks[6][i]*(10**-3),pmag*(10**-3))] - - return sortList(trackQPN) + #for i in range(len(Plims)-1): + name=f'{basename}_{int(PH[0]*10**-3)}-{int(PH[1]*10**-3)}GeV' + newdict[name]=dict(dictbase) + newdict[name]['lkwargs']={'tar':[PH[0],PH[1]]} + # break #TEMP -def ApplyCut(event, cut): - tests=[gt,lt,eq,ne] - bool1=[] - global missingattr - for attr in cut.keys(): - for i in range(len(tests)): - try: - if cut[attr][i]!=None: - value = getattr(event,attr) - bool1 += [tests[i](value,cut[attr][i]) and value != inf and value !=nan and value !=-1*inf] - if not all(bool1): break - except AttributeError: - if attr not in missingattr: - print("No attribute: ",attr) - missingattr+=[attr] - - if not all(bool1): - break - - return all(bool1) + return newdict -def ApplyAllCuts(event,dcuts=[CUTDICT],lcuts=LAMBDACUTS): #Requires all True to be True - #cutList = list of dictionaries - bool1=True - boollist=[] - for cut in dcuts: - bool1 = ApplyCut(event,cut) - if not bool1: break - if bool1: - for lcut in lcuts: - boollist+=[lcut(event)] - if not all(boollist): break +#DATA LAMBDAS (for retrieving values in complicated ways) +def RecoVsTruthMomentumMatched(event): + return [event.tracksPmag[event.trackD2i-1],event.tracksTruthPmag[event.trackD2i-1]] - return all(boollist) and bool1 - -def RootRatio(narray,darray): - #rarray = np.divide(narray,darray) - h_numerator=TH1F("num","num",15,0,10000) - h_denominator=TH1F("den","den",15,0,10000) - for i in narray: h_numerator.Fill(i) - for j in darray: h_denominator.Fill(j) - - h_ratio = h_numerator.Clone() - h_ratio.Sumw2() - h_ratio.Divide(h_denominator) - h_ratio.SetStats(0) - h_ratio.SetTitle(f"{user_input} Efficiency vs Rho^2;Rho^2 (mm^2);Efficiency(%)") - h_ratio.SetMinimum(0.) - h_ratio.Draw("ep") - input() - -def MakeWFDict(): - WFDict=dict() - waveforms={'VetoSt1':(0,1), 'VetoSt2':(0,0),'Timing':(0,3),'Preshower':(0,1),'Calo':(0,3)} - meas = 'integral' - TODO = list(waveforms.keys()) - for wf in TODO: - st_r=waveforms[wf] - for st in range(st_r[0],st_r[1]+1): - key=f'{wf}{st}_{meas}' - WFDict[key]={ - 'array':[], - 'lkwargs':{'k':key}, - 'lambda': lambda event,k: getattr(event, k), - 'plotterfunc': configBasicHist, - 'plotkwargs' : {'xscale':'symlog'} - } - return WFDict - -#SPECIFIC PLOTS - -def plotMomentumDistribution(highestrank=1,lowestrank=3): +def RecoVsTruthQPMatched(event,charge=1): + return [RecoVsMCQP(event,charge,'qopr'),RecoVsMCQP(event,charge,'qopm')] - arr_pmag=[[] for i in range(highestrank,lowestrank+1)] - for event in t: - if len(event.Tracks[0])==lowestrank: - trackQPNsorted=getQPNSorted(event,highestrank=1,lowestrank=lowestrank) - isSimilarP = True # abs(trackQPNsorted[0][4]-trackQPNsorted[1][4])<100 - if trackQPNsorted[0][0]!=trackQPNsorted[1][0] and isSimilarP: - for rank in range(highestrank-1,lowestrank): - arr_pmag[rank]+=[trackQPNsorted[rank][4]] +def ResidualVSQP_truth(event): + return [RecoVsMCQP(event,1,'qopm'),RecoVsMCQP(event,1),RecoVsMCQP(event,-1,'qopm'),RecoVsMCQP(event,-1)] - for rank in range(highestrank-1,lowestrank): - rlabel = f'P Rank {rank+1}' - configBasicHist(arr_pmag[rank],label=rlabel,bins=logspace(start=log10(30), stop=log10(7000), num=25),range=(30,7000), legend=True,kwargs={'histtype':u'step'}) - plt.xscale('log') - plt.xlabel('Track Momentum Magnitude (GeV) ') - plt.ylabel('Number of Events') - plt.title(f"Momentum Distribution of {lowestrank}-track Events ("+user_input+")") - plt.show() +def RecoVsMCQP(event,charge=-1,param=None): + i=event.trackD2i-1 + if event.tracksTruthCharge[i]!=charge: i=event.trackD3i-1 -def efficiencyP(pmin=1,pmax=4000,pinc=100): - arr_eff=[] - arr_p=[] - for pcut in range(pmin,pmax,pinc): - eventcountcut=0 - eventcount=0 - for event in t: - if ApplyAllCuts(event): - trackQPNsorted=getQPNSorted(event,highestrank=1,lowestrank=2) #[()] - if trackQPNsorted[0][0]!=trackQPNsorted[1][0]: - eventcount+=1 - if trackQPNsorted[0][-1]>pcut and trackQPNsorted[1][-1]>pcut: eventcountcut+=1 - arr_eff+= [100*eventcountcut/eventcount] - arr_p+= [pcut] - plt.plot(arr_p,arr_eff) - plt.ylabel('Cut Efficiency (%)') - plt.xlabel('P-cut (GeV)') - plt.title(user_input+'Momentum Cut Efficiency') - plt.savefig(user_input+'MomCutEff') - plt.show() + q_r=event.tracksCharge[i] + p_r=event.tracksPmag[i] + q_m=event.tracksTruthCharge[i] + p_m=event.tracksTruthPmag[i] -def dpHitMap(): - arrxp=[] - arryp=[] - arrxn=[] - arryn=[] - for event in t: - if ApplyAllCuts(event): - xp,yp,xn,yn=(event.pPos_S1L0[0],event.pPos_S1L0[1],event.nPos_S1L0[0],event.nPos_S1L0[1]) - if all([abs(i)<200 for i in [xp,yp,xn,yn]]): - arrxp+=[xp] - arryp+=[yp] - arrxn+=[xn] - arryn+=[yn] - - #plt.scatter(arrxp,arryp,color='red',s=0.2) - configHitMap(arrxp,arryp,title='Positive Track Upstream Hits') - #plotLEGO(arrxp,arryp) - plt.savefig(f"{user_input}HitMapP") - plt.close() - plt.show() - #plt.scatter(arrxn,arryn,color='blue',s=0.1) - configHitMap(arrxn,arryn,title='Negative Track Upstream Hits') - plt.savefig(f"{user_input}HitMapN") - #plotLEGO(arrxn,arryn) - plt.show() - -def CutEfficiency(Ndcuts,Nlcuts,Ddcuts=[],Dlcuts=[]): - ecount=0 - ccount=0 - for event in t: - if ApplyAllCuts(event,Ddcuts,Dlcuts): ecount+=1 - if ApplyAllCuts(event,Ndcuts,Nlcuts): ccount+=1 - return ccount,ecount,100*ccount/ecount - -def CutEfficiencyArrays(xlab='Z (mm)'): - Func = lambda event: (event.vertexPos[0]**2)+(event.vertexPos[1]**2) #event.vertexPos[2]# - narray=[] - darray=[] - for event in t: - if ApplyAllCuts(event,[CUTDICT],LAMBDACUTS): narray+=[Func(event)] - if ApplyAllCuts(event,[],FIDUCIALCUT): darray+=[Func(event)] - - # if 'Z' not in xlab: - # dn,dbin = configBasicHist(darray,bins=20,kwargs={'range':(0,10000),'label':'Fiducial Volume'},legend=True) - # nn,nbin = configBasicHist(narray,bins=20,xlabel='Rho^2 (mm)',kwargs={'range':(0,10000),'label':'Selection Cuts'},legend=True) - # else: - # dn,dbin = configBasicHist(darray,bins=20,kwargs={'range':(-1600,0),'label':'Fiducial Volume'},legend=True) - # nn,nbin = configBasicHist(narray,bins=20,xlabel=xlab,kwargs={'range':(-1600,0),'label':'Selection Cuts'},legend=True) - - # plt.title(user_input+"Efficiency vs "+xlab) - # plt.show() - - RootRatio(narray,darray) - - # x=[] - # y=[] - # err=[] - # for i in range(len(nn)): - # x+=[nbin[i]] - # y+=[100*nn[i]/dn[i]] - # err+=[100*(1/dn[i])*sqrt((nn[i]*(dn[i]-nn[i]))/dn[i])] - # #plt.plot(x,y) - # plt.errorbar(x,y,yerr=err) - # plt.ylim(bottom=0) - # plt.xlabel(xlab)#Rho^2 (mm) - # plt.ylabel("Efficiency") - # plt.title(user_input+"Efficiency vs"+xlab) - # plt.show() - -def EfficiencyPlotter(minx,maxx,stepx=1): - arr=[] - arrx=[] - for i in range(minx+stepx,maxx,stepx): - lcut=lambda event: ((event.vertexPos[0]**2)+(event.vertexPos[1]**2))<i - arr+=[CutEfficiency([CUTDICT],LAMBDACUTS,dlcuts=[lcut])] - arrx+=[i] - plt.plot(arrx,arr) - plt.ylabel("Fiducial Event Count/Cut-Applied Event Count") - plt.show() - -#FOR PLOT DICTIONARY (complex lambda functions) -def TwoMomentum(event,sorte=True): - ppmag=sqrt((event.pMom[0]**2)+(event.pMom[1]**2)+(event.pMom[2]**2))*(10**-3) - npmag=sqrt((event.nMom[0]**2)+(event.nMom[1]**2)+(event.nMom[2]**2))*(10**-3) - final = [ppmag,npmag] - if sorte: final.sort() - return final - -def AngularDistribution(event): - px1,py1,pz1 = (event.pMom[0],event.pMom[1],event.pMom[2]) - px2,py2,pz2 = (event.nMom[0],event.nMom[1],event.nMom[2]) - return [(arctan(py1/pz1)-arctan(py2/pz2))*1000,(arctan(px1/pz1)-arctan(px2/pz2))*1000] - -def PAngleX(event): - px1,py1,pz1 = (event.pMom[0],event.pMom[1],event.pMom[2]) - px2,py2,pz2 = (event.nMom[0],event.nMom[1],event.nMom[2]) - return [arctan(px1/pz1)*1000,arctan(px2/pz2)*1000] - -def PAngleY(event): - px1,py1,pz1 = (event.pMom[0],event.pMom[1],event.pMom[2]) - px2,py2,pz2 = (event.nMom[0],event.nMom[1],event.nMom[2]) - return [arctan(py1/pz1)*1000,arctan(py2/pz2)*1000] - #plotLEGO(ndiff_arrx,ndiff_arry) - -def UpstreamHitMap(event,charge=1): - xp,yp,xn,yn=(event.pPos_S1L0[0],event.pPos_S1L0[1],event.nPos_S1L0[0],event.nPos_S1L0[1]) - if charge==1: return [xp,yp] - elif charge==-1: return [xn,yn] - - -def TrackSeparation(event): - xp,yp,xn,yn=(event.pPos_S1L0[0],event.pPos_S1L0[1],event.nPos_S1L0[0],event.nPos_S1L0[1]) - if all([abs(i)<200 for i in [xp,yp,xn,yn]]): - return sqrt((xp-xn)**2+(yp-yn)**2) - else: return nan - -def SeparationDistribution(event): - xp,yp,zp,xn,yn,zn=(event.pPos_S1L0[0],event.pPos_S1L0[1],event.pPos_S1L0[2],event.nPos_S1L0[0],event.nPos_S1L0[1],event.nPos_S1L0[2]) - if all([abs(i)<200 for i in [xp,yp,xn,yn]]): - return [(arctan(yp/zp)-arctan(yn/zn))*1000,(arctan(xp/zp)-arctan(xn/zn))*1000] - else: return [-101,-101] #outside range, therefore not plotted - -def Chi2DoF(event): - try: return [event.pChi2/event.pDoF,event.nChi2/event.nDoF] - except ZeroDivisionError: return [nan,nan] - -def SumCalo(event): - Etot=0 - for st in range(0,4): - aname=f'Calo{st}_integral' - value = getattr(event, aname) - bool1= value != inf and value !=nan and value !=-1*inf - if bool1: Etot+=value - else: return nan - return Etot - -#PLOT DICTIONARY FORMAT -# arrDict={ -# 'ExampleName':{ -# 'array':[], -# 'lambda': lambda event: event.pChi2/event.pDoF, -# 'plotterfunc': configBasicHist, -# 'plotkwargs' : {'edgecolor':'black','linewidth':1.2, 'rwidth':0.9} -# } -# } -# Veto St1-2, Ch0-1 - VetoStXY_ -# Timing 0-3 - TimingX_ -# Preshower 0-1 - PreshowerX_ -# Calo 0-3 - CaloX_ -# Sum of integrals in calo wave channels --> Calo Edep sort of (missing some callibration constants) - - -#templambda = lambda ti : lambda event : event.vertexPos[2]<ti -#EfficiencyPlotter(templambda,0,1000) - + if param=='qr': return q_r + if param=='pr': return p_r + if param=='qm': return q_m + if param=='pm': return p_m + if param=='qopr': return q_r/p_r + if param=='qopm': return q_m/p_m + return ((q_r/p_r)-(q_m/p_m))/event.tracksSigmaQovP[i] + +def NormalizedResidual2(event): + return [RecoVsMCQP(event,1),RecoVsMCQP(event,-1)] + +def GetAllTrackQPReco(event,tar=1000): + measarr = [] + for ti in range(event.TrackCount): + q_r=event.tracksCharge[ti] + p_r=event.tracksPmag[ti] + p_m=event.tracksTruthPmag[ti] + if type(tar)==list: + tar=PH + if tar[0]<p_m and p_m<tar[1]: measarr+=[(q_r/p_r)*10**3] + #if tar[0]<p_m and p_m<tar[1]: measarr+=[(q_r/p_r)*10**3] + #elif p_m>tar*0.9 and p_m<tar*1.2: measarr+=[(q_r/p_r)*10**3] + + return measarr + +def GetAllTrackQPTruth(event): + measarr = [] + for ti in range(len(event.truthd0_charge)): + q_0=event.truthd0_charge[ti] + p_0=event.truthd0_P[ti] + measarr+=[(q_0/p_0)*10**3] + + for ti in range(len(event.truthd1_charge)): + q_1=event.truthd1_charge[ti] + p_1=event.truthd1_P[ti] + measarr+=[(q_1/p_1)*10**3] + + return measarr + +def GetAllTrackMomentum(event): + measarr = [] + + for ti in range(event.TrackCount): + p_r=event.tracksPmag[ti] + measarr+=[p_r*10**-3] + + return finalval + + +#For storing different plot configurations MainArrDict={ - 'CaloSum':{ + 'RecoX':{ 'array':[], - 'lambda': SumCalo, + 'lambda': lambda event: event.tracksX[0], 'plotterfunc': configBasicHist, - 'plotkwargs' : {'xscale':'log'} + 'plotkwargs' : {} }, - 'TracksPerEvent':{ + 'RecoMaxMomentum':{ 'array':[], - 'lambda': lambda event: len(event.Tracks[0]), + 'lambda': lambda event:max(event.tracksPmag), 'plotterfunc': configBasicHist, - 'plotkwargs' : {} + 'plotkwargs' : {'pckwargs':{'xscale':'log'}} }, - 'TrackSeparation':{ + 'TruthMaxMomentum':{ 'array':[], - 'lambda': TrackSeparation, + 'lambda': lambda event:max(event.tracksTruthPmag), 'plotterfunc': configBasicHist, - 'plotkwargs' : {'bins':20,'xlabel':'Distance (mm)','kwargs':{'range':(0,10)}} - }, - 'TwoMomentum':{ - 'array':[[],[]], - 'lambda': TwoMomentum, - 'plotterfunc': configMultiHist, - 'plotkwargs' : {'label':['Positive','Negative'],'xscale':'log','xlabel':'Track Momentum Magnitude (GeV) '} - }, - 'AngularDistribution':{ - 'array':[[],[]], - 'lambda': AngularDistribution, - 'plotterfunc': configMultiHist, - 'plotkwargs' : {'label':['Momentum-Y','Momentum-X'],'xlabel':'N-diff (mrad)','kwargs':{'range':(-35,35)}} - }, - 'PAngleX':{ - 'array':[[],[]], - 'lambda': PAngleX, - 'plotterfunc': configMultiHist, - 'plotkwargs' : {'label':['Positive','Negative'],'xlabel':'Angle (mrad)','kwargs':{'range':(-35,35)}} + 'plotkwargs' : {'pckwargs':{'xscale':'log'}} }, - 'PAngleY':{ + 'RecoVsTruthMaxMomentum':{ 'array':[[],[]], - 'lambda': PAngleY, + 'lambda': lambda event:[max(event.tracksPmag),max(event.tracksTruthPmag)], 'plotterfunc': configMultiHist, - 'plotkwargs' : {'label':['Positive','Negative'],'xlabel':'Angle (mrad)','kwargs':{'range':(-35,35)}} + 'plotkwargs' : {'label':['Reco','Truth'],'pckwargs':{'xscale':'log','legend':True}} }, - 'SeparationDistribution':{ + 'RecoVsTruthMaxMomentumScatter':{ 'array':[[],[]], - 'lambda': SeparationDistribution, - 'plotterfunc': configMultiHist, - 'plotkwargs' : {'label':['Y','X'],'kwargs':{'range':(-100,100)}} + 'lambda': lambda event:[max(event.tracksPmag),max(event.tracksTruthPmag)], + 'plotterfunc': config2DScatter, + 'plotkwargs' : {} }, - 'Chi2DoF':{ - 'array':[[],[]], - 'lambda': Chi2DoF, + 'QP_reco Vs QP_truth':{ + 'array':[[],[],[],[]], + 'lambda': RecoVsTruthQPMatched, 'plotterfunc': configMultiHist, - 'plotkwargs' : {'bins':20,'label':['Positive','Negative'],'kwargs':{'range':(0,11)}} + 'plotkwargs' : {'label':['Reco +','Truth +','Reco -','Truth -'],'kwargs':{'range':[-10**-5,10**-5]},'pckwargs':{'xscale':'linear','xlabel':"Q/P",'legend':True}} }, - 'DoF':{ + 'QP_truth_vs_Residual':{ 'array':[[],[]], - 'lambda': lambda event:[event.pDoF,event.nDoF], - 'plotterfunc': configMultiHist, - 'plotkwargs' : {'bins':30,'label':['Positive','Negative'],'kwargs':{'range':(0,31)}} + 'lambda': ResidualVSQP_truth, + 'plotterfunc': config2DScatter, + 'plotkwargs' : {'kwargs':{},'pckwargs':{'xlabel':"Q/P_truth",'ylabel':"Residual"}} }, - 'LayersHit':{ + 'NormalizedResidual':{ 'array':[[],[]], - 'lambda': lambda event: [event.playersHit,event.nlayersHit], + 'lambda': NormalizedResidual2, 'plotterfunc': configMultiHist, - 'plotkwargs' : {'bins':5,'label':['Positive','Negative'],'kwargs':{'range':(5,10)}} + 'plotkwargs' : {'bins':20,'kwargs':{'range':[-10,11]},'label':['Positive','Negative'],'pckwargs':{'xscale':'linear','xlabel':"Residual",'legend':True}} }, - 'VertexZ':{ + 'AllTracksQP_reco':{ 'array':[], - 'lambda': lambda event: event.vertexPos[2], + 'lambda': GetAllTrackQPReco, 'plotterfunc': configBasicHist, - 'plotkwargs' : {'xlabel':'Z (mm)'} + 'plotkwargs' :{'bins':100,'kwargs':{'range':[2*-10**-3,2*10**-3]}}, }, - 'TrueVertexRho':{ + 'AllTracksQP_truth':{ 'array':[], - 'lambda': lambda event: (event.vertexPos[0]**2)+(event.vertexPos[1]**2), + 'lambda': GetAllTrackQPTruth, 'plotterfunc': configBasicHist, - 'plotkwargs' : {'xlabel':'Rho^2 (mm^2)'} + 'plotkwargs' :{'kwargs':{'range':[2*-10**-3,2*10**-3]}}, }, - 'Rho2vsVertexZ':{ - 'array':[[],[]], - 'lambda': lambda event:[(event.vertexPos[0]**2)+(event.vertexPos[1]**2),event.vertexPos[2]], - 'plotterfunc': configHitMap2, - 'plotkwargs' : {'bins':(10,10),'xlabel':'Rho^2 (mm^2)','ylabel':'Vertex-Z (mm)'} + 'AllMomentum_Reco':{ + 'array':[], + 'lambda': GetAllTrackMomentum, + 'plotterfunc': configBasicHist, + 'plotkwargs' : {'kwargs':{'range':[0,4000]}} }, - 'UpstreamHitsPositive':{ - 'array':[[],[]], - 'lambda': UpstreamHitMap, - 'plotterfunc': configHitMap2, - 'plotkwargs' : {'xlim':(-100,100),'ylim':(-100,100)}, - 'lkwargs':{'charge':1} + 'AllTracksQP_reco':{ + 'array':[], + 'lambda': GetAllTrackQPReco, + 'plotterfunc': configBasicHist, + 'plotkwargs' :{'bins':50,'kwargs':{'range':[2*-10**-3,2*10**-3]}}, + 'lkwargs' : {'tar':2000*10**3} }, - 'UpstreamHitsNegative':{ - 'array':[[],[]], - 'lambda': UpstreamHitMap, - 'plotterfunc': configHitMap2, - 'plotkwargs' : {'xlim':(-100,100),'ylim':(-100,100)}, - 'lkwargs':{'charge':-1} + 'AllTracksTruthPmag':{ + 'array':[], + 'lambda': lambda event: list(event.tracksTruthPmag), + 'plotterfunc': configBasicHist, + 'plotkwargs' :{'bins':50,'pckwargs':{'xscale':'log'}}, }, - 'UpstreamXYPositive':{ - 'array':[[],[]], - 'lambda': lambda event: (event.pPos_S1L0[0],event.pPos_S1L0[1]), - 'plotterfunc': configMultiHist, - 'plotkwargs' : {'label':['Positive','Negative']}, + 'NormalizedResidualSum':{ + 'array':[], + 'lambda': NormalizedResidual2, + 'plotterfunc': configBasicHist, + 'plotkwargs' : {'bins':20,'kwargs':{'range':[-10,11]},'pckwargs':{'xscale':'linear','xlabel':"Residual"}} }, -} -MainArrDict.update(MakeWFDict()) #Fill with wf plots + } + + -#For testing/plotting purposes, plotting specific members of MainArrDict TestArrDict=dict() -testname='TrueVertexRho' +testname='NormalizedResidualSum' #Any key from MainArrDict TestArrDict[testname]=MainArrDict[testname] # for k in MainArrDict.keys(): -# if 'Calo' in k: +# if 'Check' in k: # TestArrDict[k]=MainArrDict[k] -def GeneralPlotter(arrDict,dcuts=[CUTDICT],lcuts=LAMBDACUTS,showplot=True,savefig=False): +def GeneralPlotter(arrDict,dcuts=[],lcuts=[],showplot=True,savefig=False): nans=0 + for event in t: if ApplyAllCuts(event,dcuts,lcuts): for name in arrDict.keys(): value=nan - if arrDict[name]['plotterfunc'] in [configMultiHist,configHitMap2]: - if 'lkwargs' in list(arrDict[name].keys()): value = arrDict[name]['lambda'](event,**arrDict[name]['lkwargs']) - else: value = arrDict[name]['lambda'](event) - checkReal = all([v != inf and v !=nan and v !=-1*inf for v in value]) - if checkReal: + if 'lkwargs' in list(arrDict[name].keys()): + value = arrDict[name]['lambda'](event,**arrDict[name]['lkwargs']) + else: value = arrDict[name]['lambda'](event) + checkReal=True + if type(value)==list: checkReal = all([v != inf and v !=nan and v !=-1*inf for v in value]) + else: checkReal = value != inf and value !=nan and value !=-1*inf + + if checkReal and type(value)==list: + if arrDict[name]['plotterfunc'] in [configBasicHist]: arrDict[name]['array']+=value + else: for iv in range(len(value)): arrDict[name]['array'][iv]+=[value[iv]] - else: nans+=1 - else: - if 'lkwargs' in list(arrDict[name].keys()): value = arrDict[name]['lambda'](event,**arrDict[name]['lkwargs']) - else: value = arrDict[name]['lambda'](event) - checkReal = value != inf and value !=nan and value !=-1*inf - if checkReal: arrDict[name]['array']+=[value] - else: nans+=1 - + elif checkReal: arrDict[name]['array']+=[value] + else: nans+=1 + print(f"# of NaNs:{nans}") for name in arrDict.keys(): + isPrintout= arrDict[name]['plotterfunc'] in [PrintBoolPercent] + print(name) + print('LEN:',len(arrDict[name]['array'])) arrDict[name]['plotterfunc']( arrDict[name]['array'], **arrDict[name]['plotkwargs']) - plt.title(user_input+name) - if savefig: plt.savefig(user_input+name) - if showplot: plt.show() - - - -#Iterate over all models and do a thing -DP_fnames=['Ntuple_Amm_316MeV_2Em6_','Ntuple_Aee_10MeV_1Em5_','Ntuple_Aee_10MeV_1Em4_','Ntuple_Aee_100MeV_1Em5_'] -for f in DP_fnames: - user_input=f - t = TChain("events") - nfiles = 0 - nfiles += t.Add("/eos/home-s/sshively/CALYPZONE/run/"+user_input+".root") - print(f) - - #GeneralPlotter(TestArrDict,dcuts=[CUTDICT],lcuts=LAMBDACUTS) - #EfficiencyPlotter(0,200,stepx=10) - #print(CutEfficiency([CUTDICT],LAMBDACUTS,Ddcuts=[],Dlcuts=FIDUCIALCUT)) - CutEfficiencyArrays(xlab='Rho^2 (mm^2)') - #EfficiencyTest() - + if not isPrintout: + plt.title(user_input+name) + if savefig: plt.savefig(user_input+name) + if showplot: plt.show() + +#EXECUTE +if __name__ == "__main__": + DP_fnames=['Ntuple_Aee_100MeV_1Em5_']# Ntuple_Aee_10MeV_1Em5_ Ntuple_Amm_316MeV_2Em6_ Ntuple_Aee_10MeV_1Em4_ + for f in DP_fnames: + user_input=f + t = TChain("events") + nfiles = 0 + nfiles += t.Add("/eos/home-s/sshively/CALYPZONE/run/BackUp2/"+user_input+".root") + print(f) + + GeneralPlotter(TestArrDict,dcuts=[{}],lcuts=[BoolDaughterCut]) + #print(GetPBounds(lcuts=[BoolDaughterCut])) diff --git a/Tracker/TrackerRecAlgs/PairVertex/scripts/PlotHelper.py b/Tracker/TrackerRecAlgs/PairVertex/scripts/PlotHelper.py new file mode 100644 index 0000000000000000000000000000000000000000..8597d9cab9779c8ff2fd2e04744730a6f2f3efa7 --- /dev/null +++ b/Tracker/TrackerRecAlgs/PairVertex/scripts/PlotHelper.py @@ -0,0 +1,102 @@ +from numpy import log10,logspace +from cmcrameri import cm +import matplotlib.pyplot as plt +from ROOT import TEfficiency, TH1F + +def PlotConfigs(xscale='linear',yscale='linear',xlim=None,ylim=None,title=None,show=False,xticks=None,xlabel=None,ylabel='#Events',legend=False,legloc='best'): + plt.xscale(xscale) + plt.yscale(yscale) + if xticks: plt.xticks(xticks) + if xlabel: plt.xlabel(xlabel) + if ylabel: plt.ylabel(ylabel) + if legend: plt.legend(loc=legloc) + if title:plt.title(title) + if show: plt.show() + +def configHitMap(arrays,bins=(50,50),pckwargs={'xlabel':"X (mm)",'ylabel':"Y (mm)"},counts=False,kwargs={}): + #2D Histogram with colors + arrayx=arrays[0] + arrayy=arrays[1] + plt.hist2d(arrayx, arrayy, bins=bins, cmap=cm.imola,**kwargs) + plt.colorbar() + if counts: plt.text(50,-185,"#EVENTS: {}".format(len(arrayx))) + PlotConfigs(**pckwargs) + +def configBasicHist(arr,bins=25,pckwargs={'xscale':'linear'},kwargs={}): + #1D Histogram + if 'log' in pckwargs['xscale']: bins=CorrectBinsForLog(arr,bins,pckwargs['xscale']) + n, binsOut, patches = plt.hist(arr,bins=bins,align="left",histtype=u'step',**kwargs) + PlotConfigs(**pckwargs) + + return n,binsOut + +def configMultiHist(arrlist,bins=25,label=[],pckwargs={'xscale':'linear','legloc':'upper left'},kwargs={}): + #1D Histogram for comparison + megarr=[] + for a in arrlist: megarr+=a + + if 'log' in pckwargs['xscale']: bins=CorrectBinsForLog(megarr,bins,pckwargs['xscale']) + for iarr in range(len(arrlist)): + arr=arrlist[iarr] + labelused='' + if len(arr)==0: + print(f"Empty array.") + else: + if len(label)==len(arrlist): labelused=label[iarr] + else: + print("Insufficient labels given.") + plt.hist(arr,bins=bins,align="left",histtype=u'step',label=labelused,**kwargs) + + PlotConfigs(**pckwargs) + +def config2DScatter(arrlist,pckwargs=dict(),kwargs={}): + x=arrlist[0] + y=arrlist[1] + # plt.ylim(-25,25) + # plt.xlim(-10**-5,10**-5) + plt.scatter(x,y,**kwargs) + PlotConfigs(**pckwargs) + +def PrintBoolPercent(arr,kwargs={}): + #For an array of boolians, print out the % of elements that are "true". + n=0.0 + d=len(arr) + for x in arr: + if x: n+=1.0 + + finalval= (n/d)*100 + print("Calculating...") + print(f"{n}/{d}") + print('Percent:'+'{:.2f}'.format(finalval)+'%') + +def PlotRootRatio(arrlist,bins=15,hmin=0,hmax=10000,title=None): + + narray,darray=arrlist[0],arrlist[1] + h_numerator=TH1F("num","num",bins,hmin,hmax) + h_denominator=TH1F("den","den",bins,hmin,hmax) + for i in narray: h_numerator.Fill(i) + for j in darray: h_denominator.Fill(j) + + h_ratio = TEfficiency(h_numerator,h_denominator) + c = h_ratio.CreateGraph() + c.GetYaxis().SetLimits(0.0, 1.05) + if title: h_ratio.SetTitle(title) + h_ratio.Draw("ep") + input() + +#Utilities +def CorrectBinsForLog(arr,bins,xscale): + minx,maxx = (min(arr),max(arr)) + if minx==maxx: + maxx+=1 + bins=1 + bins = logspace(start=log10(minx), stop=log10(maxx), num=bins) + if xscale=='symlog': + bins = [0]+list(logspace(start=log10(1), stop=log10(maxx), num=24)) + if minx>1: bins = logspace(start=log10(minx), stop=log10(maxx), num=25) + + return bins + + + + diff --git a/Tracker/TrackerRecAlgs/PairVertex/scripts/Utilities.py b/Tracker/TrackerRecAlgs/PairVertex/scripts/Utilities.py new file mode 100644 index 0000000000000000000000000000000000000000..ff711357eed1ed411749dcf9ed2e800546f358c3 --- /dev/null +++ b/Tracker/TrackerRecAlgs/PairVertex/scripts/Utilities.py @@ -0,0 +1,65 @@ +#UTILITY +from ROOT import TChain, TH2F, TH1F +print("Root loaded.") +import matplotlib.pyplot as plt +print("MPL loaded.") +from operator import lt,eq,ne,gt +from numpy import nan, seterr, inf,arctan, array +from numpy import sum as npsum +import numpy as np +from math import sqrt +print("Other stuff loaded.") + +user_input='' + +seterr(all='ignore') +missingattr=[] + +#CUTS +#attr: [>,<,==,!=] if none --> skip +BASICCUT={ + 'TrackCount':[0,None,None,None] + } + +def BoolDaughterCut(event): + if event.TrackCount>=2 and len(event.tracksTruthBarcode)>=2: + return 2 in event.tracksTruthBarcode and 3 in event.tracksTruthBarcode + else: return False + + + +def ApplyCut(event, cut): + tests=[gt,lt,eq,ne] + bool1=[] + global missingattr + for attr in cut.keys(): + for i in range(len(tests)): + try: + if cut[attr][i]!=None: + value = getattr(event,attr) + bool1 += [tests[i](value,cut[attr][i]) and value != inf and value !=nan and value !=-1*inf] + if not all(bool1): break + except AttributeError: + if attr not in missingattr: + print("No attribute: ",attr) + missingattr+=[attr] + + if not all(bool1): + break + + return all(bool1) + +def ApplyAllCuts(event,dcuts=[],lcuts=[]): #Requires all True to be True + #cutList = list of dictionaries + bool1=True + boollist=[] + for cut in dcuts: + bool1 = ApplyCut(event,cut) + if not bool1: break + if bool1: + for lcut in lcuts: + boollist+=[lcut(event)] + if not all(boollist): break + + return all(boollist) and bool1 + diff --git a/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.cxx b/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.cxx index 8009ce9a72e0efb119b0e5cf52c52d99a2add749..a44ba24c44f2b516d4f9a7769d8bad8b7405810e 100644 --- a/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.cxx +++ b/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.cxx @@ -14,13 +14,14 @@ #include "FaserCaloIdentifier/EcalID.h" #include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" #include <cmath> +#include <numeric> #include <TTree.h> #include <TBranch.h> #include <typeinfo> - +constexpr float NaN = std::numeric_limits<double>::quiet_NaN(); namespace Tracker { @@ -89,6 +90,10 @@ StatusCode PairVertexAlg::initialize() ATH_CHECK(m_preshowerContainer.initialize()); ATH_CHECK(m_ecalContainer.initialize()); + ATH_CHECK(m_fiducialParticleTool.retrieve()); + ATH_CHECK(m_trackTruthMatchingTool.retrieve()); + ATH_CHECK(m_truthParticleContainer.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); ATH_CHECK(detStore()->retrieve(m_vetoNuHelper, "VetoNuID")); @@ -98,31 +103,39 @@ StatusCode PairVertexAlg::initialize() ATH_CHECK(detStore()->retrieve(m_ecalHelper, "EcalID")); m_tree = new TTree("events", "Events"); - m_tree->Branch("Tracks", &m_tracks); + m_tree->Branch("TrackCount", &m_trackCount, "trackCount/I"); - //POSITIVE - m_tree->Branch("pPos_S1L0", &m_ppos_s1l0); // [x,y,z] - m_tree->Branch("pMom", &m_pmom); // [px,py,pz] - m_tree->Branch("pChi2", &m_pChi2); // float - m_tree->Branch("pDoF", &m_pDoF); // double - m_tree->Branch("pstationMap", &m_pstationMap); // set (int) - m_tree->Branch("playerMap", &m_playerMap); // vec(vec(int)) - m_tree->Branch("playersHit", &m_playersHit); // int - m_tree->Branch("piftHit", &m_piftHit); // int - - //NEGATIVE - m_tree->Branch("nPos_S1L0", &m_npos_s1l0); // [x,y,z] - m_tree->Branch("nMom", &m_nmom); // [px,py,pz] - m_tree->Branch("nChi2", &m_nChi2); // float - m_tree->Branch("nDoF", &m_nDoF); // double - m_tree->Branch("nstationMap", &m_nstationMap); // set (int) - m_tree->Branch("nlayerMap", &m_nlayerMap); // vec(vec(int)) - m_tree->Branch("nlayersHit", &m_nlayersHit); // int - m_tree->Branch("niftHit", &m_niftHit); // int - - //CALO - m_tree->Branch("Calo_total_Edep", &m_Calo_Total_Edep); + m_tree->Branch("tracksX", &m_tracksX); + m_tree->Branch("tracksY", &m_tracksY); + m_tree->Branch("tracksZ", &m_tracksZ); + m_tree->Branch("tracksPx", &m_tracksPx); + m_tree->Branch("tracksPy", &m_tracksPy); + m_tree->Branch("tracksPz", &m_tracksPz); + m_tree->Branch("tracksPmag", &m_tracksPmag); + + m_tree->Branch("tracksCharge", &m_tracksCharge); + m_tree->Branch("tracksSigmaQovP", &m_sigmaQoverP); + m_tree->Branch("tracksChi2", &m_tracksChi2); + m_tree->Branch("tracksDoF", &m_tracksDoF); + m_tree->Branch("trackPositiveIndicies", &m_trackPositiveIndicies); + m_tree->Branch("trackNegativeIndicies", &m_trackNegativeIndicies); + + m_tree->Branch("tracksTruthBarcode", &m_tracksTruthBarcode); + m_tree->Branch("tracksTruthPdg", &m_tracksTruthPdg); + m_tree->Branch("tracksTruthCharge", &m_tracksTruthCharge); + m_tree->Branch("tracksTruthPmag", &m_tracksTruthPmag); + m_tree->Branch("tracksIsFiducial", &m_tracksIsFiducial); + + m_tree->Branch("trackD2i", &m_trackD2i); //Index of track with daughter particle Barcode 2 + m_tree->Branch("trackD3i", &m_trackD3i); //Index of track with daughter particle Barcode 3 + + m_tree->Branch("tracksNLayersHit", & m_tracksnLayersHit); + m_tree->Branch("tracksLayersIFT", & m_tracksLayersIFT); + m_tree->Branch("tracksIFTHit", & m_tracksIFThit); + + m_tree->Branch("tracksLayerMap", &m_layerMap); + //WAVEFORM addWaveBranches("VetoSt1",2,6); @@ -133,7 +146,44 @@ StatusCode PairVertexAlg::initialize() addWaveBranches("Calo",4,0); //TRUTH - m_tree->Branch("vertexPos", &m_vertexPos); // [x,y,z] + m_tree->Branch("tTrkBarcode", &m_truthBarcode); + m_tree->Branch("tTrkPdg", &m_truthPdg); + + m_tree->Branch("vertexPos", &m_vertexPos); // [x,y,z] + m_tree->Branch("isFiducial", &m_isFiducial); + + m_tree->Branch("truthM_P", &m_truthM_P); + m_tree->Branch("truthM_px", &m_truthM_px); + m_tree->Branch("truthM_py", &m_truthM_py); + m_tree->Branch("truthM_pz", &m_truthM_pz); + m_tree->Branch("truthM_x", &m_truthM_x); + m_tree->Branch("truthM_y", &m_truthM_y); + m_tree->Branch("truthM_z", &m_truthM_z); + + //Electron + m_tree->Branch("truthd0_P", &m_truthd0_P); + m_tree->Branch("truthd0_px", &m_truthd0_px); + m_tree->Branch("truthd0_py", &m_truthd0_py); + m_tree->Branch("truthd0_pz", &m_truthd0_pz); + m_tree->Branch("truthd0_x", &m_truthd0_x); + m_tree->Branch("truthd0_y", &m_truthd0_y); + m_tree->Branch("truthd0_z", &m_truthd0_z); + m_tree->Branch("truthd0_IsFiducial", &m_truthd0_IsFiducial); + m_tree->Branch("truthd0_charge", &m_truthd0_charge); + + //Positron + m_tree->Branch("truthd1_P", &m_truthd1_P); + m_tree->Branch("truthd1_px", &m_truthd1_px); + m_tree->Branch("truthd1_py", &m_truthd1_py); + m_tree->Branch("truthd1_pz", &m_truthd1_pz); + m_tree->Branch("truthd1_x", &m_truthd1_x); + m_tree->Branch("truthd1_y", &m_truthd1_y); + m_tree->Branch("truthd1_z", &m_truthd1_z); + m_tree->Branch("truthd1_IsFiducial", &m_truthd1_IsFiducial); + m_tree->Branch("truthd1_charge", &m_truthd1_charge); + + + ATH_CHECK(histSvc()->regTree("/HIST/events", m_tree)); return StatusCode::SUCCESS; @@ -159,9 +209,75 @@ StatusCode PairVertexAlg::execute(const EventContext &ctx) const FillWaveBranches(*triggerContainer); FillWaveBranches(*preshowerContainer); FillWaveBranches(*ecalContainer); - FillWaveBranches(*vetoNuContainer); + FillWaveBranches(*vetoNuContainer); + + //FILL WITH TRUTHPARTICLECONTAINER + SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainer { m_truthParticleContainer, ctx }; + if (truthParticleContainer.isValid() && truthParticleContainer->size() > 0) + { + for (auto particle : *truthParticleContainer) + { + if ( particle->barcode() <= 3) + { - // TRACK COLLECTION + if ( particle->barcode() == 1) // mother particle (A') + { + + m_truthM_P.push_back(particle->p4().P()); + m_truthM_px.push_back(particle->p4().X()); + m_truthM_py.push_back(particle->p4().Y()); + m_truthM_pz.push_back(particle->p4().Z()); + if (m_fiducialParticleTool->isFiducial(particle->barcode())) {ATH_MSG_ERROR("DP has hits! Something is wrong");} + if ( particle->hasProdVtx()) { + m_truthM_x.push_back(particle->prodVtx()->x()); + m_truthM_y.push_back(particle->prodVtx()->y()); + m_truthM_z.push_back(particle->prodVtx()->z()); + } else { + m_truthM_x.push_back(NaN); + m_truthM_y.push_back(NaN); + m_truthM_z.push_back(NaN); + }} + + if ( particle->charge() < 0) // negative daughter particle + { + m_truthd0_P.push_back(particle->p4().P()); + m_truthd0_px.push_back(particle->p4().X()); + m_truthd0_py.push_back(particle->p4().Y()); + m_truthd0_pz.push_back(particle->p4().Z()); + m_truthd0_charge.push_back(particle->charge()); + m_truthd0_IsFiducial.push_back(m_fiducialParticleTool->isFiducial(particle->barcode())); + + if ( particle->hasProdVtx()) { + m_truthd0_x.push_back(particle->prodVtx()->x()); + m_truthd0_y.push_back(particle->prodVtx()->y()); + m_truthd0_z.push_back(particle->prodVtx()->z()); + } else { + m_truthd0_x.push_back(NaN); + m_truthd0_y.push_back(NaN); + m_truthd0_z.push_back(NaN); + }} + + if ( particle->charge() > 0) // positive daughter particle + { + m_truthd1_P.push_back(particle->p4().P()); + m_truthd1_px.push_back(particle->p4().X()); + m_truthd1_py.push_back(particle->p4().Y()); + m_truthd1_pz.push_back(particle->p4().Z()); + m_truthd1_charge.push_back(particle->charge()); + m_truthd1_IsFiducial.push_back(m_fiducialParticleTool->isFiducial(particle->barcode())); + + if ( particle->hasProdVtx()) { + m_truthd1_x.push_back(particle->prodVtx()->x()); + m_truthd1_y.push_back(particle->prodVtx()->y()); + m_truthd1_z.push_back(particle->prodVtx()->z()); + } else { + m_truthd1_x.push_back(NaN); + m_truthd1_y.push_back(NaN); + m_truthd1_z.push_back(NaN); + }} + }}} + + //FILL WITH TRACKCOLLECTION SG::ReadHandle<TrackCollection> tracks { m_trackCollectionKey, ctx }; ATH_CHECK(tracks.isValid()); for (auto trk : *tracks) @@ -204,14 +320,31 @@ StatusCode PairVertexAlg::execute(const EventContext &ctx) const m_numberOfNoUpstreamTracks++; ATH_MSG_WARNING("Unable to find track parameters on any surface"); continue; - //End error catching; assign state to upstream if everything else is ok. + }//End error catching; assign state to upstream if everything else is ok. + + + //Truth info + auto [truthParticle, hitCount] = m_trackTruthMatchingTool->getTruthParticle(trk); + if (truthParticle != nullptr) { + m_tracksTruthPdg.push_back(truthParticle->pdgId()); + m_tracksTruthBarcode.push_back(truthParticle->barcode()); + m_tracksIsFiducial.push_back(m_fiducialParticleTool->isFiducial(truthParticle->barcode())); + m_tracksTruthCharge.push_back(truthParticle->charge()); + m_tracksTruthPmag.push_back(truthParticle->p4().P()); + if (truthParticle->barcode()==2) m_trackD2i=m_trackCount; + if (truthParticle->barcode()==3) m_trackD3i=m_trackCount; + } + else { + m_tracksTruthPdg.push_back(NaN); + m_tracksTruthBarcode.push_back(NaN); + m_tracksIsFiducial.push_back(NaN); + m_tracksTruthCharge.push_back(NaN); + m_tracksTruthPmag.push_back(NaN); } - - // Check for hit in the three downstream stations + //LAYERMAPPING std::vector<std::vector<int>> layerMap={{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; std::set<int> stationMap; - std::vector<double> PH_pos_S1L0={0,0,0}; //x,y,z for (auto measurement : *(trk->measurementsOnTrack())) { const Tracker::FaserSCT_ClusterOnTrack* cluster = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*>(measurement); @@ -221,64 +354,45 @@ StatusCode PairVertexAlg::execute(const EventContext &ctx) const int layer = m_idHelper->layer(id); stationMap.emplace(station); layerMap[station][layer]+=1; - } - } - + }} int layersHit=0; int iftHit=0; for (int st=0;st<4;st++) { for (int lr=0;lr<3;lr++){ if (layerMap[st][lr]>0) layersHit++; if (st==0 && layerMap[st][lr]>0) iftHit++; - } - } + }} if (stationMap.count(1) == 0 || stationMap.count(2) == 0 || stationMap.count(3) == 0) continue; + + m_tracksnLayersHit.push_back(layersHit); + m_tracksIFThit.push_back(iftHit); + + //TRACKPARAMETERS const Trk::TrackParameters* upstreamParameters = trk->trackParameters()->front(); const Trk::TrackParameters* downstreamParameters = trk->trackParameters()->back(); + auto covariance = *upstreamParameters->covariance(); + double sigmaQoverP = sqrt(covariance(4,4)); + m_sigmaQoverP.push_back(sigmaQoverP); auto momentum = upstreamParameters->momentum(); double charge = upstreamParameters->charge(); auto position = upstreamParameters->position(); - - m_tracks[0].push_back(charge); - m_tracks[1].push_back(position.x()); - m_tracks[2].push_back(position.y()); - m_tracks[3].push_back(position.z()); - m_tracks[4].push_back(momentum.x()); - m_tracks[5].push_back(momentum.y()); - m_tracks[6].push_back(momentum.z()); - - if (charge>0){ - m_ppos_s1l0[0]=position.x(); - m_ppos_s1l0[1]=position.y(); - m_ppos_s1l0[2]=position.z(); - m_pmom[0]=momentum.x(); - m_pmom[1]=momentum.y(); - m_pmom[2]=momentum.z(); - m_pChi2=trk->fitQuality()->chiSquared(); - m_pDoF=trk->fitQuality()->numberDoF(); - m_pstationMap=stationMap; - m_playerMap=layerMap; - m_playersHit=layersHit; - m_piftHit=iftHit; - } - else{ - m_npos_s1l0[0]=position.x(); - m_npos_s1l0[1]=position.y(); - m_npos_s1l0[2]=position.z(); - m_nmom[0]=momentum.x(); - m_nmom[1]=momentum.y(); - m_nmom[2]=momentum.z(); - m_nChi2=trk->fitQuality()->chiSquared(); - m_nDoF=trk->fitQuality()->numberDoF(); - m_nstationMap=stationMap; - m_nlayerMap=layerMap; - m_nlayersHit=layersHit; - m_niftHit=iftHit; - - } + m_tracksCharge.push_back(charge); + if (charge>0){ m_trackPositiveIndicies.push_back(m_trackCount);} + if (charge>0) {m_trackNegativeIndicies.push_back(m_trackCount);} + m_tracksChi2.push_back(trk->fitQuality()->chiSquared()); + m_tracksDoF.push_back(trk->fitQuality()->numberDoF()); + + m_tracksX.push_back(position.x()); + m_tracksY.push_back(position.y()); + m_tracksZ.push_back(position.z()); + + m_tracksPx.push_back(momentum.x()); + m_tracksPy.push_back(momentum.y()); + m_tracksPz.push_back(momentum.z()); + m_tracksPmag.push_back(momentum.mag()); ++m_trackCount; @@ -305,7 +419,6 @@ StatusCode PairVertexAlg::execute(const EventContext &ctx) const m_vertexPos[2]=v->position().z(); break; } - m_tree->Fill(); @@ -325,26 +438,39 @@ StatusCode PairVertexAlg::finalize() void PairVertexAlg::clearTree() const { - for (int i = 0; i < 7; i++) {m_tracks[i].clear();} m_trackCount=0; + m_tracksPmag.clear(); + m_sigmaQoverP.clear(); + + m_tracksX.clear(); + m_tracksY.clear(); + m_tracksZ.clear(); + m_tracksPx.clear(); + m_tracksPy.clear(); + m_tracksPz.clear(); + m_tracksPmag.clear(); + + m_tracksCharge.clear(); + m_sigmaQoverP.clear(); + m_tracksChi2.clear(); + m_tracksDoF.clear(); + + m_trackPositiveIndicies.clear(); + m_trackNegativeIndicies.clear(); + m_trackD2i=-1; + m_trackD3i=-1; + + m_tracksTruthBarcode.clear(); + m_tracksTruthPdg.clear(); + m_tracksTruthCharge.clear(); + m_tracksTruthPmag.clear(); + m_tracksIsFiducial.clear(); + + m_tracksnLayersHit.clear(); + m_tracksLayersIFT.clear(); + m_tracksIFThit.clear(); + - m_pstationMap.clear(); - m_playerMap={{},{},{},{}}; - m_ppos_s1l0= {-1,-1,-1}; - m_pmom= {-1,-1,-1}; - m_pChi2=0; - m_pDoF=0; - m_playersHit=0; - m_piftHit=0; - - m_nstationMap.clear(); - m_nlayerMap={{},{},{},{}}; - m_npos_s1l0= {-1,-1,-1}; - m_nmom= {-1,-1,-1}; - m_nChi2=0; - m_nDoF=0; - m_nlayersHit=0; - m_niftHit=0; for(int ii=0;ii<15;ii++) { m_wave_localtime[ii]=0; @@ -359,6 +485,23 @@ void PairVertexAlg::clearTree() const m_wave_status[ii]=0; } m_vertexPos= {-1,-1,-1}; + m_isFiducial.clear(); + m_truthPdg.clear(); + m_truthBarcode.clear(); + + m_truthd0_P.clear(); + m_truthd0_px.clear(); + m_truthd0_py.clear(); + m_truthd0_pz.clear(); + m_truthd0_IsFiducial.clear(); + m_truthd0_charge.clear(); + + m_truthd1_P.clear(); + m_truthd1_px.clear(); + m_truthd1_py.clear(); + m_truthd1_pz.clear(); + m_truthd1_IsFiducial.clear(); + m_truthd1_charge.clear(); } diff --git a/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.h b/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.h index d0700d3a5bf4b4e891a55a7b04b102de07117f79..3495c0ed4f9b1b96aee1e364c214336ef3eb328e 100644 --- a/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.h +++ b/Tracker/TrackerRecAlgs/PairVertex/src/PairVertexAlg.h @@ -12,6 +12,11 @@ Copyright (C) 2022 CERN for the benefit of the FASER collaboration #include "xAODFaserWaveform/WaveformHit.h" #include "xAODFaserWaveform/WaveformHitContainer.h" +#include "FaserActsKalmanFilter/IFiducialParticleTool.h" +#include "FaserActsKalmanFilter/ITrackTruthMatchingTool.h" +#include "xAODTruth/TruthParticleContainer.h" +#include "xAODTruth/TruthEventContainer.h" + #include <vector> #include "TTree.h" #include <TH1.h> @@ -75,6 +80,10 @@ namespace Tracker SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerContainer { this, "PreshowerContainer", "PreshowerWaveformHits", "Preshower hit container name" }; SG::ReadHandleKey<xAOD::WaveformHitContainer> m_ecalContainer { this, "EcalContainer", "CaloWaveformHits", "Ecal hit container name" }; + ToolHandle<IFiducialParticleTool> m_fiducialParticleTool {this, "FiducialParticleTool", "FiducialParticleTool"}; + ToolHandle<ITrackTruthMatchingTool> m_trackTruthMatchingTool {this, "TrackTruthMatchingTool", "TrackTruthMatchingTool"}; + SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleContainer { this, "ParticleContainer", "TruthParticles", "Truth particle container name." }; + mutable std::atomic<size_t> m_numberOfEvents{0}; mutable std::atomic<size_t> m_numberOfPositiveTracks{0}; mutable std::atomic<size_t> m_numberOfNegativeTracks{0}; @@ -86,41 +95,39 @@ namespace Tracker mutable std::atomic<size_t> m_numberOfNoUpstreamTracks{0}; mutable TTree* m_tree; - mutable std::vector<std::vector<double>> m_tracks={{},{},{},{},{},{},{}}; //charge, x, y, z, px, py, pz, bS0,bS1,bS2,bS3 - mutable int m_trackCount=0; - - //POSITIVE - mutable std::vector<std::vector<int>> m_playerMap={{},{},{},{}}; - mutable std::set<int> m_pstationMap; - mutable std::vector<double> m_ppos_s1l0 = {-1,-1,-1}; // {x,y,z} - mutable std::vector<double> m_pmom; - mutable float m_pChi2; - mutable double m_pDoF; - mutable int m_pnLayers; - mutable int m_pnLayersIFT; - mutable int m_playersHit; - mutable int m_piftHit; - - //NEGATIVE - mutable std::vector<std::vector<int>> m_nlayerMap={{},{},{},{}}; - mutable std::set<int> m_nstationMap; - mutable std::vector<double> m_npos_s1l0 = {-1,-1,-1}; // {x,y,z} - mutable std::vector<double> m_nmom; - mutable float m_nChi2; - mutable double m_nDoF; - mutable int m_nlayersHit; - mutable int m_niftHit; - - //CALORIMETER - //StringProperty m_CaloConfig { this, "CaloConfig", "Low_gain", "Configuration found at http://aagaard.web.cern.ch/aagaard/FASERruns.html (spaces replaced with '_')" }; - mutable float m_Calo0_Edep; - mutable float m_Calo1_Edep; - mutable float m_Calo2_Edep; - mutable float m_Calo3_Edep; - mutable float m_Calo_Total_Edep; - mutable float m_MIP_sim_Edep_calo; - mutable float m_MIP_sim_Edep_preshower; + //TRACK COLLECTION + mutable int m_trackCount=0; + + mutable std::vector<double> m_tracksX; + mutable std::vector<double> m_tracksY; + mutable std::vector<double> m_tracksZ; + mutable std::vector<double> m_tracksPx; + mutable std::vector<double> m_tracksPy; + mutable std::vector<double> m_tracksPz; + mutable std::vector<double> m_tracksPmag; + + mutable std::vector<double> m_tracksCharge; + mutable std::vector<double> m_sigmaQoverP; + mutable std::vector<double> m_tracksChi2; + mutable std::vector<double> m_tracksDoF; + + mutable std::vector<double> m_tracksTruthBarcode; + mutable std::vector<double> m_tracksTruthPdg; + mutable std::vector<double> m_tracksTruthCharge; + mutable std::vector<double> m_tracksTruthPmag; + mutable std::vector<bool> m_tracksIsFiducial; + + mutable std::vector<int> m_tracksnLayersHit; + mutable std::vector<int> m_tracksLayersIFT; + mutable std::vector<int> m_tracksIFThit; + + mutable std::vector<int> m_trackPositiveIndicies; + mutable std::vector<int> m_trackNegativeIndicies; + mutable int m_trackD2i; //which track is daughter; -1 if not matched + mutable int m_trackD3i; + + mutable std::vector<std::vector<int>> m_layerMap={{},{},{},{}}; //WAVEFORM mutable float m_wave_localtime[15]; @@ -133,8 +140,58 @@ namespace Tracker mutable float m_wave_baseline_rms[15]; mutable unsigned int m_wave_status[15]; - //EXTRAPOLATION + //TRUTH + DoubleProperty m_minMomentum { this, "MinMomentum", 50000.0, "Write out all truth particles with a momentum larger MinMomentum"}; + mutable std::vector<double> m_vertexPos = {-1,-1,-1}; + mutable std::vector<bool> m_isFiducial; // track is fiducial if there are simulated hits for stations 1 - 3 and the distance from the center is smaller than 100 mm + + mutable std::vector<int> m_truthParticleBarcode; // vector of barcodes of all truth particles with a momentum larger 50 GeV + mutable std::vector<int> m_truthParticleMatchedTracks; // vector of number of tracks to which a truth particle is matched to + mutable std::vector<bool> m_truthParticleIsFiducial; // vector of boolean showing whether a truth particle is fiducial + + mutable std::vector<int> m_truthBarcode; + mutable std::vector<int> m_truthPdg; + mutable std::vector<double> m_truthPmag; + mutable std::vector<double> m_truthCharge; + + mutable std::vector<double> m_truthM_P; + + mutable std::vector<double> m_truthM_px; + mutable std::vector<double> m_truthM_py; + mutable std::vector<double> m_truthM_pz; + + mutable std::vector<double> m_truthM_x; + mutable std::vector<double> m_truthM_y; + mutable std::vector<double> m_truthM_z; + + + mutable std::vector<double> m_truthd0_P; + + mutable std::vector<double> m_truthd0_px; + mutable std::vector<double> m_truthd0_py; + mutable std::vector<double> m_truthd0_pz; + + mutable std::vector<double> m_truthd0_x; + mutable std::vector<double> m_truthd0_y; + mutable std::vector<double> m_truthd0_z; + + mutable std::vector<double> m_truthd0_IsFiducial; + mutable std::vector<double> m_truthd0_charge; + + mutable std::vector<double> m_truthd1_P; + + mutable std::vector<double> m_truthd1_px; + mutable std::vector<double> m_truthd1_py; + mutable std::vector<double> m_truthd1_pz; + + mutable std::vector<double> m_truthd1_x; + mutable std::vector<double> m_truthd1_y; + mutable std::vector<double> m_truthd1_z; + + mutable std::vector<double> m_truthd1_IsFiducial; + mutable std::vector<double> m_truthd1_charge; + };