From a61a72d7856829c89aac3d6c11f9e9acc1770ee1 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 25 Nov 2025 14:46:44 +0100 Subject: [PATCH 01/77] remove files that are now in DrawHits --- HitAnalyzer/test/floatMod.C | 12 -- HitAnalyzer/test/histogramDefinition.py | 206 ------------------------ 2 files changed, 218 deletions(-) delete mode 100644 HitAnalyzer/test/floatMod.C delete mode 100644 HitAnalyzer/test/histogramDefinition.py diff --git a/HitAnalyzer/test/floatMod.C b/HitAnalyzer/test/floatMod.C deleted file mode 100644 index 1950020..0000000 --- a/HitAnalyzer/test/floatMod.C +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -float floatMod(float a, float b) { - // - // change fmod behaviour for negative numbers - // (fmod will return -fmod(|a|,b) for a<0) - // - float result = std::fmod(a,b); - if ( result < 0. ) result += b; - return result; -} diff --git a/HitAnalyzer/test/histogramDefinition.py b/HitAnalyzer/test/histogramDefinition.py deleted file mode 100644 index 8bfc321..0000000 --- a/HitAnalyzer/test/histogramDefinition.py +++ /dev/null @@ -1,206 +0,0 @@ -# -# Definitions for histograms from a configuration file -# -from fnmatch import fnmatch - -class HistogramDefinition: - ''' A single histogram definition. - ''' - reqGenFields = [ 'canvasName', 'histogramName', 'histogramTitle', 'variable', 'baseCuts' ] - reqHistFields = [ ] - requiredFields = reqGenFields + reqHistFields - optGenFields = [ 'effCuts', 'logY' ] - optHistFields = [ 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'yNbins', 'yMin', 'yMax', \ - 'zMin', 'zMax', 'display', 'profile' ] - optionalFields = optGenFields + optHistFields - allFields = requiredFields + optionalFields - allHistFields = reqHistFields + optHistFields - - def __init__(self,name,inputDict): - ''' Define histogram and drawing parameters from dictionary. - Arguments: - name ....... name of the histogram definition - inputDict .. dictionary with values - ''' - # - assert name.isalnum() - self.name = name - # - # read parameters - # - # default is None for all parameters - # - self.parameters = { x:None for x in HistogramDefinition.allFields } - # - # loop over main dictionary - # - for k,v in inputDict.items(): - # - # skip standard python entries - # - if k.startswith('__'): - continue - # - # standard entry in main dictionary - store value - # - if k in HistogramDefinition.allFields: - # - # general variable - # - self.parameters[k] = v - # - # nested dictionary with parameters for a specific module type - # - elif k.startswith("mType"): - # - # mType-specific histogram parameters - # - assert type(v)==dict and ( not k in self.parameters ) and len(k)>5 and k[5:].isdigit() - self.parameters[k] = { x:None for x in HistogramDefinition.allHistFields } - for kh,vh in v.items(): - if kh in HistogramDefinition.allHistFields: - self.parameters[k][kh] = vh - else: - print("Warning: key",kh, \ - "is not a standard histogram field name - ignoring the entry in", \ - self.name) - # - # unknown key - # - else: - print("Warning: key",k,"is not a standard field name - ignoring the entry in",self.name) - # - # set some parameters from other inputs if unspecified - # - if self.parameters['canvasName']==None: - self.parameters['canvasName'] = "c" + self.name[0].upper() + self.name[1:] - if self.parameters['histogramName']==None: - self.parameters['histogramName'] = "h" + self.name[0].upper() + self.name[1:] - # - # make sure all required fields are present - # - for f in HistogramDefinition.requiredFields: - assert ( f in self.parameters ) and self.parameters[f]!=None - - #def __getitem__(self,field): - # if field in self.parameters: - # return self.parameters[field] - # return None - - def getParameter(self,name,mType=None): - ''' Retrieve a single parameter (optionally a specific one for a given module type) - ''' - result = None - # - # give priority to parameter specific to a module type - # - mTName = "mType"+str(mType) if mType!=None else None - if ( mTName in self.parameters ) and ( name in self.parameters[mTName] ): - result = self.parameters[mTName][name] - if result!=None: - return self.parameters[mTName][name] - # - # not found: use general parameter - # - if name in self.parameters: - return self.parameters[name] - return None - - def vetoMType(self,mType): - ''' Check for an mType entry with display = False - ''' - # - # try to get 'display' parameter - # - name = 'display' - mTName = "mType"+str(mType) if mType!=None else None - if ( mTName in self.parameters ) and ( name in self.parameters[mTName] ): - if self.parameters[mTName][name]!=None: - return not self.parameters[mTName][name] - return False - -class HistogramDefinitions: - - def __init__(self): - self.allDefinitions = { } - self.allHistoNames = set() - self.allCanvases = set() - self.byCanvas = { } - - def add(self,hdef): - assert not hdef.name in self.allDefinitions - - hName = hdef.getParameter('histogramName') - assert not hName in self.allHistoNames - self.allHistoNames.add(hName) - - cName = hdef.getParameter('canvasName') - assert not cName in self.allCanvases - self.allDefinitions[hdef.name] = hdef - self.allCanvases.add(cName) - - if not cName in self.byCanvas: - self.byCanvas[cName] = { } - self.byCanvas[cName][hdef.name] = hdef - - def canvasNames(self): - return self.allCanvases - - def __getitem__(self,name): - if name in self.allDefinitions: - return self.allDefinitions[name] - return None - -def loadHistogramDefinitions(configName,selectedNames=[],vetoedNames=[]): - ''' Load histogram definitions from a configuration file. The configuration file - defines dictionaries with the definitions as variable. The name of the variable - serves as name of the HistogramDefinition. - Arguments: - configName ..... name of the module to import from / python file name - selectedNames .. explicit list of histogram names to be imported (filename wildcard syntax) - vetoedNames .... explicit list of histogram names to be skipped (filename wildcard syntax) - ''' - # load histogram definitions - # - result = HistogramDefinitions() - if configName==None: - return result - - moduleName = configName[:-3] if configName.endswith(".py") else configName - module = __import__(moduleName) - for n in dir(module): - if n.startswith('__'): - continue - hDict = getattr(module,n) - #print(n,type(hDict)) - #sys.exit() - assert type(hDict)==dict - # - # check if in list of histograms to be displayed - # - selFlg = False - for p in selectedNames: - if fnmatch(n,p): - selFlg = True - break - if not selFlg: - continue - # - # check if in list of histograms to be vetoed - # - selFlg = True - for p in vetoedNames: - if fnmatch(n,p): - selFlg = False - break - if not selFlg: - continue - # - # add histogram - # - hDef = HistogramDefinition(n,hDict) - result.add(hDef) - print("Added",hDef.getParameter('canvasName')) - - return result - From 56e97dd779f96d0e53f06707bf36af49fe81656e Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 1 Dec 2025 18:25:57 +0100 Subject: [PATCH 02/77] logZ option --- DrawHits/drawHits.py | 10 +++++++--- DrawHits/histogramDefinition.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/DrawHits/drawHits.py b/DrawHits/drawHits.py index 3748b9f..e7ce1a8 100755 --- a/DrawHits/drawHits.py +++ b/DrawHits/drawHits.py @@ -316,7 +316,7 @@ def fillHistoByDef(tree,hDef,extraCuts): return histos -def drawHistoByDef(histos,hDef,logY=False,same=False): +def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): result = { 'cnv' : None, 'histos' : histos, 'pave' : None } savedDir = ROOT.gDirectory @@ -405,6 +405,8 @@ def drawHistoByDef(histos,hDef,logY=False,same=False): histos[mType][0].Draw("ZCOL") if logY or hDef.getParameter('logY',mType): ROOT.gPad.SetLogy(1) + if not is1D and ( logZ or hDef.getParameter('logZ',mType) ): + ROOT.gPad.SetLogz(1) ROOT.gPad.Update() #cnv.cd() @@ -484,7 +486,8 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): type=str, default='*') parser.add_argument('--vetoedHistograms', help='comma-separated names of histogram definitions not to be used', type=str, default='') -parser.add_argument('--logY', help='use log scale', action='store_true', default=False) +parser.add_argument('--logY', help='use log scale for y axis', action='store_true', default=False) +parser.add_argument('--logZ', help='use log scale for z axis', action='store_true', default=False) parser.add_argument('--printTree', '-p', help='print TTree contents', action='store_true', default=False) parser.add_argument('--listHistograms', '-l', help='list predefined and selected histograms', \ action='store_true', default=False) @@ -591,7 +594,8 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) cHistos[hName] = fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts) - allObjects.append(drawHistoByDef(cHistos[hName],allHDefs.byCanvas[cName][hName],logY=args.logY,same=same)) + allObjects.append(drawHistoByDef(cHistos[hName],allHDefs.byCanvas[cName][hName], \ + logY=args.logY,logZ=args.logZ,same=same)) same = True if args.output!=None: c = allObjects[-1]['cnv'] diff --git a/DrawHits/histogramDefinition.py b/DrawHits/histogramDefinition.py index 580f3f2..0685f28 100644 --- a/DrawHits/histogramDefinition.py +++ b/DrawHits/histogramDefinition.py @@ -13,7 +13,7 @@ class HistogramDefinition: reqHistFields = [ ] requiredFields = list(set(reqGenFields + reqHistFields)) # optional fields in the general section - optGenFields = [ 'variable', 'baseCuts', 'effCuts', 'logY' ] + optGenFields = [ 'variable', 'baseCuts', 'effCuts', 'logY', 'logZ' ] # optional fields in the histogram section optHistFields = [ 'variable', 'histogramName', 'histogramTitle', \ 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'yNbins', 'yMin', 'yMax', \ From 7f0de31edaf074c93fcbd57c3427a400f25f1827 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 2 Dec 2025 12:06:25 +0100 Subject: [PATCH 03/77] utility for histograms --- DrawHits/fitRes.py | 178 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 DrawHits/fitRes.py diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py new file mode 100644 index 0000000..1669f5e --- /dev/null +++ b/DrawHits/fitRes.py @@ -0,0 +1,178 @@ +import sys +from math import sqrt,log +import ROOT +import argparse + +class FitHistogram: + + def interpolate(y,y1,y2,x1=0.,x2=1.): + ''' Linear interpolation between two points (x1,y1) and (x2,y2) + to yield x corresponding to the target value y. + ''' + return x1 + (y-y1)/(y2-y1)*(x2-x1) + + def __init__(self,histogram): + self.hist = histogram + self.graph = None + self.intGraph = None + + def fwhm(self): + ''' Return lowest / highest x corresponding to ymax/2, and ymax/2 + ''' + # + # target y value (1/2 maximum) and bin width (assume constant bin width) + # + y = self.hist.GetBinContent(self.hist.GetMaximumBin())/2. + dx = self.hist.GetBinWidth(1) + # + # preset result (low / high x values) + # + xlow = None + xhigh = None + # + # loop over pairs of adjacent histogram bins + # + x1 = self.hist.GetBinLowEdge(1) + y1 = self.hist.GetBinContent(1) + for i in range(2,self.hist.GetNbinsX()): + # check if target value between contents of neighbouring bins + x2 = self.hist.GetBinLowEdge(i) + y2 = self.hist.GetBinContent(i) + first = None + if y>=y1 and yy2: + first = False + + if first!=None: + # calculate interpolated x value + x = FitHistogram.interpolate(y,y1,y2,x1,x2) + # store lowest and highest x corresponding to y + if first and xlow==None: + xlow = x + elif not first: + xhigh = x + # move to next bin + x1 = x2 + y1 = y2 + + # + # require result ( assumes that first and last bins are < ymax/2 ) and + # correct for bin width / 2 ( assumes that bin value corresponds to center of bin ) + assert xlow!=None and xhigh!=None + return (xlow+dx,xhigh+dx,y) + + def quantile(self,q): + +class FitCanvas: + + def __init__(self,canvas,mtype): + self.canvas = canvas + self.mtype = mtype + self.pad = None + self.fhist = None + + padName = mainCnv.GetName()+str(mtype-22) + for o in mainCnv.GetListOfPrimitives(): + if o.InheritsFrom(ROOT.TPad.Class()) and o.GetName()==padName: + assert self.pad==None + self.pad = o + assert self.pad!=None + + histNameBase = "h"+mainCnv.GetName()[1:]+str(mtype) + self.fhist = None + for o in self.pad.GetListOfPrimitives(): + if o.InheritsFrom(ROOT.TH1.Class()) and o.GetName().startswith(histNameBase): + assert self.fhist==None + self.fhist = FitHistogram(o) + assert self.fhist!=None + + def histogram(self): + print("fhist",self.fhist,self.fhist.hist) + return self.fhist.hist + + def fwhm(self): + return self.fhist.fwhm() + +parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('--moduleType', '-m', help='module type', type=int, choices=[23,24,25], default=23) +parser.add_argument('--fwhm', help='determining FWHM', action='store_true', default=False) +parser.add_argument('--slices', '-s', help='fit in slices in y', action='store_true', default=False) +parser.add_argument('file', help='input file', type=str, nargs=1, default=None) +args = parser.parse_args() + +tf = ROOT.TFile(args.file[0]) +tf.ls() +mainCnv = None +for k in tf.GetListOfKeys(): + o = k.ReadObj() + if o.IsA()==ROOT.TCanvas.Class(): + assert mainCnv==None + mainCnv = k.ReadObj() +assert mainCnv!=None + +canvases = [ ] +slices = [ ] + +mainCnv.Draw() +fitCanvas = FitCanvas(mainCnv,args.moduleType) +if not args.slices: + assert fitCanvas.histogram().GetDimension()==1 + #print(fitCanvas.fwhm()) + x1,x2,y = fitCanvas.fwhm() + print(" = {:6.1f}um, dx = {:6.1f}um, sig = {:6.1f}um ( interval {:6.4f} - {:6.4f}cm )".format( \ + 10000*(x1+x2)/2.,10000*(x2-x1),10000*(x2-x1)/2/sqrt(2*log(2)),x1,x2)) + + fitCanvas.pad.cd() + fwhmArrow = ROOT.TArrow() + fwhmArrow.SetLineColor(2) + fwhmArrow.SetLineWidth(2) + fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") + fitCanvas.pad.Update() + +else: + hist2D = fitCanvas.histogram() + assert hist2D.GetDimension()==2 + yaxis = hist2D.GetYaxis() + nby = hist2D.GetNbinsY() + ncol = int(sqrt(nby)) + while ncol*ncol") + ROOT.gPad.Update() + #cnv.Update() + From 2b8128b41999e29259eb9086c3cbe46d3402a1d3 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 2 Dec 2025 15:32:46 +0100 Subject: [PATCH 04/77] some more options for fits --- DrawHits/drawHits.py | 35 +++- DrawHits/drawHitsTmp.yaml | 30 ++++ DrawHits/fitRes.py | 281 +++++++++++++++++++++++++++----- DrawHits/histogramDefinition.py | 2 +- 4 files changed, 301 insertions(+), 47 deletions(-) diff --git a/DrawHits/drawHits.py b/DrawHits/drawHits.py index e7ce1a8..80820c2 100755 --- a/DrawHits/drawHits.py +++ b/DrawHits/drawHits.py @@ -254,6 +254,8 @@ def fillHistoByDef(tree,hDef,extraCuts): if hDef.vetoMType(mType): continue is1D = hDef.getParameter('yNbins',mType)==None + is2D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)==None + is3D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)!=None isProfile = hDef.getParameter('profile',mType)!=None and hDef.getParameter('profile',mType) effCuts = hDef.getParameter('effCuts',mType) variable = hDef.getParameter('variable',mType) @@ -290,7 +292,7 @@ def fillHistoByDef(tree,hDef,extraCuts): cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] - else: + elif is2D: nby = hDef.getParameter('yNbins',mType) ymin = hDef.getParameter('yMin',mType) ymax = hDef.getParameter('yMax',mType) @@ -310,6 +312,20 @@ def fillHistoByDef(tree,hDef,extraCuts): else: # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] + elif is3D: + nby = hDef.getParameter('yNbins',mType) + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + nbz = hDef.getParameter('zNbins',mType) + zmin = hDef.getParameter('zMin',mType) + zmax = hDef.getParameter('zMax',mType) + histos[mType] = [ ROOT.TH3F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax), \ + None, None, None ] + tree.Project(hName+"_1",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + assert effCuts==None + # always keep final histogram in 4th position + histos[mType][3] = histos[mType][0] #print("Ending for ",hDef.name,hName,hTitle) savedDir.cd() @@ -344,6 +360,8 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): if hDef.vetoMType(mType): continue is1D = hDef.getParameter('yNbins',mType)==None + is2D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)==None + is3D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)!=None isProfile = hDef.getParameter('profile',mType)!=None and hDef.getParameter('profile',mType) effCuts = hDef.getParameter('effCuts',mType) variable = hDef.getParameter('variable',mType) @@ -362,6 +380,7 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): xmax = hDef.getParameter('xMax',mType) ytitle = hDef.getParameter('yTitle',mType) if hDef.getParameter('yTitle',mType) else "" + ztitle = hDef.getParameter('zTitle',mType) if hDef.getParameter('zTitle',mType) else "" if is1D and ( not isProfile ): ymin = hDef.getParameter('yMin',mType) if hDef.getParameter('yMin',mType)!=None else 0. ymax = hDef.getParameter('yMax',mType) if hDef.getParameter('yMax',mType)!=None else 1.05 @@ -387,7 +406,7 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): #histos[mType][0].SetFillColor(ROOT.TColor.GetColorBright(ROOT.kGray)) #histos[mType][0].SetFillColor(ROOT.kGray) histos[mType][0].Draw("same" if same else "") - else: + elif is2D: assert not same zmin = hDef.getParameter('zMin',mType) if hDef.getParameter('zMin',mType)!=None else 0. zmax = hDef.getParameter('zMax',mType) if hDef.getParameter('zMax',mType)!=None else 1.05 @@ -403,9 +422,19 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): histos[mType][0].GetXaxis().SetTitle(xtitle) histos[mType][0].GetYaxis().SetTitle(ytitle) histos[mType][0].Draw("ZCOL") + elif is3D: + assert not same + zmin = hDef.getParameter('zMin',mType) if hDef.getParameter('zMin',mType)!=None else 0. + zmax = hDef.getParameter('zMax',mType) if hDef.getParameter('zMax',mType)!=None else 1.05 + assert effCuts==None + histos[mType][0].SetTitle(hTitle) + histos[mType][0].GetXaxis().SetTitle(xtitle) + histos[mType][0].GetYaxis().SetTitle(ytitle) + histos[mType][0].GetZaxis().SetTitle(ztitle) + histos[mType][0].Draw() if logY or hDef.getParameter('logY',mType): ROOT.gPad.SetLogy(1) - if not is1D and ( logZ or hDef.getParameter('logZ',mType) ): + if is2D and ( logZ or hDef.getParameter('logZ',mType) ): ROOT.gPad.SetLogz(1) ROOT.gPad.Update() diff --git a/DrawHits/drawHitsTmp.yaml b/DrawHits/drawHitsTmp.yaml index 67873c4..11e05f9 100644 --- a/DrawHits/drawHitsTmp.yaml +++ b/DrawHits/drawHitsTmp.yaml @@ -421,3 +421,33 @@ widthVsPath: yNbins: 25 yMin: 0.0 yMax: 25 + +res3DXVsDxDzModX: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -500 + xMax: 500 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 20 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 20 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 18 + yMin: 0 + yMax: 90 diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 1669f5e..554869e 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -13,56 +13,165 @@ def interpolate(y,y1,y2,x1=0.,x2=1.): def __init__(self,histogram): self.hist = histogram - self.graph = None - self.intGraph = None + self.graph_ = None + self.cumulativeGraph_ = None + self.cumNormGraph_ = None + + def graph(self): + ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = bin contents. + Ignores under- / overflow. + ''' + if self.graph_==None: + self.graph_ = [ ] + + for i in range(self.hist.GetNbinsX()): + xbin = self.hist.GetBinLowEdge(i+1) + self.hist.GetBinWidth(i+1)/2. + self.graph_.append( (xbin,self.hist.GetBinContent(i+1)) ) + + return self.graph_ + + def cumulativeGraph(self): + ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = cumulated bin contents. + Ignores under- / overflow. + ''' + if self.cumulativeGraph_==None: + self.cumulativeGraph_ = [ ] + sum = 0. + for i in range(self.hist.GetNbinsX()): + xbin = self.hist.GetBinLowEdge(i+1) + self.hist.GetBinWidth(i+1)/2. + sum += self.hist.GetBinContent(i+1) + self.cumulativeGraph_.append( (xbin,sum) ) + + return self.cumulativeGraph_ + + def cumulativeNormGraph(self): + ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = cumulated bin contents. + Normalized to total histogram contents (including under- / overflow). + ''' + if self.cumNormGraph_==None: + cg = self.cumulativeGraph() + sum = self.hist.GetSumOfWeights() + self.cumNormGraph_ = [ ( x,y/sum ) for x,y in cg ] + + return self.cumNormGraph_ + + + def intersects(self,value,cumulative=False,norm=False,direction=0): + ''' Calculate x-coordinates for intersection(s) of a graph defined by a list of (x,y) points sorted in x + with y==value. Uses linear interpolation. + Arguments: + value ....... target value + cumulative .. if true, use cumulative graph + norm ........ if true, use normalized cumulative graph + direction ... three possible values: 0 = any intersection, +1/-1 = consider only segments + with positive / negative slope. + ''' + # + # Get graph and do basic check + # + graph = None + if cumulative: + graph = self.cumulativeNormGraph() if norm else self.cumulativeGraph() + else: + assert norm==False + graph = self.graph() + + result = [ ] + if len(graph)<2: + return result + # + # loop over adjacent pairs of points + # + x1 = None + y1 = None + for x2,y2 in graph: + # + # start checking at 2nd point + # + if x1!=None: + assert x2>x1 + # + # value in interval? + # + if value>=min(y1,y2) and value<=max(y1,y2): + # check if dy is positive or negative, and compare with required sign of direction + if direction==0 or direction*(y2-y1)>0: + result.append(FitHistogram.interpolate(value,y2,y1,x2,x1)) + # + # move to next point + # + x1 = x2 + y1 = y2 + + return result def fwhm(self): ''' Return lowest / highest x corresponding to ymax/2, and ymax/2 ''' # - # target y value (1/2 maximum) and bin width (assume constant bin width) + # target y value (1/2 maximum) # y = self.hist.GetBinContent(self.hist.GetMaximumBin())/2. - dx = self.hist.GetBinWidth(1) # - # preset result (low / high x values) + # use first intersection with upward slope # - xlow = None - xhigh = None + xups = self.intersects(y,cumulative=False,direction=1) + print("xups",xups) + xlow = xups[0] if xups else None # - # loop over pairs of adjacent histogram bins + # use last intersection with downward slope # - x1 = self.hist.GetBinLowEdge(1) - y1 = self.hist.GetBinContent(1) - for i in range(2,self.hist.GetNbinsX()): - # check if target value between contents of neighbouring bins - x2 = self.hist.GetBinLowEdge(i) - y2 = self.hist.GetBinContent(i) - first = None - if y>=y1 and yy2: - first = False - - if first!=None: - # calculate interpolated x value - x = FitHistogram.interpolate(y,y1,y2,x1,x2) - # store lowest and highest x corresponding to y - if first and xlow==None: - xlow = x - elif not first: - xhigh = x - # move to next bin - x1 = x2 - y1 = y2 + xdowns = self.intersects(y,cumulative=False,direction=-1) + print("xdowns",xdowns) + xhigh = xdowns[-1] if xdowns else None + #dx = self.hist.GetBinWidth(1) + ### + ## preset result (low / high x values) + ## + #xlow = None + #xhigh = None + ## + ## loop over pairs of adjacent histogram bins + ## + #x1 = self.hist.GetBinLowEdge(1) + #y1 = self.hist.GetBinContent(1) + #for i in range(2,self.hist.GetNbinsX()): + # # check if target value between contents of neighbouring bins + # x2 = self.hist.GetBinLowEdge(i) + # y2 = self.hist.GetBinContent(i) + # first = None + # if y>=y1 and yy2: + # first = False + # + # if first!=None: + # # calculate interpolated x value + # x = FitHistogram.interpolate(y,y1,y2,x1,x2) + # # store lowest and highest x corresponding to y + # if first and xlow==None: + # xlow = x + # elif not first: + # xhigh = x + # # move to next bin + # x1 = x2 + # y1 = y2 # # require result ( assumes that first and last bins are < ymax/2 ) and # correct for bin width / 2 ( assumes that bin value corresponds to center of bin ) assert xlow!=None and xhigh!=None - return (xlow+dx,xhigh+dx,y) + return (xlow,xhigh,y) + #return (xlow+dx,xhigh+dx,y) + + def quantile(self,prob): + ''' Return x-value to quantile q. + ''' + result = self.intersects(prob,cumulative=True,norm=True,direction=1) + #print(prob,result) + assert len(result)<2 - def quantile(self,q): + return result[0] if result else None class FitCanvas: @@ -88,7 +197,7 @@ def __init__(self,canvas,mtype): assert self.fhist!=None def histogram(self): - print("fhist",self.fhist,self.fhist.hist) + #print("fhist",self.fhist,self.fhist.hist) return self.fhist.hist def fwhm(self): @@ -98,6 +207,8 @@ def fwhm(self): parser.add_argument('--moduleType', '-m', help='module type', type=int, choices=[23,24,25], default=23) parser.add_argument('--fwhm', help='determining FWHM', action='store_true', default=False) parser.add_argument('--slices', '-s', help='fit in slices in y', action='store_true', default=False) +parser.add_argument('--quantile', '-q', help='calculate quantiles corresponding to +- x sigma (can be repeated)', \ + action='append', type=float, default=[]) parser.add_argument('file', help='input file', type=str, nargs=1, default=None) args = parser.parse_args() @@ -116,7 +227,13 @@ def fwhm(self): mainCnv.Draw() fitCanvas = FitCanvas(mainCnv,args.moduleType) -if not args.slices: +fwhmArrow = ROOT.TArrow() +fwhmArrow.SetLineColor(2) +fwhmArrow.SetLineWidth(2) +quantLine = ROOT.TLine() +quantLine.SetLineColor(4) +quantLine.SetLineWidth(2) +if fitCanvas.histogram().GetDimension()==1 and ( not args.slices ): assert fitCanvas.histogram().GetDimension()==1 #print(fitCanvas.fwhm()) x1,x2,y = fitCanvas.fwhm() @@ -124,13 +241,24 @@ def fwhm(self): 10000*(x1+x2)/2.,10000*(x2-x1),10000*(x2-x1)/2/sqrt(2*log(2)),x1,x2)) fitCanvas.pad.cd() - fwhmArrow = ROOT.TArrow() - fwhmArrow.SetLineColor(2) - fwhmArrow.SetLineWidth(2) fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") + + quantiles = [ ] + qlmax = slices[-1].hist.GetMaximum()/10. + for sigma in args.quantile: + qs = [ ] + for sgn in [-1,1]: + p = ROOT.TMath.Freq(sgn*sigma) + qs.append(slices[-1].quantile(p)) + #print(sigma,sgn,p,qs[-1]) + quantiles.append(qs) + if not ( None in qs ): + quantLine.DrawLine(qs[0],0.,qs[0],qlmax) + quantLine.DrawLine(qs[1],0.,qs[1],qlmax) + fitCanvas.pad.Update() -else: +elif fitCanvas.histogram().GetDimension()==2 and args.slices: hist2D = fitCanvas.histogram() assert hist2D.GetDimension()==2 yaxis = hist2D.GetYaxis() @@ -142,9 +270,6 @@ def fwhm(self): #cnv = ROOT.TCanvas("cslice","cslice",1200,1200) #cnv.Divide(ncol,ncol) #slices = [ ] - fwhmArrow = ROOT.TArrow() - fwhmArrow.SetLineColor(2) - fwhmArrow.SetLineWidth(2) hNameBase = hist2D.GetName() hTitleBase = hist2D.GetTitle() for iby in range(nby): @@ -173,6 +298,76 @@ def fwhm(self): print(fmt.format(yaxis.GetBinLowEdge(iby+1),yaxis.GetBinUpEdge(iby+1), \ 10000*(x1+x2)/2.,10000*(x2-x1),10000*(x2-x1)/2/sqrt(2*log(2)),x1,x2)) fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") + + quantiles = [ ] + qlmax = slices[-1].hist.GetMaximum()/10. + for sigma in args.quantile: + qs = [ ] + for sgn in [-1,1]: + p = ROOT.TMath.Freq(sgn*sigma) + qs.append(slices[-1].quantile(p)) + #print(sigma,sgn,p,qs[-1]) + quantiles.append(qs) + if not ( None in qs ): + quantLine.DrawLine(qs[0],0.,qs[0],qlmax) + quantLine.DrawLine(qs[1],0.,qs[1],qlmax) + + ROOT.gPad.Update() + +elif fitCanvas.histogram().GetDimension()==3: + # + # calculate summary of quantiles in x + # + h = fitCanvas.histogram() + nby = h.GetNbinsY() + ymin = h.GetYaxis().GetXmin() + ymax = h.GetYaxis().GetXmax() + nbz = h.GetNbinsZ() + zmin = h.GetZaxis().GetXmin() + zmax = h.GetZaxis().GetXmax() + print(nby,ymin,ymax,nbz,zmin,zmax) + # + # define summary histograms + # + summaries = [ ] + for isigma,sigma in enumerate(args.quantile): + hcentre = ROOT.TH2F(h.GetName()+"Qc"+str(isigma), \ + h.GetTitle()+" (center {:3.1f}#sigma interval)".format(sigma), \ + nby,ymin,ymax,nbz,zmin,zmax) + hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ + h.GetTitle()+" (half-width {:3.1f}#sigma interval)".format(sigma), \ + nby,ymin,ymax,nbz,zmin,zmax) + hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + summaries.append((hcentre,hhalfwidth)) + + for iy in range(nby): + for iz in range(nbz): + htmp = h.ProjectionX(iymin=iy+1,iymax=iy+1,izmin=iz+1,izmax=iz+1) + if htmp.GetSumOfWeights()<100: + continue + fhtmp = FitHistogram(htmp) + for isigma,sigma in enumerate(args.quantile): + q1 = fhtmp.quantile(ROOT.TMath.Freq(-sigma)) + q2 = fhtmp.quantile(ROOT.TMath.Freq(sigma)) + if q1!=None and q2!=None: + hsum = summaries[isigma][0] + ibin = hsum.GetBin(iy+1,iz+1) + hsum.SetBinContent(ibin,(q1+q2)/2.) + hsum = summaries[isigma][1] + hsum.SetBinContent(ibin,(q2-q1)/2.) + + nsigma = len(args.quantile) + c = ROOT.TCanvas("cSum","cSum",500*nsigma,1000) + c.Divide(nsigma,2) + for i in range(nsigma): + c.cd(i+1) + summaries[i][0].Draw("ZCOL") + ROOT.gPad.Update() + c.cd(nsigma+i+1) + summaries[i][1].Draw("ZCOL") ROOT.gPad.Update() - #cnv.Update() + c.Update() diff --git a/DrawHits/histogramDefinition.py b/DrawHits/histogramDefinition.py index 0685f28..78904ac 100644 --- a/DrawHits/histogramDefinition.py +++ b/DrawHits/histogramDefinition.py @@ -17,7 +17,7 @@ class HistogramDefinition: # optional fields in the histogram section optHistFields = [ 'variable', 'histogramName', 'histogramTitle', \ 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'yNbins', 'yMin', 'yMax', \ - 'zMin', 'zMax', 'display', 'profile' ] + 'zNbins', 'zMin', 'zMax', 'display', 'profile' ] optionalFields = list(set(optGenFields + optHistFields)) allFields = list(set(requiredFields + optionalFields)) allHistFields = list(set(reqHistFields + optHistFields)) From 567be6225a7d9224ab68cded26e80645fcf485ad Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 2 Dec 2025 15:55:37 +0100 Subject: [PATCH 05/77] cosmetics for res mean/width in 2d --- DrawHits/drawHits.py | 18 ++++++++++++++++++ DrawHits/histogramDefinition.py | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/DrawHits/drawHits.py b/DrawHits/drawHits.py index 80820c2..7b04884 100755 --- a/DrawHits/drawHits.py +++ b/DrawHits/drawHits.py @@ -520,6 +520,8 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): parser.add_argument('--printTree', '-p', help='print TTree contents', action='store_true', default=False) parser.add_argument('--listHistograms', '-l', help='list predefined and selected histograms', \ action='store_true', default=False) +parser.add_argument('--zone', '-z', help='restrict to zone in OT (barrel, tilted, endcap)', type=str, \ + choices=['barrel','tilted','endcap'], default=None) parser.add_argument('file', help='input file', type=str, nargs='+', default=None) args = parser.parse_args() outputFormats = [ ] @@ -530,6 +532,20 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): fitResiduals = args.fitResiduals.split(",") if args.fitResiduals else [ ] selectedHistoNames = args.selectedHistograms.split(",") vetoedHistoNames = args.vetoedHistograms.split(",") +# +# add cut for zone definition? +# +match args.zone: + case "barrel": + zoneCuts = "detNormal.Rho()>0.99" + case "endcap": + zoneCuts = "detNormal.Rho()<0.01" + case "tilted": + zoneCuts = "detNormal.Rho()>0.05&&detNormal.Rho()<0.095" + case _: + zoneCuts = "" +args.cuts = cutString(args.cuts,zoneCuts) + # # load histogram definitions # @@ -632,6 +648,8 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): basename = os.path.join(args.output,c.GetName()) if args.sampleName!=None: basename += "_" + args.sampleName + if args.zone!=None: + basename += "_" + args.zone print(basename) for fmt in outputFormats: c.SaveAs(basename+"."+fmt) diff --git a/DrawHits/histogramDefinition.py b/DrawHits/histogramDefinition.py index 78904ac..2d585c0 100644 --- a/DrawHits/histogramDefinition.py +++ b/DrawHits/histogramDefinition.py @@ -16,7 +16,8 @@ class HistogramDefinition: optGenFields = [ 'variable', 'baseCuts', 'effCuts', 'logY', 'logZ' ] # optional fields in the histogram section optHistFields = [ 'variable', 'histogramName', 'histogramTitle', \ - 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'yNbins', 'yMin', 'yMax', \ + 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'zTitle', \ + 'yNbins', 'yMin', 'yMax', \ 'zNbins', 'zMin', 'zMax', 'display', 'profile' ] optionalFields = list(set(optGenFields + optHistFields)) allFields = list(set(requiredFields + optionalFields)) From 14b0a3444c89e295934f1254ca16328f800f5d00 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 2 Dec 2025 16:19:31 +0100 Subject: [PATCH 06/77] change match to classical if elif statement to stay compatible with older py verions --- DrawHits/drawHits.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/DrawHits/drawHits.py b/DrawHits/drawHits.py index 7b04884..a64113a 100755 --- a/DrawHits/drawHits.py +++ b/DrawHits/drawHits.py @@ -535,15 +535,14 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): # # add cut for zone definition? # -match args.zone: - case "barrel": - zoneCuts = "detNormal.Rho()>0.99" - case "endcap": - zoneCuts = "detNormal.Rho()<0.01" - case "tilted": - zoneCuts = "detNormal.Rho()>0.05&&detNormal.Rho()<0.095" - case _: - zoneCuts = "" +if args.zone=="barrel": + zoneCuts = "detNormal.Rho()>0.99" +elif args.zone=="endcap": + zoneCuts = "detNormal.Rho()<0.01" +elif args.zone=="tilted": + zoneCuts = "detNormal.Rho()>0.05&&detNormal.Rho()<0.095" +else: + zoneCuts = "" args.cuts = cutString(args.cuts,zoneCuts) # From 5fc9c8828f454cb1776eaea63c242877d7c46269 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 3 Dec 2025 12:11:49 +0100 Subject: [PATCH 07/77] cosmetics --- DrawHits/drawHitsTmp.yaml | 30 +++++++++++ DrawHits/fitRes.py | 107 +++++++++++++++++++++++++++++++++----- 2 files changed, 123 insertions(+), 14 deletions(-) diff --git a/DrawHits/drawHitsTmp.yaml b/DrawHits/drawHitsTmp.yaml index 11e05f9..77125ef 100644 --- a/DrawHits/drawHitsTmp.yaml +++ b/DrawHits/drawHitsTmp.yaml @@ -451,3 +451,33 @@ res3DXVsDxDzModX: yNbins: 18 yMin: 0 yMax: 90 + +res3DXVsDxDz: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 554869e..6d3af34 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -209,6 +209,8 @@ def fwhm(self): parser.add_argument('--slices', '-s', help='fit in slices in y', action='store_true', default=False) parser.add_argument('--quantile', '-q', help='calculate quantiles corresponding to +- x sigma (can be repeated)', \ action='append', type=float, default=[]) +parser.add_argument('--dbgQuantiles', help='modX,dxdz pairs defining individual bins for the quantile determination', \ + action='append', type=str, default=[ ]) parser.add_argument('file', help='input file', type=str, nargs=1, default=None) args = parser.parse_args() @@ -222,6 +224,10 @@ def fwhm(self): mainCnv = k.ReadObj() assert mainCnv!=None +dbgQuantPoints = [ ] +for qp in args.dbgQuantiles: + dbgQuantPoints.append( tuple([float(x.strip()) for x in qp.strip().split(",")]) ) + canvases = [ ] slices = [ ] @@ -331,18 +337,50 @@ def fwhm(self): # summaries = [ ] for isigma,sigma in enumerate(args.quantile): - hcentre = ROOT.TH2F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (center {:3.1f}#sigma interval)".format(sigma), \ - nby,ymin,ymax,nbz,zmin,zmax) - hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) - hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ - h.GetTitle()+" (half-width {:3.1f}#sigma interval)".format(sigma), \ - nby,ymin,ymax,nbz,zmin,zmax) - hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + y1 = ROOT.TMath.Freq(-sigma) + y2 = ROOT.TMath.Freq(sigma) + if nby==1: + hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ + h.GetTitle()+" (mean from quantiles)".format(y1,y2), \ + nbz,zmin,zmax) + hcentre.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) + hcentre.GetYaxis().SetTitle("mean of {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hhalfwidth = ROOT.TH1F(h.GetName()+"Qhw"+str(isigma), \ + h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ + nbz,zmin,zmax) + hhalfwidth.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + elif nbz==1: + hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ + h.GetTitle()+" (mean from quantiles)".format(y1,y2), \ + nby,ymin,ymax) + hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hcentre.GetYaxis().SetTitle("mean of {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ + h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ + nby,ymin,ymax) + hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + else: + hcentre = ROOT.TH2F(h.GetName()+"Qc"+str(isigma), \ + h.GetTitle()+" (mean from quantiles)".format(y1,y2), \ + nby,ymin,ymax,nbz,zmin,zmax) + hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + hcentre.GetZaxis().SetTitle("mean of {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ + h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ + nby,ymin,ymax,nbz,zmin,zmax) + hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + hhalfwidth.GetZaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles".format(y1,y2)) summaries.append((hcentre,hhalfwidth)) + dbgBins = [ ] + for y,z in dbgQuantPoints: + dbgBins.append( (h.GetYaxis().FindBin(y), h.GetZaxis().FindBin(z)) ) + + allDbgObjects = { x:[ ] for x in range(len(args.quantile)) } for iy in range(nby): for iz in range(nbz): htmp = h.ProjectionX(iymin=iy+1,iymax=iy+1,izmin=iz+1,izmax=iz+1) @@ -354,20 +392,61 @@ def fwhm(self): q2 = fhtmp.quantile(ROOT.TMath.Freq(sigma)) if q1!=None and q2!=None: hsum = summaries[isigma][0] - ibin = hsum.GetBin(iy+1,iz+1) + if nby==1: + ibin = hsum.GetBin(iz+1) + elif nbz==1: + ibin = hsum.GetBin(iy+1) + else: + ibin = hsum.GetBin(iy+1,iz+1) hsum.SetBinContent(ibin,(q1+q2)/2.) hsum = summaries[isigma][1] - hsum.SetBinContent(ibin,(q2-q1)/2.) + hsum.SetBinContent(ibin,(q2-q1)/2./sigma) + + #allDbgObjects[isigma] = [ ] + if (iy+1,iz+1) in dbgBins: + dbgObjects = [ ] + hResDbg =htmp.Clone("hResDbg_"+str(isigma)+"_"+str(len(allDbgObjects[isigma]))) + hResDbg.SetTitle("hResDbg "+str(isigma)+" y"+str(iy+1)+" z"+str(iz+1)) + hResDbg.GetXaxis().SetTitle(h.GetXaxis().GetTitle()) + savePad = ROOT.gPad + dbgObjects.append(ROOT.TCanvas("c"+hResDbg.GetName()[1:],"c"+hResDbg.GetName()[1:],500,500)) + dbgObjects[0].SetGridx(1) + dbgObjects[0].SetGridy(1) + dbgObjects.append(hResDbg) + hResDbg.Scale(1./hResDbg.GetMaximum()) + hResDbg.Draw("hist") + if q1!=None and q2!=None: + quantLine.DrawLine(q1,0.,q1,hResDbg.GetMaximum()/1.) + quantLine.DrawLine(q2,0.,q2,hResDbg.GetMaximum()/1.) + g = ROOT.TGraph() + g.SetLineColor(ROOT.kMagenta) + g.SetLineStyle(2) + #g.SetMarkerStyle(20) + for x,y in fhtmp.cumulativeNormGraph(): + g.SetPoint(g.GetN(),x,y) + g.Draw("L") + dbgObjects.append(g) + + dbgObjects[0].Update() + allDbgObjects[isigma].append(dbgObjects) + savePad.cd() nsigma = len(args.quantile) c = ROOT.TCanvas("cSum","cSum",500*nsigma,1000) c.Divide(nsigma,2) for i in range(nsigma): c.cd(i+1) - summaries[i][0].Draw("ZCOL") + if summaries[i][0].GetDimension()==2: + ROOT.gPad.SetRightMargin(0.15) + summaries[i][0].Draw("ZCOL") + else: + summaries[i][0].Draw("HIST") ROOT.gPad.Update() c.cd(nsigma+i+1) - summaries[i][1].Draw("ZCOL") + if summaries[i][1].GetDimension()==2: + summaries[i][1].Draw("ZCOL") + else: + summaries[i][1].Draw("HIST") ROOT.gPad.Update() c.Update() From 2fbcf3e1b42c8764c8cf8906ebad2bb1e886da07 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 3 Dec 2025 15:35:54 +0100 Subject: [PATCH 08/77] add histograms residuals (vs. pos on strip) vs. angle / cluster size --- DrawHits/drawHitsTmp.yaml | 61 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/DrawHits/drawHitsTmp.yaml b/DrawHits/drawHitsTmp.yaml index 77125ef..5bd60c5 100644 --- a/DrawHits/drawHitsTmp.yaml +++ b/DrawHits/drawHitsTmp.yaml @@ -481,3 +481,64 @@ res3DXVsDxDz: yNbins: 1 yMin: 0 yMax: 90 + +res3DXVsDxDzW1: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + +res3DXVsDxDzW2: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):10000*(localPos.x()-rhLocalPos.x())' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + From 331c60aff5834f78bf580a663bad1fae7293e3cb Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 3 Dec 2025 15:36:32 +0100 Subject: [PATCH 09/77] define quantiles from cumulative histo of residuals via spline --- DrawHits/fitRes.py | 83 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 6d3af34..0333051 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -16,6 +16,8 @@ def __init__(self,histogram): self.graph_ = None self.cumulativeGraph_ = None self.cumNormGraph_ = None + self.cumNormTGraph_ = None + self.cumNormSpline_ = None # spline corresponding to normalized cumulative graph def graph(self): ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = bin contents. @@ -54,7 +56,20 @@ def cumulativeNormGraph(self): self.cumNormGraph_ = [ ( x,y/sum ) for x,y in cg ] return self.cumNormGraph_ - + + def cumulativeNormSpline(self): + ''' Create (TGraph and) TSpline3 from cumulativeNormGraph + ''' + if self.cumNormTGraph_==None: + self.cumNormTGraph_ = ROOT.TGraph() + for x,y in self.cumulativeNormGraph(): + self.cumNormTGraph_.SetPoint(self.cumNormTGraph_.GetN(),x,y) + + if self.cumNormSpline_==None: + self.cumNormSpline_ = ROOT.TSpline3(self.hist.GetName()+"-spline",self.cumNormTGraph_) + + return self.cumNormSpline_ + def intersects(self,value,cumulative=False,norm=False,direction=0): ''' Calculate x-coordinates for intersection(s) of a graph defined by a list of (x,y) points sorted in x @@ -172,7 +187,58 @@ def quantile(self,prob): assert len(result)<2 return result[0] if result else None - + + def findRootSpline(self,value,eps=0.001): + ''' Find position where spline derived from cumulative NormGraph= value. Assumes that the spline is \ + monotonously increasing. Tolerance is eps*=ymax: + print("findRootSpline: last value <= first value") + return None + # + # Check if inside values spanned by spline + # + if valueymax: + print("findRootSpline: required value outside range") + return None + # + # tolerance for distance between points + # + dxmax = eps*(ymax-ymin) + # + # loop with cutoff in case of non-convergence + # + found = False + for i in range(1000): + if (xh-xl) Date: Thu, 4 Dec 2025 12:49:18 +0100 Subject: [PATCH 10/77] mainly cosmetics --- DrawHits/fitRes.py | 278 ++++++++++++++++++++++++++++++++------------- 1 file changed, 198 insertions(+), 80 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 0333051..2835cdc 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -1,4 +1,4 @@ -import sys +import sys,os from math import sqrt,log import ROOT import argparse @@ -247,14 +247,14 @@ def __init__(self,canvas,mtype): self.pad = None self.fhist = None - padName = mainCnv.GetName()+str(mtype-22) - for o in mainCnv.GetListOfPrimitives(): + padName = canvas.GetName()+str(mtype-22) + for o in canvas.GetListOfPrimitives(): if o.InheritsFrom(ROOT.TPad.Class()) and o.GetName()==padName: assert self.pad==None self.pad = o assert self.pad!=None - histNameBase = "h"+mainCnv.GetName()[1:]+str(mtype) + histNameBase = "h"+canvas.GetName()[1:]+str(mtype) self.fhist = None for o in self.pad.GetListOfPrimitives(): if o.InheritsFrom(ROOT.TH1.Class()) and o.GetName().startswith(histNameBase): @@ -268,7 +268,53 @@ def histogram(self): def fwhm(self): return self.fhist.fwhm() - + +def saveCanvas(canvas,inputName,outputDir,formats): + canvasName = canvas.GetName() + outputBaseName = os.path.splitext(os.path.basename(inputName))[0] + outputName = os.path.join(outputDir,outputBaseName) + if canvasName.split("_")[0]==outputBaseName.split("_")[0]: + canvasName = "_".join(canvasName.split("_")[1:]) + elif canvasName.startswith("c"): + canvasName = canvasName[1].lower() + canvasName[2:] + outputName += "_" + canvasName + for fmt in formats: + print("Saving canvas as",outputName+"."+fmt) + canvas.SaveAs(outputName+"."+fmt) + +def setHistogramMinMax(histo,limits,margins=0.05): + ''' Set minimum / maximum for histogram considering values within a range. + Arguments: + histo ...... histogram (TH1 or TH2) + limits ..... lower/upper limit of the range defining values to be considered + margins .... add this fraction of the min-max range below and above + Return value: + min / max value found within range + ''' + # + # min / max value can't be outside the range + # + vmin = limits[1] + vmax = limits[0] + # + # loop over all bins and updated vmin/vmax + # + for ibx in range(histo.GetNbinsX()): + for iby in range(histo.GetNbinsY()): + c = histo.GetBinContent(ibx+1,iby+1) + if c>=limits[0] and c<=limits[1]: + vmin = min(vmin,c) + vmax = max(vmax,c) + # + # apply min / max and return result + # + if (vmax-vmin)/(limits[1]-limits[0])<0.0001: + vmin,vmax = limits + histo.SetMinimum(vmin-margins*(vmax-vmin)) + histo.SetMaximum(vmax+margins*(vmax-vmin)) + + return (vmin,vmax) + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--moduleType', '-m', help='module type', type=int, choices=[23,24,25], default=23) parser.add_argument('--fwhm', help='determining FWHM', action='store_true', default=False) @@ -277,6 +323,11 @@ def fwhm(self): action='append', type=float, default=[]) parser.add_argument('--dbgQuantiles', help='modX,dxdz pairs defining individual bins for the quantile determination', \ action='append', type=str, default=[ ]) +parser.add_argument('--dbgAllQuantiles', help='show residuals distributions for all bins', \ + action='store_true', default=False) +parser.add_argument('--output', '-o', help='output directory', type=str, default=None) +parser.add_argument('--formats', help='comma-separated list of extensions for output files', \ + type=str, default="pdf,png") parser.add_argument('file', help='input file', type=str, nargs=1, default=None) args = parser.parse_args() @@ -294,6 +345,10 @@ def fwhm(self): for qp in args.dbgQuantiles: dbgQuantPoints.append( tuple([float(x.strip()) for x in qp.strip().split(",")]) ) +if args.output!=None: + assert os.path.isdir(args.output) + outputFormats = [ x.strip() for x in args.formats.strip().split(",") ] + canvases = [ ] slices = [ ] @@ -319,7 +374,7 @@ def fwhm(self): qlmax = slices[-1].hist.GetMaximum()/10. for sigma in args.quantile: qs = [ ] - for sgn in [-1,1]: + for sgn in [-1,0,1]: p = ROOT.TMath.Freq(sgn*sigma) #qs.append(slices[-1].quantile(p)) qs.append(slices[-1].findRootSpline(p)) @@ -328,6 +383,7 @@ def fwhm(self): if not ( None in qs ): quantLine.DrawLine(qs[0],0.,qs[0],qlmax) quantLine.DrawLine(qs[1],0.,qs[1],qlmax) + quantLine.DrawLine(qs[2],0.,qs[2],qlmax) fitCanvas.pad.Update() @@ -372,19 +428,21 @@ def fwhm(self): 10000*(x1+x2)/2.,10000*(x2-x1),10000*(x2-x1)/2/sqrt(2*log(2)),x1,x2)) fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") - quantiles = [ ] - qlmax = slices[-1].hist.GetMaximum()/10. - for sigma in args.quantile: - qs = [ ] - for sgn in [-1,1]: - p = ROOT.TMath.Freq(sgn*sigma) - #qs.append(slices[-1].quantile(p)) - qs.append(slices[-1].findRootSpline(p)) - #print(sigma,sgn,p,qs[-1]) - quantiles.append(qs) - if not ( None in qs ): - quantLine.DrawLine(qs[0],0.,qs[0],qlmax) - quantLine.DrawLine(qs[1],0.,qs[1],qlmax) + if hProj.GetMaximum()>100: + quantiles = [ ] + qlmax = slices[-1].hist.GetMaximum()/10. + for sigma in args.quantile: + qs = [ ] + for sgn in [-1,0,1]: + p = ROOT.TMath.Freq(sgn*sigma) + #qs.append(slices[-1].quantile(p)) + qs.append(slices[-1].findRootSpline(p)) + #print(sigma,sgn,p,qs[-1]) + quantiles.append(qs) + if not ( None in qs ): + quantLine.DrawLine(qs[0],0.,qs[0],qlmax) + quantLine.DrawLine(qs[1],0.,qs[1],qlmax) + quantLine.DrawLine(qs[2],0.,qs[2],qlmax) ROOT.gPad.Update() @@ -399,7 +457,6 @@ def fwhm(self): nbz = h.GetNbinsZ() zmin = h.GetZaxis().GetXmin() zmax = h.GetZaxis().GetXmax() - print(nby,ymin,ymax,nbz,zmin,zmax) # # define summary histograms # @@ -409,108 +466,167 @@ def fwhm(self): y2 = ROOT.TMath.Freq(sigma) if nby==1: hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (mean from quantiles)".format(y1,y2), \ + h.GetTitle()+" (median)", \ nbz,zmin,zmax) hcentre.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) - hcentre.GetYaxis().SetTitle("mean of {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hcentre.GetYaxis().SetTitle("median [#mum]") hhalfwidth = ROOT.TH1F(h.GetName()+"Qhw"+str(isigma), \ h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ nbz,zmin,zmax) hhalfwidth.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) - hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) elif nbz==1: hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (mean from quantiles)".format(y1,y2), \ + h.GetTitle()+" (median)", \ nby,ymin,ymax) hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hcentre.GetYaxis().SetTitle("mean of {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hcentre.GetYaxis().SetTitle("median [#mum]") hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ nby,ymin,ymax) hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) else: hcentre = ROOT.TH2F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (mean from quantiles)".format(y1,y2), \ + h.GetTitle()+" (median)", \ nby,ymin,ymax,nbz,zmin,zmax) hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) - hcentre.GetZaxis().SetTitle("mean of {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hcentre.GetZaxis().SetTitle("median [#mum]") hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ nby,ymin,ymax,nbz,zmin,zmax) hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) - hhalfwidth.GetZaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles".format(y1,y2)) + hhalfwidth.GetZaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) + hhalfwidth.SetMinimum(0.) summaries.append((hcentre,hhalfwidth)) - dbgBins = [ ] - for y,z in dbgQuantPoints: - dbgBins.append( (h.GetYaxis().FindBin(y), h.GetZaxis().FindBin(z)) ) + dbgBins = set() + if args.dbgAllQuantiles: + # get histograms for all bins + for iy in range(nby): + for iz in range(nbz): + dbgBins.add((iy+1,iz+1)) + else: + for y,z in dbgQuantPoints: + dbgBins.add( (h.GetYaxis().FindBin(y), h.GetZaxis().FindBin(z)) ) + dbgBins = sorted(dbgBins) allDbgObjects = { x:[ ] for x in range(len(args.quantile)) } + nDbg = len(dbgBins) + nrow = ncol = int(sqrt(nDbg)) + while nrow*ncol100: + #q1 = fhtmp.quantile(ROOT.TMath.Freq(-sigma)) + #q2 = fhtmp.quantile(ROOT.TMath.Freq(sigma)) + qm1 = fhtmp.findRootSpline(ROOT.TMath.Freq(-sigma)) + q0 = fhtmp.findRootSpline(ROOT.TMath.Freq(0)) + qp1 = fhtmp.findRootSpline(ROOT.TMath.Freq(sigma)) + else: + qm1 = None + q0 = None + qp1 = None + hsum = summaries[isigma][0] + if nby==1: + ibin = hsum.GetBin(iz+1) + elif nbz==1: + ibin = hsum.GetBin(iy+1) + else: + ibin = hsum.GetBin(iy+1,iz+1) + if q0!=None: + hsum.SetBinContent(ibin,q0) + else: + print("No median for bins",iy+1,iz+1,"of",htmp.GetName()) + hsum.SetBinContent(ibin,-999999) + hsum = summaries[isigma][1] + if qm1!=None and qp1!=None: + hsum.SetBinContent(ibin,(qp1-qm1)/2./sigma) + + #allDbgObjects[isigma] = [ ] + if (iy+1,iz+1) in dbgBins: + y1 = htmp.GetYaxis().GetBinLowEdge(iy+1) + y2 = y1 + htmp.GetYaxis().GetBinWidth(iy+1) + z1 = htmp.GetZaxis().GetBinLowEdge(iz+1) + z2 = z1 + htmp.GetZaxis().GetBinWidth(iz+1) + + hResName = "hResDbg_mT"+str(args.moduleType)+"_y{:02d}_z{:02d}".format(iy+1,iz+1) + hResTitle = "residual mType "+str(args.moduleType) + if nby>1: + hResTitle += " {:6.3f}1: + hResTitle += " {:6.3f} Date: Thu, 4 Dec 2025 14:40:35 +0100 Subject: [PATCH 11/77] style --- DrawHits/fitRes.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 2835cdc..6132fcb 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -357,9 +357,14 @@ def setHistogramMinMax(histo,limits,margins=0.05): fwhmArrow = ROOT.TArrow() fwhmArrow.SetLineColor(2) fwhmArrow.SetLineWidth(2) -quantLine = ROOT.TLine() -quantLine.SetLineColor(4) -quantLine.SetLineWidth(2) +quantLines = [ ] +for i in range(len(args.quantile)): + quantLine = ROOT.TLine() + quantLine.SetLineColor(4) + #quantLine.SetLineWidth(2) + quantLine.SetLineStyle(i+1) + quantLines.append(quantLine) +#quantLine.SetLineWidth(2) if fitCanvas.histogram().GetDimension()==1 and ( not args.slices ): assert fitCanvas.histogram().GetDimension()==1 #print(fitCanvas.fwhm()) @@ -372,7 +377,7 @@ def setHistogramMinMax(histo,limits,margins=0.05): quantiles = [ ] qlmax = slices[-1].hist.GetMaximum()/10. - for sigma in args.quantile: + for isigma,sigma in enumerate(args.quantile): qs = [ ] for sgn in [-1,0,1]: p = ROOT.TMath.Freq(sgn*sigma) @@ -381,9 +386,9 @@ def setHistogramMinMax(histo,limits,margins=0.05): #print(sigma,sgn,p,qs[-1]) quantiles.append(qs) if not ( None in qs ): - quantLine.DrawLine(qs[0],0.,qs[0],qlmax) - quantLine.DrawLine(qs[1],0.,qs[1],qlmax) - quantLine.DrawLine(qs[2],0.,qs[2],qlmax) + quantLines[isigma].DrawLine(qs[0],0.,qs[0],qlmax) + quantLines[0].DrawLine(qs[1],0.,qs[1],qlmax) + quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) fitCanvas.pad.Update() @@ -575,6 +580,8 @@ def setHistogramMinMax(histo,limits,margins=0.05): hResDbg.SetTitle(hResTitle) hResDbg.GetXaxis().SetTitle(h.GetXaxis().GetTitle()) hResDbg.GetYaxis().SetTitle("fraction per bin / cumulatitive fraction") + hResDbg.SetFillStyle(1001) + hResDbg.SetFillColor(ROOT.kYellow) #dbgObjects.append(ROOT.TCanvas("c"+hResDbg.GetName()[1:],"c"+hResDbg.GetName()[1:],500,500)) iDbgPad += 1 dbgObjects.append(allDbgObjects['canvas'].cd(iDbgPad)) @@ -588,11 +595,11 @@ def setHistogramMinMax(histo,limits,margins=0.05): q0 = fhtmp.findRootSpline(ROOT.TMath.Freq(0.)) qp1 = fhtmp.findRootSpline(ROOT.TMath.Freq(sigma)) if qm1!=None: - quantLine.DrawLine(qm1,0.,qm1,hResDbg.GetMaximum()/1.) + quantLines[isigma].DrawLine(qm1,0.,qm1,hResDbg.GetMaximum()/1.) if q0!=None: - quantLine.DrawLine(q0,0.,q0,hResDbg.GetMaximum()/1.) + quantLines[0].DrawLine(q0,0.,q0,hResDbg.GetMaximum()/1.) if qp1!=None: - quantLine.DrawLine(qp1,0.,qp1,hResDbg.GetMaximum()/1.) + quantLines[isigma].DrawLine(qp1,0.,qp1,hResDbg.GetMaximum()/1.) g = ROOT.TGraph() g.SetLineColor(ROOT.kMagenta) g.SetLineStyle(2) From 2e2288ea98f41e21a1d9114c7da52b39c7f64674 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 5 Dec 2025 13:48:27 +0100 Subject: [PATCH 12/77] tuning of quantile / width calculation --- DrawHits/drawHits.py | 3 + DrawHits/drawHitsTmp.yaml | 120 ++++++++++++++++++++++++++++++++ DrawHits/fitRes.py | 24 +++++-- DrawHits/histogramDefinition.py | 2 +- 4 files changed, 143 insertions(+), 6 deletions(-) diff --git a/DrawHits/drawHits.py b/DrawHits/drawHits.py index a64113a..bac27e7 100755 --- a/DrawHits/drawHits.py +++ b/DrawHits/drawHits.py @@ -398,6 +398,9 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): histos[mType][0].GetXaxis().SetTitle(xtitle) histos[mType][0].GetYaxis().SetTitle(ytitle) histos[mType][0].Draw("same" if same else "") + fitFunc = hDef.getParameter('fit') + if fitFunc!=None: + histos[mType][0].Fit(fitFunc,"Q","same") elif isProfile: histos[mType][0].SetTitle(hTitle) histos[mType][0].GetXaxis().SetTitle(xtitle) diff --git a/DrawHits/drawHitsTmp.yaml b/DrawHits/drawHitsTmp.yaml index 5bd60c5..2ba0371 100644 --- a/DrawHits/drawHitsTmp.yaml +++ b/DrawHits/drawHitsTmp.yaml @@ -542,3 +542,123 @@ res3DXVsDxDzW2: yMin: 0 yMax: 90 +pull3DXVsDxDz: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + +pull3DXVsDxDzW1: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + +pull3DXVsDxDzW2: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),100):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():floatMod(10000*localPos.x(),90):(localPos.x()-rhLocalPos.x())/rhLocalErr.x()' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + +effDxDz: + variable: 'path.x()/path.z()' + histogramTitle: 'efficiency (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + +effDxDzW1: + variable: 'path.x()/path.z()' + histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0&&clusterSize==2' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + +effDxDzW2: + variable: 'path.x()/path.z()' + histogramTitle: 'efficiency, 2-strip clusters (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0&&clusterSize==2' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 6132fcb..cf205d2 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -197,6 +197,12 @@ def findRootSpline(self,value,eps=0.001): # spline = self.cumulativeNormSpline() # + # No result if first / last point is above / below required value + # + cGraph = self.cumulativeGraph() + if len(cGraph)==0 or cGraph[0][1]>value or cGraph[-1][1]100: + #if htmp.GetSumOfWeights()>100: + # ensure sufficient statistics + p1 = ROOT.TMath.Freq(-sigma) + if htmp.GetSumOfWeights()>3/p1: #q1 = fhtmp.quantile(ROOT.TMath.Freq(-sigma)) #q2 = fhtmp.quantile(ROOT.TMath.Freq(sigma)) qm1 = fhtmp.findRootSpline(ROOT.TMath.Freq(-sigma)) @@ -543,6 +553,7 @@ def setHistogramMinMax(histo,limits,margins=0.05): qm1 = None q0 = None qp1 = None + quantiles.append((qm1,q0,qp1)) hsum = summaries[isigma][0] if nby==1: ibin = hsum.GetBin(iz+1) @@ -555,6 +566,8 @@ def setHistogramMinMax(histo,limits,margins=0.05): else: print("No median for bins",iy+1,iz+1,"of",htmp.GetName()) hsum.SetBinContent(ibin,-999999) + if htmp.GetName()=="hPull3DXVsDxDzW223_1_px" and (iy+1)==1 and (iz+1)==3: + print("...",isigma,sigma,qm1,q0,qp1,htmp.GetSumOfWeights()) hsum = summaries[isigma][1] if qm1!=None and qp1!=None: hsum.SetBinContent(ibin,(qp1-qm1)/2./sigma) @@ -581,7 +594,7 @@ def setHistogramMinMax(histo,limits,margins=0.05): hResDbg.GetXaxis().SetTitle(h.GetXaxis().GetTitle()) hResDbg.GetYaxis().SetTitle("fraction per bin / cumulatitive fraction") hResDbg.SetFillStyle(1001) - hResDbg.SetFillColor(ROOT.kYellow) + hResDbg.SetFillColor(ROOT.kOrange) #dbgObjects.append(ROOT.TCanvas("c"+hResDbg.GetName()[1:],"c"+hResDbg.GetName()[1:],500,500)) iDbgPad += 1 dbgObjects.append(allDbgObjects['canvas'].cd(iDbgPad)) @@ -591,9 +604,10 @@ def setHistogramMinMax(histo,limits,margins=0.05): hResDbg.Scale(1./hResDbg.GetMaximum()) hResDbg.Draw("hist") for isigma,sigma in enumerate(args.quantile): - qm1 = fhtmp.findRootSpline(ROOT.TMath.Freq(-sigma)) - q0 = fhtmp.findRootSpline(ROOT.TMath.Freq(0.)) - qp1 = fhtmp.findRootSpline(ROOT.TMath.Freq(sigma)) + #qm1 = fhtmp.findRootSpline(ROOT.TMath.Freq(-sigma)) + #q0 = fhtmp.findRootSpline(ROOT.TMath.Freq(0.)) + #qp1 = fhtmp.findRootSpline(ROOT.TMath.Freq(sigma)) + qm1,q0,qp1 = quantiles[isigma] if qm1!=None: quantLines[isigma].DrawLine(qm1,0.,qm1,hResDbg.GetMaximum()/1.) if q0!=None: diff --git a/DrawHits/histogramDefinition.py b/DrawHits/histogramDefinition.py index 2d585c0..0e8c451 100644 --- a/DrawHits/histogramDefinition.py +++ b/DrawHits/histogramDefinition.py @@ -15,7 +15,7 @@ class HistogramDefinition: # optional fields in the general section optGenFields = [ 'variable', 'baseCuts', 'effCuts', 'logY', 'logZ' ] # optional fields in the histogram section - optHistFields = [ 'variable', 'histogramName', 'histogramTitle', \ + optHistFields = [ 'variable', 'histogramName', 'histogramTitle', 'fit', \ 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'zTitle', \ 'yNbins', 'yMin', 'yMax', \ 'zNbins', 'zMin', 'zMax', 'display', 'profile' ] From 446a242522ed009e23928c600827fb057705c403 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 5 Dec 2025 16:51:50 +0100 Subject: [PATCH 13/77] add efficiency as f(dx/dz) --- DrawHits/drawHits.py | 3 ++- DrawHits/drawHitsTmp.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DrawHits/drawHits.py b/DrawHits/drawHits.py index bac27e7..a140072 100755 --- a/DrawHits/drawHits.py +++ b/DrawHits/drawHits.py @@ -280,6 +280,7 @@ def fillHistoByDef(tree,hDef,extraCuts): tree.Project(hName+"_2",variable, \ cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) + histos[mType][3].SetMarkerStyle(20) else: # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] @@ -391,7 +392,7 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): histos[mType][2].GetXaxis().SetTitle(xtitle) histos[mType][2].GetYaxis().SetTitle(ytitle) histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) - histos[mType][3].SetMarkerSize(0.3) + histos[mType][3].SetMarkerStyle(20) histos[mType][3].Draw("same Z") else: histos[mType][0].SetTitle(hTitle) diff --git a/DrawHits/drawHitsTmp.yaml b/DrawHits/drawHitsTmp.yaml index 2ba0371..7957666 100644 --- a/DrawHits/drawHitsTmp.yaml +++ b/DrawHits/drawHitsTmp.yaml @@ -646,7 +646,7 @@ effDxDzW1: variable: 'path.x()/path.z()' histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' baseCuts: 'tof<12.5' - effCuts: 'hasRecHit>0&&clusterSize==2' + effCuts: 'hasRecHit>0&&clusterSize==1' xTitle: 'local dx/dz' xNbins: 21 xMin: -1.05 From e6572f96a7a57c44a036837263268db39e9dee9a Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 11 Dec 2025 17:11:13 +0100 Subject: [PATCH 14/77] adding result of fit --- DrawHits/fitRes.py | 168 +++++++++++++++++++++++++++++++++------------ 1 file changed, 126 insertions(+), 42 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index cf205d2..5bdbdd6 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -244,7 +244,27 @@ def findRootSpline(self,value,eps=0.001): return (xl+xh)/2. + def fitGaus(self,prob1=0.,prob2=1.): + assert prob2>prob1 + result = ( None, None ) + xmin = self.hist.GetXaxis().GetXmin() + if prob1>0.: + xmin = self.findRootSpline(prob1) + if xmin==None: + return result + xmax = self.hist.GetXaxis().GetXmax() + if prob2<1.: + xmax = self.findRootSpline(prob2) + if xmin==None: + return result + + fitPtr = self.hist.Fit("gaus","S0","",xmin,xmax) + if ( not fitPtr.IsValid() ) or fitPtr.IsEmpty(): + return result + return fitPtr,self.hist.GetFunction("gaus") + + class FitCanvas: def __init__(self,canvas,mtype): @@ -321,6 +341,53 @@ def setHistogramMinMax(histo,limits,margins=0.05): return (vmin,vmax) +def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=None): + if isigma!=None: + y1 = ROOT.TMath.Freq(-sigma) + y2 = ROOT.TMath.Freq(sigma) + hcName = h.GetName()+"Qc"+str(isigma) + hcTitle = h.GetTitle()+" (median)" + hwName = h.GetName()+"Qhw"+str(isigma) + hwTitle = h.GetTitle()+" (#sigma from quantiles)".format(y1,y2) + hwAxis1Title = "median [#mum]" + hwAxis2Title = "#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2) + else: + y1 = None + y2 = None + hcName = h.GetName()+"Qc fit" + hcTitle = h.GetTitle()+" (fitted mean)" + hwName = h.GetName()+"Qhw fit" + hwTitle = h.GetTitle()+" (fitted sigma)" + hwAxis1Title = "mean [#mum]" + hwAxis2Title = "#sigma from fit [#mum]".format(y1,y2) + if nby==1: + hcentre = ROOT.TH1F(hcName,hcTitle,nbz,zmin,zmax) + hcentre.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) + hcentre.GetYaxis().SetTitle(hwAxis1Title) + hhalfwidth = ROOT.TH1F(hwName,hwTitle,nbz,zmin,zmax) + hhalfwidth.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle(hwAxis2Title) + elif nbz==1: + hcentre = ROOT.TH1F(hcName,hcTitle,nby,ymin,ymax) + hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hcentre.GetYaxis().SetTitle(hwAxis1Title) + hhalfwidth = ROOT.TH2F(hwName,hwTitle,nby,ymin,ymax) + hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle(hwAxis2Title) + else: + hcentre = ROOT.TH2F(hcName,hctitle,nby,ymin,ymax,nbz,zmin,zmax) + hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + hcentre.GetZaxis().SetTitle(hwAxis1Title) + hhalfwidth = ROOT.TH2F(hwName,hwTitle,nby,ymin,ymax,nbz,zmin,zmax) + hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) + hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) + hhalfwidth.GetZaxis().SetTitle(hwAxis2Title) + hhalfwidth.SetMinimum(0.) + + return hcentre,hhalfwidth + + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--moduleType', '-m', help='module type', type=int, choices=[23,24,25], default=23) parser.add_argument('--fwhm', help='determining FWHM', action='store_true', default=False) @@ -473,45 +540,48 @@ def setHistogramMinMax(histo,limits,margins=0.05): # summaries = [ ] for isigma,sigma in enumerate(args.quantile): - y1 = ROOT.TMath.Freq(-sigma) - y2 = ROOT.TMath.Freq(sigma) - if nby==1: - hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (median)", \ - nbz,zmin,zmax) - hcentre.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) - hcentre.GetYaxis().SetTitle("median [#mum]") - hhalfwidth = ROOT.TH1F(h.GetName()+"Qhw"+str(isigma), \ - h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ - nbz,zmin,zmax) - hhalfwidth.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) - hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) - elif nbz==1: - hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (median)", \ - nby,ymin,ymax) - hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hcentre.GetYaxis().SetTitle("median [#mum]") - hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ - h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ - nby,ymin,ymax) - hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) - else: - hcentre = ROOT.TH2F(h.GetName()+"Qc"+str(isigma), \ - h.GetTitle()+" (median)", \ - nby,ymin,ymax,nbz,zmin,zmax) - hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) - hcentre.GetZaxis().SetTitle("median [#mum]") - hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ - h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ - nby,ymin,ymax,nbz,zmin,zmax) - hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) - hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) - hhalfwidth.GetZaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) - hhalfwidth.SetMinimum(0.) +#!# y1 = ROOT.TMath.Freq(-sigma) +#!# y2 = ROOT.TMath.Freq(sigma) +#!# if nby==1: +#!# hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ +#!# h.GetTitle()+" (median)", \ +#!# nbz,zmin,zmax) +#!# hcentre.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) +#!# hcentre.GetYaxis().SetTitle("median [#mum]") +#!# hhalfwidth = ROOT.TH1F(h.GetName()+"Qhw"+str(isigma), \ +#!# h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ +#!# nbz,zmin,zmax) +#!# hhalfwidth.GetXaxis().SetTitle(h.GetZaxis().GetTitle()) +#!# hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) +#!# elif nbz==1: +#!# hcentre = ROOT.TH1F(h.GetName()+"Qc"+str(isigma), \ +#!# h.GetTitle()+" (median)", \ +#!# nby,ymin,ymax) +#!# hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) +#!# hcentre.GetYaxis().SetTitle("median [#mum]") +#!# hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ +#!# h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ +#!# nby,ymin,ymax) +#!# hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) +#!# hhalfwidth.GetYaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) +#!# else: +#!# hcentre = ROOT.TH2F(h.GetName()+"Qc"+str(isigma), \ +#!# h.GetTitle()+" (median)", \ +#!# nby,ymin,ymax,nbz,zmin,zmax) +#!# hcentre.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) +#!# hcentre.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) +#!# hcentre.GetZaxis().SetTitle("median [#mum]") + #!# hhalfwidth = ROOT.TH2F(h.GetName()+"Qhw"+str(isigma), \ +#!# h.GetTitle()+" (#sigma from quantiles)".format(y1,y2), \ +#!# nby,ymin,ymax,nbz,zmin,zmax) +#!# hhalfwidth.GetXaxis().SetTitle(h.GetYaxis().GetTitle()) +#!# hhalfwidth.GetYaxis().SetTitle(h.GetZaxis().GetTitle()) +#!# hhalfwidth.GetZaxis().SetTitle("#sigma from {:4.1%}/{:4.1%} quantiles [#mum]".format(y1,y2)) + #!# hhalfwidth.SetMinimum(0.) + hcentre,hhalfwidth = defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma,sigma) summaries.append((hcentre,hhalfwidth)) + hcentre,hhalfwidth = defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,None,None) + summaries.append((hcentre,hhalfwidth)) dbgBins = set() if args.dbgAllQuantiles: @@ -525,6 +595,7 @@ def setHistogramMinMax(histo,limits,margins=0.05): dbgBins = sorted(dbgBins) allDbgObjects = { x:[ ] for x in range(len(args.quantile)) } + allFitObjects = [ ] nDbg = len(dbgBins) nrow = ncol = int(sqrt(nDbg)) while nrow*ncol100: + fitPtr,fitFunc = fhtmp.fitGaus(ROOT.TMath.Freq(-2.),ROOT.TMath.Freq(2.)) + print(fitPtr,fitFunc) + if fitPtr!=None: + fitFunc2 = fitFunc.Clone() + fitFunc2.SetParameter(0,fitFunc.GetParameter(0)/hResDbgMax) + fitFunc2.Draw("same") + allFitObjects.append((fitPtr,fitFunc2)) + dbgObjects[0].Update() allDbgObjects['canvas'].Update() if args.output: @@ -639,8 +722,8 @@ def setHistogramMinMax(histo,limits,margins=0.05): cName = "cResMeanWidth_mT"+str(args.moduleType) c = ROOT.TCanvas(cName,h.GetTitle()+" (mean/width summary)",500*nsigma,1000) - c.Divide(nsigma,2) - for i in range(nsigma): + c.Divide(nsigma+1,2) + for i in range(nsigma+1): c.cd(i+1) if summaries[i][0].GetDimension()==2: ROOT.gPad.SetRightMargin(0.15) @@ -650,12 +733,13 @@ def setHistogramMinMax(histo,limits,margins=0.05): setHistogramMinMax(summaries[i][0],(-250,250),margins=0.05) summaries[i][0].Draw("HIST") ROOT.gPad.Update() - c.cd(nsigma+i+1) + c.cd(nsigma+1+i+1) if summaries[i][1].GetDimension()==2: summaries[i][1].Draw("ZCOL") else: summaries[i][1].Draw("HIST") ROOT.gPad.Update() + c.Update() if args.output!=None: saveCanvas(c,args.file[0],args.output,outputFormats) From 53950fae086ec048ae3c14d8efb2bd36d08b8b1d Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 11 Dec 2025 17:17:15 +0100 Subject: [PATCH 15/77] adding result of fit --- DrawHits/fitRes.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 5bdbdd6..9578c3a 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -709,6 +709,29 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No fitFunc2.Draw("same") allFitObjects.append((fitPtr,fitFunc2)) dbgObjects[0].Update() + hsum = summaries[-1][0] + if nby==1: + ibin = hsum.GetBin(iz+1) + elif nbz==1: + ibin = hsum.GetBin(iy+1) + else: + ibin = hsum.GetBin(iy+1,iz+1) + hsum.SetBinContent(ibin,fitPtr.Parameter(1)) + hsum.SetBinError(ibin,fitPtr.Error(1)) + hsum = summaries[-1][1] + if nby==1: + ibin = hsum.GetBin(iz+1) + elif nbz==1: + ibin = hsum.GetBin(iy+1) + else: + ibin = hsum.GetBin(iy+1,iz+1) + hsum.SetBinContent(ibin,fitPtr.Parameter(2)) + hsum.SetBinError(ibin,fitPtr.Error(2)) + else: + print("No median for bins",iy+1,iz+1,"of",htmp.GetName()) + hsum.SetBinContent(ibin,-999999) + + allDbgObjects['canvas'].Update() if args.output: @@ -724,6 +747,7 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No c = ROOT.TCanvas(cName,h.GetTitle()+" (mean/width summary)",500*nsigma,1000) c.Divide(nsigma+1,2) for i in range(nsigma+1): + hopt = "HIST" if i Date: Fri, 9 Jan 2026 12:59:48 +0100 Subject: [PATCH 16/77] update to fitRes --- DrawHits/fitRes.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 9578c3a..3f43967 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -258,11 +258,19 @@ def fitGaus(self,prob1=0.,prob2=1.): if xmin==None: return result - fitPtr = self.hist.Fit("gaus","S0","",xmin,xmax) + fitFunc = ROOT.TF1("mygaus","gaus(0)",xmin,xmax) + fitFunc.SetParameter(0,self.hist.GetMaximum()) + fitFunc.SetParameter(1,0.) + fitFunc.SetParLimits(1,-10.,10.) + fitFunc.SetParameter(2,self.hist.GetRMS()) + + fitPtr = self.hist.Fit(fitFunc,"S0") + #fitPtr = self.hist.Fit("gaus","S0","",xmin,xmax) if ( not fitPtr.IsValid() ) or fitPtr.IsEmpty(): return result - return fitPtr,self.hist.GetFunction("gaus") + #return fitPtr,self.hist.GetFunction("gaus") + return fitPtr,fitFunc class FitCanvas: @@ -700,6 +708,7 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No allDbgObjects[isigma].append(dbgObjects) fitPtr = None fitFunc = None + print(htmp.GetName(),"Sum of weights",htmp.GetSumOfWeights()) if htmp.GetSumOfWeights()>100: fitPtr,fitFunc = fhtmp.fitGaus(ROOT.TMath.Freq(-2.),ROOT.TMath.Freq(2.)) print(fitPtr,fitFunc) From 22f0207767dd5f4ca0f471da5341f054c1ee9326 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 12 Jan 2026 15:36:23 +0100 Subject: [PATCH 17/77] building config file for use with Angs Plotter scripts --- DrawHits/plotter_drawHits.yaml | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 DrawHits/plotter_drawHits.yaml diff --git a/DrawHits/plotter_drawHits.yaml b/DrawHits/plotter_drawHits.yaml new file mode 100644 index 0000000..d3075f8 --- /dev/null +++ b/DrawHits/plotter_drawHits.yaml @@ -0,0 +1,86 @@ +### GLOBAL DEFINITIONS +# This part defines some global variables, which you can use later +# Note that yaml does not support defining variables +# so it is handled as python strings and applied by +# `str.format()` method +# usage: variable_name: content +# The user can define any `variable_name` and `content`, +# but make sure the `variable_name` is not used below +#hits_size1: Hit_cluster_size + +### PRE-SELECTIONS +# This part defines the event preselection +# This selection is applied before any plotting +# usage: presel: content +# The user can define `content` but cannot change the name `presel` +presel: + +### NEW VARIABLE DEFINITION +# This part defines new variables +# It calls the `Define` method of an RDataFrame +# usage1: new_variable_name: definition +# usage2: new_variable_name: [definition(format string),global defined variables] +# if a global defined variable is used +new_variables: + pathX: 'path.fCoordinates.fX' + pathZ: 'path.fCoordinates.fZ' + dxdz: 'pathX/pathZ' + alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' + localPosX: 'localPos.fCoordinates.fX' + rhLocalPosX: 'rhLocalPos.fCoordinates.fX' + #pathX: 'ROOT::VecOps::Map(path, [](ROOT::Math::XYZVectorF x){return 3.;})' + #dxdz: 'path.fCoordinates.fX/path.fCoordinates.fZ' + + +### EVENT SELECTION +# This part defines search regions +# It calls the `Filter` method of an RDataFrame +# usage: name: selections +regions: + All: + +### EVENT VARIABLES +# event_variables: +# This part defines event variables that will be made into histograms +# All variables should be defined or exists already in the Ntuple +# event_2d_plots: +# This part defines 2D histograms that will be made +# usage: [x,y] +event_variables: + +event_2d_plots: + +### OBJECTS +# This part lists all objects that will be plotted +# The structure is: +# Object_name: the user can define the object name +# selection: similar with event level selections, any object level selection can be used here but make sure that the variables used in selection and variables below have the same dimension +# variables: variables to make 1D histograms +# 2d_plots: variables to make 2D histograms +# nm1: N-1 plots. For this part one could give it several variables with the cut values, the script will do the n-1 plots for all given variables +objects: + effAlpha: + selections: + alpha_base: tof<12.5 && pabs>0.3 + alpha_loose: hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.1 + alpha_tight: hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.0075 + variables: + - alpha + 2d_plots: + effRecHits: + selections: + dxdz_all: tof<12.5 + dxdz_recHit: tof<12.5 & hasRecHit>0 + variables: + - dxdz + 2d_plots: + + +### PLOT SETTING +# This section defines the name, titles, binning of histograms +# usage: variable_name: [name,title,number of bins,range mininum,range maximum] +plot_setting: + dxdz: [dxdz,'dx/dz (all):local dx/dz:entries / bin',21,-1.05,1.05] + alpha: [alpha,'Efficiency vs. alpha(xz): alpha(xz) [deg]:entries / bin',100,0.,100.] + #dxdz_all: [dxdz_all,'dx/dz (all):local dx/dz:entries / bin',21,-1.05,1.05] + #dxdz_rechit: [dxdz_recHit,'dx/dz (with RecHit):local dx/dz:entries / bin',21,-1.05,1.05] From 081b040796b9e8ef6b95e19df94644efa1750b36 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 12 Jan 2026 17:19:46 +0100 Subject: [PATCH 18/77] started implementing Plotter config file --- DrawHits/drawHitsTmp.yaml | 4 +-- DrawHits/floatMod.C | 14 +++++++++++ DrawHits/plotter_drawHits.yaml | 45 +++++++++++++++++++++++++++++++--- Plotter/autoplotter.py | 6 +++-- Plotter/filelist.txt | 2 +- Plotter/python/plotter.py | 5 +++- 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/DrawHits/drawHitsTmp.yaml b/DrawHits/drawHitsTmp.yaml index 7957666..3915a9f 100644 --- a/DrawHits/drawHitsTmp.yaml +++ b/DrawHits/drawHitsTmp.yaml @@ -1,7 +1,7 @@ # # # -effAlphaLoose: +effAlphaTight: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' histogramTitle: 'Efficiency vs. alpha(xz) tight' @@ -16,7 +16,7 @@ effAlphaLoose: # # # -effAlphaTight: +effAlphaLoose: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.1' histogramTitle: 'Efficiency vs. alpha(xz) loose' diff --git a/DrawHits/floatMod.C b/DrawHits/floatMod.C index 1950020..5c1585a 100644 --- a/DrawHits/floatMod.C +++ b/DrawHits/floatMod.C @@ -1,5 +1,7 @@ #include #include +#include +using RVecF = ROOT::VecOps::RVec; float floatMod(float a, float b) { // @@ -10,3 +12,15 @@ float floatMod(float a, float b) { if ( result < 0. ) result += b; return result; } + + +RVecF floatMod(const RVecF& a, float b) { + // + // apply floatMod to RVec of floats + // + RVecF result = RVecF(a.size()); + for ( unsigned int i=0; i0.3 - alpha_loose: hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.1 - alpha_tight: hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.0075 + alpha_loose: tof<12.5 && pabs>0.3 & hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.1 + alpha_tight: tof<12.5 && pabs>0.3 & hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.0075 variables: - alpha 2d_plots: + effVsModXM23: + selections: + modXM23_base: tof<12.5 && pabs>0.3 && moduleType==23 + modXM23_tight: tof<12.5 && pabs>0.3 && hasRecHit>0 && abs(localPosX-rhLocalPosX)<0.0075 && moduleType==23 + variables: + - localPosXMod100 + 2d_plots: + effVsModXM24: + selections: + modXM24_base: tof<12.5 && pabs>0.3 && moduleType==24 + modXM24_tight: tof<12.5 && pabs>0.3 && hasRecHit>0 && abs(localPosX-rhLocalPosX)<0.0075 && moduleType==24 + variables: + - localPosXMod100 + 2d_plots: + effVsModXM25: + selections: + modXM25_base: tof<12.5 && pabs>0.3 && moduleType==25 + modXM25_tight: tof<12.5 && pabs>0.3 && hasRecHit>0 && abs(localPosX-rhLocalPosX)<0.0075 && moduleType==25 + variables: + - localPosXMod90 + 2d_plots: +# effVsModXM24: +# selections: +# modXM24_base: tof<12.5 && pabs>0.3 +# modXM24_tight: tof<12.5 && pabs>0.3 & hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.0075 & moduleType=24 +# variables: +# - localPosXMod100 +# 2d_plots: +# effVsModXM25: +# selections: +# modXM25_base: tof<12.5 && pabs>0.3 +# modXM25_tight: tof<12.5 && pabs>0.3 & hasRecHit>0 & abs(localPosX-rhLocalPosX)<0.0075 & moduleType=25 +# variables: +# - localPosXMod90 +# 2d_plots: effRecHits: selections: dxdz_all: tof<12.5 @@ -82,5 +119,5 @@ objects: plot_setting: dxdz: [dxdz,'dx/dz (all):local dx/dz:entries / bin',21,-1.05,1.05] alpha: [alpha,'Efficiency vs. alpha(xz): alpha(xz) [deg]:entries / bin',100,0.,100.] - #dxdz_all: [dxdz_all,'dx/dz (all):local dx/dz:entries / bin',21,-1.05,1.05] - #dxdz_rechit: [dxdz_recHit,'dx/dz (with RecHit):local dx/dz:entries / bin',21,-1.05,1.05] + localPosXMod100: [localPosXMod100,'Efficiency vs. x % 100 #mu m: x modulo 100 #mu m [#mu m]:entries/bin',220,-5,105] + localPosXMod90: [localPosXMod90,'Efficiency vs. x % 90 #mu m: x modulo 90 #mu m [#mu m]:entries/bin',220,-5,95] diff --git a/Plotter/autoplotter.py b/Plotter/autoplotter.py index 31d33af..d4cb4c9 100644 --- a/Plotter/autoplotter.py +++ b/Plotter/autoplotter.py @@ -2,7 +2,7 @@ import math import uuid import shutil -import Phase2Tracking.Plotter.plotter as p +import Phase2Tracking.Plotter.python.plotter as p import argparse @@ -45,6 +45,8 @@ def getFileList(inputdir): help='The number of jobs to submit for each sample. Could be a list of a single value.') parser.add_argument('--nfiles', type=int, default=-1, help='The number of files per job to submit for each sample. Could be a list of a single value.') +parser.add_argument('--loadMacro', type=str, nargs='*', default=[ ], \ + help='File name for C++ macro(s) to be loaded (can be repeated)') args = parser.parse_args() @@ -137,6 +139,6 @@ def getFileList(inputdir): else: if not os.path.exists(args.filelist): raise Exception("file list not given for plotting") - plotter = p.Plotter(name=args.name,treeName=str(args.treeName),outputDir=args.output,input_filelist=args.filelist,config=args.config,isData=args.data,postfix=args.postfix) + plotter = p.Plotter(name=args.name,treeName=str(args.treeName),outputDir=args.output,input_filelist=args.filelist,config=args.config,isData=args.data,postfix=args.postfix,macros=args.loadMacro) plotter.makeHistFiles() diff --git a/Plotter/filelist.txt b/Plotter/filelist.txt index 6d254cb..d487306 100644 --- a/Plotter/filelist.txt +++ b/Plotter/filelist.txt @@ -1 +1 @@ -root://eos.grid.vbc.ac.at//eos/vbc/experiments/cms/store/user/lian/RelValSingleMuPt10/SingleMuPt10_noPU_2_lian/250916_143902/0000/rechits_tree_1.root \ No newline at end of file +../HitAnalyzer/test/rechits_tree_tt_3.root diff --git a/Plotter/python/plotter.py b/Plotter/python/plotter.py index c299674..b3a24f7 100644 --- a/Plotter/python/plotter.py +++ b/Plotter/python/plotter.py @@ -11,7 +11,8 @@ ROOT.gStyle.SetOptStat(0) class Plotter: - def __init__(self,name,treeName,outputDir="./",input_filelist=None,config="",isData=False,postfix=""): + def __init__(self,name,treeName,outputDir="./",input_filelist=None,config="",isData=False,postfix="", \ + macros=[]): self.name = name self.treeName = treeName self.outputDir = outputDir @@ -21,6 +22,8 @@ def __init__(self,name,treeName,outputDir="./",input_filelist=None,config="",isD with open(config, "r") as f_cfg: cfg = yaml.load(f_cfg, Loader=yaml.FullLoader) self.cfg = cfg + for m in macros: + ROOT.gROOT.ProcessLine(".L "+m+"+") def getFileList(self): self.filelist = [] From edaba103e5655362e113d2adf8bd10a5299af613 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 08:59:55 +0100 Subject: [PATCH 19/77] implement RDF within DrawHits --- DrawHits/plotter_drawHits.yaml | 25 +++++++++++++++++++++++++ Plotter/python/plotter.py | 16 +++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/DrawHits/plotter_drawHits.yaml b/DrawHits/plotter_drawHits.yaml index b41a8d7..10f8953 100644 --- a/DrawHits/plotter_drawHits.yaml +++ b/DrawHits/plotter_drawHits.yaml @@ -30,6 +30,9 @@ new_variables: rhLocalPosX: 'rhLocalPos.fCoordinates.fX' localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' + globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' + globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' + globPt: 'sqrt(pabs*sqrt(globRho2/globR2))' #pathX: 'ROOT::VecOps::Map(path, [](ROOT::Math::XYZVectorF x){return 3.;})' #dxdz: 'path.fCoordinates.fX/path.fCoordinates.fZ' @@ -90,6 +93,28 @@ objects: variables: - localPosXMod90 2d_plots: + effVsModX1M23: + selections: + modX1M23_base: tof<12.5 && pabs>0.3 && pabs*globPt>0.5 && hasRecHit>0 + modX1M23_1: clusterSize==1 + variables: + - localPosXMod100 + 2d_plots: + effVsModX2M23: + selections: + modX2M23_base: tof<12.5 && pabs>0.3 && pabs*globPt>0.5 && hasRecHit>0 + modX2M23_2: clusterSize==2 + variables: + - localPosXMod100 + 2d_plots: + effVsModX3pM23: + selections: + modX3pM23_base: tof<12.5 && pabs>0.3 && pabs*globPt>0.5 && hasRecHit>0 + modX3pM23_3p: clusterSize>2 + variables: + - localPosXMod100 + 2d_plots: + # effVsModXM24: # selections: # modXM24_base: tof<12.5 && pabs>0.3 diff --git a/Plotter/python/plotter.py b/Plotter/python/plotter.py index b3a24f7..8e66213 100644 --- a/Plotter/python/plotter.py +++ b/Plotter/python/plotter.py @@ -38,11 +38,13 @@ def getFileList(self): print("No files provided as input!") def AddVars(self,d): + print(type(self.cfg)) vars_to_define = ['new_variables'] for v in vars_to_define: if (not v in self.cfg) or (self.cfg[v] is None): continue if self.cfg[v] is not None: + print(v,type(self.cfg[v])) for newvar in self.cfg[v]: if isinstance(self.cfg[v][newvar],list): formatstr = [self.cfg[self.cfg[v][newvar][i]] for i in range(1,len(self.cfg[v][newvar]))] @@ -50,6 +52,7 @@ def AddVars(self,d): elif isinstance(self.cfg[v][newvar],str): var_define = self.cfg[v][newvar] d = d.Define(newvar,var_define) + print("*** Define AddVars",newvar,var_define) return d def AddVarsWithSelection(self,d): @@ -62,8 +65,10 @@ def AddVarsWithSelection(self,d): for v in variables: if selections[sel]: d = d.Define(v+sel,"{0}[{1}]".format(v,selections[sel])) + print("*** Define AddVarsWithSelection1",sel,v+sel,"{0}[{1}]".format(v,selections[sel])) else: d = d.Define(v+sel,"{0}".format(v)) + print("*** Define AddVarsWithSelection",sel,v+sel,"{0}".format(v)) if ('nm1' in self.cfg['objects'][obj]) and (self.cfg['objects'][obj]['nm1']): nm1s = self.cfg['objects'][obj]['nm1'] cutstr_objsel = "" @@ -78,16 +83,19 @@ def AddVarsWithSelection(self,d): cutstr = "&&".join(cutstrs) cutstr = cutstr_objsel + "({})".format(cutstr) d = d.Define(nm1s[i][0]+sel+'_nm1',"{0}[{1}]".format(nm1s[i][0],cutstr)) + print("*** Define AddVarsWithSelection2",nm1s[i][0]+sel+'_nm1',"{0}[{1}]".format(nm1s[i][0],cutstr)) #print("define {}: {}".format(nm1s[i][0]+sel+'_nm1',"{0}[{1}]".format(nm1s[i][0],cutstr))) return d def FilterEvents(self,d): d_filter = d.Filter(self.presel) + print("*** Filter",self.presel) return d_filter def AddWeights(self,d,weight): d = d.Define("evt_weight","{0}".format(weight)) + print("*** Define AddWeights","evt_weight","{0}".format(weight)) return d def getRDF(self): @@ -102,6 +110,7 @@ def getRDF(self): d = self.AddVarsWithSelection(d) if self.cfg['presel'] is not None: d = d.Filter(self.cfg['presel']) + print("*** Filter getRDF",self.cfg['presel']) xsec_weights = 1 d = self.AddWeights(d,xsec_weights) return d,xsec_weights @@ -114,14 +123,18 @@ def getplots(self,d,weight,plots_1d,plots_2d,plots_nm1,varlabel): plots_2d = [] if plots_nm1 is None: plots_nm1 = [] - +#!# + self.isData = True +#!# for plt in plots_1d: if not plt in self.cfg['plot_setting']: print("{} not registered in plot setting!".format(plt)) if self.isData: h = d.Histo1D(tuple(self.cfg['plot_setting'][plt]),plt+varlabel) + print("*** Histo1D getplots",plt,self.isData,tuple(self.cfg['plot_setting'][plt]),plt+varlabel) else: h = d.Histo1D(tuple(self.cfg['plot_setting'][plt]),plt+varlabel,weight) + print("*** Histo1D getplots",plt,self.isData,tuple(self.cfg['plot_setting'][plt]),plt+varlabel,weight) hs.append(h) for plt in plots_nm1: @@ -182,6 +195,7 @@ def makeHistFiles(self): d_sr = d if self.cfg['regions'][sr] is not None: d_sr = d_sr.Filter(self.cfg['regions'][sr]) + print("*** Filter makeHistFiles1",sr,self.cfg['regions'][sr]) newd_evt = fout.mkdir("{}_evt".format(sr)) hs = self.getplots(d_sr,weight="evt_weight",plots_1d=self.cfg['event_variables'],plots_2d=self.cfg['event_2d_plots'],plots_nm1=self.cfg.get('event_nm1'),varlabel="") From 5a146c4d89fd689d984573244d40abb308927dea Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 09:49:27 +0100 Subject: [PATCH 20/77] tested define histo1D --- DrawHits/drawHitsConfiguration.py | 312 ++++++++++++ DrawHits/drawHitsRDF.py | 796 ++++++++++++++++++++++++++++++ DrawHits/drawHitsTmpRDF.yaml | 684 +++++++++++++++++++++++++ 3 files changed, 1792 insertions(+) create mode 100644 DrawHits/drawHitsConfiguration.py create mode 100755 DrawHits/drawHitsRDF.py create mode 100644 DrawHits/drawHitsTmpRDF.yaml diff --git a/DrawHits/drawHitsConfiguration.py b/DrawHits/drawHitsConfiguration.py new file mode 100644 index 0000000..e510014 --- /dev/null +++ b/DrawHits/drawHitsConfiguration.py @@ -0,0 +1,312 @@ +# +# Definitions for histograms from a configuration file +# +import yaml +from fnmatch import fnmatch + +class HistogramDefinition: + ''' A single histogram definition. + ''' + # fields that have to be present in the general section + reqGenFields = [ 'canvasName' ] + # fields that have to be present in a histogram section + reqHistFields = [ ] + requiredFields = list(set(reqGenFields + reqHistFields)) + # optional fields in the general section + optGenFields = [ 'variable', 'baseCuts', 'effCuts', 'logY', 'logZ' ] + # optional fields in the histogram section + optHistFields = [ 'variable', 'histogramName', 'histogramTitle', 'fit', \ + 'xNbins', 'xMin', 'xMax', 'xTitle', 'yTitle', 'zTitle', \ + 'yNbins', 'yMin', 'yMax', \ + 'zNbins', 'zMin', 'zMax', 'display', 'profile' ] + optionalFields = list(set(optGenFields + optHistFields)) + allFields = list(set(requiredFields + optionalFields)) + allHistFields = list(set(reqHistFields + optHistFields)) + # fields that cannot be present for a single module type + vetoMtypeFields = [ 'variable', 'baseCuts', 'effCuts', 'profile' ] + vetoMtypeFields = [ 'profile' ] + + def __init__(self,name,inputDict): + ''' Define histogram and drawing parameters from dictionary. + Arguments: + name ....... name of the histogram definition + inputDict .. dictionary with values + ''' + # + assert name.isalnum() + self.name = name + # + # read parameters + # + # default is None for all parameters + # + self.parameters = { x:None for x in HistogramDefinition.allFields } + # + # loop over main dictionary + # + for k,v in inputDict.items(): + # + # skip standard python entries + # + if k.startswith('__'): + continue + # + # standard entry in main dictionary - store value + # + if k in HistogramDefinition.allFields: + # + # general variable + # + self.parameters[k] = v + # + # nested dictionary with parameters for a specific module type + # + elif k.startswith("mType"): + # + # mType-specific histogram parameters + # + assert type(v)==dict and ( not k in self.parameters ) and len(k)>5 and k[5:].isdigit() + self.parameters[k] = { x:None for x in HistogramDefinition.allHistFields } + for kh,vh in v.items(): + if kh in HistogramDefinition.allHistFields: + self.parameters[k][kh] = vh + else: + print("Warning: key",kh, \ + "is not a standard histogram field name - ignoring the entry in", \ + self.name) + # + # unknown key + # + else: + print("Warning: key",k,"is not a standard field name - ignoring the entry in",self.name) + # + # set some parameters from other inputs if unspecified + # + if self.parameters['canvasName']==None: + self.parameters['canvasName'] = "c" + self.name[0].upper() + self.name[1:] + if self.parameters['histogramName']==None: + self.parameters['histogramName'] = "h" + self.name[0].upper() + self.name[1:] + # + # make sure all required fields are present + # + for f in HistogramDefinition.requiredFields: + assert ( f in self.parameters ) and self.parameters[f]!=None + + #def __getitem__(self,field): + # if field in self.parameters: + # return self.parameters[field] + # return None + + def getParameter(self,name,mType=None): + ''' Retrieve a single parameter (optionally a specific one for a given module type) + ''' + result = None + # + # give priority to parameter specific to a module type + # + mTName = "mType"+str(mType) if mType!=None else None + if ( mTName in self.parameters ) and ( name in self.parameters[mTName] ): + result = self.parameters[mTName][name] + if result!=None: + # check for parameters that can only be general + if name in HistogramDefinition.vetoMtypeFields: + raise Exception('Parameter '+name+' cannot be present in the section for an individual module type') + return self.parameters[mTName][name] + # + # not found: use general parameter + # + if name in self.parameters: + return self.parameters[name] + return None + + def __call__(self,name,mType=None): + ''' Make access to parameters easier - use function call + ''' + return self.getParameter(name,mType) + + def vetoMType(self,mType): + ''' Check for an mType entry with display = False + ''' + # + # try to get 'display' parameter + # + name = 'display' + mTName = "mType"+str(mType) if mType!=None else None + if ( mTName in self.parameters ) and ( name in self.parameters[mTName] ): + if self.parameters[mTName][name]!=None: + return not self.parameters[mTName][name] + return False + +class HistogramDefinitions: + + def __init__(self): + self.allDefinitions = { } + self.allHistoNames = set() + self.allCanvases = set() + self.byCanvas = { } + + def add(self,hdef): + assert not hdef.name in self.allDefinitions + + hName = hdef.getParameter('histogramName') + assert not hName in self.allHistoNames + self.allHistoNames.add(hName) + + cName = hdef.getParameter('canvasName') + assert not cName in self.allCanvases + self.allDefinitions[hdef.name] = hdef + self.allCanvases.add(cName) + + if not cName in self.byCanvas: + self.byCanvas[cName] = { } + self.byCanvas[cName][hdef.name] = hdef + + def canvasNames(self): + return self.allCanvases + + def __getitem__(self,name): + if name in self.allDefinitions: + return self.allDefinitions[name] + return None + +class VarMaskCombinations: + ''' Combinations of a variable and a mask for use with RDF.Histo*. + ''' + def __init__(self): + # + # variable+mask name indexed by variable+selection string + # + self.varMaskDefinitions = { } + + def __call__(self,rdf,varName,selection): + ''' Return the name of a variable+mask combination. Define if necessary. + Arguments: + rdf ........ RDataFrame to be used for definition + varName .... name of the variable + selection .. selection string to be used as mask + ''' + # + # use variable name and normalized selection string (remove spaces) + # + selNorm = selection.replace(" ","") + varMask = varName + "["+selNorm+"]" + if varMask in self.varMaskDefinitions: + # combination exists (assume that it's also defined in the RDataFrame) + varMaskName = self.varMaskDefinitions[varMask] + assert varMaskName in rdf.GetDefinedColumnNames() + else: + # create name for combination and define it in the RDataFrame + n = len(self.varMaskDefinitions) + varMaskName = "varMask{:03d}".format(n) + self.varMaskDefinitions[varMask] = varMaskName + rdf = rdf.Define(varMaskName,varMask) + print("+++ defined new var + mask combinations:",varMaskName,varMask) + print(rdf.GetDefinedColumnNames()) + print("+++") + return rdf,varMaskName + + +def loadConfiguration(configName,selectedNames=[],vetoedNames=[]): + ''' Load variable and histogram definitions from a configuration file. The configuration file + is expected to contain a "variables" and a "histograms" section. The "histogram" section + defines dictionaries with the definitions as variable. The name of the variable + serves as name of the HistogramDefinition. + Arguments: + configName ..... name of the module to import from / python file name + selectedNames .. explicit list of histogram names to be imported (filename wildcard syntax) + vetoedNames .... explicit list of histogram names to be skipped (filename wildcard syntax) + Result: + Tuple with dictionary of variable definitions and HistogramDefinitions object + ''' + # load histogram definitions + # + vDefs = { } + hDefs = HistogramDefinitions() + if configName==None: + return ( vDefs, hDefs ) + + with open(configName,"rt") as yamlFile: + allDicts = yaml.load(yamlFile,Loader=yaml.Loader) + yamlFile.close() + # + # store variable definitions as read from configuration + # + if 'variables' in allDicts: + vDefs = allDicts['variables'] + # + # backward compatibility for histograms: treat full input as "histograms" section + # in case neither variables nor histograms sections are defined + # + if 'histograms' in allDicts: + histDicts = allDicts['histograms'] + else: + assert not ( 'variables' in allDicts ) + histDicts = allDicts + # + for n,hDict in histDicts.items(): + # + assert type(hDict)==dict + # + # check if in list of histograms to be displayed + # + selFlg = False + for p in selectedNames: + if fnmatch(n,p): + selFlg = True + break + if not selFlg: + continue + # + # check if in list of histograms to be vetoed + # + selFlg = True + for p in vetoedNames: + if fnmatch(n,p): + selFlg = False + break + if not selFlg: + continue + # + # add histogram + # + hDef = HistogramDefinition(n,hDict) + hDefs.add(hDef) + print("Added",hDef.getParameter('canvasName')) + +#!# moduleName = configName[:-3] if configName.endswith(".py") else configName +#!# module = __import__(moduleName) +#!# for n in dir(module): +#!# if n.startswith('__'): +#!# continue +#!# hDict = getattr(module,n) +#!# #print(n,type(hDict)) +#!# #sys.exit() +#!# assert type(hDict)==dict +#!# # +#!# # check if in list of histograms to be displayed +#!# # +#!# selFlg = False +#!# for p in selectedNames: +#!# if fnmatch(n,p): +#!# selFlg = True +#!# break +#!# if not selFlg: +#!# continue +#!# # +#!# # check if in list of histograms to be vetoed +#!# # +#!# selFlg = True +#!# for p in vetoedNames: +#!# if fnmatch(n,p): +#!# selFlg = False +#!# break +#!# if not selFlg: +#!# continue +#!# # +#!# # add histogram +#!# # +#!# hDef = HistogramDefinition(n,hDict) +#!# hDefs.add(hDef) +#!# print("Added",hDef.getParameter('canvasName')) + return ( vDefs, hDefs ) + diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py new file mode 100755 index 0000000..a20f1c6 --- /dev/null +++ b/DrawHits/drawHitsRDF.py @@ -0,0 +1,796 @@ +#! /bin/env python3 +import sys,os +from drawHitsConfiguration import * +import ROOT +import argparse +from fnmatch import fnmatch + +def divideRatios(cnv,nx,ny,widthRatios,heightRatios,canvasTopMargin=0.,canvasLeftMargin=0.): + result = [ ] + cnv.cd() + + wrs = len(widthRatios) + hrs = len(heightRatios) + nxl = min(nx,wrs) + nyl = min(ny,hrs) + + if wrs==0: nxl = nx + if hrs==0: nyl = ny + + pn = 1 + xr = 0. + yr = 0. + x = 0. + y = 1. + # Check the validity of the margins + if canvasTopMargin<0 or canvasTopMargin>1: + raise Exception("DivideRatios: The canvas top margin must be >= 0 and <= 1") + else: + y = 1.- canvasTopMargin + if canvasLeftMargin <0 or canvasLeftMargin >1: + raise Exception("DivideRatios", "The canvas left margin must be >= 0 and <= 1") + + # Check the validity of the ratios + sumOfHeightRatios = canvasTopMargin + if hrs: + for i in range(nyl): + yr = heightRatios[i] + sumOfHeightRatios = sumOfHeightRatios + yr + if yr<0 or yr>1: + raise Exception("DivideRatios", "Y ratios plus the top margin must be >= 0 and <= 1") + + if sumOfHeightRatios>1.: + raise Exception("DivideRatios", "The sum of Y ratios plus the top margin must be <= 1 %g",sumOfHeightRatios) + sumOfWidthRatios = canvasLeftMargin + if wrs: + for j in range(nxl): + xr = widthRatios[j] + sumOfWidthRatios = sumOfWidthRatios + xr + if xr <0 or xr >1: + raise Exception("DivideRatios", "X ratios must be >= 0 and <= 1") + if sumOfWidthRatios>1.: + raise Exception("DivideRatios", "The sum of X ratios must be <= 1 %g ",sumOfWidthRatios) + + # Create the pads according to the ratios + for i in range(nyl): + x = canvasLeftMargin + if hrs: + yr = heightRatios[i] + else: + yr = 1./nyl + for j in range(nxl): + if wrs: + xr = widthRatios[j] + else: + xr = 1./nxl + x1 = max(0., x) + y1 = max(0., y - yr) + x2 = min(1., x + xr) + y2 = min(1., y) + pad = ROOT.TPad(cnv.GetName()+str(pn),cnv.GetName()+str(pn),x1, y1, x2 ,y2) + result.append(pad) + pad.SetNumber(pn) + pad.Draw() + x = x + xr + pn += 1 + y = y - yr + + return result + +def fitHistogram(mType,h): + f1name = "f1"+str(mType) + f1 = ROOT.TF1(f1name,"gaus(0)") + f1.SetParameter(0,h.GetMaximum()) + f1.SetParLimits(0,0.,2*h.GetMaximum()) + f1.SetParameter(1,0.) + f1.SetParameter(2,h.GetRMS()/10.) + h.Fit(f1name) + f2name = "f2"+str(mType) + f2 = ROOT.TF1(f2name,"gaus(0)+gaus(3)") + f2.SetParameter(0,f1.GetParameter(0)) + f2.SetParameter(1,f1.GetParameter(1)) + f2.SetParameter(2,f1.GetParameter(2)) + f2.SetParameter(3,f1.GetParameter(0)/100.) + f2.SetParameter(4,f1.GetParameter(1)) + f2.SetParameter(5,5*f1.GetParameter(2)) + f2.SetParLimits(5,f1.GetParameter(2),10*f1.GetParameter(2)) + h.Fit(f2name) + ROOT.gPad.SetLogy(1) + ROOT.gPad.Update() + + +def cutString(*cuts): + if len(cuts)>0 and cuts[0]!=None: + return "&&".join([ c for c in cuts if ( c!=None and c.strip()!="" ) ]) + return None + +def cutLines(cuts,maxChar=40): + result = [ ] + line = "" + for ic,c in enumerate(cuts): + line += c + if ic<(len(cuts)-1): + line += "&&" + if len(line)>maxChar: + result.append(line) + line = "" + if line!="": + result.append(line) + return result + +# def drawString(pave,title,s=""): +# t = pave.AddText(title) +# t.SetTextFont(43) +# t.SetTextSize(0.06) +# t.SetTextSize(16) +# t.SetTextAlign(13) +# #yt += 14 +# if s!="": +# #t = pave.AddText("") +# t = pave.AddText(" "+s) +# t.SetTextFont(43) +# t.SetTextSize(14) +# t.SetTextAlign(13) +# #t = pave.AddText("") + +# def drawCuts(pave,title,cuts): +# #t = pave.AddText(title) +# #t = pave.AddText("") +# lines = [ ] +# line = "" +# for ic,c in enumerate(cuts): +# line += c +# if ic<(len(cuts)-1): +# line += "&&" +# if len(line)>40: +# lines.append(line) +# line = "" +# if line!="": +# lines.append(line) +# for l in lines: +# if l!="": +# t = pave.AddText(" "+l) +# t.SetTextFont(43) +# t.SetTextSize(0.04) +# t.SetTextSize(14) +# t.SetTextAlign(13) +# #l = " " + c +# #if ic<(len(cuts)-1): +# # l += " &&" +# ## if len(l +# #if +# #t = pave.AddText(l) + + +def drawCutPave(cnv,ic,variable,cuts,effcuts=None): + indBaseCuts = cuts.split("&&") + indEffCuts = None if effcuts==None else effcuts.split("&&") + #print(indBaseCuts) + #print(indEffCuts) + cnv.cd(ic+3) + #hpave = 3*0.06+(len(indBaseCuts)+1)*0.04 + #if indEffCuts!=None: + # hpave += (len(indEffCuts)+2)*0.04 + + #print(ROOT.gPad.UtoPixel(0.),ROOT.gPad.UtoPixel(1.)) + #print(ROOT.gPad.VtoPixel(0.),ROOT.gPad.VtoPixel(1.)) + allLines = [ ] + allLines.append(('hdr','Variable(s)')) + allLines.append(('txt',variable)) + allLines.append(('hdr','Basic selection')) + for l in cutLines(indBaseCuts): + if l!="": + allLines.append(('txt',l)) + if indEffCuts!=None: + allLines.append(('hdr','Efficiency selection')) + for l in cutLines(indEffCuts): + if l!="": + allLines.append(('txt',l)) + + hdrPixels = 16 + txtPixels = 14 + #pave = ROOT.TPaveText(0.05,max(0,1.0-hpave),0.95,1.0) + hpave = ((hdrPixels+txtPixels+2)*len([ x for x in allLines if x[0]=='hdr' ]) + \ + (txtPixels+2)*len([ x for x in allLines if x[0]=='txt' ])) / (ROOT.gPad.VtoPixel(0.)-ROOT.gPad.VtoPixel(1.)) + #print(hpave) + if hpave>1.: + scale = 1./hpave + hpave = 1 + else: + scale = 1 + + pave = ROOT.TPaveText(0.,1.-hpave,1.,1.) + pave.SetBorderSize(0) + pave.SetFillStyle(0) + pave.SetTextFont(43) + #pave.SetMargin(0) + #pave.SetTextSize(0.04) + pave.SetTextSize(int(scale*txtPixels)) + pave.SetTextAlign(13) + nhdr = 0 + for x,y in allLines: + if x=='hdr': + if nhdr>0: + t = pave.AddText("") + t.SetTextSize(int(scale*txtPixels)) + t = pave.AddText(y) + t.SetTextFont(63) + t.SetTextSize(int(scale*hdrPixels)) + nhdr += 1 + else: + t = pave.AddText(" "+y) + t.SetTextSize(int(scale*txtPixels)) + #drawString(pave,"Variable(s)",variable) + #drawString(pave,"Basic selection") + #drawCuts(pave,"Basic selection",indBaseCuts) + #if indEffCuts!=None: + # #t = pave.AddText("") + # drawString(pave,"Efficiency selection") + # drawCuts(pave,"Efficiency selection",indEffCuts) + + pave.Draw() + ROOT.gPad.Update() + return pave + +def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): + histos = { } + + for mType in range(23,26): + #print("Checking mType",mType,"for",hDef.name) + # + # draw histogram? + # + if hDef.vetoMType(mType): + continue + is1D = hDef.getParameter('yNbins',mType)==None + is2D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)==None + is3D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)!=None + isProfile = hDef.getParameter('profile',mType)!=None and hDef.getParameter('profile',mType) + effCuts = hDef.getParameter('effCuts',mType) + variable = hDef.getParameter('variable',mType) + ## + #cnv.cd(ic) + #ROOT.gPad.SetGridx(1) + #ROOT.gPad.SetGridy(1) + #if not is1D: + # ROOT.gPad.SetRightMargin(0.125) + hName = hDef.getParameter('histogramName',mType) + str(mType) + hTitle = hDef.getParameter('histogramTitle',mType) + " module type " +str(mType) + nbx = hDef.getParameter('xNbins',mType) + xmin = hDef.getParameter('xMin',mType) + xmax = hDef.getParameter('xMax',mType) + #print("Starting for ",hDef.name,hName,hTitle) + if is1D and ( not isProfile ): + #print(variable+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]") + #histos[mType] = [ rdf.Histo1D((hName+"_1",hName+"_1",nbx,xmin,xmax), \ + # variable+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]"), \ + # None, None, None ] + #print(rdf.GetColumnNames()) + #print(hName,effCuts) + #rdf = rdf.Define("pabsVar","pabs[pabs>0.3]") + #th1m = ROOT.RDF.TH1DModel(hName+"_1",hName+"_1",nbx,xmin,xmax) + #print(type(th1m)) + cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) + rdf,varMask = varMaskCombs(rdf,variable,cuts) + model = (hName+"_1",hName+"_1",nbx,xmin,xmax) + #print(varMask) + #print(rdf.GetDefinedColumnNames()) + histos[mType] = [ rdf.Histo1D(model,varMask), None, None, None ] + if effCuts!=None: + cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts) + rdf,varMask = varMaskCombs(rdf,variable,cuts) + model = (hName+"_2",hName+"_2",nbx,xmin,xmax) + histos[mType][1] = rdf.Histo1D(model,varMask) + sys.exit() + elif isProfile: + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + v2,v1 = variable.split(":") + histos[mType] = [ rdf.Profile1D((hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), \ + v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2), \ + None, None, None ] + elif is2D: + nby = hDef.getParameter('yNbins',mType) + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + v2,v1 = variable.split(":") + histos[mType] = [ rdf.Histo2D((hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), \ + v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2), \ + None, None, None ] + if effCuts!=None: + histos[mType][1] = rdf.Histo2D((hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax), \ + v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)+"]") + elif is3D: + nby = hDef.getParameter('yNbins',mType) + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + nbz = hDef.getParameter('zNbins',mType) + zmin = hDef.getParameter('zMin',mType) + zmax = hDef.getParameter('zMax',mType) + v3,v2,v1 = variable.split(":") + print(type(rdf)) + print(v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3) + print([hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax]) + histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ + v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ + None, None, None ] + #histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ + # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ + # None, None, None ] + assert effCuts==None + #print("Ending for ",hDef.name,hName,hTitle) + + sys.exit() + return histos + + + +def fillHistoByDef(tree,hDef,extraCuts): + histos = { } + + savedDir = ROOT.gDirectory + ROOT.gROOT.cd() + #cnv = ROOT.TCanvas(hDef.getParameter('canvasName'),hDef.getParameter('canvasName'),1000,1000) + #result['cnv'] = cnv + #cnv.Divide(2,2) + + #print(hDef['canvasName'],'is',is1D) + + ic = 0 + #hEffVs = { } + for mType in range(23,26): + #print("Checking mType",mType,"for",hDef.name) + ic += 1 + # + # draw histogram? + # + if hDef.vetoMType(mType): + continue + is1D = hDef.getParameter('yNbins',mType)==None + is2D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)==None + is3D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)!=None + isProfile = hDef.getParameter('profile',mType)!=None and hDef.getParameter('profile',mType) + effCuts = hDef.getParameter('effCuts',mType) + variable = hDef.getParameter('variable',mType) + ## + #cnv.cd(ic) + #ROOT.gPad.SetGridx(1) + #ROOT.gPad.SetGridy(1) + #if not is1D: + # ROOT.gPad.SetRightMargin(0.125) + hName = hDef.getParameter('histogramName',mType) + str(mType) + hTitle = hDef.getParameter('histogramTitle',mType) + " module type " +str(mType) + nbx = hDef.getParameter('xNbins',mType) + xmin = hDef.getParameter('xMin',mType) + xmax = hDef.getParameter('xMax',mType) + #print("Starting for ",hDef.name,hName,hTitle) + if is1D and ( not isProfile ): + histos[mType] = [ ROOT.TH1F(hName+"_1",hName+"_1",nbx,xmin,xmax), None, None, None ] + tree.Project(hName+"_1",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + if effCuts!=None: + histos[mType][1] = ROOT.TH1F(hName+"_2",hName+"_2",nbx,xmin,xmax) + tree.Project(hName+"_2",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) + histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) + histos[mType][3].SetMarkerStyle(20) + else: + # always keep final histogram in 4th position + histos[mType][3] = histos[mType][0] + elif isProfile: + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + #histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), None, None, None ] + histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax), None, None, None ] + tree.Project(hName+"_1",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + # always keep final histogram in 4th position + histos[mType][3] = histos[mType][0] + elif is2D: + nby = hDef.getParameter('yNbins',mType) + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + histos[mType] = [ ROOT.TH2F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), None, None, None ] + tree.Project(hName+"_1",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + if effCuts!=None: + histos[mType][1] = ROOT.TH2F(hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax) + #tree.Draw(variable+">>"+hName+"_2("+str(nbx)+","+str(xmin)+","+str(xmax)+","+ \ + # str(nby)+","+str(ymin)+","+str(ymax)+")", + # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) + tree.Project(hName+"_2",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) + histos[mType][1].Divide(histos[mType][0]) + # always keep final histogram in 4th position + histos[mType][3] = histos[mType][1] + else: + # always keep final histogram in 4th position + histos[mType][3] = histos[mType][0] + elif is3D: + nby = hDef.getParameter('yNbins',mType) + ymin = hDef.getParameter('yMin',mType) + ymax = hDef.getParameter('yMax',mType) + nbz = hDef.getParameter('zNbins',mType) + zmin = hDef.getParameter('zMin',mType) + zmax = hDef.getParameter('zMax',mType) + histos[mType] = [ ROOT.TH3F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax), \ + None, None, None ] + tree.Project(hName+"_1",variable, \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + assert effCuts==None + # always keep final histogram in 4th position + histos[mType][3] = histos[mType][0] + #print("Ending for ",hDef.name,hName,hTitle) + + savedDir.cd() + return histos + + +def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): + result = { 'cnv' : None, 'histos' : histos, 'pave' : None } + + savedDir = ROOT.gDirectory + ROOT.gROOT.cd() + cnvName = hDef.getParameter('canvasName') + cnv = ROOT.TCanvas(cnvName,cnvName,1500,800) + result['cnv'] = cnv + #cnv.Divide(3,2) + result['pads'] = divideRatios(cnv,3,2,[1./3.,1./3.,1/3.],[2/3.,1/3.]) + + #print(hDef['canvasName'],'is',is1D) + + ic = 0 + #hEffVs = { } + for mType in range(23,26): + #print("Checking mType",mType,"for",hDef.name) + ic += 1 + cnv.cd(ic) + #padNameUp = cnvName+str(mType)+'up' + #result[padNameUp] = ROOT.TPad(padNameUp,padNameUp,(ic-1)/3.,1/3.,ic/3.,1.) + #result[padNameUp].Draw() + # + # draw histogram? + # + if hDef.vetoMType(mType): + continue + is1D = hDef.getParameter('yNbins',mType)==None + is2D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)==None + is3D = hDef.getParameter('yNbins',mType)!=None and hDef.getParameter('zNbins',mType)!=None + isProfile = hDef.getParameter('profile',mType)!=None and hDef.getParameter('profile',mType) + effCuts = hDef.getParameter('effCuts',mType) + variable = hDef.getParameter('variable',mType) + # + #result[padNameUp].cd() + ROOT.gPad.SetGridx(1) + ROOT.gPad.SetGridy(1) + if not is1D: + ROOT.gPad.SetRightMargin(0.125) + hName = hDef.getParameter('histogramName',mType) + str(mType) + hTitle = hDef.getParameter('histogramTitle',mType) + " module type " +str(mType) + + xtitle = hDef.getParameter('xTitle',mType) if hDef.getParameter('xTitle',mType) else variable + nbx = hDef.getParameter('xNbins',mType) + xmin = hDef.getParameter('xMin',mType) + xmax = hDef.getParameter('xMax',mType) + + ytitle = hDef.getParameter('yTitle',mType) if hDef.getParameter('yTitle',mType) else "" + ztitle = hDef.getParameter('zTitle',mType) if hDef.getParameter('zTitle',mType) else "" + if is1D and ( not isProfile ): + ymin = hDef.getParameter('yMin',mType) if hDef.getParameter('yMin',mType)!=None else 0. + ymax = hDef.getParameter('yMax',mType) if hDef.getParameter('yMax',mType)!=None else 1.05 + if effCuts!=None: + if not same: + histos[mType][2] = ROOT.gPad.DrawFrame(xmin,ymin,xmax,ymax) + histos[mType][2].SetTitle(hTitle) + histos[mType][2].GetXaxis().SetTitle(xtitle) + histos[mType][2].GetYaxis().SetTitle(ytitle) + histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) + histos[mType][3].SetMarkerStyle(20) + histos[mType][3].Draw("same Z") + else: + histos[mType][0].SetTitle(hTitle) + histos[mType][0].GetXaxis().SetTitle(xtitle) + histos[mType][0].GetYaxis().SetTitle(ytitle) + histos[mType][0].Draw("same" if same else "") + fitFunc = hDef.getParameter('fit') + if fitFunc!=None: + histos[mType][0].Fit(fitFunc,"Q","same") + elif isProfile: + histos[mType][0].SetTitle(hTitle) + histos[mType][0].GetXaxis().SetTitle(xtitle) + histos[mType][0].GetYaxis().SetTitle(ytitle) + histos[mType][0].SetMarkerSize(0.5) + #histos[mType][0].SetFillColor(ROOT.TColor.GetColorBright(ROOT.kGray)) + #histos[mType][0].SetFillColor(ROOT.kGray) + histos[mType][0].Draw("same" if same else "") + elif is2D: + assert not same + zmin = hDef.getParameter('zMin',mType) if hDef.getParameter('zMin',mType)!=None else 0. + zmax = hDef.getParameter('zMax',mType) if hDef.getParameter('zMax',mType)!=None else 1.05 + if effCuts!=None: + histos[mType][1].SetTitle(hTitle) + histos[mType][1].GetXaxis().SetTitle(xtitle) + histos[mType][1].GetYaxis().SetTitle(ytitle) + histos[mType][1].SetMinimum(zmin) + histos[mType][1].SetMaximum(zmax) + histos[mType][1].Draw("ZCOL") + else: + histos[mType][0].SetTitle(hTitle) + histos[mType][0].GetXaxis().SetTitle(xtitle) + histos[mType][0].GetYaxis().SetTitle(ytitle) + histos[mType][0].Draw("ZCOL") + elif is3D: + assert not same + zmin = hDef.getParameter('zMin',mType) if hDef.getParameter('zMin',mType)!=None else 0. + zmax = hDef.getParameter('zMax',mType) if hDef.getParameter('zMax',mType)!=None else 1.05 + assert effCuts==None + histos[mType][0].SetTitle(hTitle) + histos[mType][0].GetXaxis().SetTitle(xtitle) + histos[mType][0].GetYaxis().SetTitle(ytitle) + histos[mType][0].GetZaxis().SetTitle(ztitle) + histos[mType][0].Draw() + if logY or hDef.getParameter('logY',mType): + ROOT.gPad.SetLogy(1) + if is2D and ( logZ or hDef.getParameter('logZ',mType) ): + ROOT.gPad.SetLogz(1) + ROOT.gPad.Update() + + #cnv.cd() + #padNameDown = cnvName+str(mType)+'down' + #result[padNameDown] = ROOT.TPad(padNameDown,padNameDown,(ic-1)/3.,0.,ic/3.,1/3.) + #result[padNameDown].Draw() + result['pave'+str(mType)] = drawCutPave(cnv,ic,hDef.getParameter('variable',mType), \ + cutString(extraCuts,hDef.getParameter('baseCuts',mType)), \ + cutString(hDef.getParameter('effCuts',mType))) + + #for k,v in result.items(): + # print(k,v) + savedDir.cd() + return result + +def addHistogram(varString,cuts,effCuts=None,name='userHist'): + extraHDict = { } + # split into string defining the variable(s) and (1 or 2) axis definition(s) + fields1 = varString.split(";") + assert len(fields1)<=3 + extraHDict['variable'] = fields1[0] + #extraHDict['canvasName'] = "cEffArg" + #extraHDict['histogramName'] = "hEffArg" + extraHDict['histogramTitle'] = name + # x-axis + fields2 = fields1[1].split(",") + assert len(fields2)==3 + extraHDict['xNbins'] = int(fields2[0]) + extraHDict['xMin'] = float(fields2[1]) + extraHDict['xMax'] = float(fields2[2]) + # check for info on y axis (== presence of 2nd variable) + if len(fields1)==3: + assert ":" in extraHDict['variable'] + fields3 = fields1[2].split(",") + extraHDict['yNbins'] = int(fields3[0]) + extraHDict['yMin'] = float(fields3[1]) + extraHDict['yMax'] = float(fields3[2]) + extraHDict['xTitle'] = extraHDict['variable'].split(":")[1] + extraHDict['yTitle'] = extraHDict['variable'].split(":")[0] + else: + extraHDict['yMin'] = 0. + extraHDict['yMax'] = 1.05 + extraHDict['xTitle'] = extraHDict['variable'] + extraHDict['yTitle'] = 'efficiency' if effCuts!=None else 'events/bin' + extraHDict['baseCuts'] = cuts + if effCuts!=None: + extraHDict['effCuts'] = effCuts + #xxx = HistogramDefinition("effV",extraHDict) + #print("xxx",xxx) + #print("xxx",xxx.parameters) + #allHDefs.add(HistogramDefinition("effV",extraHDict)) + #print(allHDefs.allDefinitions.keys()) + #print(allHDefs.allCanvases) + #print(allHDefs['hEffArg']) + return HistogramDefinition(name,extraHDict) + + + +parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('--definitions', '-d', help='python module with dictionaries defining efficiency histograms', \ + type=str, default=None) +parser.add_argument('--histogram', \ + help='definition of extra histogram (format ;,,[;,,)', \ + action='append', type=str, default=[]) +parser.add_argument('--batch', '-b', help='ROOT batch mode', action='store_true', default=False) +parser.add_argument('--dxMax', help='max. local dx for efficiency plots', type=float, default=0.0075) +parser.add_argument('--cuts', '-c', help="basic cut string", type=str, default="") +parser.add_argument('--effCuts', '-e', help="basic cut string", type=str, default=None) +parser.add_argument('--output', '-o', help='output directory for graphic output', type=str, default=None) +parser.add_argument('--formats', help='comma-separated list of extensions for output files', \ + type=str, default="pdf,png") +parser.add_argument('--sampleName', help='sample label for output', type=str, default=None) +parser.add_argument('--fitResiduals', '-f', \ + help='comma-separated list of names of histogram sets with residuals to be fit', \ + type=str, default=None) +parser.add_argument('--selectedHistograms', help='comma-separated names of histogram definitions to be used', \ + type=str, default='*') +parser.add_argument('--vetoedHistograms', help='comma-separated names of histogram definitions not to be used', + type=str, default='') +parser.add_argument('--logY', help='use log scale for y axis', action='store_true', default=False) +parser.add_argument('--logZ', help='use log scale for z axis', action='store_true', default=False) +parser.add_argument('--printTree', '-p', help='print TTree contents', action='store_true', default=False) +parser.add_argument('--listHistograms', '-l', help='list predefined and selected histograms', \ + action='store_true', default=False) +parser.add_argument('--zone', '-z', help='restrict to zone in OT (barrel, tilted, endcap)', type=str, \ + choices=['barrel','tilted','endcap'], default=None) +parser.add_argument('file', help='input file', type=str, nargs='+', default=None) +args = parser.parse_args() +outputFormats = [ ] +if args.output!=None: + assert os.path.isdir(args.output) + print("***",args.output) + outputFormats = [ x.strip() for x in args.formats.strip().split(",") ] +fitResiduals = args.fitResiduals.split(",") if args.fitResiduals else [ ] +selectedHistoNames = args.selectedHistograms.split(",") +vetoedHistoNames = args.vetoedHistograms.split(",") +# +# add cut for zone definition? +# +if args.zone=="barrel": + zoneCuts = "detNormalT>0.99" +elif args.zone=="endcap": + zoneCuts = "detNormalT<0.01" +elif args.zone=="tilted": + zoneCuts = "detNormalT>0.05&&detNormalT<0.095" +else: + zoneCuts = "" +args.cuts = cutString(args.cuts,zoneCuts) + +# +# load histogram definitions +# +allVDefs,allHDefs = loadConfiguration(args.definitions,selectedHistoNames,vetoedHistoNames) +if args.listHistograms: + hnames = sorted(allHDefs.allHistoNames) + for hn in hnames: + print(hn) + sys.exit() + +for ih,h in enumerate(args.histogram): + allHDefs.add(addHistogram(h,args.cuts,args.effCuts,name="userH"+str(ih+1))) + +#!# varEffDict = { } +#!# # split into string defining the variable(s) and (1 or 2) axis definition(s) +#!# fields1 = args.varEff.split(";") +#!# assert len(fields1)<=3 +#!# varEffDict['variable'] = fields1[0] +#!# #varEffDict['canvasName'] = "cEffArg" +#!# #varEffDict['histogramName'] = "hEffArg" +#!# varEffDict['histogramTitle'] = "hEffArg" +#!# # x-axis +#!# fields2 = fields1[1].split(",") +#!# assert len(fields2)==3 +#!# varEffDict['xNbins'] = int(fields2[0]) +#!# varEffDict['xMin'] = float(fields2[1]) +#!# varEffDict['xMax'] = float(fields2[2]) +#!# # check for info on y axis (== presence of 2nd variable) +#!# if len(fields1)==3: +#!# assert ":" in varEffDict['variable'] +#!# fields3 = fields1[2].split(",") +#!# varEffDict['yNbins'] = int(fields3[0]) +#!# varEffDict['yMin'] = float(fields3[1]) +#!# varEffDict['yMax'] = float(fields3[2]) +#!# varEffDict['xTitle'] = varEffDict['variable'].split(":")[1] +#!# varEffDict['yTitle'] = varEffDict['variable'].split(":")[0] +#!# else: +#!# varEffDict['yMin'] = 0. +#!# varEffDict['yMax'] = 1.05 +#!# varEffDict['xTitle'] = varEffDict['variable'] +#!# varEffDict['yTitle'] = 'efficiency' +#!# varEffDict['baseCuts'] = args.cuts +#!# varEffDict['effCuts'] = cutString("hasRecHit>0","abs(localPos.x()-rhLocalPos.x())<"+str(args.dxMax)) +#!# #xxx = HistogramDefinition("effV",varEffDict) +#!# #print("xxx",xxx) +#!# #print("xxx",xxx.parameters) +#!# allHDefs.add(HistogramDefinition("effV",varEffDict)) +#!# #print(allHDefs.allDefinitions.keys()) +#!# #print(allHDefs.allCanvases) +#!# #print(allHDefs['hEffArg']) + +#extraCuts = "abs(particleType)==13" +#extraCuts = "tof<12.5" +extraCuts = args.cuts + +if args.batch: + ROOT.gROOT.SetBatch(1) +ROOT.gROOT.ProcessLine(".L setTDRStyle.C") +ROOT.gROOT.ProcessLine(".L floatMod.C+") +ROOT.setTDRStyle() +ROOT.gStyle.SetOptStat(0) +ROOT.gStyle.SetOptFit(1) +ROOT.gStyle.SetTitleFont(42) +ROOT.gStyle.SetTitleFontSize(0.03) +ROOT.gStyle.SetTitleX(0.12) +ROOT.gStyle.SetTitleY(1.00) +ROOT.gStyle.SetTitleAlign(13) +ROOT.gStyle.SetTitleBorderSize(0) +#ROOT.gStyle.SetTitleFillColor(0) +ROOT.gStyle.SetOptTitle(1) +#tf = ROOT.TFile(args.file[0]) +#simHitTree = simHitTree = tf.Get("analysis").Get("SimHitTree") +simHitTree = ROOT.TChain("analysis/SimHitTree") +for fn in args.file: + simHitTree.Add(fn) +#print(type(tchain)) +#tchain.Print() +if args.printTree: + simHitTree.Print() + sys.exit() +# +# create RDataFrame and define additional columns +# +#simHitRDF = ROOT.RDataFrame(simHitTree) +simHitRDF = ROOT.RDataFrame("analysis/SimHitTree",args.file) +for k,v in allVDefs.items(): + simHitRDF = simHitRDF.Define(k,v) + +canvases = [ ] +histos = { } +paves = [ ] +varMaskCombs = VarMaskCombinations() + +for cName in allHDefs.canvasNames(): + for hName in allHDefs.byCanvas[cName]: + print("Processing histogram",hName,"in canvas",cName) + cHistos[hName] = createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) +sys.exit() + +allObjects = [ ] +for cName in allHDefs.canvasNames(): + same = False + cHistos = { } + for hName in allHDefs.byCanvas[cName]: + print("Processing histogram",hName,"in canvas",cName) + cHistos[hName] = fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts) + allObjects.append(drawHistoByDef(cHistos[hName],allHDefs.byCanvas[cName][hName], \ + logY=args.logY,logZ=args.logZ,same=same)) + same = True + if args.output!=None: + c = allObjects[-1]['cnv'] + #for c in [ x['cnv'] for x in allObjects ]: + basename = os.path.join(args.output,c.GetName()) + if args.sampleName!=None: + basename += "_" + args.sampleName + if args.zone!=None: + basename += "_" + args.zone + print(basename) + for fmt in outputFormats: + c.SaveAs(basename+"."+fmt) +# yMin = min([ x.GetMinimum() for x in cHistos +#sys.exit() + +#!# allObjects = [ ] +#!# for hdef in allHDefs.allDefinitions.values(): +#!# # +#!# # draw histograms according to definition +#!# # +#!# histos = fillHistoByDef(simHitTree,hdef,extraCuts) +#!# allObjects.append(drawHistoByDef(histos,hdef)) +#!# # +#!# # perform fit of resolution histogram +#!# # +#!# if hdef.name in fitResiduals: +#!# objects = allObjects[-1] +#!# cnv = objects['cnv'] +#!# # fit and redraw each panel +#!# ic = 0 +#!# for mType in range(23,26): +#!# ic += 1 +#!# cnv.cd(ic) +#!# f = fitHistogram(mType,objects['histos'][mType][0]) + + +#if args.output!=None: +# for c in [ x['cnv'] for x in allObjects ]: +# basename = os.path.join(args.output,c.GetName()) +# if args.sampleName!=None: +# basename += "_" + args.sampleName +# print(basename) +# c.SaveAs(basename+".pdf") +# c.SaveAs(basename+".png") diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml new file mode 100644 index 0000000..4e8baa8 --- /dev/null +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -0,0 +1,684 @@ +# +# definitions of new variables +# +variables: + pathX: 'path.fCoordinates.fX' + pathZ: 'path.fCoordinates.fZ' + dxdz: 'pathX/pathZ' + alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' + localPosX: 'localPos.fCoordinates.fX' + rhLocalPosX: 'rhLocalPos.fCoordinates.fX' + localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' + localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' + globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' + globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' + globPt: 'pabs*sqrt(sqrt(globRho2/globR2))' + detNormalT: 'detNormal.fCoordinates.fX*detNormal.fCoordinates.fX+detNormal.fCoordinates.fY*detNormal.fCoordinates.fY' +# +# definitions of canvases and histograms +# +histograms: +# +# +# + effAlphaTight: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' + histogramTitle: 'Efficiency vs. alpha(xz) tight' + variable: 'alpha0' + xMax: 100.0 + xMin: 0 + xNbins: 100 + xTitle: 'alpha(xz) [deg]' + yMax: 1.05 + yMin: 0.5 + yTitle: 'efficiency' +# +# +# + effAlphaLoose: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.1' + histogramTitle: 'Efficiency vs. alpha(xz) loose' + variable: 'alpha0' + xMax: 100.0 + xMin: 0 + xNbins: 100 + xTitle: 'alpha(xz) [deg]' + yMax: 1.05 + yMin: 0.5 + yTitle: 'efficiency' +# +# +# + effVsModX: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsModX1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize==1' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsModX2: + baseCuts: 'tof<12.5&&pabs>0.3&&pabs*globalDir.Rho()/globalDir.R()>0.5&&hasRecHit>0' + effCuts: 'clusterSize==2' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsModX3p: + baseCuts: 'tof<12.5&&pabs>0.3&&pabs*globalDir.Rho()/globalDir.R()>0.5&&hasRecHit>0' + effCuts: 'clusterSize>2' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 +# +# +# + effVsModY: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. y % 1.5 mm' + variable: 'floatMod(100*localPos.y(),15)/10.' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency vs. y % 2.5 cm' + variable: 'floatMod(10*localPos.y(),25)/10.' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency vs. y % 5 cm' + variable: 'floatMod(10*localPos.y(),50)/10.' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 +# +# +# + effX: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' + histogramTitle: 'Efficiency 1D' + variable: 'localPosX' + xTitle: 'local x [cm]' + yMax: 1.05 + yMin: 0.8 + yTitle: 'efficiency' + mType23: + xMax: 5.5 + xMin: -5.5 + xNbins: 550 + mType24: + xMax: 5.0 + xMin: -5.0 + xNbins: 250 + mType25: + xMax: 5 + xMin: -5 + xNbins: 250 +# +# +# + effY: + variable: 'localPos.y()' + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' + histogramTitle: 'Efficiency Y 1D' + xTitle: 'local y [cm]' + xNbins: 550 + xMax: 5.5 + xMin: -5.5 + yTitle: 'efficiency' + yMax: 1.05 + yMin: 0.8 +# +# +# + pathX: + histogramTitle: 'path (x)' + variable: '10000*abs(path.x())' + baseCuts: 'tof<12.5&&pabs>0.3' + xTitle: 'SimHit path (x) [#mum]' + xNbins: 200 + xMax: 1000 + xMin: 0 +# +# +# + pathY: + histogramTitle: 'path (y)' + variable: '10000*abs(path.y())' + baseCuts: 'tof<12.5&&pabs>0.3' + xTitle: 'SimHit path (y [#mum])' + xNbins: 200 + xMax: 2000 + xMin: 0 +# +# +# + pullX: + histogramTitle: 'pulls (x)' + variable: '(localPosX-rhLocalPosX)/rhLocalErr.x()' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'pull local x' + xNbins: 200 + xMax: 5 + xMin: -5 + logY: true +# +# +# + resX: + histogramTitle: 'residuals (x)' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + logY: true +# +# +# + resX1: + histogramTitle: 'residuals (x) - cluster size 1' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + logY: true +# +# +# + resX2: + histogramTitle: 'residuals (x) - cluster size 2' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + logY: true +# +# +# + resX3P: + histogramTitle: 'residuals (x) - cluster size >2' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize>2' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + logY: true +# +# +# + resY: + histogramTitle: 'pulls (y)' + variable: '(localPos.y()-rhLocalPos.y())/rhLocalErr.y()' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'pull local y' + xNbins: 200 + xMax: 5 + xMin: -5 + logY: true +# +# +# + stdRes2D: + histogramTitle: 'my resolution' + variable: 'abs(path.x()):localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'residual x [cm]' + xNbins: 200 + xMin: -0.1 + xMax: 0.1 + yTitle: 'dx [cm]' + yNbins: 20 + yMin: 0.0 + yMax: 0.1 +# +# +# + widthVsMod2DX: + baseCuts: 'tof<12.5&&pabs>0.3' + yTitle: 'cluster width' + yNbins: 10 + yMin: 0 + yMax: 10 + mType23: + histogramTitle: 'width vs x modula 100 #mu m' + variable: 'clusterSize:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 110 + xMin: -5 + xMax: 105 + mType24: + histogramTitle: 'width vs x modula 100 #mu m' + variable: 'clusterSize:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 110 + xMin: -5 + xMax: 105 + mType25: + histogramTitle: 'width vs x modula 90 #mu m' + variable: 'clusterSize:localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 100 + xMin: -5 + xMax: 95 +# +# +# + widthVsModX: + baseCuts: 'tof<12.5&&pabs>0.3' + profile: true + yTitle: 'cluster width' + yMin: 0 + yMax: 25 + mType23: + histogramTitle: 'width vs x modula 100 #mu m' + variable: 'clusterSize:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 110 + xMin: -5 + xMax: 105 + mType24: + histogramTitle: 'width vs x modula 100 #mu m' + variable: 'clusterSize:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 110 + xMin: -5 + xMax: 105 + mType25: + histogramTitle: 'width vs x modula 90 #mu m' + variable: 'clusterSize:localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 100 + xMin: -5 + xMax: 95 +# +# +# + widthVsModY: + baseCuts: 'tof<12.5&&pabs>0.3' + yTitle: 'cluster width' + yMin: 0 + yMax: 25 + profile: true + mType23: + histogramTitle: 'Width vs. y % 1.5 mm' + variable: 'clusterSize:floatMod(100*localPos.y(),15)/10.' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 200 + xMin: -0.25 + xMax: 1.75 + mType24: + histogramTitle: 'Width vs. y % 2.5 cm' + variable: 'clusterSize:floatMod(10*localPos.y(),25)/10.' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 300 + xMin: -0.25 + xMax: 2.75 + mType25: + histogramTitle: 'Width vs. y % 5 cm' + variable: 'clusterSize:floatMod(10*localPos.y(),50)/10.' + xTitle: 'y modulo 5cm [cm]' + xNbins: 275 + xMin: -0.25 + xMax: 5.25 +# +# +# + widthVsPath: + histogramTitle: 'width vs path' + variable: 'clusterSize:abs(path.x())' + baseCuts: 'tof<12.5&&hasRecHit>0' + profile: true + xTitle: 'SimHit path (x)' + xNbins: 100 + xMin: 0 + xMax: 0.2 + yTitle: 'clustersize' + yNbins: 25 + yMin: 0.0 + yMax: 25 + + res3DXVsDxDzModX: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -500 + xMax: 500 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 20 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 20 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 18 + yMin: 0 + yMax: 90 + + res3DXVsDxDz: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + res3DXVsDxDzW1: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + res3DXVsDxDzW2: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + pull3DXVsDxDz: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + pull3DXVsDxDzW1: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + pull3DXVsDxDzW2: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'path.x()/path.z():localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErr.x()' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + effDxDz: + variable: 'path.x()/path.z()' + histogramTitle: 'efficiency (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + + effDxDzW1: + variable: 'path.x()/path.z()' + histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0&&clusterSize==1' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + + effDxDzW2: + variable: 'path.x()/path.z()' + histogramTitle: 'efficiency, 2-strip clusters (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0&&clusterSize==2' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + From 60b3a4a59c0be242b6ddaf1d3135e180a0bdfae7 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 09:54:04 +0100 Subject: [PATCH 21/77] tested define histo1D --- DrawHits/drawHitsRDF.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index a20f1c6..13bad81 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -281,7 +281,7 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): rdf,varMask = varMaskCombs(rdf,variable,cuts) model = (hName+"_2",hName+"_2",nbx,xmin,xmax) histos[mType][1] = rdf.Histo1D(model,varMask) - sys.exit() + #sys.exit() elif isProfile: ymin = hDef.getParameter('yMin',mType) ymax = hDef.getParameter('yMax',mType) @@ -320,6 +320,7 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): assert effCuts==None #print("Ending for ",hDef.name,hName,hTitle) + print(histos) sys.exit() return histos @@ -365,13 +366,13 @@ def fillHistoByDef(tree,hDef,extraCuts): xmax = hDef.getParameter('xMax',mType) #print("Starting for ",hDef.name,hName,hTitle) if is1D and ( not isProfile ): - histos[mType] = [ ROOT.TH1F(hName+"_1",hName+"_1",nbx,xmin,xmax), None, None, None ] - tree.Project(hName+"_1",variable, \ - cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + #histos[mType] = [ ROOT.TH1F(hName+"_1",hName+"_1",nbx,xmin,xmax), None, None, None ] + #tree.Project(hName+"_1",variable, \ + # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) if effCuts!=None: - histos[mType][1] = ROOT.TH1F(hName+"_2",hName+"_2",nbx,xmin,xmax) - tree.Project(hName+"_2",variable, \ - cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) + #histos[mType][1] = ROOT.TH1F(hName+"_2",hName+"_2",nbx,xmin,xmax) + #tree.Project(hName+"_2",variable, \ + # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) histos[mType][3].SetMarkerStyle(20) else: @@ -739,7 +740,7 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) cHistos[hName] = createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) -sys.exit() +#sys.exit() allObjects = [ ] for cName in allHDefs.canvasNames(): From 11d904055da47b65c929cd9913f6943667e25a87 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 11:26:30 +0100 Subject: [PATCH 22/77] add helper for showing histogram definitions --- DrawHits/drawHitsRDF.py | 27 ++++++++------ DrawHits/drawHitsTmpRDF.yaml | 60 ++++++++++++++++--------------- DrawHits/showHitsConfiguration.py | 50 ++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 39 deletions(-) create mode 100644 DrawHits/showHitsConfiguration.py diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 13bad81..9e1e141 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -319,15 +319,16 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): # None, None, None ] assert effCuts==None #print("Ending for ",hDef.name,hName,hTitle) - - print(histos) - sys.exit() + + #for mType in range(23,26): + # print(histos[mType][0].GetEntries(),histos[mType][1].GetEntries()) + #sys.exit() return histos -def fillHistoByDef(tree,hDef,extraCuts): - histos = { } +def fillHistoByDef(tree,hDef,extraCuts,histos): + #histos = { } savedDir = ROOT.gDirectory ROOT.gROOT.cd() @@ -373,7 +374,7 @@ def fillHistoByDef(tree,hDef,extraCuts): #histos[mType][1] = ROOT.TH1F(hName+"_2",hName+"_2",nbx,xmin,xmax) #tree.Project(hName+"_2",variable, \ # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) - histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) + histos[mType][3] = ROOT.TEfficiency(histos[mType][1].GetValue(),histos[mType][0].GetValue()) histos[mType][3].SetMarkerStyle(20) else: # always keep final histogram in 4th position @@ -485,7 +486,7 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): histos[mType][2].SetTitle(hTitle) histos[mType][2].GetXaxis().SetTitle(xtitle) histos[mType][2].GetYaxis().SetTitle(ytitle) - histos[mType][3] = ROOT.TEfficiency(histos[mType][1],histos[mType][0]) + histos[mType][3] = ROOT.TEfficiency(histos[mType][1].GetValue(),histos[mType][0].GetValue()) histos[mType][3].SetMarkerStyle(20) histos[mType][3].Draw("same Z") else: @@ -736,10 +737,12 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): paves = [ ] varMaskCombs = VarMaskCombinations() +allHistos = { } for cName in allHDefs.canvasNames(): + allHistos[cName] = {} for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) - cHistos[hName] = createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) + allHistos[cName][hName] = createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) #sys.exit() allObjects = [ ] @@ -748,8 +751,11 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): cHistos = { } for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) - cHistos[hName] = fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts) - allObjects.append(drawHistoByDef(cHistos[hName],allHDefs.byCanvas[cName][hName], \ + print(allHistos[cName][hName]) + #cHistos[hName] = fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts,allHistos[cName][hName]) + fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts,allHistos[cName][hName]) + print(allHistos[cName][hName]) + allObjects.append(drawHistoByDef(allHistos[cName][hName],allHDefs.byCanvas[cName][hName], \ logY=args.logY,logZ=args.logZ,same=same)) same = True if args.output!=None: @@ -763,6 +769,7 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): print(basename) for fmt in outputFormats: c.SaveAs(basename+"."+fmt) + # yMin = min([ x.GetMinimum() for x in cHistos #sys.exit() diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index 4e8baa8..bdf085f 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -3,11 +3,13 @@ # variables: pathX: 'path.fCoordinates.fX' + pathY: 'path.fCoordinates.fY' pathZ: 'path.fCoordinates.fZ' dxdz: 'pathX/pathZ' alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' localPosX: 'localPos.fCoordinates.fX' rhLocalPosX: 'rhLocalPos.fCoordinates.fX' + rhLocalErrX: 'rhLocalErr.fCoordinates.fX' localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' @@ -231,7 +233,7 @@ histograms: # pathX: histogramTitle: 'path (x)' - variable: '10000*abs(path.x())' + variable: '10000*abs(pathX)' baseCuts: 'tof<12.5&&pabs>0.3' xTitle: 'SimHit path (x) [#mum]' xNbins: 200 @@ -242,7 +244,7 @@ histograms: # pathY: histogramTitle: 'path (y)' - variable: '10000*abs(path.y())' + variable: '10000*abs(pathY)' baseCuts: 'tof<12.5&&pabs>0.3' xTitle: 'SimHit path (y [#mum])' xNbins: 200 @@ -253,7 +255,7 @@ histograms: # pullX: histogramTitle: 'pulls (x)' - variable: '(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: '(localPosX-rhLocalPosX)/rhLocalErrX' baseCuts: 'tof<12.5&&hasRecHit>0' xTitle: 'pull local x' xNbins: 200 @@ -325,7 +327,7 @@ histograms: # stdRes2D: histogramTitle: 'my resolution' - variable: 'abs(path.x()):localPosX-rhLocalPosX' + variable: 'abs(pathX):localPosX-rhLocalPosX' baseCuts: 'tof<12.5&&hasRecHit>0' xTitle: 'residual x [cm]' xNbins: 200 @@ -430,7 +432,7 @@ histograms: # widthVsPath: histogramTitle: 'width vs path' - variable: 'clusterSize:abs(path.x())' + variable: 'clusterSize:abs(pathX)' baseCuts: 'tof<12.5&&hasRecHit>0' profile: true xTitle: 'SimHit path (x)' @@ -454,19 +456,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 20 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 20 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 18 yMin: 0 @@ -484,19 +486,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -514,19 +516,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -544,19 +546,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -574,19 +576,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -604,19 +606,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -634,26 +636,26 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'path.x()/path.z():localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'path.x()/path.z():localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErr.x()' + variable: 'pathX/pathZ:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 90 effDxDz: - variable: 'path.x()/path.z()' + variable: 'pathX/pathZ' histogramTitle: 'efficiency (dx/dz)' baseCuts: 'tof<12.5' effCuts: 'hasRecHit>0' @@ -663,7 +665,7 @@ histograms: xMax: 1.05 effDxDzW1: - variable: 'path.x()/path.z()' + variable: 'pathX/pathZ' histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' baseCuts: 'tof<12.5' effCuts: 'hasRecHit>0&&clusterSize==1' @@ -673,7 +675,7 @@ histograms: xMax: 1.05 effDxDzW2: - variable: 'path.x()/path.z()' + variable: 'pathX/pathZ' histogramTitle: 'efficiency, 2-strip clusters (dx/dz)' baseCuts: 'tof<12.5' effCuts: 'hasRecHit>0&&clusterSize==2' diff --git a/DrawHits/showHitsConfiguration.py b/DrawHits/showHitsConfiguration.py new file mode 100644 index 0000000..925a7c7 --- /dev/null +++ b/DrawHits/showHitsConfiguration.py @@ -0,0 +1,50 @@ +# +# Show definitions for histograms from a configuration file +# +import sys +from drawHitsConfiguration import * +import argparse + +def printDict(d,indent=0): + for k,v in d.items(): + if type(v)==dict: + print(indent*" "+k+":") + printDict(v,indent+2) + else: + print(indent*" "+k+":",v) + +if __name__=="__main__": + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('--isEff', help='Select efficiency plots', action='store_true', default=False) + parser.add_argument('--isNoEff', help='Veto efficiency plots', action='store_true', default=False) + parser.add_argument('--isProfile', help='Select profile histograms', action='store_true', default=False) + parser.add_argument('--isNoProfile', help='Veto profile histograms', action='store_true', default=False) + parser.add_argument('--is1D', help='Select 1D histograms', action='store_true', default=False) + parser.add_argument('--is2D', help='Select 2D histograms', action='store_true', default=False) + parser.add_argument('--is3D', help='Select 3D histograms', action='store_true', default=False) + parser.add_argument('--verbose', '-v', help='Show details for selected histograms', \ + action='store_true', default=False) + parser.add_argument('file', help='yaml defining efficiency histograms', type=str, nargs=1, default=None) + args = parser.parse_args() + + allVDefs,allHDefs = loadConfiguration(args.file[0],['*']) + print() + + for hDef in allHDefs.allDefinitions.values(): + skip = True + if args.is1D and hDef('yNbins')==None: + skip = False + if args.is2D and hDef('yNbins')!=None and hDef('zNbins')==None: + skip = False + if args.is3D and hDef('zNbins')!=None: + skip = False + if skip: + continue + if ( args.isEff and hDef('effCuts')==None ) or ( args.isNoEff and hDef('effCuts')!=None ) : + continue + if ( args.isProfile and hDef('profile')==None ) or ( args.isNoProfile and hDef('profile')!=None ) : + continue + print(hDef.name) + if args.verbose: + printDict(hDef.parameters,2) + From 0756c0b6eebd3292f47fc46f7ac3099ef5db6712 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 11:39:27 +0100 Subject: [PATCH 23/77] tested RDF with 2D --- DrawHits/drawHitsRDF.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 9e1e141..44ae7ea 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -294,12 +294,17 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): ymin = hDef.getParameter('yMin',mType) ymax = hDef.getParameter('yMax',mType) v2,v1 = variable.split(":") - histos[mType] = [ rdf.Histo2D((hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), \ - v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2), \ - None, None, None ] + cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) + rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + model = (hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax) + histos[mType] = [ rdf.Histo2D(model,varMask1,varMask2), None, None, None ] if effCuts!=None: - histos[mType][1] = rdf.Histo2D((hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax), \ - v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)+"]") + cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts) + rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + model = (hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax) + histos[mType][1] = rdf.Histo2D(model,varMask1,varMask2) elif is3D: nby = hDef.getParameter('yNbins',mType) ymin = hDef.getParameter('yMin',mType) @@ -392,19 +397,16 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): nby = hDef.getParameter('yNbins',mType) ymin = hDef.getParameter('yMin',mType) ymax = hDef.getParameter('yMax',mType) - histos[mType] = [ ROOT.TH2F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), None, None, None ] - tree.Project(hName+"_1",variable, \ - cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + #histos[mType] = [ ROOT.TH2F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), None, None, None ] + #tree.Project(hName+"_1",variable, \ + # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) if effCuts!=None: - histos[mType][1] = ROOT.TH2F(hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax) - #tree.Draw(variable+">>"+hName+"_2("+str(nbx)+","+str(xmin)+","+str(xmax)+","+ \ - # str(nby)+","+str(ymin)+","+str(ymax)+")", + #histos[mType][1] = ROOT.TH2F(hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax) + #tree.Project(hName+"_2",variable, \ # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) - tree.Project(hName+"_2",variable, \ - cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) - histos[mType][1].Divide(histos[mType][0]) + #histos[mType][1].Divide(histos[mType][0]) # always keep final histogram in 4th position - histos[mType][3] = histos[mType][1] + histos[mType][3] = histos[mType][1].Divide(histos[mType][0].GetValue()) else: # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] From 3b2b7621ae320e21c425bf64e7a362dbe430d56b Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 11:43:43 +0100 Subject: [PATCH 24/77] tested RDF with Profile1D --- DrawHits/drawHitsRDF.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 44ae7ea..336768a 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -286,9 +286,14 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): ymin = hDef.getParameter('yMin',mType) ymax = hDef.getParameter('yMax',mType) v2,v1 = variable.split(":") - histos[mType] = [ rdf.Profile1D((hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), \ - v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2), \ - None, None, None ] + cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) + rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + model = (hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax) + histos[mType] = [ rdf.Profile1D(model,varMask1,varMask2), None, None, None ] + #histos[mType] = [ rdf.Profile1D((hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), \ + # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2), \ + # None, None, None ] elif is2D: nby = hDef.getParameter('yNbins',mType) ymin = hDef.getParameter('yMin',mType) @@ -385,12 +390,12 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif isProfile: - ymin = hDef.getParameter('yMin',mType) - ymax = hDef.getParameter('yMax',mType) - #histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), None, None, None ] - histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax), None, None, None ] - tree.Project(hName+"_1",variable, \ - cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + #ymin = hDef.getParameter('yMin',mType) + #ymax = hDef.getParameter('yMax',mType) + ##histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), None, None, None ] + #histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax), None, None, None ] + #tree.Project(hName+"_1",variable, \ + # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif is2D: From 3808aa09a35b1669c22fcedb37d2752a1bfa1e25 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 11:52:03 +0100 Subject: [PATCH 25/77] tested RDF with 3D --- DrawHits/drawHitsConfiguration.py | 2 +- DrawHits/drawHitsRDF.py | 43 +++++++++++++++++-------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/DrawHits/drawHitsConfiguration.py b/DrawHits/drawHitsConfiguration.py index e510014..413c4ea 100644 --- a/DrawHits/drawHitsConfiguration.py +++ b/DrawHits/drawHitsConfiguration.py @@ -189,7 +189,7 @@ def __call__(self,rdf,varName,selection): # use variable name and normalized selection string (remove spaces) # selNorm = selection.replace(" ","") - varMask = varName + "["+selNorm+"]" + varMask = "(" + varName + ")["+selNorm+"]" if varMask in self.varMaskDefinitions: # combination exists (assume that it's also defined in the RDataFrame) varMaskName = self.varMaskDefinitions[varMask] diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 336768a..aae1e1b 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -318,12 +318,15 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): zmin = hDef.getParameter('zMin',mType) zmax = hDef.getParameter('zMax',mType) v3,v2,v1 = variable.split(":") - print(type(rdf)) - print(v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3) - print([hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax]) - histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ - v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ - None, None, None ] + cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) + rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + rdf,varMask3 = varMaskCombs(rdf,v3,cuts) + model = (hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax) + histos[mType] = [ rdf.Histo3D(model,varMask1,varMask2,varMask3), None, None, None ] + #histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ + # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ + # None, None, None ] #histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ # None, None, None ] @@ -399,9 +402,9 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif is2D: - nby = hDef.getParameter('yNbins',mType) - ymin = hDef.getParameter('yMin',mType) - ymax = hDef.getParameter('yMax',mType) + #nby = hDef.getParameter('yNbins',mType) + #ymin = hDef.getParameter('yMin',mType) + #ymax = hDef.getParameter('yMax',mType) #histos[mType] = [ ROOT.TH2F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), None, None, None ] #tree.Project(hName+"_1",variable, \ # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) @@ -416,17 +419,17 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif is3D: - nby = hDef.getParameter('yNbins',mType) - ymin = hDef.getParameter('yMin',mType) - ymax = hDef.getParameter('yMax',mType) - nbz = hDef.getParameter('zNbins',mType) - zmin = hDef.getParameter('zMin',mType) - zmax = hDef.getParameter('zMax',mType) - histos[mType] = [ ROOT.TH3F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax), \ - None, None, None ] - tree.Project(hName+"_1",variable, \ - cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) - assert effCuts==None + #nby = hDef.getParameter('yNbins',mType) + #ymin = hDef.getParameter('yMin',mType) + #ymax = hDef.getParameter('yMax',mType) + #nbz = hDef.getParameter('zNbins',mType) + #zmin = hDef.getParameter('zMin',mType) + #zmax = hDef.getParameter('zMax',mType) + #histos[mType] = [ ROOT.TH3F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax), \ + # None, None, None ] + #tree.Project(hName+"_1",variable, \ + # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) + #assert effCuts==None # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] #print("Ending for ",hDef.name,hName,hTitle) From a41b9de56af2f7265c8b970cc7435326c3f6c8e8 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 13:34:00 +0100 Subject: [PATCH 26/77] working version for all histograms in drawHitsTmpRDF.yaml --- DrawHits/drawHitsConfiguration.py | 1 + DrawHits/drawHitsRDF.py | 10 ++++- DrawHits/drawHitsTmpRDF.yaml | 75 ++++++++++++++++--------------- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/DrawHits/drawHitsConfiguration.py b/DrawHits/drawHitsConfiguration.py index 413c4ea..9ce0d14 100644 --- a/DrawHits/drawHitsConfiguration.py +++ b/DrawHits/drawHitsConfiguration.py @@ -193,6 +193,7 @@ def __call__(self,rdf,varName,selection): if varMask in self.varMaskDefinitions: # combination exists (assume that it's also defined in the RDataFrame) varMaskName = self.varMaskDefinitions[varMask] + print("*** found",varMaskName,"for",varMask,"in local definitions") assert varMaskName in rdf.GetDefinedColumnNames() else: # create name for combination and define it in the RDataFrame diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index aae1e1b..8b55d0b 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -336,7 +336,7 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): #for mType in range(23,26): # print(histos[mType][0].GetEntries(),histos[mType][1].GetEntries()) #sys.exit() - return histos + return rdf,histos @@ -752,7 +752,13 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): allHistos[cName] = {} for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) - allHistos[cName][hName] = createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) + print(" ",simHitRDF.GetDefinedColumnNames()) + try: + simHitRDF,allHistos[cName][hName] = \ + createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) + except: + print("Exception for",cName,hName) + raise #sys.exit() allObjects = [ ] diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index bdf085f..b5c987c 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -8,8 +8,11 @@ variables: dxdz: 'pathX/pathZ' alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' localPosX: 'localPos.fCoordinates.fX' + localPosY: 'localPos.fCoordinates.fY' rhLocalPosX: 'rhLocalPos.fCoordinates.fX' + rhLocalPosY: 'rhLocalPos.fCoordinates.fY' rhLocalErrX: 'rhLocalErr.fCoordinates.fX' + rhLocalErrY: 'rhLocalErr.fCoordinates.fY' localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' @@ -27,7 +30,7 @@ histograms: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency vs. alpha(xz) tight' - variable: 'alpha0' + variable: 'alpha' xMax: 100.0 xMin: 0 xNbins: 100 @@ -42,7 +45,7 @@ histograms: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.1' histogramTitle: 'Efficiency vs. alpha(xz) loose' - variable: 'alpha0' + variable: 'alpha' xMax: 100.0 xMin: 0 xNbins: 100 @@ -108,7 +111,7 @@ histograms: xMin: -5 effVsModX2: - baseCuts: 'tof<12.5&&pabs>0.3&&pabs*globalDir.Rho()/globalDir.R()>0.5&&hasRecHit>0' + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' effCuts: 'clusterSize==2' yMin: 0 yMax: 1.05 @@ -135,7 +138,7 @@ histograms: xMin: -5 effVsModX3p: - baseCuts: 'tof<12.5&&pabs>0.3&&pabs*globalDir.Rho()/globalDir.R()>0.5&&hasRecHit>0' + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' effCuts: 'clusterSize>2' yMin: 0 yMax: 1.05 @@ -170,21 +173,21 @@ histograms: yMax: 1.05 mType23: histogramTitle: 'Efficiency vs. y % 1.5 mm' - variable: 'floatMod(100*localPos.y(),15)/10.' + variable: 'floatMod(100*localPosY,15)/10.' xTitle: 'y modulo 1.5mm [mm]' xNbins: 400 xMax: 1.75 xMin: -0.25 mType24: histogramTitle: 'Efficiency vs. y % 2.5 cm' - variable: 'floatMod(10*localPos.y(),25)/10.' + variable: 'floatMod(10*localPosY,25)/10.' xTitle: 'y modulo 2.5cm [cm]' xNbins: 600 xMax: 2.75 xMin: -0.25 mType25: histogramTitle: 'Efficiency vs. y % 5 cm' - variable: 'floatMod(10*localPos.y(),50)/10.' + variable: 'floatMod(10*localPosY,50)/10.' xTitle: 'y modulo 5cm [cm]' xNbins: 550 xMax: 5.25 @@ -217,7 +220,7 @@ histograms: # # effY: - variable: 'localPos.y()' + variable: 'localPosY' baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency Y 1D' @@ -315,7 +318,7 @@ histograms: # resY: histogramTitle: 'pulls (y)' - variable: '(localPos.y()-rhLocalPos.y())/rhLocalErr.y()' + variable: '(localPosY-rhLocalPosY)/rhLocalErrY' baseCuts: 'tof<12.5&&hasRecHit>0' xTitle: 'pull local y' xNbins: 200 @@ -408,21 +411,21 @@ histograms: profile: true mType23: histogramTitle: 'Width vs. y % 1.5 mm' - variable: 'clusterSize:floatMod(100*localPos.y(),15)/10.' + variable: 'clusterSize:floatMod(100*localPosY,15)/10.' xTitle: 'y modulo 1.5mm [mm]' xNbins: 200 xMin: -0.25 xMax: 1.75 mType24: histogramTitle: 'Width vs. y % 2.5 cm' - variable: 'clusterSize:floatMod(10*localPos.y(),25)/10.' + variable: 'clusterSize:floatMod(10*localPosY,25)/10.' xTitle: 'y modulo 2.5cm [cm]' xNbins: 300 xMin: -0.25 xMax: 2.75 mType25: histogramTitle: 'Width vs. y % 5 cm' - variable: 'clusterSize:floatMod(10*localPos.y(),50)/10.' + variable: 'clusterSize:floatMod(10*localPosY,50)/10.' xTitle: 'y modulo 5cm [cm]' xNbins: 275 xMin: -0.25 @@ -456,19 +459,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 20 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 20 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 18 yMin: 0 @@ -486,19 +489,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -516,19 +519,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -546,19 +549,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:10000*(localPosX-rhLocalPosX)' + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -576,19 +579,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -606,19 +609,19 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 @@ -636,26 +639,26 @@ histograms: zMin: -1.05 zMax: 1.05 mType23: - variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType24: - variable: 'pathX/pathZ:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 100 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 100 mType25: - variable: 'pathX/pathZ:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' + variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' yTitle: 'x modulo 90 #mum [#mum]' yNbins: 1 yMin: 0 yMax: 90 effDxDz: - variable: 'pathX/pathZ' + variable: 'dxdz' histogramTitle: 'efficiency (dx/dz)' baseCuts: 'tof<12.5' effCuts: 'hasRecHit>0' @@ -665,7 +668,7 @@ histograms: xMax: 1.05 effDxDzW1: - variable: 'pathX/pathZ' + variable: 'dxdz' histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' baseCuts: 'tof<12.5' effCuts: 'hasRecHit>0&&clusterSize==1' @@ -675,7 +678,7 @@ histograms: xMax: 1.05 effDxDzW2: - variable: 'pathX/pathZ' + variable: 'dxdz' histogramTitle: 'efficiency, 2-strip clusters (dx/dz)' baseCuts: 'tof<12.5' effCuts: 'hasRecHit>0&&clusterSize==2' From c4c69aa21dc55b8fb6d75eec4e538615146012da Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 14 Jan 2026 13:55:00 +0100 Subject: [PATCH 27/77] remove obsolete / dbg code --- DrawHits/drawHitsConfiguration.py | 42 +-------- DrawHits/drawHitsRDF.py | 144 ------------------------------ 2 files changed, 3 insertions(+), 183 deletions(-) diff --git a/DrawHits/drawHitsConfiguration.py b/DrawHits/drawHitsConfiguration.py index 9ce0d14..2cfc0ed 100644 --- a/DrawHits/drawHitsConfiguration.py +++ b/DrawHits/drawHitsConfiguration.py @@ -193,7 +193,6 @@ def __call__(self,rdf,varName,selection): if varMask in self.varMaskDefinitions: # combination exists (assume that it's also defined in the RDataFrame) varMaskName = self.varMaskDefinitions[varMask] - print("*** found",varMaskName,"for",varMask,"in local definitions") assert varMaskName in rdf.GetDefinedColumnNames() else: # create name for combination and define it in the RDataFrame @@ -201,9 +200,9 @@ def __call__(self,rdf,varName,selection): varMaskName = "varMask{:03d}".format(n) self.varMaskDefinitions[varMask] = varMaskName rdf = rdf.Define(varMaskName,varMask) - print("+++ defined new var + mask combinations:",varMaskName,varMask) - print(rdf.GetDefinedColumnNames()) - print("+++") + #print("+++ defined new var + mask combinations:",varMaskName,varMask) + #print(rdf.GetDefinedColumnNames()) + #print("+++") return rdf,varMaskName @@ -274,40 +273,5 @@ def loadConfiguration(configName,selectedNames=[],vetoedNames=[]): hDefs.add(hDef) print("Added",hDef.getParameter('canvasName')) -#!# moduleName = configName[:-3] if configName.endswith(".py") else configName -#!# module = __import__(moduleName) -#!# for n in dir(module): -#!# if n.startswith('__'): -#!# continue -#!# hDict = getattr(module,n) -#!# #print(n,type(hDict)) -#!# #sys.exit() -#!# assert type(hDict)==dict -#!# # -#!# # check if in list of histograms to be displayed -#!# # -#!# selFlg = False -#!# for p in selectedNames: -#!# if fnmatch(n,p): -#!# selFlg = True -#!# break -#!# if not selFlg: -#!# continue -#!# # -#!# # check if in list of histograms to be vetoed -#!# # -#!# selFlg = True -#!# for p in vetoedNames: -#!# if fnmatch(n,p): -#!# selFlg = False -#!# break -#!# if not selFlg: -#!# continue -#!# # -#!# # add histogram -#!# # -#!# hDef = HistogramDefinition(n,hDict) -#!# hDefs.add(hDef) -#!# print("Added",hDef.getParameter('canvasName')) return ( vDefs, hDefs ) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 8b55d0b..9df4d19 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -165,15 +165,11 @@ def cutLines(cuts,maxChar=40): def drawCutPave(cnv,ic,variable,cuts,effcuts=None): indBaseCuts = cuts.split("&&") indEffCuts = None if effcuts==None else effcuts.split("&&") - #print(indBaseCuts) - #print(indEffCuts) cnv.cd(ic+3) #hpave = 3*0.06+(len(indBaseCuts)+1)*0.04 #if indEffCuts!=None: # hpave += (len(indEffCuts)+2)*0.04 - #print(ROOT.gPad.UtoPixel(0.),ROOT.gPad.UtoPixel(1.)) - #print(ROOT.gPad.VtoPixel(0.),ROOT.gPad.VtoPixel(1.)) allLines = [ ] allLines.append(('hdr','Variable(s)')) allLines.append(('txt',variable)) @@ -192,7 +188,6 @@ def drawCutPave(cnv,ic,variable,cuts,effcuts=None): #pave = ROOT.TPaveText(0.05,max(0,1.0-hpave),0.95,1.0) hpave = ((hdrPixels+txtPixels+2)*len([ x for x in allLines if x[0]=='hdr' ]) + \ (txtPixels+2)*len([ x for x in allLines if x[0]=='txt' ])) / (ROOT.gPad.VtoPixel(0.)-ROOT.gPad.VtoPixel(1.)) - #print(hpave) if hpave>1.: scale = 1./hpave hpave = 1 @@ -261,20 +256,9 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): xmax = hDef.getParameter('xMax',mType) #print("Starting for ",hDef.name,hName,hTitle) if is1D and ( not isProfile ): - #print(variable+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]") - #histos[mType] = [ rdf.Histo1D((hName+"_1",hName+"_1",nbx,xmin,xmax), \ - # variable+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]"), \ - # None, None, None ] - #print(rdf.GetColumnNames()) - #print(hName,effCuts) - #rdf = rdf.Define("pabsVar","pabs[pabs>0.3]") - #th1m = ROOT.RDF.TH1DModel(hName+"_1",hName+"_1",nbx,xmin,xmax) - #print(type(th1m)) cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) rdf,varMask = varMaskCombs(rdf,variable,cuts) model = (hName+"_1",hName+"_1",nbx,xmin,xmax) - #print(varMask) - #print(rdf.GetDefinedColumnNames()) histos[mType] = [ rdf.Histo1D(model,varMask), None, None, None ] if effCuts!=None: cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts) @@ -324,18 +308,9 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): rdf,varMask3 = varMaskCombs(rdf,v3,cuts) model = (hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax) histos[mType] = [ rdf.Histo3D(model,varMask1,varMask2,varMask3), None, None, None ] - #histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ - # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ - # None, None, None ] - #histos[mType] = [ rdf.Histo3D((hName+"_1",hName+"_1",nbx,float(xmin),float(xmax),nby,float(ymin),float(ymax),nbz,float(zmin),float(zmax)), \ - # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2,v3), \ - # None, None, None ] assert effCuts==None #print("Ending for ",hDef.name,hName,hTitle) - #for mType in range(23,26): - # print(histos[mType][0].GetEntries(),histos[mType][1].GetEntries()) - #sys.exit() return rdf,histos @@ -345,14 +320,8 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): savedDir = ROOT.gDirectory ROOT.gROOT.cd() - #cnv = ROOT.TCanvas(hDef.getParameter('canvasName'),hDef.getParameter('canvasName'),1000,1000) - #result['cnv'] = cnv - #cnv.Divide(2,2) - - #print(hDef['canvasName'],'is',is1D) ic = 0 - #hEffVs = { } for mType in range(23,26): #print("Checking mType",mType,"for",hDef.name) ic += 1 @@ -369,10 +338,6 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): variable = hDef.getParameter('variable',mType) ## #cnv.cd(ic) - #ROOT.gPad.SetGridx(1) - #ROOT.gPad.SetGridy(1) - #if not is1D: - # ROOT.gPad.SetRightMargin(0.125) hName = hDef.getParameter('histogramName',mType) + str(mType) hTitle = hDef.getParameter('histogramTitle',mType) + " module type " +str(mType) nbx = hDef.getParameter('xNbins',mType) @@ -380,56 +345,23 @@ def fillHistoByDef(tree,hDef,extraCuts,histos): xmax = hDef.getParameter('xMax',mType) #print("Starting for ",hDef.name,hName,hTitle) if is1D and ( not isProfile ): - #histos[mType] = [ ROOT.TH1F(hName+"_1",hName+"_1",nbx,xmin,xmax), None, None, None ] - #tree.Project(hName+"_1",variable, \ - # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) if effCuts!=None: - #histos[mType][1] = ROOT.TH1F(hName+"_2",hName+"_2",nbx,xmin,xmax) - #tree.Project(hName+"_2",variable, \ - # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) histos[mType][3] = ROOT.TEfficiency(histos[mType][1].GetValue(),histos[mType][0].GetValue()) histos[mType][3].SetMarkerStyle(20) else: # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif isProfile: - #ymin = hDef.getParameter('yMin',mType) - #ymax = hDef.getParameter('yMax',mType) - ##histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), None, None, None ] - #histos[mType] = [ ROOT.TProfile(hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax), None, None, None ] - #tree.Project(hName+"_1",variable, \ - # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif is2D: - #nby = hDef.getParameter('yNbins',mType) - #ymin = hDef.getParameter('yMin',mType) - #ymax = hDef.getParameter('yMax',mType) - #histos[mType] = [ ROOT.TH2F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax), None, None, None ] - #tree.Project(hName+"_1",variable, \ - # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) if effCuts!=None: - #histos[mType][1] = ROOT.TH2F(hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax) - #tree.Project(hName+"_2",variable, \ - # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts)) - #histos[mType][1].Divide(histos[mType][0]) # always keep final histogram in 4th position histos[mType][3] = histos[mType][1].Divide(histos[mType][0].GetValue()) else: # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] elif is3D: - #nby = hDef.getParameter('yNbins',mType) - #ymin = hDef.getParameter('yMin',mType) - #ymax = hDef.getParameter('yMax',mType) - #nbz = hDef.getParameter('zNbins',mType) - #zmin = hDef.getParameter('zMin',mType) - #zmax = hDef.getParameter('zMax',mType) - #histos[mType] = [ ROOT.TH3F(hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax), \ - # None, None, None ] - #tree.Project(hName+"_1",variable, \ - # cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))) - #assert effCuts==None # always keep final histogram in 4th position histos[mType][3] = histos[mType][0] #print("Ending for ",hDef.name,hName,hTitle) @@ -592,13 +524,6 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): extraHDict['baseCuts'] = cuts if effCuts!=None: extraHDict['effCuts'] = effCuts - #xxx = HistogramDefinition("effV",extraHDict) - #print("xxx",xxx) - #print("xxx",xxx.parameters) - #allHDefs.add(HistogramDefinition("effV",extraHDict)) - #print(allHDefs.allDefinitions.keys()) - #print(allHDefs.allCanvases) - #print(allHDefs['hEffArg']) return HistogramDefinition(name,extraHDict) @@ -667,43 +592,6 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): for ih,h in enumerate(args.histogram): allHDefs.add(addHistogram(h,args.cuts,args.effCuts,name="userH"+str(ih+1))) -#!# varEffDict = { } -#!# # split into string defining the variable(s) and (1 or 2) axis definition(s) -#!# fields1 = args.varEff.split(";") -#!# assert len(fields1)<=3 -#!# varEffDict['variable'] = fields1[0] -#!# #varEffDict['canvasName'] = "cEffArg" -#!# #varEffDict['histogramName'] = "hEffArg" -#!# varEffDict['histogramTitle'] = "hEffArg" -#!# # x-axis -#!# fields2 = fields1[1].split(",") -#!# assert len(fields2)==3 -#!# varEffDict['xNbins'] = int(fields2[0]) -#!# varEffDict['xMin'] = float(fields2[1]) -#!# varEffDict['xMax'] = float(fields2[2]) -#!# # check for info on y axis (== presence of 2nd variable) -#!# if len(fields1)==3: -#!# assert ":" in varEffDict['variable'] -#!# fields3 = fields1[2].split(",") -#!# varEffDict['yNbins'] = int(fields3[0]) -#!# varEffDict['yMin'] = float(fields3[1]) -#!# varEffDict['yMax'] = float(fields3[2]) -#!# varEffDict['xTitle'] = varEffDict['variable'].split(":")[1] -#!# varEffDict['yTitle'] = varEffDict['variable'].split(":")[0] -#!# else: -#!# varEffDict['yMin'] = 0. -#!# varEffDict['yMax'] = 1.05 -#!# varEffDict['xTitle'] = varEffDict['variable'] -#!# varEffDict['yTitle'] = 'efficiency' -#!# varEffDict['baseCuts'] = args.cuts -#!# varEffDict['effCuts'] = cutString("hasRecHit>0","abs(localPos.x()-rhLocalPos.x())<"+str(args.dxMax)) -#!# #xxx = HistogramDefinition("effV",varEffDict) -#!# #print("xxx",xxx) -#!# #print("xxx",xxx.parameters) -#!# allHDefs.add(HistogramDefinition("effV",varEffDict)) -#!# #print(allHDefs.allDefinitions.keys()) -#!# #print(allHDefs.allCanvases) -#!# #print(allHDefs['hEffArg']) #extraCuts = "abs(particleType)==13" #extraCuts = "tof<12.5" @@ -759,7 +647,6 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): except: print("Exception for",cName,hName) raise -#sys.exit() allObjects = [ ] for cName in allHDefs.canvasNames(): @@ -768,9 +655,7 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) print(allHistos[cName][hName]) - #cHistos[hName] = fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts,allHistos[cName][hName]) fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts,allHistos[cName][hName]) - print(allHistos[cName][hName]) allObjects.append(drawHistoByDef(allHistos[cName][hName],allHDefs.byCanvas[cName][hName], \ logY=args.logY,logZ=args.logZ,same=same)) same = True @@ -789,32 +674,3 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): # yMin = min([ x.GetMinimum() for x in cHistos #sys.exit() -#!# allObjects = [ ] -#!# for hdef in allHDefs.allDefinitions.values(): -#!# # -#!# # draw histograms according to definition -#!# # -#!# histos = fillHistoByDef(simHitTree,hdef,extraCuts) -#!# allObjects.append(drawHistoByDef(histos,hdef)) -#!# # -#!# # perform fit of resolution histogram -#!# # -#!# if hdef.name in fitResiduals: -#!# objects = allObjects[-1] -#!# cnv = objects['cnv'] -#!# # fit and redraw each panel -#!# ic = 0 -#!# for mType in range(23,26): -#!# ic += 1 -#!# cnv.cd(ic) -#!# f = fitHistogram(mType,objects['histos'][mType][0]) - - -#if args.output!=None: -# for c in [ x['cnv'] for x in allObjects ]: -# basename = os.path.join(args.output,c.GetName()) -# if args.sampleName!=None: -# basename += "_" + args.sampleName -# print(basename) -# c.SaveAs(basename+".pdf") -# c.SaveAs(basename+".png") From a2bb11e1587da0004c93907471fe2b4673580f12 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 15 Jan 2026 13:32:20 +0100 Subject: [PATCH 28/77] hide Define for variable+mask within a wrapper around RDataFrame --- DrawHits/drawHitsConfiguration.py | 42 +++++++++++++++++++++ DrawHits/drawHitsRDF.py | 61 ++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 22 deletions(-) diff --git a/DrawHits/drawHitsConfiguration.py b/DrawHits/drawHitsConfiguration.py index 2cfc0ed..c8b8095 100644 --- a/DrawHits/drawHitsConfiguration.py +++ b/DrawHits/drawHitsConfiguration.py @@ -205,6 +205,48 @@ def __call__(self,rdf,varName,selection): #print("+++") return rdf,varMaskName +class RDFWrapper: + ''' Wrapper of RDataFrame with possibility to define variable+mask combinations + ''' + def __init__(self,rdf): + # + # variable+mask name indexed by variable+selection string + # + self.rdf = rdf + self.varMaskDefinitions = { } + + def __call__(self): + ''' Easy access to RDataFrame + ''' + return self.rdf + + def defineVarMask(self,varName,selection): + ''' Return the name of a variable+mask combination. Define if necessary. + Arguments: + rdf ........ RDataFrame to be used for definition + varName .... name of the variable + selection .. selection string to be used as mask + ''' + # + # use variable name and normalized selection string (remove spaces) + # + selNorm = selection.replace(" ","") + varMask = "(" + varName + ")["+selNorm+"]" + if varMask in self.varMaskDefinitions: + # combination exists (assume that it's also defined in the RDataFrame) + varMaskName = self.varMaskDefinitions[varMask] + assert varMaskName in self.rdf.GetDefinedColumnNames() + else: + # create name for combination and define it in the RDataFrame + n = len(self.varMaskDefinitions) + varMaskName = "varMask{:03d}".format(n) + self.varMaskDefinitions[varMask] = varMaskName + self.rdf = self.rdf.Define(varMaskName,varMask) + #print("+++ defined new var + mask combinations:",varMaskName,varMask) + #print(rdf.GetDefinedColumnNames()) + #print("+++") + return varMaskName + def loadConfiguration(configName,selectedNames=[],vetoedNames=[]): ''' Load variable and histogram definitions from a configuration file. The configuration file diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 9df4d19..bbc4dc6 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -227,7 +227,8 @@ def drawCutPave(cnv,ic,variable,cuts,effcuts=None): ROOT.gPad.Update() return pave -def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): +#def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): +def createHistoByDef(rdfWrapper,hDef,extraCuts): histos = { } for mType in range(23,26): @@ -257,24 +258,28 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): #print("Starting for ",hDef.name,hName,hTitle) if is1D and ( not isProfile ): cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) - rdf,varMask = varMaskCombs(rdf,variable,cuts) +#!# rdf,varMask = varMaskCombs(rdf,variable,cuts) + varMask = rdfWrapper.defineVarMask(variable,cuts) model = (hName+"_1",hName+"_1",nbx,xmin,xmax) - histos[mType] = [ rdf.Histo1D(model,varMask), None, None, None ] + histos[mType] = [ rdfWrapper().Histo1D(model,varMask), None, None, None ] if effCuts!=None: cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts) - rdf,varMask = varMaskCombs(rdf,variable,cuts) +#!# rdf,varMask = varMaskCombs(rdf,variable,cuts) + varMask = rdfWrapper.defineVarMask(variable,cuts) model = (hName+"_2",hName+"_2",nbx,xmin,xmax) - histos[mType][1] = rdf.Histo1D(model,varMask) + histos[mType][1] = rdfWrapper().Histo1D(model,varMask) #sys.exit() elif isProfile: ymin = hDef.getParameter('yMin',mType) ymax = hDef.getParameter('yMax',mType) v2,v1 = variable.split(":") cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) - rdf,varMask1 = varMaskCombs(rdf,v1,cuts) - rdf,varMask2 = varMaskCombs(rdf,v2,cuts) +#!# rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + varMask1 = rdfWrapper.defineVarMask(v1,cuts) +#!# rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + varMask2 = rdfWrapper.defineVarMask(v2,cuts) model = (hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax) - histos[mType] = [ rdf.Profile1D(model,varMask1,varMask2), None, None, None ] + histos[mType] = [ rdfWrapper().Profile1D(model,varMask1,varMask2), None, None, None ] #histos[mType] = [ rdf.Profile1D((hName+"_1",hName+"_1",nbx,xmin,xmax,ymin,ymax,'S'), \ # v1+"["+cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType))+"]",v2), \ # None, None, None ] @@ -284,16 +289,20 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): ymax = hDef.getParameter('yMax',mType) v2,v1 = variable.split(":") cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) - rdf,varMask1 = varMaskCombs(rdf,v1,cuts) - rdf,varMask2 = varMaskCombs(rdf,v2,cuts) +#!# rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + varMask1 = rdfWrapper.defineVarMask(v1,cuts) +#!# rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + varMask2 = rdfWrapper.defineVarMask(v2,cuts) model = (hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax) - histos[mType] = [ rdf.Histo2D(model,varMask1,varMask2), None, None, None ] + histos[mType] = [ rdfWrapper().Histo2D(model,varMask1,varMask2), None, None, None ] if effCuts!=None: cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType),effCuts) - rdf,varMask1 = varMaskCombs(rdf,v1,cuts) - rdf,varMask2 = varMaskCombs(rdf,v2,cuts) +#!# rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + varMask1 = rdfWrapper.defineVarMask(v1,cuts) +#!# rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + varMask2 = rdfWrapper.defineVarMask(v2,cuts) model = (hName+"_2",hName+"_2",nbx,xmin,xmax,nby,ymin,ymax) - histos[mType][1] = rdf.Histo2D(model,varMask1,varMask2) + histos[mType][1] = rdfWrapper().Histo2D(model,varMask1,varMask2) elif is3D: nby = hDef.getParameter('yNbins',mType) ymin = hDef.getParameter('yMin',mType) @@ -303,15 +312,18 @@ def createHistoByDef(rdf,hDef,extraCuts,varMaskCombs): zmax = hDef.getParameter('zMax',mType) v3,v2,v1 = variable.split(":") cuts = cutString(extraCuts,hDef.getParameter('baseCuts',mType),"moduleType=="+str(mType)) - rdf,varMask1 = varMaskCombs(rdf,v1,cuts) - rdf,varMask2 = varMaskCombs(rdf,v2,cuts) - rdf,varMask3 = varMaskCombs(rdf,v3,cuts) +#!# rdf,varMask1 = varMaskCombs(rdf,v1,cuts) + varMask1 = rdfWrapper.defineVarMask(v1,cuts) +#!# rdf,varMask2 = varMaskCombs(rdf,v2,cuts) + varMask2 = rdfWrapper.defineVarMask(v2,cuts) +#!# rdf,varMask3 = varMaskCombs(rdf,v3,cuts) + varMask3 = rdfWrapper.defineVarMask(v3,cuts) model = (hName+"_1",hName+"_1",nbx,xmin,xmax,nby,ymin,ymax,nbz,zmin,zmax) - histos[mType] = [ rdf.Histo3D(model,varMask1,varMask2,varMask3), None, None, None ] + histos[mType] = [ rdfWrapper().Histo3D(model,varMask1,varMask2,varMask3), None, None, None ] assert effCuts==None #print("Ending for ",hDef.name,hName,hTitle) - return rdf,histos + return histos @@ -633,7 +645,8 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): canvases = [ ] histos = { } paves = [ ] -varMaskCombs = VarMaskCombinations() +#varMaskCombs = VarMaskCombinations() +simHitRDFW = RDFWrapper(simHitRDF) allHistos = { } for cName in allHDefs.canvasNames(): @@ -642,11 +655,15 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): print("Processing histogram",hName,"in canvas",cName) print(" ",simHitRDF.GetDefinedColumnNames()) try: - simHitRDF,allHistos[cName][hName] = \ - createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) + allHistos[cName][hName] = \ + createHistoByDef(simHitRDFW,allHDefs.byCanvas[cName][hName],extraCuts) +# simHitRDF,allHistos[cName][hName] = \ +# createHistoByDef(simHitRDF,allHDefs.byCanvas[cName][hName],extraCuts,varMaskCombs) except: print("Exception for",cName,hName) raise +# keep reference to RDF with all definitions +simHitRDF = simHitRDFW() allObjects = [ ] for cName in allHDefs.canvasNames(): From a82c154e8b87431378b80905fbe53527a0a0c19f Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 15 Jan 2026 14:13:27 +0100 Subject: [PATCH 29/77] prepare also drawHitsRes config for RDF --- DrawHits/drawHitsRDF.py | 3 +- DrawHits/drawHitsResRDF.yaml | 150 +++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 DrawHits/drawHitsResRDF.yaml diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index bbc4dc6..5852301 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -653,7 +653,6 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): allHistos[cName] = {} for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) - print(" ",simHitRDF.GetDefinedColumnNames()) try: allHistos[cName][hName] = \ createHistoByDef(simHitRDFW,allHDefs.byCanvas[cName][hName],extraCuts) @@ -671,7 +670,7 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): cHistos = { } for hName in allHDefs.byCanvas[cName]: print("Processing histogram",hName,"in canvas",cName) - print(allHistos[cName][hName]) + #print(allHistos[cName][hName]) fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts,allHistos[cName][hName]) allObjects.append(drawHistoByDef(allHistos[cName][hName],allHDefs.byCanvas[cName][hName], \ logY=args.logY,logZ=args.logZ,same=same)) diff --git a/DrawHits/drawHitsResRDF.yaml b/DrawHits/drawHitsResRDF.yaml new file mode 100644 index 0000000..b403ed7 --- /dev/null +++ b/DrawHits/drawHitsResRDF.yaml @@ -0,0 +1,150 @@ +# +# definitions of new variables +# +variables: + pathX: 'path.fCoordinates.fX' + pathY: 'path.fCoordinates.fY' + pathZ: 'path.fCoordinates.fZ' + dxdz: 'pathX/pathZ' + alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' + localPosX: 'localPos.fCoordinates.fX' + localPosY: 'localPos.fCoordinates.fY' + rhLocalPosX: 'rhLocalPos.fCoordinates.fX' + rhLocalPosY: 'rhLocalPos.fCoordinates.fY' + rhLocalErrX: 'rhLocalErr.fCoordinates.fX' + rhLocalErrY: 'rhLocalErr.fCoordinates.fY' + globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' + globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' + globPt: 'pabs*sqrt(sqrt(globRho2/globR2))' + detNormalT: 'detNormal.fCoordinates.fX*detNormal.fCoordinates.fX+detNormal.fCoordinates.fY*detNormal.fCoordinates.fY' +# +# +# +histograms: + + pullX: + histogramTitle: 'pulls (x)' + variable: '(localPosX-rhLocalPosX)/rhLocalErrX' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'pull local x' + xNbins: 200 + xMax: 5 + xMin: -5 + fit: 'gaus' + logY: true + pullXW1: + histogramTitle: 'pulls (x)' + variable: '(localPosX-rhLocalPosX)/rhLocalErrX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: 'pull local x' + xNbins: 200 + xMax: 5 + xMin: -5 + fit: 'gaus' + logY: true + pullXW2: + histogramTitle: 'pulls (x)' + variable: '(localPosX-rhLocalPosX)/rhLocalErrX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: 'pull local x' + xNbins: 200 + xMax: 5 + xMin: -5 + fit: 'gaus' + logY: true +# +# +# + resX: + histogramTitle: 'residuals (x)' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + fit: 'gaus' + logY: true +# +# +# + resX1: + histogramTitle: 'residuals (x) - cluster size 1' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + fit: 'gaus' + logY: true +# +# +# + resX2: + histogramTitle: 'residuals (x) - cluster size 2' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [cm]' + xNbins: 800 + xMax: 0.040 + xMin: -0.040 + fit: 'gaus' + logY: true +# +# +# + resX3P: + histogramTitle: 'residuals (x) - cluster size >2' + variable: 'localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize>2' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + logY: true +# +# +# + res2DX1: + histogramTitle: 'track dx/dz vs. residuals (x) - cluster size 1' + variable: 'pathX/pathZ:localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [cm]' + xNbins: 300 + xMax: 0.075 + xMin: -0.075 + yNbins: 21 + yMin: -1.05 + yMax: 1.05 + logZ: true +# +# +# + res2DX2: + histogramTitle: 'track dz/dx vs. residuals (x) - cluster size 2' + variable: 'pathX/pathZ:localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [cm]' + xNbins: 800 + xMax: 0.040 + xMin: -0.040 + yNbins: 21 + yMin: -1.05 + yMax: 1.05 + logZ: true +# +# +# + resY: + histogramTitle: 'pulls (y)' + variable: '(localPosY-rhLocalPosY)/rhLocalErrY' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'pull local y' + xNbins: 200 + xMax: 5 + xMin: -5 + logY: true +# +# +# From 5d79e9423757ad2d386dd19cd0df084d737e7121 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 27 Jan 2026 13:48:11 +0100 Subject: [PATCH 30/77] adding histograms for rechit multiplicity --- DrawHits/drawHitsTmpRDF.yaml | 249 ++++++++++++++++++++++++++++++++++- 1 file changed, 243 insertions(+), 6 deletions(-) diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index b5c987c..e5adc69 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -1,3 +1,10 @@ +# +# sensor dimensions: +# +# 2S: 10 x 10 cm2; 2 x 1016 strips at 90 μm x 5 cm +# PS: 5 x 10 cm2; 2 x 960 strips at 100 μm x 2.5 cm +# PSp: 5 x 10 cm2; 32 x 960 pixel at 100 μm x 1.5 mm + # # definitions of new variables # @@ -15,6 +22,9 @@ variables: rhLocalErrY: 'rhLocalErr.fCoordinates.fY' localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' + localPosYMod500: 'floatMod(10*localPosY,50)/10.' + localPosYMod250: 'floatMod(10*localPosY,25)/10.' + localPosYMod15: 'floatMod(100*localPosY,15)/10' globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' globPt: 'pabs*sqrt(sqrt(globRho2/globR2))' @@ -173,21 +183,21 @@ histograms: yMax: 1.05 mType23: histogramTitle: 'Efficiency vs. y % 1.5 mm' - variable: 'floatMod(100*localPosY,15)/10.' + variable: 'localPosYMod15' xTitle: 'y modulo 1.5mm [mm]' xNbins: 400 xMax: 1.75 xMin: -0.25 mType24: histogramTitle: 'Efficiency vs. y % 2.5 cm' - variable: 'floatMod(10*localPosY,25)/10.' + variable: 'localPosYMod250' xTitle: 'y modulo 2.5cm [cm]' xNbins: 600 xMax: 2.75 xMin: -0.25 mType25: histogramTitle: 'Efficiency vs. y % 5 cm' - variable: 'floatMod(10*localPosY,50)/10.' + variable: 'localPosYMod500' xTitle: 'y modulo 5cm [cm]' xNbins: 550 xMax: 5.25 @@ -411,21 +421,21 @@ histograms: profile: true mType23: histogramTitle: 'Width vs. y % 1.5 mm' - variable: 'clusterSize:floatMod(100*localPosY,15)/10.' + variable: 'clusterSize:localPosYMod15' xTitle: 'y modulo 1.5mm [mm]' xNbins: 200 xMin: -0.25 xMax: 1.75 mType24: histogramTitle: 'Width vs. y % 2.5 cm' - variable: 'clusterSize:floatMod(10*localPosY,25)/10.' + variable: 'clusterSize:localPosYMod250' xTitle: 'y modulo 2.5cm [cm]' xNbins: 300 xMin: -0.25 xMax: 2.75 mType25: histogramTitle: 'Width vs. y % 5 cm' - variable: 'clusterSize:floatMod(10*localPosY,50)/10.' + variable: 'clusterSize:localPosYMod500' xTitle: 'y modulo 5cm [cm]' xNbins: 275 xMin: -0.25 @@ -687,3 +697,230 @@ histograms: xMin: -1.05 xMax: 1.05 + nrhVsModX: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + yTitle: 'nr of rechits' + yNbins: 10 + yMin: 0 + yMax: 10 + mType23: + histogramTitle: 'nr of rechits vs. x % 100 #mu m' + variable: 'rhNMatched:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'nr of rechits vs. x % 100 #mu m' + variable: 'rhNMatched:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'nr of rechits vs. x % 90 #mu m' + variable: 'rhNMatched:localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + +#!# nrhEffVsModX1: +#!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' +#!# effCuts: 'rhNMatched==1' +#!# yTitle: 'Efficieny (nrh==1)' +#!# yMin: 0 +#!# yMax: 1.05 +#!# mType23: +#!# histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' +#!# variable: 'localPosXMod100' +#!# xTitle: 'x modulo 100 #mu m [#mu m]' +#!# xNbins: 220 +#!# xMax: 105 +#!# xMin: -5 +#!# mType24: +#!# histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' +#!# variable: 'localPosXMod100' +#!# xTitle: 'x modulo 100 #mu m [#mu m]' +#!# xNbins: 220 +#!# xMax: 105 +#!# xMin: -5 +#!# mType25: +#!# histogramTitle: 'Efficiency (nrh=1) vs. x % 90 #mu m' +#!# variable: 'localPosXMod90' +#!# xTitle: 'x modulo 90 #mu m [#mu m]' +#!# xNbins: 200 +#!# xMax: 95 +#!# xMin: -5 + +#!# nrhEffVsModX2: +#!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' +#!# effCuts: 'rhNMatched==2' +#!# yTitle: 'Efficieny (nrh==2)' +#!# yMin: 0 +#!# yMax: 1.05 +#!# mType23: +#!# histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' +#!# variable: 'localPosXMod100' +#!# xTitle: 'x modulo 100 #mu m [#mu m]' +#!# xNbins: 220 +#!# xMax: 105 +#!# xMin: -5 +#!# mType24: +#!# histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' +#!# variable: 'localPosXMod100' +#!# xTitle: 'x modulo 100 #mu m [#mu m]' +#!# xNbins: 220 +#!# xMax: 105 +#!# xMin: -5 +#!# mType25: +#!# histogramTitle: 'Efficiency (nrh=2) vs. x % 90 #mu m' +#!# variable: 'localPosXMod90' +#!# xTitle: 'x modulo 90 #mu m [#mu m]' +#!# xNbins: 200 +#!# xMax: 95 +#!# xMin: -5 + +#!# nrhEffVsModX3p: +#!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' +#!# effCuts: 'rhNMatched>2' +#!# yTitle: 'Efficieny (nrh>2)' +#!# yMin: 0 +#!# yMax: 1.05 +#!# mType23: +#!# histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' +#!# variable: 'localPosXMod100' +#!# xTitle: 'x modulo 100 #mu m [#mu m]' +#!# xNbins: 220 +#!# xMax: 105 +#!# xMin: -5 +#!# mType24: +#!# histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' +#!# variable: 'localPosXMod100' +#!# xTitle: 'x modulo 100 #mu m [#mu m]' +#!# xNbins: 220 +#!# xMax: 105 +#!# xMin: -5 +#!# mType25: +#!# histogramTitle: 'Efficiency (nrh>2) vs. x % 90 #mu m' +#!# variable: 'localPosXMod90' +#!# xTitle: 'x modulo 90 #mu m [#mu m]' +#!# xNbins: 200 +#!# xMax: 95 +#!# xMin: -5 + + nrhVsModY: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + yTitle: 'nr of rechits' + yNbins: 10 + yMin: 0 + yMax: 10 + variable: 'rhNMatched:localPosY' + histogramTitle: 'nr of rechits vs. local y' + mType23: + histogramTitle: 'nr of rechits vs. y % 1.5 mm' + variable: 'rhNMatched:localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'nr of rechits vs. y % 2.5 cm' + variable: 'rhNMatched:localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'nr of rechits vs. y % 5 cm' + variable: 'rhNMatched:localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + + nrhEffVsModY1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==1' + yTitle: 'Efficieny (nrh==1)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=1) vs. y % 1.5 mm' + variable: 'localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency (nrh=1) vs. y % 2.5 cm' + variable: 'localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency (nrh=1) vs. y % 5 cm' + variable: 'localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + + nrhEffVsModY2: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==2' + yTitle: 'Efficiency (nrh==2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=2) vs. y % 1.5 mm' + variable: 'localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency (nrh=2) vs. y % 2.5 cm' + variable: 'localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency (nrh=2) vs. y % 5 cm' + variable: 'localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + + nrhEffVsModY3p: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched>2' + yTitle: 'Efficiency (nrh>2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh>2) vs. y % 1.5 mm' + variable: 'localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency (nrh>2) vs. y % 2.5 cm' + variable: 'localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency (nrh>2) vs. y % 5 cm' + variable: 'localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + + From 61652bdcb1fec2d83c211f3774ade424a616b49a Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 27 Jan 2026 13:48:40 +0100 Subject: [PATCH 31/77] adding histograms for rechit multiplicity --- DrawHits/drawHitsTmpRDF.yaml | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index e5adc69..acf8738 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -725,33 +725,33 @@ histograms: xMax: 95 xMin: -5 -#!# nrhEffVsModX1: -#!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' -#!# effCuts: 'rhNMatched==1' -#!# yTitle: 'Efficieny (nrh==1)' -#!# yMin: 0 -#!# yMax: 1.05 -#!# mType23: -#!# histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' -#!# variable: 'localPosXMod100' -#!# xTitle: 'x modulo 100 #mu m [#mu m]' -#!# xNbins: 220 -#!# xMax: 105 -#!# xMin: -5 -#!# mType24: -#!# histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' -#!# variable: 'localPosXMod100' -#!# xTitle: 'x modulo 100 #mu m [#mu m]' -#!# xNbins: 220 -#!# xMax: 105 -#!# xMin: -5 -#!# mType25: -#!# histogramTitle: 'Efficiency (nrh=1) vs. x % 90 #mu m' -#!# variable: 'localPosXMod90' -#!# xTitle: 'x modulo 90 #mu m [#mu m]' -#!# xNbins: 200 -#!# xMax: 95 -#!# xMin: -5 + nrhEffVsModX1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==1' + yTitle: 'Efficieny (nrh==1)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency (nrh=1) vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 #!# nrhEffVsModX2: #!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' From 6d9af786760b1817c1f0c04f3159b8b1887d1ed5 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 29 Jan 2026 13:13:31 +0100 Subject: [PATCH 32/77] add histograms of # RecHits / SimHit --- DrawHits/drawHitsTmpRDF.yaml | 139 +++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 55 deletions(-) diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index acf8738..22f9909 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -753,61 +753,61 @@ histograms: xMax: 95 xMin: -5 -#!# nrhEffVsModX2: -#!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' -#!# effCuts: 'rhNMatched==2' -#!# yTitle: 'Efficieny (nrh==2)' -#!# yMin: 0 -#!# yMax: 1.05 -#!# mType23: -#!# histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' -#!# variable: 'localPosXMod100' -#!# xTitle: 'x modulo 100 #mu m [#mu m]' -#!# xNbins: 220 -#!# xMax: 105 -#!# xMin: -5 -#!# mType24: -#!# histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' -#!# variable: 'localPosXMod100' -#!# xTitle: 'x modulo 100 #mu m [#mu m]' -#!# xNbins: 220 -#!# xMax: 105 -#!# xMin: -5 -#!# mType25: -#!# histogramTitle: 'Efficiency (nrh=2) vs. x % 90 #mu m' -#!# variable: 'localPosXMod90' -#!# xTitle: 'x modulo 90 #mu m [#mu m]' -#!# xNbins: 200 -#!# xMax: 95 -#!# xMin: -5 + nrhEffVsModX2: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==2' + yTitle: 'Efficieny (nrh==2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency (nrh=2) vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 -#!# nrhEffVsModX3p: -#!# baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' -#!# effCuts: 'rhNMatched>2' -#!# yTitle: 'Efficieny (nrh>2)' -#!# yMin: 0 -#!# yMax: 1.05 -#!# mType23: -#!# histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' -#!# variable: 'localPosXMod100' -#!# xTitle: 'x modulo 100 #mu m [#mu m]' -#!# xNbins: 220 -#!# xMax: 105 -#!# xMin: -5 -#!# mType24: -#!# histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' -#!# variable: 'localPosXMod100' -#!# xTitle: 'x modulo 100 #mu m [#mu m]' -#!# xNbins: 220 -#!# xMax: 105 -#!# xMin: -5 -#!# mType25: -#!# histogramTitle: 'Efficiency (nrh>2) vs. x % 90 #mu m' -#!# variable: 'localPosXMod90' -#!# xTitle: 'x modulo 90 #mu m [#mu m]' -#!# xNbins: 200 -#!# xMax: 95 -#!# xMin: -5 + nrhEffVsModX3p: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched>2' + yTitle: 'Efficieny (nrh>2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency (nrh>2) vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 nrhVsModY: baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' @@ -923,4 +923,33 @@ histograms: xMax: 5.25 xMin: -0.25 - + nrRecHitsAll: + baseCuts: 'tof<12.' + histogramTitle: 'Number of RecHits (all)' + variable: 'rhNMatched' + xTitle: 'number of matched RecHits' + xNbins: 100 + xMax: 99.5 + xMin: -0.5 + logY: true + + nrRecHitsPabs: + baseCuts: 'tof<12.&&pabs>3.' + histogramTitle: 'Number of RecHits (all)' + variable: 'rhNMatched' + xTitle: 'number of matched RecHits' + xNbins: 100 + xMax: 99.5 + xMin: -0.5 + logY: true + + nrRecHitsPt: + baseCuts: 'tof<12.&&pabs>0.3&&globPt>0.5' + histogramTitle: 'Number of RecHits (all)' + variable: 'rhNMatched' + xTitle: 'number of matched RecHits' + xNbins: 100 + xMax: 99.5 + xMin: -0.5 + logY: true + From b7604180dfdd95fe147435b4640f14744d2b79e5 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 29 Jan 2026 13:15:35 +0100 Subject: [PATCH 33/77] add #simtracks to RecHitInfo --- HitAnalyzer/interface/RecHitInfo.h | 1 + HitAnalyzer/src/RecHitInfo.cc | 7 +++++-- HitAnalyzer/src/SimHitInfo.cc | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/HitAnalyzer/interface/RecHitInfo.h b/HitAnalyzer/interface/RecHitInfo.h index 1c1e561..8c95146 100644 --- a/HitAnalyzer/interface/RecHitInfo.h +++ b/HitAnalyzer/interface/RecHitInfo.h @@ -59,6 +59,7 @@ class RecHitInfo { std::vector moduleType; std::vector detNormal; std::vector trackId; + std::vector nSimTracks; }; RecHitData recHitData; diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index d386dfb..3fa699b 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -41,7 +41,8 @@ void RecHitInfo::setBranches(TTree& tree) { tree.Branch("layer", &recHitData.layer); tree.Branch("moduleType", &recHitData.moduleType); tree.Branch("detNormal", &recHitData.detNormal); - tree.Branch("trackId", &recHitData.trackId); + tree.Branch("trackId", &recHitData.trackId); + tree.Branch("nSimTracks", &recHitData.nSimTracks); }; std::vector RecHitInfo::getSimTrackId( @@ -255,13 +256,14 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in recHitData.Hit_cluster_closestSimHit_local_z.push_back(simhit->localPosition().z()); fillSimHitInfo(*simhit); } + recHitData.nSimTracks.push_back(clusterSimTrackIds.size()); recHitData.Hit_det_rawid.push_back(rawid); recHitData.Hit_cluster_firstStrip.push_back(clustIt->firstStrip()); recHitData.Hit_cluster_firstRow.push_back(clustIt->firstRow()); recHitData.Hit_cluster_column.push_back(clustIt->column()); recHitData.Hit_cluster_edge.push_back(clustIt->edge()); recHitData.Hit_cluster_threshold.push_back(clustIt->threshold()); - + }; void RecHitInfo::clear() { @@ -301,4 +303,5 @@ void RecHitInfo::clear() { recHitData.moduleType.clear(); recHitData.detNormal.clear(); recHitData.trackId.clear(); + recHitData.nSimTracks.clear(); }; diff --git a/HitAnalyzer/src/SimHitInfo.cc b/HitAnalyzer/src/SimHitInfo.cc index 99dfa18..9eae439 100644 --- a/HitAnalyzer/src/SimHitInfo.cc +++ b/HitAnalyzer/src/SimHitInfo.cc @@ -258,6 +258,24 @@ void SimHitInfo::fillSimHitInfo(const PSimHit& simHit) { // find all rechits with contributions from the SimTrack related to simHit // RecHitDistancePairs matchedRecHits = matchRecHitOnDet(&simHit,detId,ivrh->second); + // //// + // if ( matchedRecHits.size()>50 ) { + // std::cout << "SimHit with " << matchedRecHits.size() << " matched hits" << std::endl; + // std::cout << " " << "at " << &simHit << " detid " << simHit.detUnitId() << " loc pos " + // << simHit.localPosition().x() << " / " << simHit.localPosition().y() << std::endl; + // std::cout << " " << "entry " << simHit.entryPoint().x() << " / " << simHit.entryPoint().y() + // << " ; exit " << simHit.exitPoint().x() << " / " << simHit.exitPoint().y() << std::endl; + // std::cout << " " << "trackId " << simHit.trackId() << " ; pType " << simHit.particleType() + // << " ; pabs " << simHit.pabs() << std::endl; + // for ( SimHitInfo::RecHitDistancePairs::const_iterator irrr=matchedRecHits.begin(); + // irrr!=matchedRecHits.end(); ++irrr ) { + // std::cout << " RecHit on detid " << irrr->first->geographicalId() << " loc pos " + // << irrr->first->localPosition().x() << " / " << irrr->first->localPosition().y() << std::endl; + // const Phase2TrackerCluster1D& cluster = *(irrr->first->cluster()); + // std::cout << " first row / column " << cluster.firstRow() << " / " << cluster.column() << std::endl; + // } + // } + // //// // store best match (if any) nMatched = matchedRecHits.size(); if ( nMatched>0 ) rechit = matchedRecHits[0].first; From da11501c255ef2aa7992433ba098dce3b8230dc6 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 29 Jan 2026 17:42:44 +0100 Subject: [PATCH 34/77] small bug fix / optimisations in SimHit / RecHit match --- HitAnalyzer/src/RecHitInfo.cc | 21 ++++++--------------- HitAnalyzer/src/SimHitInfo.cc | 12 ++---------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index 3fa699b..9816d69 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -125,7 +125,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in const Phase2TrackerCluster1D* clustIt = &*recHit.cluster(); // Get all the simTracks that form the cluster - std::vector clusterSimTrackIds; + std::set clusterSimTrackIds; for (unsigned int i(0); i < clustIt->size(); ++i) { unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); @@ -135,18 +135,9 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in if (istfind != simTracks.end()) simTrackIds.push_back(istId); } - for (unsigned int i = 0; i < simTrackIds.size(); ++i) { - bool add = true; - for (unsigned int j = 0; j < clusterSimTrackIds.size(); ++j) { - // only save simtrackids that are not present yet - if (simTrackIds.at(i) == clusterSimTrackIds.at(j)) - add = false; - } - if (add) - clusterSimTrackIds.push_back(simTrackIds.at(i)); - } + clusterSimTrackIds.insert(simTrackIds.begin(),simTrackIds.end()); } - + // find the closest simhit // this is needed because otherwise you get cases with simhits and clusters being swapped // when there are more than 1 cluster with common simtrackids @@ -159,9 +150,9 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in ++simhitIt) { // check SimHit detId is the same with the RecHit if (rawid == simhitIt->detUnitId()) { - auto it = std::lower_bound(clusterSimTrackIds.begin(), clusterSimTrackIds.end(), simhitIt->trackId()); - // check SimHit track id is included in the cluster - if (it != clusterSimTrackIds.end() && *it == simhitIt->trackId()) { + // auto it = std::lower_bound(clusterSimTrackIds.begin(), clusterSimTrackIds.end(), simhitIt->trackId()); + // // check SimHit track id is included in the cluster + if ( clusterSimTrackIds.find(simhitIt->trackId()) != clusterSimTrackIds.end() ) { trackSimHits.push_back(&*simhitIt); if (!simhit || fabs(simhitIt->localPosition().x() - localPosClu.x()) < minx) { minx = fabs(simhitIt->localPosition().x() - localPosClu.x()); diff --git a/HitAnalyzer/src/SimHitInfo.cc b/HitAnalyzer/src/SimHitInfo.cc index 9eae439..6a24cbd 100644 --- a/HitAnalyzer/src/SimHitInfo.cc +++ b/HitAnalyzer/src/SimHitInfo.cc @@ -148,16 +148,8 @@ SimHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, // find SimTracks contributing to the channel unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); std::vector simTrackIds = getSimTrackId(detId,channel); - // std::cout << "SimHitInfo " << simTrackIds.size() << " simTracks" << std::endl; - for ( std::vector::const_iterator ist=simTrackIds.begin(); ist!=simTrackIds.end(); ++ist ) { - // std::cout << "SimHitInfo track id " << *ist << " (simhit track id " << (*simHit).trackId() << " ) " - // << std::endl; - // compare to track id of the SimHit - if ( (*ist)==(*simHit).trackId() ) { - matched = true; - break; - } - } + // // std::cout << "SimHitInfo " << simTrackIds.size() << " simTracks" << std::endl; + matched = std::find(simTrackIds.begin(),simTrackIds.end(),(*simHit).trackId())!=simTrackIds.end(); // if match was found: consider RecHit // std::cout << "SimHitInfo matched : " << matched << std::endl; if ( matched ) break; From b3951fa3dbc86f07458780ba91e20ebe21d74593 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 9 Feb 2026 10:44:15 +0100 Subject: [PATCH 35/77] some debug code for RecHits --- HitAnalyzer/src/RecHitInfo.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index 9816d69..d167499 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -137,7 +137,21 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in } clusterSimTrackIds.insert(simTrackIds.begin(),simTrackIds.end()); } - + // debug + if ( clusterSimTrackIds.size()==0 ) { + std::cout << "** RecHit without SimTrackIds on detId " << rawid << " layer " << layer + << " module type " << (unsigned int)tkGeom->getDetectorType(detId) << std::endl; + for (unsigned int i(0); i < clustIt->size(); ++i) { + unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); + std::cout << " channel " << clustIt->firstRow()+i << " " << clustIt->column() << std::endl; + std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); + std::cout << " simTrackIds"; + for ( auto istid=simTrackIds_unselected.begin(); + istid!=simTrackIds_unselected.end(); ++istid ) std::cout << " " << *istid; + std::cout << std::endl; + } + } + // debug // find the closest simhit // this is needed because otherwise you get cases with simhits and clusters being swapped // when there are more than 1 cluster with common simtrackids From 75f2e111adef45670bed8425312f07e4510052e4 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 9 Feb 2026 10:44:28 +0100 Subject: [PATCH 36/77] small changes in input file list in cfgs --- HitAnalyzer/test/rechittreewa_mu10_cfg.py | 11 ++++++++--- HitAnalyzer/test/rechittreewa_tt_cfg.py | 14 +++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/HitAnalyzer/test/rechittreewa_mu10_cfg.py b/HitAnalyzer/test/rechittreewa_mu10_cfg.py index 994ce7c..025c195 100644 --- a/HitAnalyzer/test/rechittreewa_mu10_cfg.py +++ b/HitAnalyzer/test/rechittreewa_mu10_cfg.py @@ -23,13 +23,18 @@ # Input file process.source = cms.Source('PoolSource', - #fileNames = cms.untracked.vstring('file:/afs/cern.ch/work/l/lian/public/Phase2Tracker/CMSSW_15_0_0_pre3/src/29617.0_SingleMuPt1Extended+Run4D110/step3.root') - fileNames = cms.untracked.vstring('file:/eos/user/a/adamwo/CMS/Phase2DPG/Data/0b0d313e-56e1-4e64-aa58-8a2e61767bf5.root') + fileNames = cms.untracked.vstring( \ + '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/0b0d313e-56e1-4e64-aa58-8a2e61767bf5.root', \ + '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/66c7ce91-878a-449b-b0fb-1cb8d3084116.root', \ + '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/6cd776e0-dd34-48c4-81cc-844435564ea5.root', \ + '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/94a5b755-f778-4861-a83d-94eb46c18acb.root', \ + '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/a146954f-f6be-46bc-95e8-dd1016306930.root', \ + '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/f459a343-5615-46f5-9ebc-f07e87c3db8e.root') ) # Output process.TFileService = cms.Service('TFileService', - fileName = cms.string('file:rechits_tree.root') + fileName = cms.string('file:rechits_tree_mu10.root') ) process.load('RecoLocalTracker.SiPhase2Clusterizer.phase2TrackerClusterizer_cfi') diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index 245fcfb..21180b9 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -27,14 +27,14 @@ #fileNames = cms.untracked.vstring('file:/afs/cern.ch/work/l/lian/public/Phase2Tracker/CMSSW_15_0_0_pre3/src/29617.0_SingleMuPt1Extended+Run4D110/step3.root') #fileNames = cms.untracked.vstring('file:/eos/user/a/adamwo/CMS/Phase2DPG/Data/0b0d313e-56e1-4e64-aa58-8a2e61767bf5.root') - fileNames = cms.untracked.vstring( - '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ - '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root') #fileNames = cms.untracked.vstring( # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/3db44076-4bb3-415b-b3a9-feb742460636.root', \ + # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root') + fileNames = cms.untracked.vstring( + '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ + '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ + '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ + '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/3db44076-4bb3-415b-b3a9-feb742460636.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/41d76683-9927-42e5-8c22-dfa056c56294.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/4bfe3713-82f0-43ac-8bd6-b16afd9d93e5.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/4c1b3277-7e2b-48c1-83b2-36ca12ea1a81.root', \ @@ -51,7 +51,7 @@ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/fb22dfc2-87a5-40d5-b8c3-feb1e6df4047.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/fb6db36e-f813-4f25-92ea-afd7ed1ac961.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/fc0a3df9-3f08-4355-9a91-12c1b3bd74ef.root' - #) + ) ) # Output From 975ea71ff02fcce84306e1371ff836aef4b16290 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 9 Feb 2026 15:58:12 +0100 Subject: [PATCH 37/77] more flexible access to SimHit collections --- HitAnalyzer/interface/RecHitInfo.h | 3 +- HitAnalyzer/interface/SimHitInfo.h | 4 +-- HitAnalyzer/plugins/RecHitTreeWA.cc | 23 ++++++++++----- HitAnalyzer/src/RecHitInfo.cc | 39 +++++++++++++------------ HitAnalyzer/src/SimHitInfo.cc | 13 +++++---- HitAnalyzer/test/rechittreewa_tt_cfg.py | 4 +-- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/HitAnalyzer/interface/RecHitInfo.h b/HitAnalyzer/interface/RecHitInfo.h index 8c95146..4ce1a91 100644 --- a/HitAnalyzer/interface/RecHitInfo.h +++ b/HitAnalyzer/interface/RecHitInfo.h @@ -81,7 +81,8 @@ class RecHitInfo { void fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned int rawid, const GeomDetUnit* geomDetUnit, edm::Handle >* pixelSimLinks, - std::map& simTracks, edm::Handle* simHitsRaw, + std::map& simTracks, + const std::vector& simHitsRaw, bool debugHitMatch); void clear(); diff --git a/HitAnalyzer/interface/SimHitInfo.h b/HitAnalyzer/interface/SimHitInfo.h index 18aa7e1..83d8f1d 100644 --- a/HitAnalyzer/interface/SimHitInfo.h +++ b/HitAnalyzer/interface/SimHitInfo.h @@ -84,7 +84,7 @@ class SimHitInfo { std::vector getSimTrackId(const DetId&, unsigned int); - void fillSimHitsPerDet(edm::Handle *simHitsRaw); + void fillSimHitsPerDet(const std::vector& simHitsRaw); void fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits); @@ -100,7 +100,7 @@ class SimHitInfo { void setupEvent(const TrackerTopology* topo, const TrackerGeometry* geom, const edm::DetSetVector* links, - edm::Handle *simHitsRaw, + const std::vector& simHitsRaw, const Phase2TrackerRecHit1DCollectionNew& rechits, const TrackIdSimTrackMap* simTrackMap) { tTopo_ = topo; diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index 5794b93..05834ea 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -135,9 +135,15 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event event.getByToken(tokenLinks_, pixelSimLinks); // Get the SimHits - edm::Handle simHitsRaw[2]; - event.getByToken(tokenSimHitsB_, simHitsRaw[0]); - event.getByToken(tokenSimHitsE_, simHitsRaw[1]); + edm::Handle simHitHandle; + // edm::Handle simHitsRaw[2]; + // event.getByToken(tokenSimHitsB_, simHitsRaw[0]); + // event.getByToken(tokenSimHitsE_, simHitsRaw[1]); + std::vector simHitsRaw; + event.getByToken(tokenSimHitsB_, simHitHandle); + simHitsRaw.push_back(simHitHandle.product()); + event.getByToken(tokenSimHitsE_, simHitHandle); + simHitsRaw.push_back(simHitHandle.product()); // Get the SimTracks edm::Handle simTracksRaw; @@ -158,9 +164,12 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event simTrackTree->Fill(); simHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),simHitsRaw,*rechits.product(),&simTracks); - for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits - for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); - simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { + // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits + // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); + // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { + // loop over both barrel and endcap hits + for (auto simhitsId=simHitsRaw.begin(); simhitsId!=simHitsRaw.end(); ++simhitsId ) { + for (auto simhitIt=(**simhitsId).begin(); simhitIt!=(**simhitsId).end(); ++simhitIt) { // Get the detector unit's id DetId detId(simhitIt->detUnitId()); unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides @@ -204,7 +213,7 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event // Loop over the rechits in the detector unit for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); - rechitIt != DSViter->end(); ++rechitIt) { + rechitIt != DSViter->end(); ++rechitIt) { recHitInfo_.fillRecHitInfo(*rechitIt,rawid,geomDetUnit,&pixelSimLinks,simTracks,simHitsRaw,debugHitMatch_); } } diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index d167499..dc61d4b 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -110,7 +110,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in const GeomDetUnit* geomDetUnit, edm::Handle >* pixelSimLinks, std::map& simTracks, - edm::Handle* simHitsRaw, + const std::vector& simHitsRaw, bool debugHitMatch) { // get DetUnit DetId detId(rawid); @@ -138,19 +138,19 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in clusterSimTrackIds.insert(simTrackIds.begin(),simTrackIds.end()); } // debug - if ( clusterSimTrackIds.size()==0 ) { - std::cout << "** RecHit without SimTrackIds on detId " << rawid << " layer " << layer - << " module type " << (unsigned int)tkGeom->getDetectorType(detId) << std::endl; - for (unsigned int i(0); i < clustIt->size(); ++i) { - unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); - std::cout << " channel " << clustIt->firstRow()+i << " " << clustIt->column() << std::endl; - std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); - std::cout << " simTrackIds"; - for ( auto istid=simTrackIds_unselected.begin(); - istid!=simTrackIds_unselected.end(); ++istid ) std::cout << " " << *istid; - std::cout << std::endl; - } - } + // if ( clusterSimTrackIds.size()==0 ) { + // std::cout << "** RecHit without SimTrackIds on detId " << rawid << " layer " << layer + // << " module type " << (unsigned int)tkGeom->getDetectorType(detId) << std::endl; + // for (unsigned int i(0); i < clustIt->size(); ++i) { + // unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); + // std::cout << " channel " << clustIt->firstRow()+i << " " << clustIt->column() << std::endl; + // std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); + // std::cout << " simTrackIds"; + // for ( auto istid=simTrackIds_unselected.begin(); + // istid!=simTrackIds_unselected.end(); ++istid ) std::cout << " " << *istid; + // std::cout << std::endl; + // } + // } // debug // find the closest simhit // this is needed because otherwise you get cases with simhits and clusters being swapped @@ -158,10 +158,13 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in const PSimHit* simhit = 0; // bad naming to avoid changing code below. This is the closest simhit in x float minx = 10000; std::vector trackSimHits; - for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits - for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); - simhitIt != simHitsRaw[simhitidx]->end(); - ++simhitIt) { + // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits + // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); + // simhitIt != simHitsRaw[simhitidx]->end(); + // ++simhitIt) { + + for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { + for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { // check SimHit detId is the same with the RecHit if (rawid == simhitIt->detUnitId()) { // auto it = std::lower_bound(clusterSimTrackIds.begin(), clusterSimTrackIds.end(), simhitIt->trackId()); diff --git a/HitAnalyzer/src/SimHitInfo.cc b/HitAnalyzer/src/SimHitInfo.cc index 6a24cbd..d670c74 100644 --- a/HitAnalyzer/src/SimHitInfo.cc +++ b/HitAnalyzer/src/SimHitInfo.cc @@ -53,15 +53,18 @@ std::vector SimHitInfo::getSimTrackId(const DetId& detId, unsigned return retvec; }; -void SimHitInfo::fillSimHitsPerDet(edm::Handle *simHitsRaw) { +void SimHitInfo::fillSimHitsPerDet(const std::vector& simHitsRaw) { // // fill map of SimHits / detId // simHitsPerDet_.clear(); - for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits - // std::cout << simhitidx << " " << simHitsRaw[simhitidx]->size() << std::endl; - for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); - simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { + // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits + // // std::cout << simhitidx << " " << simHitsRaw[simhitidx]->size() << std::endl; + // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); + // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { + // loop over both barrel and endcap hits + for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { + for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { const PSimHit* simhit(&*simhitIt); unsigned int rawid(simhit->detUnitId()); DetSimHitsMap::iterator idet(simHitsPerDet_.find(rawid)); diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index 21180b9..7020b57 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -33,8 +33,8 @@ fileNames = cms.untracked.vstring( '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ - '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ - '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/3db44076-4bb3-415b-b3a9-feb742460636.root', \ + # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ + # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/3db44076-4bb3-415b-b3a9-feb742460636.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/41d76683-9927-42e5-8c22-dfa056c56294.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/4bfe3713-82f0-43ac-8bd6-b16afd9d93e5.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/4c1b3277-7e2b-48c1-83b2-36ca12ea1a81.root', \ From aa38e7de0f95eeb7f943fc17bd76399ddeeeb440 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 11 Feb 2026 10:35:54 +0100 Subject: [PATCH 38/77] create common helper classes for SimHitInfo and RecHitInfo --- HitAnalyzer/interface/CommonHitInfo.h | 82 +++++++++++++ HitAnalyzer/plugins/RecHitTreeWA.cc | 62 ++++++++-- HitAnalyzer/src/CommonHitInfo.cc | 149 ++++++++++++++++++++++++ HitAnalyzer/src/RecHitInfo.cc | 10 ++ HitAnalyzer/test/rechittreewa_tt_cfg.py | 21 +++- 5 files changed, 309 insertions(+), 15 deletions(-) create mode 100644 HitAnalyzer/interface/CommonHitInfo.h create mode 100644 HitAnalyzer/src/CommonHitInfo.cc diff --git a/HitAnalyzer/interface/CommonHitInfo.h b/HitAnalyzer/interface/CommonHitInfo.h new file mode 100644 index 0000000..6f49042 --- /dev/null +++ b/HitAnalyzer/interface/CommonHitInfo.h @@ -0,0 +1,82 @@ +#ifndef HITANALYZER_SIMHITINFO_H +#define HITANALYZER_SIMHITINFO_H + +#include "DataFormats/TrackerCommon/interface/TrackerTopology.h" + +#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h" +#include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h" +#include "SimDataFormats/TrackerDigiSimLink/interface/PixelDigiSimLink.h" +#include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h" +#include "SimDataFormats/Track/interface/SimTrack.h" + +#include "DataFormats/Math/interface/Point3D.h" +#include "DataFormats/Math/interface/Vector3D.h" +#include + +#include "TTree.h" + +/// spatial vector with cartesian internal representation +typedef ROOT::Math::DisplacementVector2D > XYVectorF; + +class CommonHitInfo { + + typedef std::map< unsigned int, std::vector > DetSimHitsMap; + typedef std::pair< unsigned int, std::vector > DetSimHitsPair; + typedef std::map< unsigned int, std::vector > DetRecHitsMap; + typedef std::pair< unsigned int, std::vector > DetRecHitsPair; + + typedef std::pair RecHitDistancePair; + typedef std::vector RecHitDistancePairs; + + typedef std::map TrackIdSimTrackMap; + + public: + + CommonHitInfo() { + tTopo_ = 0; + tkGeom_ = 0; + simTracksById_ = 0; + }; + + ~CommonHitInfo() {} + + std::vector getSimTrackId(const DetId&, unsigned int); + + void fillSimHitsPerDet(const std::vector& simHitsRaw); + + void fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits); + + RecHitDistancePairs matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, + const std::vector& detRecHits); + + + void setupEvent(const TrackerTopology* topo, const TrackerGeometry* geom, + const edm::DetSetVector* links, + const std::vector& simHitsRaw, + const Phase2TrackerRecHit1DCollectionNew& rechits, + const TrackIdSimTrackMap* simTrackMap) { + tTopo_ = topo; + tkGeom_ = geom; + pixelSimLinks = links; + simTracksById_ = simTrackMap; + // fill SimHit map + // + fillSimHitsPerDet(simHitsRaw); + // + // fill RecHit map (uses SimHit map!) + // + fillRecHitsPerDet(rechits); + } + + private: + const TrackerTopology* tTopo_; + const TrackerGeometry* tkGeom_; + const edm::DetSetVector* pixelSimLinks; + + DetSimHitsMap simHitsPerDet_; + DetRecHitsMap recHitsPerDet_; + + const TrackIdSimTrackMap* simTracksById_; +}; + +#endif diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index 05834ea..f77128c 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -66,6 +66,9 @@ class RecHitTreeWA : public edm::one::EDAnalyzer { const edm::EDGetTokenT tokenSimHitsE_; const edm::EDGetTokenT tokenSimTracks_; + std::vector> shInfoSimHitTokens_; + std::vector> rhInfoSimHitTokens_; + const double simtrackminpt_; SimHitInfo simHitInfo_; @@ -105,6 +108,26 @@ RecHitTreeWA::RecHitTreeWA(const edm::ParameterSet& cfg) simtrackminpt_(cfg.getParameter("SimTrackMinPt")), debugHitMatch_(cfg.getParameter("debugHitMatch")) { + // + // SimHit collections for the SimHitInfo part + // + const edm::ParameterSet shInfoPSet(cfg.getParameter("simHitInfo")); + const std::vector + shInfoSimHitTags(shInfoPSet.getParameter>("simHits")); + for ( auto vpsetIt=shInfoSimHitTags.begin(); vpsetIt!=shInfoSimHitTags.end(); ++vpsetIt ) { + std::cout << "Getting shInfoSimHitToken" << std::endl; + shInfoSimHitTokens_.push_back(consumes(*vpsetIt)); + } + // + // RecHit collections for the RecHitInfo part + // + const edm::ParameterSet rhInfoPSet(cfg.getParameter("recHitInfo")); + const std::vector + rhInfoSimHitTags(rhInfoPSet.getParameter>("simHits")); + for ( auto vpsetIt=rhInfoSimHitTags.begin(); vpsetIt!=rhInfoSimHitTags.end(); ++vpsetIt ) { + std::cout << "Getting rhInfoSimHitToken" << std::endl; + rhInfoSimHitTokens_.push_back(consumes(*vpsetIt)); + } //recHitInfo_ = new RecHitInfo; //simTrackInfo = new SimTrackInfo; //simHitInfo_ = new SimHitInfo(); @@ -133,17 +156,32 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event // Get the PixelDigiSimLinks edm::Handle > pixelSimLinks; event.getByToken(tokenLinks_, pixelSimLinks); - - // Get the SimHits + // + // Get the SimHits for SimHitInfo + // edm::Handle simHitHandle; // edm::Handle simHitsRaw[2]; // event.getByToken(tokenSimHitsB_, simHitsRaw[0]); // event.getByToken(tokenSimHitsE_, simHitsRaw[1]); - std::vector simHitsRaw; - event.getByToken(tokenSimHitsB_, simHitHandle); - simHitsRaw.push_back(simHitHandle.product()); - event.getByToken(tokenSimHitsE_, simHitHandle); - simHitsRaw.push_back(simHitHandle.product()); + std::vector shInfoSimHitsRaw; + for ( auto tokenIt=shInfoSimHitTokens_.begin(); tokenIt!=shInfoSimHitTokens_.end(); ++tokenIt ) { + event.getByToken(*tokenIt, simHitHandle); + shInfoSimHitsRaw.push_back(simHitHandle.product()); + } + // + // Get the SimHits for RecHitInfo + // + // edm::Handle simHitHandle; + std::vector rhInfoSimHitsRaw; + for ( auto tokenIt=rhInfoSimHitTokens_.begin(); tokenIt!=rhInfoSimHitTokens_.end(); ++tokenIt ) { + event.getByToken(*tokenIt, simHitHandle); + rhInfoSimHitsRaw.push_back(simHitHandle.product()); + } + + // event.getByToken(tokenSimHitsB_, simHitHandle); + // shInfoSimHitsRaw.push_back(simHitHandle.product()); + // event.getByToken(tokenSimHitsE_, simHitHandle); + // shInfoSimHitsRaw.push_back(simHitHandle.product()); // Get the SimTracks edm::Handle simTracksRaw; @@ -163,12 +201,12 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event } simTrackTree->Fill(); - simHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),simHitsRaw,*rechits.product(),&simTracks); + simHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),shInfoSimHitsRaw,*rechits.product(),&simTracks); // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits - // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); - // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { + // for (edm::PSimHitContainer::const_iterator simhitIt(shInfoSimHitsRaw[simhitidx]->begin()); + // simhitIt != shInfoSimHitsRaw[simhitidx]->end(); ++simhitIt) { // loop over both barrel and endcap hits - for (auto simhitsId=simHitsRaw.begin(); simhitsId!=simHitsRaw.end(); ++simhitsId ) { + for (auto simhitsId=shInfoSimHitsRaw.begin(); simhitsId!=shInfoSimHitsRaw.end(); ++simhitsId ) { for (auto simhitIt=(**simhitsId).begin(); simhitIt!=(**simhitsId).end(); ++simhitIt) { // Get the detector unit's id DetId detId(simhitIt->detUnitId()); @@ -214,7 +252,7 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event // Loop over the rechits in the detector unit for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); rechitIt != DSViter->end(); ++rechitIt) { - recHitInfo_.fillRecHitInfo(*rechitIt,rawid,geomDetUnit,&pixelSimLinks,simTracks,simHitsRaw,debugHitMatch_); + recHitInfo_.fillRecHitInfo(*rechitIt,rawid,geomDetUnit,&pixelSimLinks,simTracks,rhInfoSimHitsRaw,debugHitMatch_); } } recHitTree->Fill(); diff --git a/HitAnalyzer/src/CommonHitInfo.cc b/HitAnalyzer/src/CommonHitInfo.cc new file mode 100644 index 0000000..bf44b58 --- /dev/null +++ b/HitAnalyzer/src/CommonHitInfo.cc @@ -0,0 +1,149 @@ +#include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" +#include "DataFormats/DetId/interface/DetId.h" + +// #include + +// #include + + +std::vector CommonHitInfo::getSimTrackId(const DetId& detId, unsigned int channel) { + std::vector retvec; + edm::DetSetVector::const_iterator DSViter(pixelSimLinks->find(detId)); + if (DSViter == pixelSimLinks->end()) return retvec; + for (edm::DetSet::const_iterator it = DSViter->data.begin(); it != DSViter->data.end(); ++it) { + if (channel == it->channel()) { + retvec.push_back(it->SimTrackId()); + } + } + return retvec; +}; + +void CommonHitInfo::fillSimHitsPerDet(const std::vector& simHitsRaw) { + // + // fill map of SimHits / detId + // + simHitsPerDet_.clear(); + // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits + // // std::cout << simhitidx << " " << simHitsRaw[simhitidx]->size() << std::endl; + // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); + // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { + // loop over both barrel and endcap hits + for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { + for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { + const PSimHit* simhit(&*simhitIt); + unsigned int rawid(simhit->detUnitId()); + DetSimHitsMap::iterator idet(simHitsPerDet_.find(rawid)); + if ( idet!=simHitsPerDet_.end() ) { + // std::cout << "CommonHitInfoadding sim entry for det id " << rawid << std::endl; + idet->second.push_back(simhit); + } + else { + // std::cout << "CommonHitInfonew sim entry for det id " << rawid << std::endl; + simHitsPerDet_.insert(DetSimHitsPair(rawid,std::vector{simhit})); + } + } + } + // for (auto it(simHitsPerDet_.begin()); it!=simHitsPerDet_.end(); ++it ) { + // std::cout << it->second.size() << " sim hits for det id "<< it->first << std::endl; + // } + // std::cout << std::endl; + +}; + +void CommonHitInfo::fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits) { + // + // create map of RecHits + // + recHitsPerDet_.clear(); + for (Phase2TrackerRecHit1DCollectionNew::const_iterator DSViter = rechits.begin(); + DSViter != rechits.end(); ++DSViter) { + // Get the detector unit's id + unsigned int rawid(DSViter->detId()); + // only consider dets with SimHits + if ( simHitsPerDet_.find(rawid)!=simHitsPerDet_.end() ) { + // Loop over the rechits in the detector unit + for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); + rechitIt != DSViter->end(); ++rechitIt) { + const Phase2TrackerRecHit1D* rechit(&*rechitIt); + DetRecHitsMap::iterator idet(recHitsPerDet_.find(rawid)); + if ( idet!=recHitsPerDet_.end() ) { + // std::cout << "CommonHitInfoadding rec entry for det id " << rawid << std::endl; + idet->second.push_back(rechit); + } + else { + // std::cout << "CommonHitInfonew rec entry for det id " << rawid << std::endl; + recHitsPerDet_.insert(DetRecHitsPair(rawid,std::vector{rechit})); + } + } + + } + } + // for (auto it(recHitsPerDet_.begin()); it!=recHitsPerDet_.end(); ++it ) { + // std::cout << it->second.size() << " rec hits for det id "<< it->first << std::endl; + // } + // std::cout << std::endl; + +}; + +//const Phase2TrackerRecHit1D* CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, +// const std::vector& detRecHits) { +CommonHitInfo::RecHitDistancePairs +CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, + const std::vector& detRecHits) { + // + // loop over RecHits (assumes simHit and detRecHits are on the same DetUnit!!) + // + // std::cout << "CommonHitInfo Checking SimHit at " << simHit << " detid " << simHit->detUnitId() << " loc pos " + // << simHit->localPosition().x() << " / " << simHit->localPosition().y() << std::endl; + // const Phase2TrackerRecHit1D* rechit(0); + // std::vector< const Phase2TrackerRecHit1D* rechit(0); + CommonHitInfo::RecHitDistancePairs matchedRecHits; + + // float dxmin(1.e30); + for ( std::vector::const_iterator irh=detRecHits.begin(); + irh!=detRecHits.end(); ++irh ) { + // std::cout << "CommonHitInfo Checking RecHit at " << *irh + // << " 1st strip " << (**irh).cluster()->firstStrip() + // << " 1st row " << (**irh).cluster()->firstRow() + // << " columns "<< (**irh).cluster()->column() + // << " detid " << (**irh).geographicalId() << std::endl; + bool matched(false); + // Get the cluster from the rechit and loop over channels + const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); + // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; + for (unsigned int i(0); i < cluster.size(); ++i) { + // std::cout << "CommonHitInfo channel " << i << std::endl; + // find SimTracks contributing to the channel + unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); + std::vector simTrackIds = getSimTrackId(detId,channel); + // // std::cout << "CommonHitInfo " << simTrackIds.size() << " simTracks" << std::endl; + matched = std::find(simTrackIds.begin(),simTrackIds.end(),(*simHit).trackId())!=simTrackIds.end(); + // if match was found: consider RecHit + // std::cout << "CommonHitInfo matched : " << matched << std::endl; + if ( matched ) break; + } + // + // select closest RecHit + // + if ( matched ) { + float dx = fabs((**irh).localPosition().x()-(*simHit).localPosition().x()); + matchedRecHits.push_back(RecHitDistancePair(&(**irh),dx)); + // // std::cout << "CommonHitInfo dx, dxmin " << dx << " " << dxmin; + // if ( !rechit || dxend(); // ++simhitIt) { + // std::cout << "#hits ="; + std::cout << clusterSimTrackIds.size() << " trackIds for cluster" << std::endl; for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { + // std::cout << " " << (**simhitsIt).size(); for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { // check SimHit detId is the same with the RecHit if (rawid == simhitIt->detUnitId()) { @@ -179,6 +182,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in } } } + std::cout << " hasSimHit " << (simhit!=0) << std::endl; if ( debugHitMatch ) { if ( trackSimHits.size()==0 || trackSimHits.size()>1 ) { TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); @@ -204,17 +208,23 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in << ", entry-exit (y) " << (**itsh).entryPoint().y() << " / " << (**itsh).exitPoint().y() << std::endl; } if ( trackSimHits.size()==0 ) { + std::cout << "--- clusterSimTrackIds " << clusterSimTrackIds.size() + << " clusterSize " << recHit.cluster()->size() << std::endl; for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { // check SimHit detId is the same with the RecHit if (rawid == simhitIt->detUnitId()) { + float shxMin = std::min(simhitIt->entryPoint().x(),simhitIt->exitPoint().x()); + float shxMax = std::max(simhitIt->entryPoint().x(),simhitIt->exitPoint().x()); + if ( ( localPosClu.x()>=shxMin ) && ( localPosClu.x()<=shxMax ) ) { std::cout << " SimHit: pabs = " << simhitIt->pabs() << " loss " << simhitIt->energyLoss() << ", pdgId " << simhitIt->particleType() << ", entry-exit (x) " << simhitIt->entryPoint().x() << " / " << simhitIt->exitPoint().x() << ", " << ", entry-exit (y) " << simhitIt->entryPoint().y() << " / " << simhitIt->exitPoint().y() << std::endl; + } } } } diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index 7020b57..11af2f4 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -17,8 +17,8 @@ # Number of events (-1 = all) process.maxEvents = cms.untracked.PSet( - input = cms.untracked.int32(-1) - #input = cms.untracked.int32(100) + #input = cms.untracked.int32(-1) + input = cms.untracked.int32(10) ) # Input file @@ -80,7 +80,22 @@ #MakeEtaPlots = cms.bool(False), #MinEta = cms.double(0.), #MaxEta = cms.double(10.) - debugHitMatch = cms.bool(False) + debugHitMatch = cms.bool(True), + simHitInfo = cms.PSet( + simHits = cms.VInputTag( + cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelLowTof"), + cms.InputTag("g4SimHits", "TrackerHitsPixelEndcapLowTof") + ) + ), + recHitInfo = cms.PSet( + simHits = cms.VInputTag( + cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelLowTof"), + #cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelHighTof"), + cms.InputTag("g4SimHits", "TrackerHitsPixelEndcapLowTof") #, + #cms.InputTag("g4SimHits", "TrackerHitsPixelEndcapHighTof") + ) + ) + ) # Processes to run From cc62282ba5f3054d6c601d9f7304f2f5e4df9a6b Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 11 Feb 2026 15:31:57 +0100 Subject: [PATCH 39/77] moved functionality from SimHitInfo to CommonHitInfo --- HitAnalyzer/interface/CommonHitInfo.h | 22 ++- HitAnalyzer/interface/SimHitInfo.h | 88 +++++---- HitAnalyzer/plugins/RecHitTreeWA.cc | 76 +++++--- HitAnalyzer/src/CommonHitInfo.cc | 1 - HitAnalyzer/src/SimHitInfo.cc | 269 +++++++++++++------------- 5 files changed, 249 insertions(+), 207 deletions(-) diff --git a/HitAnalyzer/interface/CommonHitInfo.h b/HitAnalyzer/interface/CommonHitInfo.h index 6f49042..3d25366 100644 --- a/HitAnalyzer/interface/CommonHitInfo.h +++ b/HitAnalyzer/interface/CommonHitInfo.h @@ -1,5 +1,5 @@ -#ifndef HITANALYZER_SIMHITINFO_H -#define HITANALYZER_SIMHITINFO_H +#ifndef HITANALYZER_COMMONHITINFO_H +#define HITANALYZER_COMMONHITINFO_H #include "DataFormats/TrackerCommon/interface/TrackerTopology.h" @@ -19,6 +19,8 @@ typedef ROOT::Math::DisplacementVector2D > XYVectorF; class CommonHitInfo { + + public: typedef std::map< unsigned int, std::vector > DetSimHitsMap; typedef std::pair< unsigned int, std::vector > DetSimHitsPair; @@ -29,8 +31,6 @@ class CommonHitInfo { typedef std::vector RecHitDistancePairs; typedef std::map TrackIdSimTrackMap; - - public: CommonHitInfo() { tTopo_ = 0; @@ -59,6 +59,7 @@ class CommonHitInfo { tkGeom_ = geom; pixelSimLinks = links; simTracksById_ = simTrackMap; + // // fill SimHit map // fillSimHitsPerDet(simHitsRaw); @@ -67,16 +68,25 @@ class CommonHitInfo { // fillRecHitsPerDet(rechits); } + + const DetSimHitsMap& simHitsPerDet() { + return simHitsPerDet_; + } + + const DetRecHitsMap& recHitsPerDet() { + return recHitsPerDet_; + } - private: + protected: const TrackerTopology* tTopo_; const TrackerGeometry* tkGeom_; const edm::DetSetVector* pixelSimLinks; + const TrackIdSimTrackMap* simTracksById_; + private: DetSimHitsMap simHitsPerDet_; DetRecHitsMap recHitsPerDet_; - const TrackIdSimTrackMap* simTracksById_; }; #endif diff --git a/HitAnalyzer/interface/SimHitInfo.h b/HitAnalyzer/interface/SimHitInfo.h index 83d8f1d..3daa0fe 100644 --- a/HitAnalyzer/interface/SimHitInfo.h +++ b/HitAnalyzer/interface/SimHitInfo.h @@ -1,6 +1,7 @@ #ifndef HITANALYZER_SIMHITINFO_H #define HITANALYZER_SIMHITINFO_H +#include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" #include "DataFormats/TrackerCommon/interface/TrackerTopology.h" #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h" @@ -18,17 +19,17 @@ /// spatial vector with cartesian internal representation typedef ROOT::Math::DisplacementVector2D > XYVectorF; -class SimHitInfo { +class SimHitInfo : public CommonHitInfo { - typedef std::map< unsigned int, std::vector > DetSimHitsMap; - typedef std::pair< unsigned int, std::vector > DetSimHitsPair; - typedef std::map< unsigned int, std::vector > DetRecHitsMap; - typedef std::pair< unsigned int, std::vector > DetRecHitsPair; + /* typedef std::map< unsigned int, std::vector > DetSimHitsMap; */ + /* typedef std::pair< unsigned int, std::vector > DetSimHitsPair; */ + /* typedef std::map< unsigned int, std::vector > DetRecHitsMap; */ + /* typedef std::pair< unsigned int, std::vector > DetRecHitsPair; */ - typedef std::pair RecHitDistancePair; - typedef std::vector RecHitDistancePairs; + /* typedef std::pair RecHitDistancePair; */ + /* typedef std::vector RecHitDistancePairs; */ - typedef std::map TrackIdSimTrackMap; + /* typedef std::map TrackIdSimTrackMap; */ public: struct SimHitData { @@ -73,60 +74,65 @@ class SimHitInfo { SimHitData simHitData; SimHitInfo() { - tTopo_ = 0; - tkGeom_ = 0; - simTracksById_ = 0; + /* tTopo_ = 0; */ + /* tkGeom_ = 0; */ + /* simTracksById_ = 0; */ }; ~SimHitInfo() {} void setBranches(TTree& tree); - std::vector getSimTrackId(const DetId&, unsigned int); + /* std::vector getSimTrackId(const DetId&, unsigned int); */ - void fillSimHitsPerDet(const std::vector& simHitsRaw); + /* void fillSimHitsPerDet(const std::vector& simHitsRaw); */ - void fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits); + /* void fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits); */ // const Phase2TrackerRecHit1D* matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, // const std::vector& detRecHits); - RecHitDistancePairs matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, - const std::vector& detRecHits); + /* RecHitDistancePairs matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, */ + /* const std::vector& detRecHits); */ void fillSimHitInfo(const PSimHit& simHit); void clear(); - void setupEvent(const TrackerTopology* topo, const TrackerGeometry* geom, - const edm::DetSetVector* links, - const std::vector& simHitsRaw, - const Phase2TrackerRecHit1DCollectionNew& rechits, - const TrackIdSimTrackMap* simTrackMap) { - tTopo_ = topo; - tkGeom_ = geom; - pixelSimLinks = links; - simTracksById_ = simTrackMap; - // fill SimHit map - // - // simHitsPerDet_.clear(); - fillSimHitsPerDet(simHitsRaw); - // - // fill RecHit map (uses SimHit map!) - // - // recHitsPerDet_.clear(); - fillRecHitsPerDet(rechits); - } + /* void setupEvent(const TrackerTopology* topo, const TrackerGeometry* geom, */ + /* const edm::DetSetVector* links, */ + /* const std::vector& simHitsRaw, */ + /* const Phase2TrackerRecHit1DCollectionNew& rechits, */ + /* const TrackIdSimTrackMap* simTrackMap) { */ + + /* commonHitInfo.setupEvent(topo,geom,links,simHitsRaw,rechits,simTrackMap); */ + + /* tTopo_ = topo; */ + /* tkGeom_ = geom; */ + /* pixelSimLinks = links; */ + /* simTracksById_ = simTrackMap; */ + /* /\* // fill SimHit map *\/ */ + /* /\* // *\/ */ + /* /\* // simHitsPerDet_.clear(); *\/ */ + /* /\* fillSimHitsPerDet(simHitsRaw); *\/ */ + /* /\* // *\/ */ + /* /\* // fill RecHit map (uses SimHit map!) *\/ */ + /* /\* // *\/ */ + /* /\* // recHitsPerDet_.clear(); *\/ */ + /* /\* fillRecHitsPerDet(rechits); *\/ */ + /* } */ private: - const TrackerTopology* tTopo_; - const TrackerGeometry* tkGeom_; - const edm::DetSetVector* pixelSimLinks; + /* const TrackerTopology* tTopo_; */ + /* const TrackerGeometry* tkGeom_; */ + /* const edm::DetSetVector* pixelSimLinks; */ + + /* DetSimHitsMap simHitsPerDet_; */ + /* DetRecHitsMap recHitsPerDet_; */ - DetSimHitsMap simHitsPerDet_; - DetRecHitsMap recHitsPerDet_; + /* const TrackIdSimTrackMap* simTracksById_; */ - const TrackIdSimTrackMap* simTracksById_; + CommonHitInfo commonHitInfo_; }; #endif diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index f77128c..f795678 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -202,35 +202,60 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event simTrackTree->Fill(); simHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),shInfoSimHitsRaw,*rechits.product(),&simTracks); - // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits - // for (edm::PSimHitContainer::const_iterator simhitIt(shInfoSimHitsRaw[simhitidx]->begin()); - // simhitIt != shInfoSimHitsRaw[simhitidx]->end(); ++simhitIt) { - // loop over both barrel and endcap hits - for (auto simhitsId=shInfoSimHitsRaw.begin(); simhitsId!=shInfoSimHitsRaw.end(); ++simhitsId ) { - for (auto simhitIt=(**simhitsId).begin(); simhitIt!=(**simhitsId).end(); ++simhitIt) { - // Get the detector unit's id - DetId detId(simhitIt->detUnitId()); - unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides - layer += tTopo->layer(detId); - //hitInfo->Hit_ModuleType.push_back((unsigned short)(tkGeom->getDetectorType(detId))); - TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); - // Restrict to Phase2 OT - if ( mType!=TrackerGeometry::ModuleType::Ph2PSP && - mType!=TrackerGeometry::ModuleType::Ph2PSS && - mType!=TrackerGeometry::ModuleType::Ph2SS ) continue; - - // Get the geomdet - const GeomDetUnit* geomDetUnit(tkGeom->idToDetUnit(detId)); - if (!geomDetUnit) { - std::cout << "*** did not find geomDetUnit ***" << std::endl; - continue; - } + for (auto detHitsIt=simHitInfo_.simHitsPerDet().begin(); detHitsIt!=simHitInfo_.simHitsPerDet().end(); ++detHitsIt ) { + DetId detId(detHitsIt->first); + unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides + layer += tTopo->layer(detId); + //hitInfo->Hit_ModuleType.push_back((unsigned short)(tkGeom->getDetectorType(detId))); + TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); + // Restrict to Phase2 OT + if ( mType!=TrackerGeometry::ModuleType::Ph2PSP && + mType!=TrackerGeometry::ModuleType::Ph2PSS && + mType!=TrackerGeometry::ModuleType::Ph2SS ) continue; + // Get the geomdet + const GeomDetUnit* geomDetUnit(tkGeom->idToDetUnit(detId)); + if (!geomDetUnit) { + std::cout << "*** did not find geomDetUnit ***" << std::endl; + continue; + } + std::cout << "DetId " << detHitsIt->first << " " << detHitsIt->second.size() << std::endl << std::flush; + + for (auto simhitIt=detHitsIt->second.begin(); simhitIt!=detHitsIt->second.end(); ++simhitIt) { // std::cout << "Filling sim hit info" << std::endl; - simHitInfo_.fillSimHitInfo(*simhitIt); - + simHitInfo_.fillSimHitInfo(**simhitIt); } + std::cout << "... done" << std::endl << std::flush; } + // // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits + // // for (edm::PSimHitContainer::const_iterator simhitIt(shInfoSimHitsRaw[simhitidx]->begin()); + // // simhitIt != shInfoSimHitsRaw[simhitidx]->end(); ++simhitIt) { + // // loop over both barrel and endcap hits + // for (auto simhitsId=shInfoSimHitsRaw.begin(); simhitsId!=shInfoSimHitsRaw.end(); ++simhitsId ) { + // for (auto simhitIt=(**simhitsId).begin(); simhitIt!=(**simhitsId).end(); ++simhitIt) { + // // Get the detector unit's id + // DetId detId(simhitIt->detUnitId()); + // unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides + // layer += tTopo->layer(detId); + // //hitInfo->Hit_ModuleType.push_back((unsigned short)(tkGeom->getDetectorType(detId))); + // TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); + // // Restrict to Phase2 OT + // if ( mType!=TrackerGeometry::ModuleType::Ph2PSP && + // mType!=TrackerGeometry::ModuleType::Ph2PSS && + // mType!=TrackerGeometry::ModuleType::Ph2SS ) continue; + + // // Get the geomdet + // const GeomDetUnit* geomDetUnit(tkGeom->idToDetUnit(detId)); + // if (!geomDetUnit) { + // std::cout << "*** did not find geomDetUnit ***" << std::endl; + // continue; + // } + + // // std::cout << "Filling sim hit info" << std::endl; + // simHitInfo_.fillSimHitInfo(*simhitIt); + + // } + // } simHitTree->Fill(); for (Phase2TrackerRecHit1DCollectionNew::const_iterator DSViter = rechits->begin(); @@ -288,4 +313,3 @@ void RecHitTreeWA::initEventStructure() } DEFINE_FWK_MODULE(RecHitTreeWA); - diff --git a/HitAnalyzer/src/CommonHitInfo.cc b/HitAnalyzer/src/CommonHitInfo.cc index bf44b58..4393511 100644 --- a/HitAnalyzer/src/CommonHitInfo.cc +++ b/HitAnalyzer/src/CommonHitInfo.cc @@ -146,4 +146,3 @@ CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, }); return matchedRecHits; }; - diff --git a/HitAnalyzer/src/SimHitInfo.cc b/HitAnalyzer/src/SimHitInfo.cc index d670c74..2af2752 100644 --- a/HitAnalyzer/src/SimHitInfo.cc +++ b/HitAnalyzer/src/SimHitInfo.cc @@ -1,4 +1,5 @@ #include "Phase2Tracking/HitAnalyzer/interface/SimHitInfo.h" +#include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" #include "DataFormats/DetId/interface/DetId.h" // #include @@ -41,146 +42,148 @@ void SimHitInfo::setBranches(TTree& tree) { tree.Branch("clusterThreshold", &simHitData.clusterThreshold); }; -std::vector SimHitInfo::getSimTrackId(const DetId& detId, unsigned int channel) { - std::vector retvec; - edm::DetSetVector::const_iterator DSViter(pixelSimLinks->find(detId)); - if (DSViter == pixelSimLinks->end()) return retvec; - for (edm::DetSet::const_iterator it = DSViter->data.begin(); it != DSViter->data.end(); ++it) { - if (channel == it->channel()) { - retvec.push_back(it->SimTrackId()); - } - } - return retvec; -}; +// std::vector SimHitInfo::getSimTrackId(const DetId& detId, unsigned int channel) { +// std::vector retvec; +// edm::DetSetVector::const_iterator DSViter(pixelSimLinks->find(detId)); +// if (DSViter == pixelSimLinks->end()) return retvec; +// for (edm::DetSet::const_iterator it = DSViter->data.begin(); it != DSViter->data.end(); ++it) { +// if (channel == it->channel()) { +// retvec.push_back(it->SimTrackId()); +// } +// } +// return retvec; +// }; -void SimHitInfo::fillSimHitsPerDet(const std::vector& simHitsRaw) { - // - // fill map of SimHits / detId - // - simHitsPerDet_.clear(); - // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits - // // std::cout << simhitidx << " " << simHitsRaw[simhitidx]->size() << std::endl; - // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); - // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { - // loop over both barrel and endcap hits - for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { - for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { - const PSimHit* simhit(&*simhitIt); - unsigned int rawid(simhit->detUnitId()); - DetSimHitsMap::iterator idet(simHitsPerDet_.find(rawid)); - if ( idet!=simHitsPerDet_.end() ) { - // std::cout << "SimHitInfoadding sim entry for det id " << rawid << std::endl; - idet->second.push_back(simhit); - } - else { - // std::cout << "SimHitInfonew sim entry for det id " << rawid << std::endl; - simHitsPerDet_.insert(DetSimHitsPair(rawid,std::vector{simhit})); - } - } - } - // for (auto it(simHitsPerDet_.begin()); it!=simHitsPerDet_.end(); ++it ) { - // std::cout << it->second.size() << " sim hits for det id "<< it->first << std::endl; - // } - // std::cout << std::endl; +// void SimHitInfo::fillSimHitsPerDet(const std::vector& simHitsRaw) { +// // +// // fill map of SimHits / detId +// // +// commonHitInfo.fillSimHitsPerDet(simHitsRaw); +// // simHitsPerDet_.clear(); +// // // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits +// // // // std::cout << simhitidx << " " << simHitsRaw[simhitidx]->size() << std::endl; +// // // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); +// // // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { +// // // loop over both barrel and endcap hits +// // for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { +// // for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { +// // const PSimHit* simhit(&*simhitIt); +// // unsigned int rawid(simhit->detUnitId()); +// // DetSimHitsMap::iterator idet(simHitsPerDet_.find(rawid)); +// // if ( idet!=simHitsPerDet_.end() ) { +// // // std::cout << "SimHitInfoadding sim entry for det id " << rawid << std::endl; +// // idet->second.push_back(simhit); +// // } +// // else { +// // // std::cout << "SimHitInfonew sim entry for det id " << rawid << std::endl; +// // simHitsPerDet_.insert(DetSimHitsPair(rawid,std::vector{simhit})); +// // } +// // } +// // } +// // // for (auto it(simHitsPerDet_.begin()); it!=simHitsPerDet_.end(); ++it ) { +// // // std::cout << it->second.size() << " sim hits for det id "<< it->first << std::endl; +// // // } +// // // std::cout << std::endl; -}; +// }; -void SimHitInfo::fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits) { - // - // create map of RecHits - // - recHitsPerDet_.clear(); - for (Phase2TrackerRecHit1DCollectionNew::const_iterator DSViter = rechits.begin(); - DSViter != rechits.end(); ++DSViter) { - // Get the detector unit's id - unsigned int rawid(DSViter->detId()); - // only consider dets with SimHits - if ( simHitsPerDet_.find(rawid)!=simHitsPerDet_.end() ) { - // Loop over the rechits in the detector unit - for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); - rechitIt != DSViter->end(); ++rechitIt) { - const Phase2TrackerRecHit1D* rechit(&*rechitIt); - DetRecHitsMap::iterator idet(recHitsPerDet_.find(rawid)); - if ( idet!=recHitsPerDet_.end() ) { - // std::cout << "SimHitInfoadding rec entry for det id " << rawid << std::endl; - idet->second.push_back(rechit); - } - else { - // std::cout << "SimHitInfonew rec entry for det id " << rawid << std::endl; - recHitsPerDet_.insert(DetRecHitsPair(rawid,std::vector{rechit})); - } - } +// void SimHitInfo::fillRecHitsPerDet(const Phase2TrackerRecHit1DCollectionNew& rechits) { +// // +// // create map of RecHits +// // +// commonHitInfo.fillRecHitsPerDet(rechits); +// // recHitsPerDet_.clear(); +// // for (Phase2TrackerRecHit1DCollectionNew::const_iterator DSViter = rechits.begin(); +// // DSViter != rechits.end(); ++DSViter) { +// // // Get the detector unit's id +// // unsigned int rawid(DSViter->detId()); +// // // only consider dets with SimHits +// // if ( simHitsPerDet_.find(rawid)!=simHitsPerDet_.end() ) { +// // // Loop over the rechits in the detector unit +// // for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); +// // rechitIt != DSViter->end(); ++rechitIt) { +// // const Phase2TrackerRecHit1D* rechit(&*rechitIt); +// // DetRecHitsMap::iterator idet(recHitsPerDet_.find(rawid)); +// // if ( idet!=recHitsPerDet_.end() ) { +// // // std::cout << "SimHitInfoadding rec entry for det id " << rawid << std::endl; +// // idet->second.push_back(rechit); +// // } +// // else { +// // // std::cout << "SimHitInfonew rec entry for det id " << rawid << std::endl; +// // recHitsPerDet_.insert(DetRecHitsPair(rawid,std::vector{rechit})); +// // } +// // } - } - } - // for (auto it(recHitsPerDet_.begin()); it!=recHitsPerDet_.end(); ++it ) { - // std::cout << it->second.size() << " rec hits for det id "<< it->first << std::endl; - // } - // std::cout << std::endl; +// // } +// } +// // for (auto it(recHitsPerDet_.begin()); it!=recHitsPerDet_.end(); ++it ) { +// // std::cout << it->second.size() << " rec hits for det id "<< it->first << std::endl; +// // } +// // std::cout << std::endl; -}; +// }; //const Phase2TrackerRecHit1D* SimHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, // const std::vector& detRecHits) { -SimHitInfo::RecHitDistancePairs -SimHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, - const std::vector& detRecHits) { - // - // loop over RecHits (assumes simHit and detRecHits are on the same DetUnit!!) - // - // std::cout << "SimHitInfo Checking SimHit at " << simHit << " detid " << simHit->detUnitId() << " loc pos " - // << simHit->localPosition().x() << " / " << simHit->localPosition().y() << std::endl; - // const Phase2TrackerRecHit1D* rechit(0); - // std::vector< const Phase2TrackerRecHit1D* rechit(0); - SimHitInfo::RecHitDistancePairs matchedRecHits; +// SimHitInfo::RecHitDistancePairs +// SimHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, +// const std::vector& detRecHits) { +// // +// // loop over RecHits (assumes simHit and detRecHits are on the same DetUnit!!) +// // +// // std::cout << "SimHitInfo Checking SimHit at " << simHit << " detid " << simHit->detUnitId() << " loc pos " +// // << simHit->localPosition().x() << " / " << simHit->localPosition().y() << std::endl; +// // const Phase2TrackerRecHit1D* rechit(0); +// // std::vector< const Phase2TrackerRecHit1D* rechit(0); +// SimHitInfo::RecHitDistancePairs matchedRecHits; - // float dxmin(1.e30); - for ( std::vector::const_iterator irh=detRecHits.begin(); - irh!=detRecHits.end(); ++irh ) { - // std::cout << "SimHitInfo Checking RecHit at " << *irh - // << " 1st strip " << (**irh).cluster()->firstStrip() - // << " 1st row " << (**irh).cluster()->firstRow() - // << " columns "<< (**irh).cluster()->column() - // << " detid " << (**irh).geographicalId() << std::endl; - bool matched(false); - // Get the cluster from the rechit and loop over channels - const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); - // std::cout << "SimHitInfo cluster size " << cluster.size() << std::endl; - for (unsigned int i(0); i < cluster.size(); ++i) { - // std::cout << "SimHitInfo channel " << i << std::endl; - // find SimTracks contributing to the channel - unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); - std::vector simTrackIds = getSimTrackId(detId,channel); - // // std::cout << "SimHitInfo " << simTrackIds.size() << " simTracks" << std::endl; - matched = std::find(simTrackIds.begin(),simTrackIds.end(),(*simHit).trackId())!=simTrackIds.end(); - // if match was found: consider RecHit - // std::cout << "SimHitInfo matched : " << matched << std::endl; - if ( matched ) break; - } - // - // select closest RecHit - // - if ( matched ) { - float dx = fabs((**irh).localPosition().x()-(*simHit).localPosition().x()); - matchedRecHits.push_back(RecHitDistancePair(&(**irh),dx)); - // // std::cout << "SimHitInfo dx, dxmin " << dx << " " << dxmin; - // if ( !rechit || dx::const_iterator irh=detRecHits.begin(); +// irh!=detRecHits.end(); ++irh ) { +// // std::cout << "SimHitInfo Checking RecHit at " << *irh +// // << " 1st strip " << (**irh).cluster()->firstStrip() +// // << " 1st row " << (**irh).cluster()->firstRow() +// // << " columns "<< (**irh).cluster()->column() +// // << " detid " << (**irh).geographicalId() << std::endl; +// bool matched(false); +// // Get the cluster from the rechit and loop over channels +// const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); +// // std::cout << "SimHitInfo cluster size " << cluster.size() << std::endl; +// for (unsigned int i(0); i < cluster.size(); ++i) { +// // std::cout << "SimHitInfo channel " << i << std::endl; +// // find SimTracks contributing to the channel +// unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); +// std::vector simTrackIds = getSimTrackId(detId,channel); +// // // std::cout << "SimHitInfo " << simTrackIds.size() << " simTracks" << std::endl; +// matched = std::find(simTrackIds.begin(),simTrackIds.end(),(*simHit).trackId())!=simTrackIds.end(); +// // if match was found: consider RecHit +// // std::cout << "SimHitInfo matched : " << matched << std::endl; +// if ( matched ) break; +// } +// // +// // select closest RecHit +// // +// if ( matched ) { +// float dx = fabs((**irh).localPosition().x()-(*simHit).localPosition().x()); +// matchedRecHits.push_back(RecHitDistancePair(&(**irh),dx)); +// // // std::cout << "SimHitInfo dx, dxmin " << dx << " " << dxmin; +// // if ( !rechit || dx Date: Wed, 11 Feb 2026 16:19:37 +0100 Subject: [PATCH 40/77] start to move functionality from RecHitInfo to CommonHitInfo --- HitAnalyzer/interface/RecHitInfo.h | 33 +++++++++-------- HitAnalyzer/plugins/RecHitTreeWA.cc | 31 +++++++++++----- HitAnalyzer/src/RecHitInfo.cc | 57 +++++++++++++++-------------- 3 files changed, 67 insertions(+), 54 deletions(-) diff --git a/HitAnalyzer/interface/RecHitInfo.h b/HitAnalyzer/interface/RecHitInfo.h index 4ce1a91..5771c81 100644 --- a/HitAnalyzer/interface/RecHitInfo.h +++ b/HitAnalyzer/interface/RecHitInfo.h @@ -1,6 +1,7 @@ #ifndef HITANALYZER_RECHITINFO_H #define HITANALYZER_RECHITINFO_H +#include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" #include "DataFormats/Common/interface/DetSetVector.h" #include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h" @@ -18,7 +19,7 @@ #include "TTree.h" -class RecHitInfo { +class RecHitInfo : public CommonHitInfo { public: struct RecHitData @@ -65,40 +66,40 @@ class RecHitInfo { RecHitData recHitData; RecHitInfo() { - tTopo = 0; - tkGeom = 0; + /* tTopo = 0; */ + /* tkGeom = 0; */ }; ~RecHitInfo() {} void setBranches(TTree& tree); - std::vector getSimTrackId( - edm::Handle >& pixelSimLinks, - const DetId& detId, unsigned int channel); + /* std::vector getSimTrackId( */ + /* edm::Handle >& pixelSimLinks, */ + /* const DetId& detId, unsigned int channel); */ void fillSimHitInfo(const PSimHit& simHit); void fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned int rawid, const GeomDetUnit* geomDetUnit, - edm::Handle >* pixelSimLinks, - std::map& simTracks, + // edm::Handle >* pixelSimLinks, + // std::map& simTracks, const std::vector& simHitsRaw, bool debugHitMatch); void clear(); - void setTopology(const TrackerTopology* topo) { - tTopo = topo; - } + /* void setTopology(const TrackerTopology* topo) { */ + /* tTopo = topo; */ + /* } */ - void setGeometry(const TrackerGeometry* geom) { - tkGeom = geom; - } + /* void setGeometry(const TrackerGeometry* geom) { */ + /* tkGeom = geom; */ + /* } */ private: - const TrackerTopology* tTopo; - const TrackerGeometry* tkGeom; + /* const TrackerTopology* tTopo; */ + /* const TrackerGeometry* tkGeom; */ }; #endif diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index f795678..9268f64 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -187,8 +187,9 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event edm::Handle simTracksRaw; event.getByToken(tokenSimTracks_, simTracksRaw); // std::cout << "#simTracks " << simTracksRaw.product()->size() << std::endl; - + // // Rearrange the simTracks for ease of use + // std::map simTracks; for (edm::SimTrackContainer::const_iterator simTrackIt(simTracksRaw->begin()); simTrackIt != simTracksRaw->end(); ++simTrackIt) { @@ -200,8 +201,13 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event simTrackInfo_.fillSimTrackInfo(*simTrackIt); } simTrackTree->Fill(); - + // + // Prepare SimHitInfo - setup new event + // simHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),shInfoSimHitsRaw,*rechits.product(),&simTracks); + // + // loop over dets + // for (auto detHitsIt=simHitInfo_.simHitsPerDet().begin(); detHitsIt!=simHitInfo_.simHitsPerDet().end(); ++detHitsIt ) { DetId detId(detHitsIt->first); unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides @@ -219,13 +225,15 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event std::cout << "*** did not find geomDetUnit ***" << std::endl; continue; } - std::cout << "DetId " << detHitsIt->first << " " << detHitsIt->second.size() << std::endl << std::flush; - + // std::cout << "DetId " << detHitsIt->first << " " << detHitsIt->second.size() << std::endl << std::flush; + // + // loop over SimHits on Det + // for (auto simhitIt=detHitsIt->second.begin(); simhitIt!=detHitsIt->second.end(); ++simhitIt) { // std::cout << "Filling sim hit info" << std::endl; simHitInfo_.fillSimHitInfo(**simhitIt); } - std::cout << "... done" << std::endl << std::flush; + // std::cout << "... done" << std::endl << std::flush; } // // for (unsigned int simhitidx = 0; simhitidx < 2; ++simhitidx) { // loop over both barrel and endcap hits // // for (edm::PSimHitContainer::const_iterator simhitIt(shInfoSimHitsRaw[simhitidx]->begin()); @@ -257,7 +265,10 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event // } // } simHitTree->Fill(); - + // + // Prepare RecHitInfo - setup new event + // + recHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),rhInfoSimHitsRaw,*rechits.product(),&simTracks); for (Phase2TrackerRecHit1DCollectionNew::const_iterator DSViter = rechits->begin(); DSViter != rechits->end(); ++DSViter) { // Get the detector unit's id @@ -271,20 +282,20 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event if (!geomDetUnit) continue; - recHitInfo_.setTopology(tTopo); - recHitInfo_.setGeometry(tkGeom); + // recHitInfo_.setTopology(tTopo); + // recHitInfo_.setGeometry(tkGeom); // Loop over the rechits in the detector unit for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); rechitIt != DSViter->end(); ++rechitIt) { - recHitInfo_.fillRecHitInfo(*rechitIt,rawid,geomDetUnit,&pixelSimLinks,simTracks,rhInfoSimHitsRaw,debugHitMatch_); + recHitInfo_.fillRecHitInfo(*rechitIt,rawid,geomDetUnit, // &pixelSimLinks,simTracks, + rhInfoSimHitsRaw,debugHitMatch_); } } recHitTree->Fill(); } - void RecHitTreeWA::beginJob() { edm::Service fs; diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index e4bc266..da69597 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -45,31 +45,31 @@ void RecHitInfo::setBranches(TTree& tree) { tree.Branch("nSimTracks", &recHitData.nSimTracks); }; -std::vector RecHitInfo::getSimTrackId( - edm::Handle >& pixelSimLinks, - const DetId& detId, unsigned int channel) { - std::vector retvec; - edm::DetSetVector::const_iterator DSViter(pixelSimLinks->find(detId)); - if (DSViter == pixelSimLinks->end()) - return retvec; - for (edm::DetSet::const_iterator it = DSViter->data.begin(); it != DSViter->data.end(); ++it) { - if (channel == it->channel()) { - retvec.push_back(it->SimTrackId()); - } - } - return retvec; -} +// std::vector RecHitInfo::getSimTrackId( +// edm::Handle >& pixelSimLinks, +// const DetId& detId, unsigned int channel) { +// std::vector retvec; +// edm::DetSetVector::const_iterator DSViter(pixelSimLinks->find(detId)); +// if (DSViter == pixelSimLinks->end()) +// return retvec; +// for (edm::DetSet::const_iterator it = DSViter->data.begin(); it != DSViter->data.end(); ++it) { +// if (channel == it->channel()) { +// retvec.push_back(it->SimTrackId()); +// } +// } +// return retvec; +// } void RecHitInfo::fillSimHitInfo(const PSimHit& simHit) { // // Get the detector unit's id // DetId detId(simHit.detUnitId()); - unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides - layer += tTopo->layer(detId); - TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); + unsigned int layer = (tTopo_->side(detId) != 0) * 1000; // don't split up endcap sides + layer += tTopo_->layer(detId); + TrackerGeometry::ModuleType mType = tkGeom_->getDetectorType(detId); // Get the geomdet - const GeomDetUnit* geomDetUnit(tkGeom->idToDetUnit(detId)); + const GeomDetUnit* geomDetUnit(tkGeom_->idToDetUnit(detId)); if (!geomDetUnit) { std::cout << "*** did not find geomDetUnit ***" << std::endl; return; @@ -108,14 +108,14 @@ void RecHitInfo::fillSimHitInfo(const PSimHit& simHit) { void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned int rawid, const GeomDetUnit* geomDetUnit, - edm::Handle >* pixelSimLinks, - std::map& simTracks, + // edm::Handle >* pixelSimLinks, + // std::map& simTracks, const std::vector& simHitsRaw, bool debugHitMatch) { // get DetUnit DetId detId(rawid); - unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides - layer += tTopo->layer(detId); + unsigned int layer = (tTopo_->side(detId) != 0) * 1000; // don't split up endcap sides + layer += tTopo_->layer(detId); // determine the position LocalPoint localPosClu = recHit.localPosition(); Global3DPoint globalPosClu = geomDetUnit->surface().toGlobal(localPosClu); @@ -128,11 +128,12 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in std::set clusterSimTrackIds; for (unsigned int i(0); i < clustIt->size(); ++i) { unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); - std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); + // std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); + std::vector simTrackIds_unselected(getSimTrackId(detId, channel)); std::vector simTrackIds; for (auto istId : simTrackIds_unselected) { - std::map::const_iterator istfind(simTracks.find(istId)); - if (istfind != simTracks.end()) + std::map::const_iterator istfind(simTracksById_->find(istId)); + if (istfind != simTracksById_->end()) simTrackIds.push_back(istId); } clusterSimTrackIds.insert(simTrackIds.begin(),simTrackIds.end()); @@ -140,7 +141,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in // debug // if ( clusterSimTrackIds.size()==0 ) { // std::cout << "** RecHit without SimTrackIds on detId " << rawid << " layer " << layer - // << " module type " << (unsigned int)tkGeom->getDetectorType(detId) << std::endl; + // << " module type " << (unsigned int)tkGeom_->getDetectorType(detId) << std::endl; // for (unsigned int i(0); i < clustIt->size(); ++i) { // unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); // std::cout << " channel " << clustIt->firstRow()+i << " " << clustIt->column() << std::endl; @@ -185,7 +186,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in std::cout << " hasSimHit " << (simhit!=0) << std::endl; if ( debugHitMatch ) { if ( trackSimHits.size()==0 || trackSimHits.size()>1 ) { - TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); + TrackerGeometry::ModuleType mType = tkGeom_->getDetectorType(detId); std::cout << "RecHit on rawid " << rawid <<", layer " << layer << ", mType "<< (unsigned int)mType << std::endl; std::cout << " localPos " << localPosClu.x() << " / " << localPosClu.y() << std::endl; @@ -236,7 +237,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in recHitData.Hit_cluster_global_y.push_back(globalPosClu.y()); recHitData.Hit_cluster_global_z.push_back(globalPosClu.z()); recHitData.Hit_layer.push_back(layer); - recHitData.Hit_ModuleType.push_back((unsigned short)(tkGeom->getDetectorType(detId))); + recHitData.Hit_ModuleType.push_back((unsigned short)(tkGeom_->getDetectorType(detId))); recHitData.Hit_cluster_size.push_back(clustIt->size()); recHitData.Hit_cluster_SimTrack_size.push_back(clusterSimTrackIds.size()); recHitData.Hit_cluster_local_x.push_back(localPosClu.x()); From 7dd0f358950da7c4dcbcfc2e54731b5284a7a7b6 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 12 Feb 2026 09:14:35 +0100 Subject: [PATCH 41/77] adapt mu cfg file --- HitAnalyzer/test/rechittreewa_mu10_cfg.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/HitAnalyzer/test/rechittreewa_mu10_cfg.py b/HitAnalyzer/test/rechittreewa_mu10_cfg.py index 025c195..9f70010 100644 --- a/HitAnalyzer/test/rechittreewa_mu10_cfg.py +++ b/HitAnalyzer/test/rechittreewa_mu10_cfg.py @@ -17,8 +17,8 @@ # Number of events (-1 = all) process.maxEvents = cms.untracked.PSet( - input = cms.untracked.int32(-1) - #input = cms.untracked.int32(100) + #input = cms.untracked.int32(-1) + input = cms.untracked.int32(10) ) # Input file @@ -58,7 +58,21 @@ #MakeEtaPlots = cms.bool(False), #MinEta = cms.double(0.), #MaxEta = cms.double(10.) - debugHitMatch = cms.bool(False) + debugHitMatch = cms.bool(True), + simHitInfo = cms.PSet( + simHits = cms.VInputTag( + cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelLowTof"), + cms.InputTag("g4SimHits", "TrackerHitsPixelEndcapLowTof") + ) + ), + recHitInfo = cms.PSet( + simHits = cms.VInputTag( + cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelLowTof"), + #cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelHighTof"), + cms.InputTag("g4SimHits", "TrackerHitsPixelEndcapLowTof") #, + #cms.InputTag("g4SimHits", "TrackerHitsPixelEndcapHighTof") + ) + ) ) # Processes to run From 2ca94219682ded7afc98b1cf30776e66bdd0b49b Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 12 Feb 2026 09:48:36 +0100 Subject: [PATCH 42/77] debug information --- HitAnalyzer/plugins/RecHitTreeWA.cc | 3 ++- HitAnalyzer/src/SimHitInfo.cc | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index 9268f64..1e7c10d 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -225,7 +225,8 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event std::cout << "*** did not find geomDetUnit ***" << std::endl; continue; } - // std::cout << "DetId " << detHitsIt->first << " " << detHitsIt->second.size() << std::endl << std::flush; + std::cout << "Found " << detHitsIt->second.size() << " SimHits on DetId " << detHitsIt->first + << std::endl << std::flush; // // loop over SimHits on Det // diff --git a/HitAnalyzer/src/SimHitInfo.cc b/HitAnalyzer/src/SimHitInfo.cc index 2af2752..af90580 100644 --- a/HitAnalyzer/src/SimHitInfo.cc +++ b/HitAnalyzer/src/SimHitInfo.cc @@ -190,6 +190,7 @@ void SimHitInfo::fillSimHitInfo(const PSimHit& simHit) { // Get the detector unit's id // unsigned int rawid(simHit.detUnitId()); + std::cout << " Filling SimHitInfo for hit on DetId " << rawid << std::endl; DetId detId(rawid); unsigned int layer = (tTopo_->side(detId) != 0) * 1000; // don't split up endcap sides layer += tTopo_->layer(detId); From 3b2e7d26b5cadf7960aa1b1346e4d22b5c947e06 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 13 Feb 2026 10:23:07 +0100 Subject: [PATCH 43/77] cosmetic mod in tt cfg --- HitAnalyzer/test/rechittreewa_tt_cfg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index 11af2f4..24c51e6 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -18,7 +18,7 @@ # Number of events (-1 = all) process.maxEvents = cms.untracked.PSet( #input = cms.untracked.int32(-1) - input = cms.untracked.int32(10) + input = cms.untracked.int32(2) ) # Input file From e78aeeffb664fb7564651d091a0bc03e2522c678 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 13 Feb 2026 17:34:42 +0100 Subject: [PATCH 44/77] preparing common sim / rechit matching --- HitAnalyzer/interface/ClusterSimTracks.h | 47 ++++++++++++++++++++++++ HitAnalyzer/interface/CommonHitInfo.h | 6 +++ HitAnalyzer/src/ClusterSimTracks.cc | 47 ++++++++++++++++++++++++ HitAnalyzer/src/CommonHitInfo.cc | 17 +++++++-- 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 HitAnalyzer/interface/ClusterSimTracks.h create mode 100644 HitAnalyzer/src/ClusterSimTracks.cc diff --git a/HitAnalyzer/interface/ClusterSimTracks.h b/HitAnalyzer/interface/ClusterSimTracks.h new file mode 100644 index 0000000..0829be5 --- /dev/null +++ b/HitAnalyzer/interface/ClusterSimTracks.h @@ -0,0 +1,47 @@ +#ifndef HITANALYZER_CLUSTERSIMTRACKS_H +#define HITANALYZER_CLUSTERSIMTRACKS_H + +#include "SimDataFormats/TrackerDigiSimLink/interface/PixelDigiSimLink.h" +#include "DataFormats/Phase2TrackerCluster/interface/Phase2TrackerCluster1D.h" +/* #include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h" */ +#include "SimDataFormats/TrackerDigiSimLink/interface/PixelDigiSimLink.h" +#include "DataFormats/DetId/interface/DetId.h" +#include "DataFormats/Common/interface/DetSetVector.h" + +class ClusterSimTracks { + + public: + + ClusterSimTracks(const Phase2TrackerCluster1D& cluster, const DetId& detId, const edm::DetSetVector& pixelSimLinks): + cluster_(cluster), detId_(detId), pixelSimLinks_(pixelSimLinks), channelsChecked_(0) {}; + + std::set getSimTrackId(unsigned int channel) const; + + bool listIsComplete() { + // + // Return true if simTrackIds have been collected from all cluster channels + // + return channelsChecked_==cluster_.size(); + }; + + bool simTrackInCluster(unsigned int simTrackId); + + const std::set& simTrackIds() { + // + // List of all simTrackIds associated to cluster. + // Only available if listIsComplete() is true !!! + // + if ( not listIsComplete() ) + throw std::logic_error("ClusterSimTracks: trying to retrieve incomplete list of SimTrackIds"); + + return simTrackIds_; + }; + + private: + const Phase2TrackerCluster1D& cluster_; + const DetId& detId_; + const edm::DetSetVector& pixelSimLinks_; + unsigned short channelsChecked_; + std::set simTrackIds_; +}; +#endif diff --git a/HitAnalyzer/interface/CommonHitInfo.h b/HitAnalyzer/interface/CommonHitInfo.h index 3d25366..fd6bf0d 100644 --- a/HitAnalyzer/interface/CommonHitInfo.h +++ b/HitAnalyzer/interface/CommonHitInfo.h @@ -26,6 +26,7 @@ class CommonHitInfo { typedef std::pair< unsigned int, std::vector > DetSimHitsPair; typedef std::map< unsigned int, std::vector > DetRecHitsMap; typedef std::pair< unsigned int, std::vector > DetRecHitsPair; + typedef std::map RecHitClusterMap; typedef std::pair RecHitDistancePair; typedef std::vector RecHitDistancePairs; @@ -67,6 +68,10 @@ class CommonHitInfo { // fill RecHit map (uses SimHit map!) // fillRecHitsPerDet(rechits); + // + // reset cluster map + // + clustersByHit_.clear(); } const DetSimHitsMap& simHitsPerDet() { @@ -86,6 +91,7 @@ class CommonHitInfo { private: DetSimHitsMap simHitsPerDet_; DetRecHitsMap recHitsPerDet_; + RecHitClusterMap clustersByHit_; }; diff --git a/HitAnalyzer/src/ClusterSimTracks.cc b/HitAnalyzer/src/ClusterSimTracks.cc new file mode 100644 index 0000000..affac7f --- /dev/null +++ b/HitAnalyzer/src/ClusterSimTracks.cc @@ -0,0 +1,47 @@ +#include "Phase2Tracking/HitAnalyzer/interface/ClusterSimTracks.h" +// #include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" +// #include "DataFormats/DetId/interface/DetId.h" +// +// return SimTrack ids for a given DetId / channel +// +std::set ClusterSimTracks::getSimTrackId(unsigned int channel) const { + std::set result; + edm::DetSetVector::const_iterator DSViter(pixelSimLinks_.find(detId_)); + if (DSViter == pixelSimLinks_.end()) return result; + for (edm::DetSet::const_iterator it = DSViter->data.begin(); it != DSViter->data.end(); ++it) { + if (channel == it->channel()) { + result.insert(it->SimTrackId()); + } + } + return result; +}; + +bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) { + // + // Return true if contributed to one or more channels of + // Keep a (partial) cache of SimTrackIds + // + // + // Start with existing list + // + bool matched = std::find(simTrackIds_.begin(),simTrackIds_.end(),simTrackId)!=simTrackIds_.end(); + // + // This is the final result if the list is complete + // + if ( listIsComplete() ) return matched; + // + // Otherwise: loop over missing channels + // + // + while ( ++channelsChecked_ simTrackIds = getSimTrackId(channel); + matched = std::find(simTrackIds.begin(),simTrackIds.end(),simTrackId)!=simTrackIds.end(); + if ( matched ) break; + simTrackIds_.insert(simTrackIds.begin(),simTrackIds.end()); + } + return matched; +}; + diff --git a/HitAnalyzer/src/CommonHitInfo.cc b/HitAnalyzer/src/CommonHitInfo.cc index 4393511..e57c678 100644 --- a/HitAnalyzer/src/CommonHitInfo.cc +++ b/HitAnalyzer/src/CommonHitInfo.cc @@ -102,17 +102,28 @@ CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, // float dxmin(1.e30); for ( std::vector::const_iterator irh=detRecHits.begin(); irh!=detRecHits.end(); ++irh ) { + // Get the cluster from the rechit and loop over channels + RecHitClusterMap::const_iterator icl(clustersByHit_.find(*irh)); + const Phase2TrackerCluster1D* clusterPtr(0); + if ( icl==clustersByHit_.end() ) { + clusterPtr = &(*(**irh).cluster()); + clustersByHit_.insert(std::pair(*irh,clusterPtr)); + } + else { + clusterPtr = icl->second; + } + const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); + // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; // std::cout << "CommonHitInfo Checking RecHit at " << *irh // << " 1st strip " << (**irh).cluster()->firstStrip() // << " 1st row " << (**irh).cluster()->firstRow() // << " columns "<< (**irh).cluster()->column() // << " detid " << (**irh).geographicalId() << std::endl; bool matched(false); - // Get the cluster from the rechit and loop over channels - const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); - // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; for (unsigned int i(0); i < cluster.size(); ++i) { // std::cout << "CommonHitInfo channel " << i << std::endl; + // const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); + // // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; // find SimTracks contributing to the channel unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); std::vector simTrackIds = getSimTrackId(detId,channel); From e08a4beb39c017e5a570c42b369d5c9bf6caf033 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 19 Feb 2026 16:27:58 +0100 Subject: [PATCH 45/77] moving to ClusterSimTracks class --- HitAnalyzer/interface/ClusterSimTracks.h | 5 +-- HitAnalyzer/src/ClusterSimTracks.cc | 14 +++++--- HitAnalyzer/src/CommonHitInfo.cc | 44 +++++++++++++----------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/HitAnalyzer/interface/ClusterSimTracks.h b/HitAnalyzer/interface/ClusterSimTracks.h index 0829be5..5a5ac98 100644 --- a/HitAnalyzer/interface/ClusterSimTracks.h +++ b/HitAnalyzer/interface/ClusterSimTracks.h @@ -12,10 +12,11 @@ class ClusterSimTracks { public: - ClusterSimTracks(const Phase2TrackerCluster1D& cluster, const DetId& detId, const edm::DetSetVector& pixelSimLinks): + ClusterSimTracks(const Phase2TrackerCluster1D& cluster, const DetId& detId, + const edm::DetSetVector& pixelSimLinks): cluster_(cluster), detId_(detId), pixelSimLinks_(pixelSimLinks), channelsChecked_(0) {}; - std::set getSimTrackId(unsigned int channel) const; + std::set getSimTrackIds(unsigned int channel) const; bool listIsComplete() { // diff --git a/HitAnalyzer/src/ClusterSimTracks.cc b/HitAnalyzer/src/ClusterSimTracks.cc index affac7f..e31f1d9 100644 --- a/HitAnalyzer/src/ClusterSimTracks.cc +++ b/HitAnalyzer/src/ClusterSimTracks.cc @@ -4,7 +4,7 @@ // // return SimTrack ids for a given DetId / channel // -std::set ClusterSimTracks::getSimTrackId(unsigned int channel) const { +std::set ClusterSimTracks::getSimTrackIds(unsigned int channel) const { std::set result; edm::DetSetVector::const_iterator DSViter(pixelSimLinks_.find(detId_)); if (DSViter == pixelSimLinks_.end()) return result; @@ -37,11 +37,17 @@ bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) { // get channel number unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster_.firstRow() + channelsChecked_, cluster_.column())); // get SimTrackIds for this channel - std::set simTrackIds = getSimTrackId(channel); + std::set simTrackIds = getSimTrackIds(channel); matched = std::find(simTrackIds.begin(),simTrackIds.end(),simTrackId)!=simTrackIds.end(); - if ( matched ) break; + if ( matched ) { + std::cout << "ClusterSimTracks: break channel loop at channel " << channelsChecked_ + << " out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; + break; + } simTrackIds_.insert(simTrackIds.begin(),simTrackIds.end()); } + std::cout << "ClusterSimTracks: reached end of channel loop for cluster at " << &cluster_ + << " with size " << cluster_.size() << " ; matched = " << matched << std::endl; + return matched; }; - diff --git a/HitAnalyzer/src/CommonHitInfo.cc b/HitAnalyzer/src/CommonHitInfo.cc index e57c678..806d0f0 100644 --- a/HitAnalyzer/src/CommonHitInfo.cc +++ b/HitAnalyzer/src/CommonHitInfo.cc @@ -1,5 +1,6 @@ #include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" #include "DataFormats/DetId/interface/DetId.h" +#include "Phase2Tracking/HitAnalyzer/interface/ClusterSimTracks.h" // #include @@ -113,26 +114,29 @@ CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, clusterPtr = icl->second; } const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); - // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; - // std::cout << "CommonHitInfo Checking RecHit at " << *irh - // << " 1st strip " << (**irh).cluster()->firstStrip() - // << " 1st row " << (**irh).cluster()->firstRow() - // << " columns "<< (**irh).cluster()->column() - // << " detid " << (**irh).geographicalId() << std::endl; - bool matched(false); - for (unsigned int i(0); i < cluster.size(); ++i) { - // std::cout << "CommonHitInfo channel " << i << std::endl; - // const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); - // // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; - // find SimTracks contributing to the channel - unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); - std::vector simTrackIds = getSimTrackId(detId,channel); - // // std::cout << "CommonHitInfo " << simTrackIds.size() << " simTracks" << std::endl; - matched = std::find(simTrackIds.begin(),simTrackIds.end(),(*simHit).trackId())!=simTrackIds.end(); - // if match was found: consider RecHit - // std::cout << "CommonHitInfo matched : " << matched << std::endl; - if ( matched ) break; - } + + ClusterSimTracks cSimTrackIds(cluster,detId,*pixelSimLinks); + bool matched = cSimTrackIds.simTrackInCluster(simHit->trackId()); + // // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; + // // std::cout << "CommonHitInfo Checking RecHit at " << *irh + // // << " 1st strip " << (**irh).cluster()->firstStrip() + // // << " 1st row " << (**irh).cluster()->firstRow() + // // << " columns "<< (**irh).cluster()->column() + // // << " detid " << (**irh).geographicalId() << std::endl; + // bool matched(false); + // for (unsigned int i(0); i < cluster.size(); ++i) { + // // std::cout << "CommonHitInfo channel " << i << std::endl; + // // const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); + // // // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; + // // find SimTracks contributing to the channel + // unsigned int channel(Phase2TrackerDigi::pixelToChannel(cluster.firstRow() + i, cluster.column())); + // std::vector simTrackIds = getSimTrackId(detId,channel); + // // // std::cout << "CommonHitInfo " << simTrackIds.size() << " simTracks" << std::endl; + // matched = std::find(simTrackIds.begin(),simTrackIds.end(),(*simHit).trackId())!=simTrackIds.end(); + // // if match was found: consider RecHit + // // std::cout << "CommonHitInfo matched : " << matched << std::endl; + // if ( matched ) break; + // } // // select closest RecHit // From e766cd2570ae0454c98e6a0b9ef039406897f2ec Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 12 Mar 2026 17:37:45 +0100 Subject: [PATCH 46/77] extra dbg info --- HitAnalyzer/src/ClusterSimTracks.cc | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/HitAnalyzer/src/ClusterSimTracks.cc b/HitAnalyzer/src/ClusterSimTracks.cc index e31f1d9..1611b60 100644 --- a/HitAnalyzer/src/ClusterSimTracks.cc +++ b/HitAnalyzer/src/ClusterSimTracks.cc @@ -22,32 +22,45 @@ bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) { // Keep a (partial) cache of SimTrackIds // // - // Start with existing list + // Start with existing list. Return immediately if result is positive. // + std::cout << "ClusterSimTracks: called simTrackInCluster; currently at channel " << channelsChecked_ << + " out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; bool matched = std::find(simTrackIds_.begin(),simTrackIds_.end(),simTrackId)!=simTrackIds_.end(); + if ( matched ) std::cout << "ClusterSimTracks: found track in current list of " << channelsChecked_ << + " channels out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; + else if ( channelsChecked_>0 ) std::cout << "ClusterSimTracks: did not find track in current list of " << channelsChecked_ << + " channels out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; // // This is the final result if the list is complete // - if ( listIsComplete() ) return matched; + if ( listIsComplete() ) { + std::cout << "ClusterSimTracks: return result for complete channel list (" << cluster_.size() << + " channels) for cluster at " << &cluster_ << " ; matched = " << matched << std::endl; + return matched; + } // // Otherwise: loop over missing channels // // - while ( ++channelsChecked_ simTrackIds = getSimTrackIds(channel); matched = std::find(simTrackIds.begin(),simTrackIds.end(),simTrackId)!=simTrackIds.end(); + simTrackIds_.insert(simTrackIds.begin(),simTrackIds.end()); + channelsChecked_ += 1; if ( matched ) { - std::cout << "ClusterSimTracks: break channel loop at channel " << channelsChecked_ + // std::cout << "ClusterSimTracks: break channel loop at channel " << channelsChecked_ + std::cout << "ClusterSimTracks: break channel loop at channel " << (channelsChecked_-1) << " out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; break; } - simTrackIds_.insert(simTrackIds.begin(),simTrackIds.end()); } - std::cout << "ClusterSimTracks: reached end of channel loop for cluster at " << &cluster_ - << " with size " << cluster_.size() << " ; matched = " << matched << std::endl; + std::cout << "ClusterSimTracks: reached end of loop for " << cluster_.size() << + " channels for cluster at " << &cluster_ << " ; matched = " << matched << " " << listIsComplete() << std::endl; return matched; }; From d7546ededc53669e9d4c5001f575e06b57baa197 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 13 Mar 2026 17:00:14 +0100 Subject: [PATCH 47/77] remove by channel cache from ClusterSimTracks --- HitAnalyzer/interface/ClusterSimTracks.h | 24 ++--------- HitAnalyzer/src/ClusterSimTracks.cc | 54 ++++++++---------------- HitAnalyzer/src/RecHitInfo.cc | 28 ++++++------ 3 files changed, 37 insertions(+), 69 deletions(-) diff --git a/HitAnalyzer/interface/ClusterSimTracks.h b/HitAnalyzer/interface/ClusterSimTracks.h index 5a5ac98..cb9f9d5 100644 --- a/HitAnalyzer/interface/ClusterSimTracks.h +++ b/HitAnalyzer/interface/ClusterSimTracks.h @@ -14,35 +14,19 @@ class ClusterSimTracks { ClusterSimTracks(const Phase2TrackerCluster1D& cluster, const DetId& detId, const edm::DetSetVector& pixelSimLinks): - cluster_(cluster), detId_(detId), pixelSimLinks_(pixelSimLinks), channelsChecked_(0) {}; + cluster_(cluster), detId_(detId), pixelSimLinks_(pixelSimLinks), simTracksValid_(false) {}; - std::set getSimTrackIds(unsigned int channel) const; - - bool listIsComplete() { - // - // Return true if simTrackIds have been collected from all cluster channels - // - return channelsChecked_==cluster_.size(); - }; + std::set simTrackIdsPerChannel(unsigned int channel) const; bool simTrackInCluster(unsigned int simTrackId); - const std::set& simTrackIds() { - // - // List of all simTrackIds associated to cluster. - // Only available if listIsComplete() is true !!! - // - if ( not listIsComplete() ) - throw std::logic_error("ClusterSimTracks: trying to retrieve incomplete list of SimTrackIds"); - - return simTrackIds_; - }; + const std::set& simTrackIds(); private: const Phase2TrackerCluster1D& cluster_; const DetId& detId_; const edm::DetSetVector& pixelSimLinks_; - unsigned short channelsChecked_; + bool simTracksValid_; std::set simTrackIds_; }; #endif diff --git a/HitAnalyzer/src/ClusterSimTracks.cc b/HitAnalyzer/src/ClusterSimTracks.cc index 1611b60..3c215eb 100644 --- a/HitAnalyzer/src/ClusterSimTracks.cc +++ b/HitAnalyzer/src/ClusterSimTracks.cc @@ -4,7 +4,7 @@ // // return SimTrack ids for a given DetId / channel // -std::set ClusterSimTracks::getSimTrackIds(unsigned int channel) const { +std::set ClusterSimTracks::simTrackIdsPerChannel(unsigned int channel) const { std::set result; edm::DetSetVector::const_iterator DSViter(pixelSimLinks_.find(detId_)); if (DSViter == pixelSimLinks_.end()) return result; @@ -19,48 +19,30 @@ std::set ClusterSimTracks::getSimTrackIds(unsigned int channel) co bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) { // // Return true if contributed to one or more channels of - // Keep a (partial) cache of SimTrackIds // + // caching handled by simTrackIds() // - // Start with existing list. Return immediately if result is positive. - // - std::cout << "ClusterSimTracks: called simTrackInCluster; currently at channel " << channelsChecked_ << - " out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; - bool matched = std::find(simTrackIds_.begin(),simTrackIds_.end(),simTrackId)!=simTrackIds_.end(); - if ( matched ) std::cout << "ClusterSimTracks: found track in current list of " << channelsChecked_ << - " channels out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; - else if ( channelsChecked_>0 ) std::cout << "ClusterSimTracks: did not find track in current list of " << channelsChecked_ << - " channels out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; + const std::set& trackIds = simTrackIds(); + + return std::find(trackIds.begin(),trackIds.end(),simTrackId)!=trackIds.end(); +}; + +const std::set& ClusterSimTracks::simTrackIds() { // - // This is the final result if the list is complete + // List of all SimTrackIds associated to this cluster // - if ( listIsComplete() ) { - std::cout << "ClusterSimTracks: return result for complete channel list (" << cluster_.size() << - " channels) for cluster at " << &cluster_ << " ; matched = " << matched << std::endl; - return matched; - } + if ( simTracksValid_ ) return simTrackIds_; // - // Otherwise: loop over missing channels + // Loop over all channels // - // - while ( channelsChecked_ simTrackIds = getSimTrackIds(channel); - matched = std::find(simTrackIds.begin(),simTrackIds.end(),simTrackId)!=simTrackIds.end(); - simTrackIds_.insert(simTrackIds.begin(),simTrackIds.end()); - channelsChecked_ += 1; - if ( matched ) { - // std::cout << "ClusterSimTracks: break channel loop at channel " << channelsChecked_ - std::cout << "ClusterSimTracks: break channel loop at channel " << (channelsChecked_-1) - << " out of " << cluster_.size() << " for cluster at " << &cluster_ << std::endl; - break; - } + std::set trackIds(simTrackIdsPerChannel(channel)); + simTrackIds_.insert(trackIds.begin(),trackIds.end()); } - std::cout << "ClusterSimTracks: reached end of loop for " << cluster_.size() << - " channels for cluster at " << &cluster_ << " ; matched = " << matched << " " << listIsComplete() << std::endl; - - return matched; + + simTracksValid_ = true; + return simTrackIds_; }; diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index da69597..7fe4085 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -1,4 +1,5 @@ #include "Phase2Tracking/HitAnalyzer/interface/RecHitInfo.h" +#include "Phase2Tracking/HitAnalyzer/interface/ClusterSimTracks.h" #include "DataFormats/DetId/interface/DetId.h" #include "DataFormats/Phase2TrackerCluster/interface/Phase2TrackerCluster1D.h" #include "SimDataFormats/Track/interface/SimTrackContainer.h" @@ -125,19 +126,20 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in const Phase2TrackerCluster1D* clustIt = &*recHit.cluster(); // Get all the simTracks that form the cluster - std::set clusterSimTrackIds; - for (unsigned int i(0); i < clustIt->size(); ++i) { - unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); - // std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); - std::vector simTrackIds_unselected(getSimTrackId(detId, channel)); - std::vector simTrackIds; - for (auto istId : simTrackIds_unselected) { - std::map::const_iterator istfind(simTracksById_->find(istId)); - if (istfind != simTracksById_->end()) - simTrackIds.push_back(istId); - } - clusterSimTrackIds.insert(simTrackIds.begin(),simTrackIds.end()); - } + ClusterSimTracks cSimTrackIds(*clustIt,detId,*pixelSimLinks); + const std::set& clusterSimTrackIds = cSimTrackIds.simTrackIds(); + // for (unsigned int i(0); i < clustIt->size(); ++i) { + // unsigned int channel(Phase2TrackerDigi::pixelToChannel(clustIt->firstRow() + i, clustIt->column())); + // // std::vector simTrackIds_unselected(getSimTrackId(*pixelSimLinks, detId, channel)); + // std::vector simTrackIds_unselected(getSimTrackId(detId, channel)); + // std::vector simTrackIds; + // for (auto istId : simTrackIds_unselected) { + // std::map::const_iterator istfind(simTracksById_->find(istId)); + // if (istfind != simTracksById_->end()) + // simTrackIds.push_back(istId); + // } + // clusterSimTrackIds.insert(simTrackIds.begin(),simTrackIds.end()); + // } // debug // if ( clusterSimTrackIds.size()==0 ) { // std::cout << "** RecHit without SimTrackIds on detId " << rawid << " layer " << layer From fca2da283ec1dbcb4f29267d1450868c802d622b Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 17 Mar 2026 17:16:22 +0100 Subject: [PATCH 48/77] fix use of ClusterSimTracks --- HitAnalyzer/interface/ClusterSimTracks.h | 39 +++++++++++++++------ HitAnalyzer/interface/CommonHitInfo.h | 5 ++- HitAnalyzer/plugins/RecHitTreeWA.cc | 26 +++++++++++++- HitAnalyzer/src/ClusterSimTracks.cc | 4 +-- HitAnalyzer/src/CommonHitInfo.cc | 44 +++++++++++++++++++++--- HitAnalyzer/src/RecHitInfo.cc | 4 +-- HitAnalyzer/src/SimHitInfo.cc | 2 +- HitAnalyzer/test/rechittreewa_tt_cfg.py | 11 +++--- 8 files changed, 107 insertions(+), 28 deletions(-) diff --git a/HitAnalyzer/interface/ClusterSimTracks.h b/HitAnalyzer/interface/ClusterSimTracks.h index cb9f9d5..e84dfd0 100644 --- a/HitAnalyzer/interface/ClusterSimTracks.h +++ b/HitAnalyzer/interface/ClusterSimTracks.h @@ -9,24 +9,41 @@ #include "DataFormats/Common/interface/DetSetVector.h" class ClusterSimTracks { - + // + // Class to return (and cache) SimTrack ids for a cluster + // public: - + ClusterSimTracks(const Phase2TrackerCluster1D& cluster, const DetId& detId, const edm::DetSetVector& pixelSimLinks): cluster_(cluster), detId_(detId), pixelSimLinks_(pixelSimLinks), simTracksValid_(false) {}; + // + // Get SimTrack ids for specific channel + // std::set simTrackIdsPerChannel(unsigned int channel) const; - - bool simTrackInCluster(unsigned int simTrackId); - - const std::set& simTrackIds(); + // + // Check if SimTrack id contributed to cluster + // + bool simTrackInCluster(unsigned int simTrackId) const; + // + // All SimTrack ids contributing to cluster + // + const std::set& simTrackIds() const; + // + // Access to DetId (for reference) + // + const DetId& detId() const {return detId_;}; + // + // Verify if DetId matches with current object + // + bool sameDet(const DetId& detId) const {return detId_==detId;}; private: - const Phase2TrackerCluster1D& cluster_; - const DetId& detId_; - const edm::DetSetVector& pixelSimLinks_; - bool simTracksValid_; - std::set simTrackIds_; + const Phase2TrackerCluster1D& cluster_; // Pointer to cluster + const DetId detId_; // DetId (for reference) + const edm::DetSetVector& pixelSimLinks_; // PixelDigiSimLinks for finding SimTrack contributions + mutable bool simTracksValid_; // Has cache been filled? + mutable std::set simTrackIds_; // Cache of all SimTrack ids }; #endif diff --git a/HitAnalyzer/interface/CommonHitInfo.h b/HitAnalyzer/interface/CommonHitInfo.h index fd6bf0d..5689f04 100644 --- a/HitAnalyzer/interface/CommonHitInfo.h +++ b/HitAnalyzer/interface/CommonHitInfo.h @@ -8,6 +8,7 @@ #include "SimDataFormats/TrackerDigiSimLink/interface/PixelDigiSimLink.h" #include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h" #include "SimDataFormats/Track/interface/SimTrack.h" +#include "Phase2Tracking/HitAnalyzer/interface/ClusterSimTracks.h" #include "DataFormats/Math/interface/Point3D.h" #include "DataFormats/Math/interface/Vector3D.h" @@ -33,6 +34,8 @@ class CommonHitInfo { typedef std::map TrackIdSimTrackMap; + typedef std::map ClusterSimTracksMap; + CommonHitInfo() { tTopo_ = 0; tkGeom_ = 0; @@ -92,7 +95,7 @@ class CommonHitInfo { DetSimHitsMap simHitsPerDet_; DetRecHitsMap recHitsPerDet_; RecHitClusterMap clustersByHit_; - + ClusterSimTracksMap cstByCluster_; }; #endif diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index 1e7c10d..160c14b 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -272,11 +272,27 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event recHitInfo_.setupEvent(tTopo,tkGeom,pixelSimLinks.product(),rhInfoSimHitsRaw,*rechits.product(),&simTracks); for (Phase2TrackerRecHit1DCollectionNew::const_iterator DSViter = rechits->begin(); DSViter != rechits->end(); ++DSViter) { + // for (auto detHitsIt=recHitInfo_.recHitsPerDet().begin(); detHitsIt!=recHitInfo_.recHitsPerDet().end(); ++detHitsIt ) { + // DetId detId(detHitsIt->first); + // unsigned int rawid(detId.rawId()); + // unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides + // layer += tTopo->layer(detId); + // TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); + // // Restrict to Phase2 OT + // if ( mType!=TrackerGeometry::ModuleType::Ph2PSP && + // mType!=TrackerGeometry::ModuleType::Ph2PSS && + // mType!=TrackerGeometry::ModuleType::Ph2SS ) continue; + // Get the detector unit's id unsigned int rawid(DSViter->detId()); DetId detId(rawid); unsigned int layer = (tTopo->side(detId) != 0) * 1000; // don't split up endcap sides layer += tTopo->layer(detId); + TrackerGeometry::ModuleType mType = tkGeom->getDetectorType(detId); + // Restrict to Phase2 OT + if ( mType!=TrackerGeometry::ModuleType::Ph2PSP && + mType!=TrackerGeometry::ModuleType::Ph2PSS && + mType!=TrackerGeometry::ModuleType::Ph2SS ) continue; // Get the geomdet const GeomDetUnit* geomDetUnit(tkGeom->idToDetUnit(detId)); @@ -286,9 +302,17 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event // recHitInfo_.setTopology(tTopo); // recHitInfo_.setGeometry(tkGeom); + std::cout << "Found " << DSViter->size() << " RecHits on DetId " << rawid << std::endl << std::flush; + // // Loop over the rechits in the detector unit + // for (edmNew::DetSet::const_iterator rechitIt = DSViter->begin(); - rechitIt != DSViter->end(); ++rechitIt) { + rechitIt != DSViter->end(); ++rechitIt) { + // // + // // loop over RecHits on Det + // // + // for (auto rechitIt=detHitsIt->second.begin(); rechitIt!=detHitsIt->second.end(); ++rechitIt) { + // std::cout << "Filling sim hit info" << std::endl; recHitInfo_.fillRecHitInfo(*rechitIt,rawid,geomDetUnit, // &pixelSimLinks,simTracks, rhInfoSimHitsRaw,debugHitMatch_); } diff --git a/HitAnalyzer/src/ClusterSimTracks.cc b/HitAnalyzer/src/ClusterSimTracks.cc index 3c215eb..16f7b8a 100644 --- a/HitAnalyzer/src/ClusterSimTracks.cc +++ b/HitAnalyzer/src/ClusterSimTracks.cc @@ -16,7 +16,7 @@ std::set ClusterSimTracks::simTrackIdsPerChannel(unsigned int chan return result; }; -bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) { +bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) const { // // Return true if contributed to one or more channels of // @@ -27,7 +27,7 @@ bool ClusterSimTracks::simTrackInCluster(unsigned int simTrackId) { return std::find(trackIds.begin(),trackIds.end(),simTrackId)!=trackIds.end(); }; -const std::set& ClusterSimTracks::simTrackIds() { +const std::set& ClusterSimTracks::simTrackIds() const { // // List of all SimTrackIds associated to this cluster // diff --git a/HitAnalyzer/src/CommonHitInfo.cc b/HitAnalyzer/src/CommonHitInfo.cc index 806d0f0..fa0540f 100644 --- a/HitAnalyzer/src/CommonHitInfo.cc +++ b/HitAnalyzer/src/CommonHitInfo.cc @@ -1,6 +1,5 @@ #include "Phase2Tracking/HitAnalyzer/interface/CommonHitInfo.h" #include "DataFormats/DetId/interface/DetId.h" -#include "Phase2Tracking/HitAnalyzer/interface/ClusterSimTracks.h" // #include @@ -25,7 +24,7 @@ void CommonHitInfo::fillSimHitsPerDet(const std::vectorsize() << std::endl; + // // std::cout<< simhitidx << " " << simHitsRaw[simhitidx]->size() << std::endl; // for (edm::PSimHitContainer::const_iterator simhitIt(simHitsRaw[simhitidx]->begin()); // simhitIt != simHitsRaw[simhitidx]->end(); ++simhitIt) { // loop over both barrel and endcap hits @@ -98,8 +97,27 @@ CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, // << simHit->localPosition().x() << " / " << simHit->localPosition().y() << std::endl; // const Phase2TrackerRecHit1D* rechit(0); // std::vector< const Phase2TrackerRecHit1D* rechit(0); + // + // prepare result + // CommonHitInfo::RecHitDistancePairs matchedRecHits; - + // + // restart cache of ClusterSimTracks objects with new detid (only useful + // if SimHits on same Det are treated in sequence) + // + if ( cstByCluster_.size()>0 ) { + const ClusterSimTracks& cst = cstByCluster_.begin()->second; + // std::cout << " Existing *detId = " << &cst.detId() << " " << cst.detId().rawId() << + // " / new *detId = " << &detId << " " << detId.rawId() << std::endl; + if ( !cst.sameDet(detId) ) { + // std::cout << " Changed DetId" << std::endl; + cstByCluster_.clear(); + } + } + // else { + // std::cout << " cstByCluster is empty" << std::endl; + // } + // float dxmin(1.e30); for ( std::vector::const_iterator irh=detRecHits.begin(); irh!=detRecHits.end(); ++irh ) { @@ -115,8 +133,23 @@ CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, } const Phase2TrackerCluster1D& cluster = *(**irh).cluster(); - ClusterSimTracks cSimTrackIds(cluster,detId,*pixelSimLinks); - bool matched = cSimTrackIds.simTrackInCluster(simHit->trackId()); + const ClusterSimTracks* cst(0); + ClusterSimTracksMap::const_iterator cstit = cstByCluster_.find(&cluster); + // std::cout << " #entries of cstByCluster_ = " << cstByCluster_.size() << std::endl; + // for ( auto it=cstByCluster_.begin(); it!=cstByCluster_.end(); ++it ) + // std::cout << " cluster pointer = " << it->first << " cst pointer " << &(it->second) + // << " rawid " << (it->second).detId().rawId() << std::endl; + if ( cstit==cstByCluster_.end() ) { + // std::cout << " Adding CST for cluster at " << &cluster << " on det " << detId << std::endl; + cstit = + cstByCluster_.insert({&cluster,ClusterSimTracks(cluster,detId,*pixelSimLinks)}).first; + } + // else { + // std::cout << " Reusing CST for cluster at " << &cluster << " on det " << detId << std::endl; + // } + cst = &(cstit->second); + // ClusterSimTracks cSimTrackIds(cluster,detId,*pixelSimLinks); + bool matched = cst->simTrackInCluster(simHit->trackId()); // // std::cout << "CommonHitInfo cluster size " << cluster.size() << std::endl; // // std::cout << "CommonHitInfo Checking RecHit at " << *irh // // << " 1st strip " << (**irh).cluster()->firstStrip() @@ -161,3 +194,4 @@ CommonHitInfo::matchRecHitOnDet(const PSimHit* simHit, const DetId& detId, }); return matchedRecHits; }; + diff --git a/HitAnalyzer/src/RecHitInfo.cc b/HitAnalyzer/src/RecHitInfo.cc index 7fe4085..1e3a7c4 100644 --- a/HitAnalyzer/src/RecHitInfo.cc +++ b/HitAnalyzer/src/RecHitInfo.cc @@ -167,7 +167,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in // ++simhitIt) { // std::cout << "#hits ="; - std::cout << clusterSimTrackIds.size() << " trackIds for cluster" << std::endl; + // std::cout << clusterSimTrackIds.size() << " trackIds for cluster" << std::endl; for (auto simhitsIt=simHitsRaw.begin(); simhitsIt!=simHitsRaw.end(); ++simhitsIt) { // std::cout << " " << (**simhitsIt).size(); for (auto simhitIt=(**simhitsIt).begin(); simhitIt!=(**simhitsIt).end(); ++simhitIt) { @@ -185,7 +185,7 @@ void RecHitInfo::fillRecHitInfo(const Phase2TrackerRecHit1D& recHit, unsigned in } } } - std::cout << " hasSimHit " << (simhit!=0) << std::endl; + // std::cout << " hasSimHit " << (simhit!=0) << std::endl; if ( debugHitMatch ) { if ( trackSimHits.size()==0 || trackSimHits.size()>1 ) { TrackerGeometry::ModuleType mType = tkGeom_->getDetectorType(detId); diff --git a/HitAnalyzer/src/SimHitInfo.cc b/HitAnalyzer/src/SimHitInfo.cc index af90580..a89040e 100644 --- a/HitAnalyzer/src/SimHitInfo.cc +++ b/HitAnalyzer/src/SimHitInfo.cc @@ -190,7 +190,7 @@ void SimHitInfo::fillSimHitInfo(const PSimHit& simHit) { // Get the detector unit's id // unsigned int rawid(simHit.detUnitId()); - std::cout << " Filling SimHitInfo for hit on DetId " << rawid << std::endl; + // std::cout << " Filling SimHitInfo for hit on DetId " << rawid << std::endl; DetId detId(rawid); unsigned int layer = (tTopo_->side(detId) != 0) * 1000; // don't split up endcap sides layer += tTopo_->layer(detId); diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index 24c51e6..ef7abb5 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -17,8 +17,8 @@ # Number of events (-1 = all) process.maxEvents = cms.untracked.PSet( - #input = cms.untracked.int32(-1) - input = cms.untracked.int32(2) + input = cms.untracked.int32(-1) + #input = cms.untracked.int32(2) ) # Input file @@ -31,8 +31,9 @@ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root') fileNames = cms.untracked.vstring( - '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ - '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ + 'file:/eos/user/a/adamw/CMSAnalysis/DPG/Phase2Tracking/Data/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root' + # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ + # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/3db44076-4bb3-415b-b3a9-feb742460636.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/41d76683-9927-42e5-8c22-dfa056c56294.root', \ @@ -80,7 +81,7 @@ #MakeEtaPlots = cms.bool(False), #MinEta = cms.double(0.), #MaxEta = cms.double(10.) - debugHitMatch = cms.bool(True), + debugHitMatch = cms.bool(False), simHitInfo = cms.PSet( simHits = cms.VInputTag( cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelLowTof"), From 64f207968cbc0dc890990360ba3299b802b4d081 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 1 Apr 2026 16:55:20 +0200 Subject: [PATCH 49/77] fix fitRes for 1D histograms --- DrawHits/fitRes.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 3f43967..0293382 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -209,6 +209,8 @@ def findRootSpline(self,value,eps=0.001): yl = spline.Eval(xl) xh = spline.GetXmax() yh = spline.Eval(xh) + ymin = yl + ymax = yh if ymin>=ymax: print("findRootSpline: last value <= first value") return None @@ -439,15 +441,16 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No fwhmArrow.SetLineColor(2) fwhmArrow.SetLineWidth(2) quantLines = [ ] -for i in range(len(args.quantile)): +for i in range(len(args.quantile)+1): quantLine = ROOT.TLine() - quantLine.SetLineColor(4) + quantLine.SetLineColor(4-i) #quantLine.SetLineWidth(2) - quantLine.SetLineStyle(i+1) + #quantLine.SetLineStyle(i+1) quantLines.append(quantLine) #quantLine.SetLineWidth(2) if fitCanvas.histogram().GetDimension()==1 and ( not args.slices ): assert fitCanvas.histogram().GetDimension()==1 + slices = [ fitCanvas.fhist ] #print(fitCanvas.fwhm()) x1,x2,y = fitCanvas.fwhm() print(" = {:6.1f}um, dx = {:6.1f}um, sig = {:6.1f}um ( interval {:6.4f} - {:6.4f}cm )".format( \ @@ -467,9 +470,14 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No #print(sigma,sgn,p,qs[-1]) quantiles.append(qs) if not ( None in qs ): - quantLines[isigma].DrawLine(qs[0],0.,qs[0],qlmax) - quantLines[0].DrawLine(qs[1],0.,qs[1],qlmax) - quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) + for iq in range(3): + il = 0 if iq==1 else isigma+1 + h = slices[-1].hist + qlmax = h.GetBinContent(h.FindBin(qs[iq])) + quantLines[il].DrawLine(qs[iq],0.,qs[iq],qlmax) + #quantLines[isigma].DrawLine(qs[0],0.,qs[0],qlmax) + #quantLines[0].DrawLine(qs[1],0.,qs[1],qlmax) + #quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) fitCanvas.pad.Update() From eabac6817bd07b67476c472d5e87334ce72088d3 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 1 Apr 2026 16:57:51 +0200 Subject: [PATCH 50/77] added some histogram fitting to drawHitsRDF --- DrawHits/drawHitsRDF.py | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 5852301..5901df0 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -95,6 +95,8 @@ def fitHistogram(mType,h): f2.SetParameter(5,5*f1.GetParameter(2)) f2.SetParLimits(5,f1.GetParameter(2),10*f1.GetParameter(2)) h.Fit(f2name) + func = h.GetFunction(f2name) + func.SetLineWidth(5) ROOT.gPad.SetLogy(1) ROOT.gPad.Update() @@ -442,11 +444,13 @@ def drawHistoByDef(histos,hDef,logY=False,logZ=False,same=False): histos[mType][2].GetYaxis().SetTitle(ytitle) histos[mType][3] = ROOT.TEfficiency(histos[mType][1].GetValue(),histos[mType][0].GetValue()) histos[mType][3].SetMarkerStyle(20) + histos[mType][3].SetLineWidth(3) histos[mType][3].Draw("same Z") else: histos[mType][0].SetTitle(hTitle) histos[mType][0].GetXaxis().SetTitle(xtitle) histos[mType][0].GetYaxis().SetTitle(ytitle) + histos[mType][0].SetLineWidth(3) histos[mType][0].Draw("same" if same else "") fitFunc = hDef.getParameter('fit') if fitFunc!=None: @@ -674,6 +678,25 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): fillHistoByDef(simHitTree,allHDefs.byCanvas[cName][hName],extraCuts,allHistos[cName][hName]) allObjects.append(drawHistoByDef(allHistos[cName][hName],allHDefs.byCanvas[cName][hName], \ logY=args.logY,logZ=args.logZ,same=same)) + #!# + print(allHDefs.byCanvas[cName][hName]) + print(allHDefs.byCanvas[cName][hName].name) + hdef = allHDefs.byCanvas[cName][hName] + fitHisto = False + for fr in fitResiduals: + if fnmatch(hdef.name,fr): + fitHisto = True + break + if fitHisto: + objects = allObjects[-1] + cnv = objects['cnv'] + # fit and redraw each panel + ic = 0 + for mType in range(23,26): + ic += 1 + cnv.cd(ic) + f = fitHistogram(mType,objects['histos'][mType][0]) + #!# same = True if args.output!=None: c = allObjects[-1]['cnv'] @@ -690,3 +713,22 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): # yMin = min([ x.GetMinimum() for x in cHistos #sys.exit() +#!# allObjects = [ ] +#!# for hdef in allHDefs.allDefinitions.values(): +#!# # +#!# # draw histograms according to definition +#!# # +#!# histos = fillHistoByDef(simHitTree,hdef,extraCuts) +#!# allObjects.append(drawHistoByDef(histos,hdef)) +#!# # +#!# # perform fit of resolution histogram +#!# # +#!# if hdef.name in fitResiduals: +#!# objects = allObjects[-1] +#!# cnv = objects['cnv'] +#!# # fit and redraw each panel +#!# ic = 0 +#!# for mType in range(23,26): +#!# ic += 1 +#!# cnv.cd(ic) +#!# f = fitHistogram(mType,objects['histos'][mType][0]) From 9e979e4b93542a208db7f2604285db07cd084ebf Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 1 Apr 2026 16:59:09 +0200 Subject: [PATCH 51/77] removed debug output in RecHitTreeWA --- HitAnalyzer/plugins/RecHitTreeWA.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HitAnalyzer/plugins/RecHitTreeWA.cc b/HitAnalyzer/plugins/RecHitTreeWA.cc index 160c14b..376521a 100644 --- a/HitAnalyzer/plugins/RecHitTreeWA.cc +++ b/HitAnalyzer/plugins/RecHitTreeWA.cc @@ -225,8 +225,8 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event std::cout << "*** did not find geomDetUnit ***" << std::endl; continue; } - std::cout << "Found " << detHitsIt->second.size() << " SimHits on DetId " << detHitsIt->first - << std::endl << std::flush; + // std::cout << "Found " << detHitsIt->second.size() << " SimHits on DetId " << detHitsIt->first + // << std::endl << std::flush; // // loop over SimHits on Det // @@ -302,7 +302,7 @@ void RecHitTreeWA::analyze(const edm::Event& event, const edm::EventSetup& event // recHitInfo_.setTopology(tTopo); // recHitInfo_.setGeometry(tkGeom); - std::cout << "Found " << DSViter->size() << " RecHits on DetId " << rawid << std::endl << std::flush; + // std::cout << "Found " << DSViter->size() << " RecHits on DetId " << rawid << std::endl << std::flush; // // Loop over the rechits in the detector unit // From 00efbd81ebe7437ea08e08dcf72b2241d9161426 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 1 Apr 2026 17:20:02 +0200 Subject: [PATCH 52/77] fit all 3 module types at once --- DrawHits/fitRes.py | 88 +++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 0293382..ced3547 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -399,7 +399,8 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument('--moduleType', '-m', help='module type', type=int, choices=[23,24,25], default=23) +#parser.add_argument('--moduleType', '-m', help='module type', type=int, choices=[23,24,25], default=23) +parser.add_argument('--moduleTypes', '-m', help='comma-separated list of module types', type=str, default="23,24,25") parser.add_argument('--fwhm', help='determining FWHM', action='store_true', default=False) parser.add_argument('--slices', '-s', help='fit in slices in y', action='store_true', default=False) parser.add_argument('--quantile', '-q', help='calculate quantiles corresponding to +- x sigma (can be repeated)', \ @@ -414,6 +415,10 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No parser.add_argument('file', help='input file', type=str, nargs=1, default=None) args = parser.parse_args() +moduleTypes = sorted(set([ int(x) for x in args.moduleTypes.split(",") ])) +assert moduleTypes[0]>=23 and moduleTypes[-1]<=25 +moduleType = moduleTypes[0] + tf = ROOT.TFile(args.file[0]) tf.ls() mainCnv = None @@ -436,7 +441,9 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No slices = [ ] mainCnv.Draw() -fitCanvas = FitCanvas(mainCnv,args.moduleType) +fitCanvases = { x:FitCanvas(mainCnv,x) for x in moduleTypes } +fitCanvas = fitCanvases[moduleType] +#fitCanvas = FitCanvas(mainCnv,moduleType) fwhmArrow = ROOT.TArrow() fwhmArrow.SetLineColor(2) fwhmArrow.SetLineWidth(2) @@ -449,37 +456,44 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No quantLines.append(quantLine) #quantLine.SetLineWidth(2) if fitCanvas.histogram().GetDimension()==1 and ( not args.slices ): - assert fitCanvas.histogram().GetDimension()==1 - slices = [ fitCanvas.fhist ] - #print(fitCanvas.fwhm()) - x1,x2,y = fitCanvas.fwhm() - print(" = {:6.1f}um, dx = {:6.1f}um, sig = {:6.1f}um ( interval {:6.4f} - {:6.4f}cm )".format( \ - 10000*(x1+x2)/2.,10000*(x2-x1),10000*(x2-x1)/2/sqrt(2*log(2)),x1,x2)) - - fitCanvas.pad.cd() - fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") - - quantiles = [ ] - qlmax = slices[-1].hist.GetMaximum()/10. - for isigma,sigma in enumerate(args.quantile): - qs = [ ] - for sgn in [-1,0,1]: - p = ROOT.TMath.Freq(sgn*sigma) - #qs.append(slices[-1].quantile(p)) - qs.append(slices[-1].findRootSpline(p)) - #print(sigma,sgn,p,qs[-1]) - quantiles.append(qs) - if not ( None in qs ): - for iq in range(3): - il = 0 if iq==1 else isigma+1 - h = slices[-1].hist - qlmax = h.GetBinContent(h.FindBin(qs[iq])) - quantLines[il].DrawLine(qs[iq],0.,qs[iq],qlmax) - #quantLines[isigma].DrawLine(qs[0],0.,qs[0],qlmax) - #quantLines[0].DrawLine(qs[1],0.,qs[1],qlmax) - #quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) - - fitCanvas.pad.Update() + for im in moduleTypes: + print("Module type",im) + fc = fitCanvases[im] + assert fc.histogram().GetDimension()==1 + slices = [ fc.fhist ] + #print(fc.fwhm()) + x1,x2,y = fc.fwhm() + print(" FWHM: = {:6.1f}um, dx = {:6.1f}um, sig = {:6.1f}um ( interval {:6.4f} - {:6.4f}cm )".format( \ + 10000*(x1+x2)/2.,10000*(x2-x1),10000*(x2-x1)/2/sqrt(2*log(2)),x1,x2)) + + fc.pad.cd() + fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") + + quantiles = [ ] + qlmax = slices[-1].hist.GetMaximum()/10. + for isigma,sigma in enumerate(args.quantile): + qs = [ ] + for sgn in [-1,0,1]: + p = ROOT.TMath.Freq(sgn*sigma) + #qs.append(slices[-1].quantile(p)) + qs.append(slices[-1].findRootSpline(p)) + #print(sigma,sgn,p,qs[-1]) + quantiles.append(qs) + if not ( None in qs ): + for iq in range(3): + il = 0 if iq==1 else isigma+1 + h = slices[-1].hist + qlmax = h.GetBinContent(h.FindBin(qs[iq])) + quantLines[il].DrawLine(qs[iq],0.,qs[iq],qlmax) + line = " from sigma = {:3.1f} quantile: ".format(sigma) + line += "median = {:6.1f}um, half-width/sigma = {:6.1f}um".format(10000*qs[1], \ + 10000*(qs[2]-qs[0])/2/sigma) + print(line) + #quantLines[isigma].DrawLine(qs[0],0.,qs[0],qlmax) + #quantLines[0].DrawLine(qs[1],0.,qs[1],qlmax) + #quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) + + fc.pad.Update() elif fitCanvas.histogram().GetDimension()==2 and args.slices: hist2D = fitCanvas.histogram() @@ -617,7 +631,7 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No while nrow*ncol1: hResTitle += " {:6.3f}1: @@ -759,7 +773,7 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No # create from histogram name (remove version number last "_", split of last two digits (mod. type) cName = "c"+"_".join(h.GetName()[1:].split("_")[:-1]) cName = cName[:-2] + "_mT" + cName[-2:] + "_MeanWidth" - cName = "cResMeanWidth_mT"+str(args.moduleType) + cName = "cResMeanWidth_mT"+str(moduleType) c = ROOT.TCanvas(cName,h.GetTitle()+" (mean/width summary)",500*nsigma,1000) c.Divide(nsigma+1,2) From ba5e1da3339f4d3061b08c9e6b4384775b5df7c4 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 2 Apr 2026 16:49:45 +0200 Subject: [PATCH 53/77] adding width summaries for 1D residuals (in progress) --- DrawHits/fitRes.py | 49 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index ced3547..07188fa 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -351,6 +351,22 @@ def setHistogramMinMax(histo,limits,margins=0.05): return (vmin,vmax) +def defineWidthVsSigma(h,sigmas): + hwName = h.GetName()+"Qw1D" + hwTitle = h.GetTitle()+" (half-width from quantiles)" + hwAxis1Title = "quantiles in units of #sigmas" + hwAxis2Title = "half width from quantiles" + hhalfwidth = ROOT.TH1F(hwName,hwTitle,len(sigmas),-0.5,len(sigmas)-0.5) + hhalfwidth.SetStats(0) + hhalfwidth.SetMinimum(0.) + hhalfwidth.GetXaxis().SetTitle(hwAxis1Title) + hhalfwidth.GetYaxis().SetTitle(hwAxis2Title) + xaxis = hhalfwidth.GetXaxis() + for i,s in enumerate(sigmas): + xaxis.SetBinLabel(i+1,"{:3.1f}#sigma".format(s)) + + return hhalfwidth + def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=None): if isigma!=None: y1 = ROOT.TMath.Freq(-sigma) @@ -456,9 +472,11 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No quantLines.append(quantLine) #quantLine.SetLineWidth(2) if fitCanvas.histogram().GetDimension()==1 and ( not args.slices ): + summaries = [ ] for im in moduleTypes: print("Module type",im) fc = fitCanvases[im] + print(type(fc)) assert fc.histogram().GetDimension()==1 slices = [ fc.fhist ] #print(fc.fwhm()) @@ -469,6 +487,11 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No fc.pad.cd() fwhmArrow.DrawArrow(x1,y,x2,y,0.005,"<>") + # + # define summary histograms + # + summaries.append(defineWidthVsSigma(fc.histogram(),args.quantile)) + quantiles = [ ] qlmax = slices[-1].hist.GetMaximum()/10. for isigma,sigma in enumerate(args.quantile): @@ -477,6 +500,7 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No p = ROOT.TMath.Freq(sgn*sigma) #qs.append(slices[-1].quantile(p)) qs.append(slices[-1].findRootSpline(p)) + print(sigma,sgn,type(slices[-1])) #print(sigma,sgn,p,qs[-1]) quantiles.append(qs) if not ( None in qs ): @@ -488,13 +512,34 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No line = " from sigma = {:3.1f} quantile: ".format(sigma) line += "median = {:6.1f}um, half-width/sigma = {:6.1f}um".format(10000*qs[1], \ 10000*(qs[2]-qs[0])/2/sigma) - print(line) + print(line) + summaries[-1].SetBinContent(isigma+1,10000*(qs[2]-qs[0])/2/sigma) #quantLines[isigma].DrawLine(qs[0],0.,qs[0],qlmax) #quantLines[0].DrawLine(qs[1],0.,qs[1],qlmax) #quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) + else: + print("(At least) one quantile computation failed: sigma =",sigma," p =",ROOT.TMath.Freq(-sigma),qs) fc.pad.Update() + nmod = len(moduleTypes) + cName = "c"+"_".join(h.GetName()[1:].split("_")[:-1]) + cName = cName[:-2] + "_mT" + cName[-2:] + "_Widths" + cName = "cResWidths_mT"+str(moduleType) + c = ROOT.TCanvas(cName,h.GetTitle()+" (width summary)",500*nmod,500) + c.Divide(nmod,1) + # set common maximum for all plots + hmax = max([ x.GetMaximum() for x in summaries ]) + for i in range(nmod): + c.cd(i+1) + #setHistogramMinMax(summaries[i],(-250,250),margins=0.05) + summaries[i].SetMaximum(hmax*1.05) + summaries[i].Draw("HIST") + ROOT.gPad.Update() + c.Update() + if args.output!=None: + saveCanvas(c,args.file[0],args.output,outputFormats) + elif fitCanvas.histogram().GetDimension()==2 and args.slices: hist2D = fitCanvas.histogram() assert hist2D.GetDimension()==2 @@ -771,10 +816,10 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No nsigma = len(args.quantile) # create from histogram name (remove version number last "_", split of last two digits (mod. type) + cName = "c"+"_".join(h.GetName()[1:].split("_")[:-1]) cName = cName[:-2] + "_mT" + cName[-2:] + "_MeanWidth" cName = "cResMeanWidth_mT"+str(moduleType) - c = ROOT.TCanvas(cName,h.GetTitle()+" (mean/width summary)",500*nsigma,1000) c.Divide(nsigma+1,2) for i in range(nsigma+1): From 2d4c8fd72425067657eec701719741dd98639560 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 09:08:34 +0200 Subject: [PATCH 54/77] move to 15_1_0 sample --- HitAnalyzer/test/rechittreewa_tt_cfg.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index ef7abb5..23c03c6 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -31,7 +31,17 @@ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root') fileNames = cms.untracked.vstring( - 'file:/eos/user/a/adamw/CMSAnalysis/DPG/Phase2Tracking/Data/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root' + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/002a6949-6471-46fd-8c44-1f09e7717c8f.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/0e60c3b1-0c21-41d2-94de-435382ae2b44.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/3342a947-891b-41b1-9ed1-dc0a79e52e2c.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/43fa9e06-8d30-423d-a656-7a136aa58dc6.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/93b9335c-5bb3-46a9-9851-3a982b4df225.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/9f157d02-3a77-4ed3-a64b-013ab978ad3d.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/a9b19378-c427-4f38-8cc9-0a6c7212bbd7.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/ab55d910-204b-451d-862d-2a2c35af456a.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/ddebeaf9-afd7-478f-8803-cc1c66bbc7d1.root', \ + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/f00daee7-b0bd-47ab-96fe-dfc16c78f923.root' #, \ + # 'file:/eos/user/a/adamw/CMSAnalysis/DPG/Phase2Tracking/Data/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root' # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ @@ -107,3 +117,4 @@ process.schedule = cms.Schedule(process.rechits_step, process.analyze_step) + From ef5542b4d7f366253ba9165205c903a60cdb65ea Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 09:11:38 +0200 Subject: [PATCH 55/77] debug statements --- DrawHits/fitRes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 07188fa..3317cb7 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -519,6 +519,7 @@ def defineMeanWidthHistograms(h,nby,ymin,ymax,nbz,zmin,zmax,isigma=None,sigma=No #quantLines[isigma].DrawLine(qs[2],0.,qs[2],qlmax) else: print("(At least) one quantile computation failed: sigma =",sigma," p =",ROOT.TMath.Freq(-sigma),qs) + print(" ",slices[-1].hist.GetSumOfWeights(),slices[-1].hist.GetMaximum()) fc.pad.Update() From 1b68b0878555123d54d6d8d0c071998421bea674 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 09:14:52 +0200 Subject: [PATCH 56/77] bug fix in globPt variable and (almost complete) implementation of RDF changes for efficiency histograms --- DrawHits/drawHitsEffRDF.yaml | 302 +++++++++++++++++++++++++++++++++++ DrawHits/drawHitsTmpRDF.yaml | 2 +- 2 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 DrawHits/drawHitsEffRDF.yaml diff --git a/DrawHits/drawHitsEffRDF.yaml b/DrawHits/drawHitsEffRDF.yaml new file mode 100644 index 0000000..9ce1133 --- /dev/null +++ b/DrawHits/drawHitsEffRDF.yaml @@ -0,0 +1,302 @@ + +# +# sensor dimensions: +# +# 2S: 10 x 10 cm2; 2 x 1016 strips at 90 μm x 5 cm +# PS: 5 x 10 cm2; 2 x 960 strips at 100 μm x 2.5 cm +# PSp: 5 x 10 cm2; 32 x 960 pixel at 100 μm x 1.5 mm + +# +# definitions of new variables +# +variables: + pathX: 'path.fCoordinates.fX' + pathY: 'path.fCoordinates.fY' + pathZ: 'path.fCoordinates.fZ' + dxdz: 'pathX/pathZ' + alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' + localPosX: 'localPos.fCoordinates.fX' + localPosY: 'localPos.fCoordinates.fY' + rhLocalPosX: 'rhLocalPos.fCoordinates.fX' + rhLocalPosY: 'rhLocalPos.fCoordinates.fY' + rhLocalErrX: 'rhLocalErr.fCoordinates.fX' + rhLocalErrY: 'rhLocalErr.fCoordinates.fY' + localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' + localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' + localPosYMod500: 'floatMod(10*localPosY,50)/10.' + localPosYMod250: 'floatMod(10*localPosY,25)/10.' + localPosYMod15: 'floatMod(100*localPosY,15)/10' + globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' + globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' + globPt: 'pabs*sqrt(globRho2/globR2)' + detNormalT: 'detNormal.fCoordinates.fX*detNormal.fCoordinates.fX+detNormal.fCoordinates.fY*detNormal.fCoordinates.fY' +# +# histogram section +# +histograms: + # + # + # + effAlphaLoose: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + histogramTitle: 'Efficiency vs. alpha(xz) tight' + variable: 'atan2(abs(path.x()),abs(path.z()))/3.1415*180' + xMax: 100.0 + xMin: 0 + xNbins: 100 + xTitle: 'alpha(xz) [deg]' + yMax: 1.05 + yMin: 0.5 + yTitle: 'efficiency' + # + # + # + effAlphaTight: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.1' + histogramTitle: 'Efficiency vs. alpha(xz) loose' + variable: 'atan2(abs(path.x()),abs(path.z()))/3.1415*180' + xMax: 100.0 + xMin: 0 + xNbins: 100 + xTitle: 'alpha(xz) [deg]' + yMax: 1.05 + yMin: 0.5 + yTitle: 'efficiency' + # + # + # + effVsModX: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'floatMod(10000*localPos.x(),100)' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsModX1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize==1' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsModX2: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize==2' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsModX3p: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize>2' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsMod2DX1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize==1' + yNbins: 80 + yMin: -1. + yMax: 1. + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + variable: 'dxdz:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + variable: 'dxdz:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mum' + variable: 'dxdz:localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsMod2DX2: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize==2' + yNbins: 80 + yMin: -1. + yMax: 1. + mType23: + histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + variable: 'dxdz:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + variable: 'dxdz:localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency vs. x % 90 #mum' + variable: 'dxdz:localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + + # + # + # + effVsModY: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency vs. y % 1.5 mm' + variable: 'floatMod(100*localPos.y(),15)/10.' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency vs. y % 2.5 cm' + variable: 'floatMod(10*localPos.y(),25)/10.' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency vs. y % 5 cm' + variable: 'floatMod(10*localPos.y(),50)/10.' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + # + # + # + effX: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + histogramTitle: 'Efficiency 1D' + variable: 'localPos.x()' + xTitle: 'local x [cm]' + yMax: 1.05 + yMin: 0.8 + yTitle: 'efficiency' + mType23: + xMax: 5.5 + xMin: -5.5 + xNbins: 550 + mType24: + xMax: 5.0 + xMin: -5.0 + xNbins: 250 + mType25: + xMax: 5 + xMin: -5 + xNbins: 250 + # + # + # + effY: + variable: 'localPos.y()' + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + histogramTitle: 'Efficiency Y 1D' + xTitle: 'local y [cm]' + xNbins: 550 + xMax: 5.5 + xMin: -5.5 + yTitle: 'efficiency' + yMax: 1.05 + yMin: 0.8 diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index 22f9909..21132e1 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -27,7 +27,7 @@ variables: localPosYMod15: 'floatMod(100*localPosY,15)/10' globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' - globPt: 'pabs*sqrt(sqrt(globRho2/globR2))' + globPt: 'pabs*sqrt(globRho2/globR2)' detNormalT: 'detNormal.fCoordinates.fX*detNormal.fCoordinates.fX+detNormal.fCoordinates.fY*detNormal.fCoordinates.fY' # # definitions of canvases and histograms From 01d60385a0f0f62e2c68180255b6fe419fbf5034 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 09:16:17 +0200 Subject: [PATCH 57/77] raise exception when trying to fit resolution on 2D histogram --- DrawHits/drawHitsRDF.py | 1 + 1 file changed, 1 insertion(+) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 5901df0..1dd2c2a 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -78,6 +78,7 @@ def divideRatios(cnv,nx,ny,widthRatios,heightRatios,canvasTopMargin=0.,canvasLef return result def fitHistogram(mType,h): + assert h.GetDimension()==1 f1name = "f1"+str(mType) f1 = ROOT.TF1(f1name,"gaus(0)") f1.SetParameter(0,h.GetMaximum()) From e90fb7e28dd9eebe771bce1f415bfe843ad10877 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 09:45:04 +0200 Subject: [PATCH 58/77] bug fix for definition of tilted sensors --- DrawHits/drawHitsRDF.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DrawHits/drawHitsRDF.py b/DrawHits/drawHitsRDF.py index 1dd2c2a..bc294ad 100755 --- a/DrawHits/drawHitsRDF.py +++ b/DrawHits/drawHitsRDF.py @@ -591,7 +591,7 @@ def addHistogram(varString,cuts,effCuts=None,name='userHist'): elif args.zone=="endcap": zoneCuts = "detNormalT<0.01" elif args.zone=="tilted": - zoneCuts = "detNormalT>0.05&&detNormalT<0.095" + zoneCuts = "detNormalT>0.05&&detNormalT<0.95" else: zoneCuts = "" args.cuts = cutString(args.cuts,zoneCuts) From 4feae17db3410e0a3023107092abd97225743bb6 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 09:45:30 +0200 Subject: [PATCH 59/77] cosmetics for prob vs. x vs dx/dz histograms --- DrawHits/drawHitsEffRDF.yaml | 106 +++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/DrawHits/drawHitsEffRDF.yaml b/DrawHits/drawHitsEffRDF.yaml index 9ce1133..349ddc6 100644 --- a/DrawHits/drawHitsEffRDF.yaml +++ b/DrawHits/drawHitsEffRDF.yaml @@ -73,23 +73,23 @@ histograms: yMin: 0 yMax: 1.05 mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Efficiency vs. x % 100 #mum' variable: 'floatMod(10000*localPos.x(),100)' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Efficiency vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' + histogramTitle: 'Efficiency vs. x % 90 #mum' variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' + xTitle: 'x modulo 90 #mum [#mum]' xNbins: 200 xMax: 95 xMin: -5 @@ -100,23 +100,23 @@ histograms: yMin: 0 yMax: 1.05 mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Prob. (1 strip) vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Prob. (1 strip) vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' + histogramTitle: 'Prob. (1 strip) vs. x % 90 #mum' variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' + xTitle: 'x modulo 90 #mum [#mum]' xNbins: 200 xMax: 95 xMin: -5 @@ -127,23 +127,23 @@ histograms: yMin: 0 yMax: 1.05 mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Prob. (2 strips) vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Prob. (2 strips) vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' + histogramTitle: 'Prob. (2 strips) vs. x % 90 #mum' variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' + xTitle: 'x modulo 90 #mum [#mum]' xNbins: 200 xMax: 95 xMin: -5 @@ -154,23 +154,23 @@ histograms: yMin: 0 yMax: 1.05 mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Prob. (>2 strips) vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' + histogramTitle: 'Prob. (>2 strips) vs. x % 100 #mum' variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' + histogramTitle: 'Prob. (>2 strips) vs. x % 90 #mum' variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' + xTitle: 'x modulo 90 #mum [#mum]' xNbins: 200 xMax: 95 xMin: -5 @@ -181,24 +181,26 @@ histograms: yNbins: 80 yMin: -1. yMax: 1. + yTitle: 'dx/dz' + zMax: 1. mType23: - histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + histogramTitle: 'Prob. (1 strip) vs. x%100#mum and dx/dz' variable: 'dxdz:localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType24: - histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + histogramTitle: 'Prob. (1 strip) vs. x%100#mum and dx/dz' variable: 'dxdz:localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType25: - histogramTitle: 'Efficiency vs. x % 90 #mum' + histogramTitle: 'Prob. (1 strip) vs. x%90#mum' variable: 'dxdz:localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' + xTitle: 'x modulo 90 #mum [#mum]' xNbins: 200 xMax: 95 xMin: -5 @@ -209,24 +211,56 @@ histograms: yNbins: 80 yMin: -1. yMax: 1. + yTitle: 'dx/dz' + zMax: 1. mType23: - histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + histogramTitle: 'Prob. (2 strips) vs. x%100#mum and dx/dz' variable: 'dxdz:localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType24: - histogramTitle: 'Efficiency vs. x % 100 #mum and dx/dz' + histogramTitle: 'Prob. (2 strips) vs. x%100#mum and dx/dz' variable: 'dxdz:localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' + xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 xMin: -5 mType25: - histogramTitle: 'Efficiency vs. x % 90 #mum' + histogramTitle: 'Prob. (2 strips) vs. x%90#mum' + variable: 'dxdz:localPosXMod90' + xTitle: 'x modulo 90 #mum [#mum]' + xNbins: 200 + xMax: 95 + xMin: -5 + + effVsMod2DX3p: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' + effCuts: 'clusterSize>2' + yNbins: 80 + yMin: -1. + yMax: 1. + yTitle: 'dx/dz' + zMax: 1. + mType23: + histogramTitle: 'Prob. (>2 strips) vs. x%100#mum and dx/dz' + variable: 'dxdz:localPosXMod100' + xTitle: 'x modulo 100 #mum [#mum]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Prob. (>2 strips) vs. x%100#mum and dx/dz' + variable: 'dxdz:localPosXMod100' + xTitle: 'x modulo 100 #mum [#mum]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Prob. (>2 strips) vs. x%90#mum' variable: 'dxdz:localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' + xTitle: 'x modulo 90 #mum [#mum]' xNbins: 200 xMax: 95 xMin: -5 From 44299708991b30a67c0f6a737dd8f207e82080d1 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 8 Apr 2026 11:19:26 +0200 Subject: [PATCH 60/77] more fixes for RDF for efficiency histograms --- DrawHits/drawHitsEffRDF.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/DrawHits/drawHitsEffRDF.yaml b/DrawHits/drawHitsEffRDF.yaml index 349ddc6..48ea84b 100644 --- a/DrawHits/drawHitsEffRDF.yaml +++ b/DrawHits/drawHitsEffRDF.yaml @@ -39,7 +39,7 @@ histograms: # effAlphaLoose: baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency vs. alpha(xz) tight' variable: 'atan2(abs(path.x()),abs(path.z()))/3.1415*180' xMax: 100.0 @@ -54,7 +54,7 @@ histograms: # effAlphaTight: baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.1' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.1' histogramTitle: 'Efficiency vs. alpha(xz) loose' variable: 'atan2(abs(path.x()),abs(path.z()))/3.1415*180' xMax: 100.0 @@ -69,12 +69,12 @@ histograms: # effVsModX: baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' yMin: 0 yMax: 1.05 mType23: histogramTitle: 'Efficiency vs. x % 100 #mum' - variable: 'floatMod(10000*localPos.x(),100)' + variable: 'localPosXMod100' xTitle: 'x modulo 100 #mum [#mum]' xNbins: 220 xMax: 105 @@ -271,26 +271,26 @@ histograms: # effVsModY: baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' yMin: 0 yMax: 1.05 mType23: histogramTitle: 'Efficiency vs. y % 1.5 mm' - variable: 'floatMod(100*localPos.y(),15)/10.' + variable: 'localPosYMod15' xTitle: 'y modulo 1.5mm [mm]' xNbins: 400 xMax: 1.75 xMin: -0.25 mType24: histogramTitle: 'Efficiency vs. y % 2.5 cm' - variable: 'floatMod(10*localPos.y(),25)/10.' + variable: 'localPosYMod250' xTitle: 'y modulo 2.5cm [cm]' xNbins: 600 xMax: 2.75 xMin: -0.25 mType25: histogramTitle: 'Efficiency vs. y % 5 cm' - variable: 'floatMod(10*localPos.y(),50)/10.' + variable: 'localPosYMod500' xTitle: 'y modulo 5cm [cm]' xNbins: 550 xMax: 5.25 @@ -300,9 +300,9 @@ histograms: # effX: baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency 1D' - variable: 'localPos.x()' + variable: 'localPosX' xTitle: 'local x [cm]' yMax: 1.05 yMin: 0.8 @@ -325,7 +325,7 @@ histograms: effY: variable: 'localPos.y()' baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPos.x()-rhLocalPos.x())<0.0075' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency Y 1D' xTitle: 'local y [cm]' xNbins: 550 From f06fd29e5b2302e3cc1c8f8ef11e31616eefd839 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 9 Apr 2026 10:20:34 +0200 Subject: [PATCH 61/77] helper script to extract histogram definitions in text form --- DrawHits/histogramConfigsToText.py | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 DrawHits/histogramConfigsToText.py diff --git a/DrawHits/histogramConfigsToText.py b/DrawHits/histogramConfigsToText.py new file mode 100644 index 0000000..df51e22 --- /dev/null +++ b/DrawHits/histogramConfigsToText.py @@ -0,0 +1,100 @@ +# +# Extract individual definitions from a yaml file to be used with drawHitsRDF.py to text files +# Text files are named with the histogram name and written to a directory derived from the configuration file name +# The individual directories are created if not yet present; existing files are not removed but will be replaced +# +import sys,os +import yaml + +def writeDict(d,txtFile,indent=0): + ''' Write contents of a dictionary to a text file + Arguments: + d ........ input dictionary + txtFile .. text file object open for writing + indent ... number of spaces at the start of each line + ''' + # + # define lists of dictionaries and all other (scalar!) items + # + kOthers = [ ] + kDicts = [ ] + for k,v in d.items(): + if type(v)==dict: + kDicts.append(k) + else: + kOthers.append(k) + # + # write non-dictionary (scalar) items + # + for k in sorted(kOthers): + v = d[k] + # start with key + line = indent*" "+k+": " + # write variable (strings enclosed in quotes) + if type(v)==str: + line += "'"+v+"'" + else: + line += str(v) + # write line + txtFile.write(line+"\n") + # + # write dictionaries via recursive use of the function + # + for k in sorted(kDicts): + # write header line + txtFile.write(indent*" "+k+":\n") + # write dictionary with increased indent + writeDict(d[k],txtFile,indent+2) +# +# main body +# +if __name__=="__main__": + # + # arguments are the path to the config file and the base directory for the output + # + # + # configuration file + # + configFile = sys.argv[1] + assert os.path.isfile(configFile) + # + # output directory constructed from argument and the config file name + # + outputBase = sys.argv[2] + assert os.path.isdir(outputBase) + configName = os.path.splitext(os.path.basename(configFile))[0] + outputDir = os.path.join(outputBase,configName) + # directory is created if it doesn't exist + if not os.path.exists(outputDir): + os.mkdir(outputDir) + assert os.path.isdir(outputDir) + # + # read all dictionaries from config file + # + with open(sys.argv[1],"rt") as yamlFile: + allDicts = yaml.load(yamlFile,Loader=yaml.Loader) + yamlFile.close() + # + # All variable definitions are written to a single file 'variables.txt' + # + if 'variables' in allDicts: + varDict = allDicts['variables'] + with open(os.path.join(outputDir,'variables.txt'),"wt") as txtFile: + writeDict(varDict,txtFile) + txtFile.close() + # + # Histograms + # + if 'histograms' in allDicts: + histDict = allDicts['histograms'] + # + # loop over sorted keys (==histogram names) in the configuration + # + for k1 in sorted(histDict.keys()): + v1 = histDict[k1] + assert type(v1)==dict + # + # create output file for this histogram and write definitions, including nested dicts + # + with open(os.path.join(outputDir,k1+".txt"),"wt") as txtFile: + writeDict({k1:v1},txtFile,0) From c93b477cde44768ffc66503ec345a45bb4bd4086 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 9 Apr 2026 11:26:40 +0200 Subject: [PATCH 62/77] script to compare outputs of histogramConfigsToText.py --- DrawHits/compareHistogramConfigs.py | 95 +++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 DrawHits/compareHistogramConfigs.py diff --git a/DrawHits/compareHistogramConfigs.py b/DrawHits/compareHistogramConfigs.py new file mode 100644 index 0000000..9865e7b --- /dev/null +++ b/DrawHits/compareHistogramConfigs.py @@ -0,0 +1,95 @@ +import sys,os +import subprocess +import csv + +allFiles = { } +allDirs = set() +# +# loop over directories with text files +# +for d in sys.argv[1:]: + # + # assume last part of directory name is unique + # + dn = os.path.basename(os.path.normpath(d)) + assert not dn in allDirs + allDirs.add(dn) + # + # retrieve cksums for all text files + # + filePattern = os.path.join(d,"*.txt") + result = subprocess.run("cksum "+filePattern, text=True, capture_output=True, shell=True) + result.check_returncode() + # + # loop over output + # + for l in result.stdout.split(chr(10)): + if l=="": + continue + # + # decode output line + # + fields = l.split() + assert len(fields)==3 + cksum = int(fields[0]) + size = int(fields[1]) + name = os.path.splitext(os.path.basename(fields[2]))[0] + # + # store result by name ( directory, cksum, and size ) + # + if not name in allFiles: + allFiles[name] = [ ( dn, cksum, size ) ] + else: + allFiles[name].append( ( dn, cksum, size ) ) +# +allDirs = sorted(allDirs) +# +# write result to output file +# +with open("compareHistogramConfigs.csv","wt") as csvFile: + csvwriter = csv.writer(csvFile) + # header row 1 + row = [ "Name" ] + for d in allDirs: + row.extend([ d, "", "" ]) + row.append("#ids") + row.append("#dirs") + csvwriter.writerow(row) + # header row 2 + row = [ "" ] + for d in allDirs: + row.extend([ "size", "cksum", "id" ]) + row.append("") + row.append("") + csvwriter.writerow(row) + # + # loop over all definitions + # + for n in sorted(allFiles.keys()): + # + row = [ n ] + # + # create list of all unique file ids (defined by size and cksum) + # + cksums = set([ ( x[2], x[1] ) for x in allFiles[n] ]) + cksums = sorted(cksums) + # + # add information for each directory + # + for dn in allDirs: + rowExt = [ "", "", "" ] + # + # (try to) find directory in list for this name + # + for d,c,s in allFiles[n]: + if d==dn: + idx = cksums.index((s,c)) + rowExt = [s,c,idx] + break + row.extend(rowExt) + # + row.append(len(cksums)) + row.append(len(allFiles[n])) + csvwriter.writerow(row) + csvFile.close() + From 702c18ead3681c53ae832d654d250586bae18c03 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 9 Apr 2026 14:31:22 +0200 Subject: [PATCH 63/77] (re-)moving histogram definitions in / between RDF.yaml config files --- DrawHits/drawHitsEffRDF.yaml | 65 ++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/DrawHits/drawHitsEffRDF.yaml b/DrawHits/drawHitsEffRDF.yaml index 48ea84b..56a92f2 100644 --- a/DrawHits/drawHitsEffRDF.yaml +++ b/DrawHits/drawHitsEffRDF.yaml @@ -37,30 +37,30 @@ histograms: # # # - effAlphaLoose: + effAlphaTight: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency vs. alpha(xz) tight' - variable: 'atan2(abs(path.x()),abs(path.z()))/3.1415*180' + variable: 'alpha' xMax: 100.0 xMin: 0 xNbins: 100 - xTitle: 'alpha(xz) [deg]' + xTitle: '#alpha(xz) from path [deg]' yMax: 1.05 yMin: 0.5 yTitle: 'efficiency' # # # - effAlphaTight: + effAlphaLoose: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.1' histogramTitle: 'Efficiency vs. alpha(xz) loose' - variable: 'atan2(abs(path.x()),abs(path.z()))/3.1415*180' + variable: 'alpha' xMax: 100.0 xMin: 0 xNbins: 100 - xTitle: 'alpha(xz) [deg]' + xTitle: '#alpha(xz) from path [deg]' yMax: 1.05 yMin: 0.5 yTitle: 'efficiency' @@ -301,7 +301,7 @@ histograms: effX: baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' - histogramTitle: 'Efficiency 1D' + histogramTitle: 'Efficiency X 1D' variable: 'localPosX' xTitle: 'local x [cm]' yMax: 1.05 @@ -323,14 +323,57 @@ histograms: # # effY: - variable: 'localPos.y()' baseCuts: 'tof<12.5&&pabs>0.3' effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' histogramTitle: 'Efficiency Y 1D' + variable: 'localPosY' xTitle: 'local y [cm]' - xNbins: 550 - xMax: 5.5 - xMin: -5.5 yTitle: 'efficiency' yMax: 1.05 yMin: 0.8 + mType23: + xMax: 3 + xMin: -3 + xNbins: 120 + mType24: + xMax: 3.0 + xMin: -3.0 + xNbins: 120 + mType25: + xMax: 5.5 + xMin: -5.5 + xNbins: 220 + + # + # + # + effXY: + baseCuts: 'tof<12.5&&pabs>0.3' + effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' + histogramTitle: 'Efficiency XY 2D' + variable: 'localPosY:localPosX' + xTitle: 'local x [cm]' + yTitle: 'local y [cm]' + zMax: 1.0 + zMin: 0.5 + mType23: + xMax: 5.5 + xMin: -5.5 + xNbins: 55 + yMax: 3 + yMin: -3 + yNbins: 24 + mType24: + xMax: 5.0 + xMin: -5.0 + xNbins: 50 + yMax: 3.0 + yMin: -3.0 + yNbins: 40 + mType25: + xMax: 5 + xMin: -5 + xNbins: 50 + yMax: 6 + yMin: -6 + yNbins: 40 From 6f810b44ef24d96f043b9b397530f2cd2e253301 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 9 Apr 2026 14:31:26 +0200 Subject: [PATCH 64/77] (re-)moving histogram definitions in / between RDF.yaml config files --- DrawHits/drawHitsResRDF.yaml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/DrawHits/drawHitsResRDF.yaml b/DrawHits/drawHitsResRDF.yaml index b403ed7..297e3d7 100644 --- a/DrawHits/drawHitsResRDF.yaml +++ b/DrawHits/drawHitsResRDF.yaml @@ -15,7 +15,7 @@ variables: rhLocalErrY: 'rhLocalErr.fCoordinates.fY' globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' - globPt: 'pabs*sqrt(sqrt(globRho2/globR2))' + globPt: 'pabs*sqrt(globRho2/globR2)' detNormalT: 'detNormal.fCoordinates.fX*detNormal.fCoordinates.fX+detNormal.fCoordinates.fY*detNormal.fCoordinates.fY' # # @@ -52,6 +52,15 @@ histograms: xMin: -5 fit: 'gaus' logY: true + pullY: + histogramTitle: 'pulls (y)' + variable: '(localPosY-rhLocalPosY)/rhLocalErrY' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'pull local y' + xNbins: 200 + xMax: 5 + xMin: -5 + logY: true # # # @@ -102,6 +111,7 @@ histograms: xNbins: 300 xMax: 0.075 xMin: -0.075 + fit: 'gaus' logY: true # # @@ -135,16 +145,4 @@ histograms: logZ: true # # -# - resY: - histogramTitle: 'pulls (y)' - variable: '(localPosY-rhLocalPosY)/rhLocalErrY' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: 'pull local y' - xNbins: 200 - xMax: 5 - xMin: -5 - logY: true -# -# # From c152b37befb305644a227a82daedd0267d2f1ff2 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 9 Apr 2026 14:31:32 +0200 Subject: [PATCH 65/77] (re-)moving histogram definitions in / between RDF.yaml config files --- DrawHits/drawHitsTmpRDF.yaml | 279 ----------------------------------- 1 file changed, 279 deletions(-) diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index 21132e1..143c926 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -33,214 +33,7 @@ variables: # definitions of canvases and histograms # histograms: -# -# -# - effAlphaTight: - baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' - histogramTitle: 'Efficiency vs. alpha(xz) tight' - variable: 'alpha' - xMax: 100.0 - xMin: 0 - xNbins: 100 - xTitle: 'alpha(xz) [deg]' - yMax: 1.05 - yMin: 0.5 - yTitle: 'efficiency' -# -# -# - effAlphaLoose: - baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.1' - histogramTitle: 'Efficiency vs. alpha(xz) loose' - variable: 'alpha' - xMax: 100.0 - xMin: 0 - xNbins: 100 - xTitle: 'alpha(xz) [deg]' - yMax: 1.05 - yMin: 0.5 - yTitle: 'efficiency' -# -# -# - effVsModX: - baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 - effVsModX1: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' - effCuts: 'clusterSize==1' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 - - effVsModX2: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' - effCuts: 'clusterSize==2' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 - - effVsModX3p: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5&&hasRecHit>0' - effCuts: 'clusterSize>2' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 -# -# -# - effVsModY: - baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency vs. y % 1.5 mm' - variable: 'localPosYMod15' - xTitle: 'y modulo 1.5mm [mm]' - xNbins: 400 - xMax: 1.75 - xMin: -0.25 - mType24: - histogramTitle: 'Efficiency vs. y % 2.5 cm' - variable: 'localPosYMod250' - xTitle: 'y modulo 2.5cm [cm]' - xNbins: 600 - xMax: 2.75 - xMin: -0.25 - mType25: - histogramTitle: 'Efficiency vs. y % 5 cm' - variable: 'localPosYMod500' - xTitle: 'y modulo 5cm [cm]' - xNbins: 550 - xMax: 5.25 - xMin: -0.25 -# -# -# - effX: - baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' - histogramTitle: 'Efficiency 1D' - variable: 'localPosX' - xTitle: 'local x [cm]' - yMax: 1.05 - yMin: 0.8 - yTitle: 'efficiency' - mType23: - xMax: 5.5 - xMin: -5.5 - xNbins: 550 - mType24: - xMax: 5.0 - xMin: -5.0 - xNbins: 250 - mType25: - xMax: 5 - xMin: -5 - xNbins: 250 -# -# -# - effY: - variable: 'localPosY' - baseCuts: 'tof<12.5&&pabs>0.3' - effCuts: 'hasRecHit>0&&abs(localPosX-rhLocalPosX)<0.0075' - histogramTitle: 'Efficiency Y 1D' - xTitle: 'local y [cm]' - xNbins: 550 - xMax: 5.5 - xMin: -5.5 - yTitle: 'efficiency' - yMax: 1.05 - yMin: 0.8 # # # @@ -265,78 +58,6 @@ histograms: xMin: 0 # # -# - pullX: - histogramTitle: 'pulls (x)' - variable: '(localPosX-rhLocalPosX)/rhLocalErrX' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: 'pull local x' - xNbins: 200 - xMax: 5 - xMin: -5 - logY: true -# -# -# - resX: - histogramTitle: 'residuals (x)' - variable: 'localPosX-rhLocalPosX' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: '#Delta x [cm]' - xNbins: 300 - xMax: 0.075 - xMin: -0.075 - logY: true -# -# -# - resX1: - histogramTitle: 'residuals (x) - cluster size 1' - variable: 'localPosX-rhLocalPosX' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' - xTitle: '#Delta x [cm]' - xNbins: 300 - xMax: 0.075 - xMin: -0.075 - logY: true -# -# -# - resX2: - histogramTitle: 'residuals (x) - cluster size 2' - variable: 'localPosX-rhLocalPosX' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' - xTitle: '#Delta x [cm]' - xNbins: 300 - xMax: 0.075 - xMin: -0.075 - logY: true -# -# -# - resX3P: - histogramTitle: 'residuals (x) - cluster size >2' - variable: 'localPosX-rhLocalPosX' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize>2' - xTitle: '#Delta x [cm]' - xNbins: 300 - xMax: 0.075 - xMin: -0.075 - logY: true -# -# -# - resY: - histogramTitle: 'pulls (y)' - variable: '(localPosY-rhLocalPosY)/rhLocalErrY' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: 'pull local y' - xNbins: 200 - xMax: 5 - xMin: -5 - logY: true -# -# # stdRes2D: histogramTitle: 'my resolution' From d94e3b78d30bc442e04a5ef7f5c5b550842fbd5e Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 10 Apr 2026 17:08:19 +0200 Subject: [PATCH 66/77] moving histograms between configs --- DrawHits/drawHitsEffRDF.yaml | 211 ++++++++++++++++++++++++++++++++++- DrawHits/drawHitsTmpRDF.yaml | 167 --------------------------- 2 files changed, 208 insertions(+), 170 deletions(-) diff --git a/DrawHits/drawHitsEffRDF.yaml b/DrawHits/drawHitsEffRDF.yaml index 56a92f2..011ef4b 100644 --- a/DrawHits/drawHitsEffRDF.yaml +++ b/DrawHits/drawHitsEffRDF.yaml @@ -1,10 +1,9 @@ - # # sensor dimensions: # -# 2S: 10 x 10 cm2; 2 x 1016 strips at 90 μm x 5 cm -# PS: 5 x 10 cm2; 2 x 960 strips at 100 μm x 2.5 cm # PSp: 5 x 10 cm2; 32 x 960 pixel at 100 μm x 1.5 mm +# PS: 5 x 10 cm2; 2 x 960 strips at 100 μm x 2.5 cm +# 2S: 10 x 10 cm2; 2 x 1016 strips at 90 μm x 5 cm # # definitions of new variables @@ -17,6 +16,7 @@ variables: alpha: 'atan2(abs(pathX),abs(pathZ))/3.1415*180' localPosX: 'localPos.fCoordinates.fX' localPosY: 'localPos.fCoordinates.fY' + globalPosZ: 'globalPos.fCoordinates.fZ' rhLocalPosX: 'rhLocalPos.fCoordinates.fX' rhLocalPosY: 'rhLocalPos.fCoordinates.fY' rhLocalErrX: 'rhLocalErr.fCoordinates.fX' @@ -377,3 +377,208 @@ histograms: yMax: 6 yMin: -6 yNbins: 40 +# +# +# + nrhEffVsModX1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==1' + yTitle: 'Efficieny (nrh==1)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency (nrh=1) vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + nrhEffVsModX2: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==2' + yTitle: 'Efficieny (nrh==2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency (nrh=2) vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 + + nrhEffVsModX3p: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched>2' + yTitle: 'Efficieny (nrh>2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType24: + histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' + variable: 'localPosXMod100' + xTitle: 'x modulo 100 #mu m [#mu m]' + xNbins: 220 + xMax: 105 + xMin: -5 + mType25: + histogramTitle: 'Efficiency (nrh>2) vs. x % 90 #mu m' + variable: 'localPosXMod90' + xTitle: 'x modulo 90 #mu m [#mu m]' + xNbins: 200 + xMax: 95 + xMin: -5 +# +# +# + nrhEffVsModY1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==1' + yTitle: 'Efficieny (nrh==1)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=1) vs. y % 1.5 mm' + variable: 'localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency (nrh=1) vs. y % 2.5 cm' + variable: 'localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency (nrh=1) vs. y % 5 cm' + variable: 'localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + + nrhEffVsModY2: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==2' + yTitle: 'Efficiency (nrh==2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=2) vs. y % 1.5 mm' + variable: 'localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency (nrh=2) vs. y % 2.5 cm' + variable: 'localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency (nrh=2) vs. y % 5 cm' + variable: 'localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + + nrhEffVsModY3p: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched>2' + yTitle: 'Efficiency (nrh>2)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh>2) vs. y % 1.5 mm' + variable: 'localPosYMod15' + xTitle: 'y modulo 1.5mm [mm]' + xNbins: 400 + xMax: 1.75 + xMin: -0.25 + mType24: + histogramTitle: 'Efficiency (nrh>2) vs. y % 2.5 cm' + variable: 'localPosYMod250' + xTitle: 'y modulo 2.5cm [cm]' + xNbins: 600 + xMax: 2.75 + xMin: -0.25 + mType25: + histogramTitle: 'Efficiency (nrh>2) vs. y % 5 cm' + variable: 'localPosYMod500' + xTitle: 'y modulo 5cm [cm]' + xNbins: 550 + xMax: 5.25 + xMin: -0.25 + +# +# test case for nrh==1 efficiency +# + + nrhEffVsY1: + baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' + effCuts: 'rhNMatched==1' + yTitle: 'Efficieny (nrh==1)' + yMin: 0 + yMax: 1.05 + mType23: + histogramTitle: 'Efficiency (nrh=1) vs. y % 1.5 mm' + variable: 'localPosY' + xTitle: 'y [cm]' + xNbins: 5100 + xMax: 2.55 + xMin: -2.55 + mType24: + histogramTitle: 'Efficiency (nrh=1) vs. y % 2.5 cm' + variable: 'localPosY' + xTitle: 'y [cm]' + xNbins: 520 + xMax: 2.6 + xMin: -2.6 + mType25: + histogramTitle: 'Efficiency (nrh=1) vs. y % 2.5 cm' + variable: 'localPosY' + xTitle: 'y [cm]' + xNbins: 880 + xMax: 5.5 + xMin: -5.5 + diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index 143c926..bd8320b 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -446,89 +446,6 @@ histograms: xMax: 95 xMin: -5 - nrhEffVsModX1: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' - effCuts: 'rhNMatched==1' - yTitle: 'Efficieny (nrh==1)' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency (nrh=1) vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency (nrh=1) vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 - - nrhEffVsModX2: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' - effCuts: 'rhNMatched==2' - yTitle: 'Efficieny (nrh==2)' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency (nrh=2) vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency (nrh=2) vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 - - nrhEffVsModX3p: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' - effCuts: 'rhNMatched>2' - yTitle: 'Efficieny (nrh>2)' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType24: - histogramTitle: 'Efficiency (nrh>2) vs. x % 100 #mu m' - variable: 'localPosXMod100' - xTitle: 'x modulo 100 #mu m [#mu m]' - xNbins: 220 - xMax: 105 - xMin: -5 - mType25: - histogramTitle: 'Efficiency (nrh>2) vs. x % 90 #mu m' - variable: 'localPosXMod90' - xTitle: 'x modulo 90 #mu m [#mu m]' - xNbins: 200 - xMax: 95 - xMin: -5 nrhVsModY: baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' @@ -560,90 +477,6 @@ histograms: xMax: 5.25 xMin: -0.25 - nrhEffVsModY1: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' - effCuts: 'rhNMatched==1' - yTitle: 'Efficieny (nrh==1)' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency (nrh=1) vs. y % 1.5 mm' - variable: 'localPosYMod15' - xTitle: 'y modulo 1.5mm [mm]' - xNbins: 400 - xMax: 1.75 - xMin: -0.25 - mType24: - histogramTitle: 'Efficiency (nrh=1) vs. y % 2.5 cm' - variable: 'localPosYMod250' - xTitle: 'y modulo 2.5cm [cm]' - xNbins: 600 - xMax: 2.75 - xMin: -0.25 - mType25: - histogramTitle: 'Efficiency (nrh=1) vs. y % 5 cm' - variable: 'localPosYMod500' - xTitle: 'y modulo 5cm [cm]' - xNbins: 550 - xMax: 5.25 - xMin: -0.25 - - nrhEffVsModY2: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' - effCuts: 'rhNMatched==2' - yTitle: 'Efficiency (nrh==2)' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency (nrh=2) vs. y % 1.5 mm' - variable: 'localPosYMod15' - xTitle: 'y modulo 1.5mm [mm]' - xNbins: 400 - xMax: 1.75 - xMin: -0.25 - mType24: - histogramTitle: 'Efficiency (nrh=2) vs. y % 2.5 cm' - variable: 'localPosYMod250' - xTitle: 'y modulo 2.5cm [cm]' - xNbins: 600 - xMax: 2.75 - xMin: -0.25 - mType25: - histogramTitle: 'Efficiency (nrh=2) vs. y % 5 cm' - variable: 'localPosYMod500' - xTitle: 'y modulo 5cm [cm]' - xNbins: 550 - xMax: 5.25 - xMin: -0.25 - - nrhEffVsModY3p: - baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' - effCuts: 'rhNMatched>2' - yTitle: 'Efficiency (nrh>2)' - yMin: 0 - yMax: 1.05 - mType23: - histogramTitle: 'Efficiency (nrh>2) vs. y % 1.5 mm' - variable: 'localPosYMod15' - xTitle: 'y modulo 1.5mm [mm]' - xNbins: 400 - xMax: 1.75 - xMin: -0.25 - mType24: - histogramTitle: 'Efficiency (nrh>2) vs. y % 2.5 cm' - variable: 'localPosYMod250' - xTitle: 'y modulo 2.5cm [cm]' - xNbins: 600 - xMax: 2.75 - xMin: -0.25 - mType25: - histogramTitle: 'Efficiency (nrh>2) vs. y % 5 cm' - variable: 'localPosYMod500' - xTitle: 'y modulo 5cm [cm]' - xNbins: 550 - xMax: 5.25 - xMin: -0.25 - nrRecHitsAll: baseCuts: 'tof<12.' histogramTitle: 'Number of RecHits (all)' From 6bab327d734b7cd5a1bef53bd76849072bcf319c Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 10 Apr 2026 17:08:53 +0200 Subject: [PATCH 67/77] moving to CMSSW_15_1 sample --- HitAnalyzer/test/rechittreewa_mu10_cfg.py | 24 +++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/HitAnalyzer/test/rechittreewa_mu10_cfg.py b/HitAnalyzer/test/rechittreewa_mu10_cfg.py index 9f70010..88e7cdb 100644 --- a/HitAnalyzer/test/rechittreewa_mu10_cfg.py +++ b/HitAnalyzer/test/rechittreewa_mu10_cfg.py @@ -17,19 +17,23 @@ # Number of events (-1 = all) process.maxEvents = cms.untracked.PSet( - #input = cms.untracked.int32(-1) - input = cms.untracked.int32(10) + input = cms.untracked.int32(-1) + #input = cms.untracked.int32(10) ) - +# Dataset: /RelValSingleMuPt10/CMSSW_15_1_0-150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/GEN-SIM-RECO # Input file process.source = cms.Source('PoolSource', fileNames = cms.untracked.vstring( \ - '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/0b0d313e-56e1-4e64-aa58-8a2e61767bf5.root', \ - '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/66c7ce91-878a-449b-b0fb-1cb8d3084116.root', \ - '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/6cd776e0-dd34-48c4-81cc-844435564ea5.root', \ - '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/94a5b755-f778-4861-a83d-94eb46c18acb.root', \ - '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/a146954f-f6be-46bc-95e8-dd1016306930.root', \ - '/store/relval/CMSSW_15_0_0/RelValSingleMuPt10/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/f459a343-5615-46f5-9ebc-f07e87c3db8e.root') + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/0166e3ce-e26d-483c-8226-cac472af699c.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/0562962b-66c8-488b-89d5-6df21d71f0b6.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/319ecc54-5d83-4e72-8d4a-3f73563e6d37.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/34e25999-54a2-4134-8703-241898703fed.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/37360339-d4dc-4270-85d1-8b89448a6504.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/49967669-571d-4a2b-aca2-6a148ebdb729.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/a88d679b-a909-47a4-8006-2455d1db2d5c.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/ae60ec5b-9009-4a17-8bcb-760c22430149.root', \ + '/store/relval/CMSSW_15_1_0/RelValSingleMuPt10/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/f931e711-1c11-47ce-9de3-49bd3966438d.root' + ) ) # Output @@ -58,7 +62,7 @@ #MakeEtaPlots = cms.bool(False), #MinEta = cms.double(0.), #MaxEta = cms.double(10.) - debugHitMatch = cms.bool(True), + debugHitMatch = cms.bool(False), simHitInfo = cms.PSet( simHits = cms.VInputTag( cms.InputTag("g4SimHits", "TrackerHitsPixelBarrelLowTof"), From 9b3a2cfaf36c379d1eaa7ed7cab1ead079acc424 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 10 Apr 2026 17:17:09 +0200 Subject: [PATCH 68/77] moved remaining eff histograms from Tmp to Eff --- DrawHits/drawHitsEffRDF.yaml | 30 ++++++++++++++++++++++++++++++ DrawHits/drawHitsTmpRDF.yaml | 30 ------------------------------ 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/DrawHits/drawHitsEffRDF.yaml b/DrawHits/drawHitsEffRDF.yaml index 011ef4b..e8fb202 100644 --- a/DrawHits/drawHitsEffRDF.yaml +++ b/DrawHits/drawHitsEffRDF.yaml @@ -582,3 +582,33 @@ histograms: xMax: 5.5 xMin: -5.5 + effDxDz: + variable: 'dxdz' + histogramTitle: 'efficiency (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + + effDxDzW1: + variable: 'dxdz' + histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0&&clusterSize==1' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + + effDxDzW2: + variable: 'dxdz' + histogramTitle: 'efficiency, 2-strip clusters (dx/dz)' + baseCuts: 'tof<12.5' + effCuts: 'hasRecHit>0&&clusterSize==2' + xTitle: 'local dx/dz' + xNbins: 21 + xMin: -1.05 + xMax: 1.05 + diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index bd8320b..f5e0f9d 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -388,36 +388,6 @@ histograms: yMin: 0 yMax: 90 - effDxDz: - variable: 'dxdz' - histogramTitle: 'efficiency (dx/dz)' - baseCuts: 'tof<12.5' - effCuts: 'hasRecHit>0' - xTitle: 'local dx/dz' - xNbins: 21 - xMin: -1.05 - xMax: 1.05 - - effDxDzW1: - variable: 'dxdz' - histogramTitle: 'efficiency, 1-strip clusters (dx/dz)' - baseCuts: 'tof<12.5' - effCuts: 'hasRecHit>0&&clusterSize==1' - xTitle: 'local dx/dz' - xNbins: 21 - xMin: -1.05 - xMax: 1.05 - - effDxDzW2: - variable: 'dxdz' - histogramTitle: 'efficiency, 2-strip clusters (dx/dz)' - baseCuts: 'tof<12.5' - effCuts: 'hasRecHit>0&&clusterSize==2' - xTitle: 'local dx/dz' - xNbins: 21 - xMin: -1.05 - xMax: 1.05 - nrhVsModX: baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' yTitle: 'nr of rechits' From 6bef868a19003590e31d53a892023247ac1f2ca4 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 10 Apr 2026 17:33:05 +0200 Subject: [PATCH 69/77] moved remaining res/pull histograms from Tmp to Res --- DrawHits/drawHitsTmpRDF.yaml | 225 ----------------------------------- 1 file changed, 225 deletions(-) diff --git a/DrawHits/drawHitsTmpRDF.yaml b/DrawHits/drawHitsTmpRDF.yaml index f5e0f9d..a9d67a3 100644 --- a/DrawHits/drawHitsTmpRDF.yaml +++ b/DrawHits/drawHitsTmpRDF.yaml @@ -58,21 +58,6 @@ histograms: xMin: 0 # # -# - stdRes2D: - histogramTitle: 'my resolution' - variable: 'abs(pathX):localPosX-rhLocalPosX' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: 'residual x [cm]' - xNbins: 200 - xMin: -0.1 - xMax: 0.1 - yTitle: 'dx [cm]' - yNbins: 20 - yMin: 0.0 - yMax: 0.1 -# -# # widthVsMod2DX: baseCuts: 'tof<12.5&&pabs>0.3' @@ -178,216 +163,6 @@ histograms: yMin: 0.0 yMax: 25 - res3DXVsDxDzModX: - histogramTitle: 'residuals 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -500 - xMax: 500 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 20 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 20 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 18 - yMin: 0 - yMax: 90 - - res3DXVsDxDz: - histogramTitle: 'residuals 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -200 - xMax: 200 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 90 - - res3DXVsDxDzW1: - histogramTitle: 'residuals 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -200 - xMax: 200 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 90 - - res3DXVsDxDzW2: - histogramTitle: 'residuals 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -200 - xMax: 200 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 90 - - pull3DXVsDxDz: - histogramTitle: 'pulls 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -10 - xMax: 10 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 90 - - pull3DXVsDxDzW1: - histogramTitle: 'pulls 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -10 - xMax: 10 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 90 - - pull3DXVsDxDzW2: - histogramTitle: 'pulls 3D (x)' - baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' - xTitle: '#Delta x [#mum]' - xNbins: 100 - xMin: -10 - xMax: 10 - zTitle: 'local dx/dz' - zNbins: 21 - zMin: -1.05 - zMax: 1.05 - mType23: - variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType24: - variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 100 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 100 - mType25: - variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' - yTitle: 'x modulo 90 #mum [#mum]' - yNbins: 1 - yMin: 0 - yMax: 90 - nrhVsModX: baseCuts: 'tof<12.5&&pabs>0.3&&globPt>0.5' yTitle: 'nr of rechits' From 0d819a098066e1fa274b8ec5648bfb82ef5b9d82 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 10 Apr 2026 17:33:26 +0200 Subject: [PATCH 70/77] moved remaining res/pull histograms from Tmp to Res --- DrawHits/drawHitsResRDF.yaml | 225 +++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/DrawHits/drawHitsResRDF.yaml b/DrawHits/drawHitsResRDF.yaml index 297e3d7..fb3d133 100644 --- a/DrawHits/drawHitsResRDF.yaml +++ b/DrawHits/drawHitsResRDF.yaml @@ -115,6 +115,21 @@ histograms: logY: true # # +# + stdRes2D: + histogramTitle: 'my resolution' + variable: 'abs(pathX):localPosX-rhLocalPosX' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: 'residual x [cm]' + xNbins: 200 + xMin: -0.1 + xMax: 0.1 + yTitle: 'dx [cm]' + yNbins: 20 + yMin: 0.0 + yMax: 0.1 +# +# # res2DX1: histogramTitle: 'track dx/dz vs. residuals (x) - cluster size 1' @@ -146,3 +161,213 @@ histograms: # # # + res3DXVsDxDzModX: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -500 + xMax: 500 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 20 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 20 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 18 + yMin: 0 + yMax: 90 + + res3DXVsDxDz: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + res3DXVsDxDzW1: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + res3DXVsDxDzW2: + histogramTitle: 'residuals 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -200 + xMax: 200 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:10000*(localPosX-rhLocalPosX)' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + pull3DXVsDxDz: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + pull3DXVsDxDzW1: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==1' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + + pull3DXVsDxDzW2: + histogramTitle: 'pulls 3D (x)' + baseCuts: 'tof<12.5&&hasRecHit>0&&clusterSize==2' + xTitle: '#Delta x [#mum]' + xNbins: 100 + xMin: -10 + xMax: 10 + zTitle: 'local dx/dz' + zNbins: 21 + zMin: -1.05 + zMax: 1.05 + mType23: + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType24: + variable: 'dxdz:localPosXMod100:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 100 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 100 + mType25: + variable: 'dxdz:localPosXMod90:(localPosX-rhLocalPosX)/rhLocalErrX' + yTitle: 'x modulo 90 #mum [#mum]' + yNbins: 1 + yMin: 0 + yMax: 90 + From 35cacd30b706d6d76c8005dbdda79e8a09e5f946 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Fri, 10 Apr 2026 17:33:55 +0200 Subject: [PATCH 71/77] moving to CMSSW_15_1 sample --- HitAnalyzer/test/rechittreewa_tt_cfg.py | 37 ++++--------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/HitAnalyzer/test/rechittreewa_tt_cfg.py b/HitAnalyzer/test/rechittreewa_tt_cfg.py index 23c03c6..c863fd3 100644 --- a/HitAnalyzer/test/rechittreewa_tt_cfg.py +++ b/HitAnalyzer/test/rechittreewa_tt_cfg.py @@ -17,19 +17,13 @@ # Number of events (-1 = all) process.maxEvents = cms.untracked.PSet( - input = cms.untracked.int32(-1) - #input = cms.untracked.int32(2) + #input = cms.untracked.int32(-1) + input = cms.untracked.int32(3) ) # Input file -# dataset: /RelValTTbar_14TeV/CMSSW_15_0_0-141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/GEN-SIM-RECO +# dataset: /RelValTTbar_14TeV/CMSSW_15_1_0-150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/GEN-SIM-RECO process.source = cms.Source('PoolSource', - - #fileNames = cms.untracked.vstring('file:/afs/cern.ch/work/l/lian/public/Phase2Tracker/CMSSW_15_0_0_pre3/src/29617.0_SingleMuPt1Extended+Run4D110/step3.root') - #fileNames = cms.untracked.vstring('file:/eos/user/a/adamwo/CMS/Phase2DPG/Data/0b0d313e-56e1-4e64-aa58-8a2e61767bf5.root') - #fileNames = cms.untracked.vstring( - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root') fileNames = cms.untracked.vstring( '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/002a6949-6471-46fd-8c44-1f09e7717c8f.root', \ '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/0e60c3b1-0c21-41d2-94de-435382ae2b44.root', \ @@ -40,29 +34,8 @@ '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/a9b19378-c427-4f38-8cc9-0a6c7212bbd7.root', \ '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/ab55d910-204b-451d-862d-2a2c35af456a.root', \ '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/ddebeaf9-afd7-478f-8803-cc1c66bbc7d1.root', \ - '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/f00daee7-b0bd-47ab-96fe-dfc16c78f923.root' #, \ - # 'file:/eos/user/a/adamw/CMSAnalysis/DPG/Phase2Tracking/Data/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root' - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/061404ed-7c65-4f6e-88e9-b45a468f1cbe.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/162e0007-7588-46d8-9c93-a2b4b243885e.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/1bb480aa-0bad-439e-a6a4-a75780d0be9c.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/3db44076-4bb3-415b-b3a9-feb742460636.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/41d76683-9927-42e5-8c22-dfa056c56294.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/4bfe3713-82f0-43ac-8bd6-b16afd9d93e5.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/4c1b3277-7e2b-48c1-83b2-36ca12ea1a81.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/739566a2-723b-4c45-a40b-9d7a0f9e5434.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/75a2a485-cea5-4b7c-ab46-f08964fd9ac0.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/8490e1fb-3678-42b9-8010-d82ee3ec2a88.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/99ee730a-ec1c-4c3e-a345-71c82d1f2f41.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/a448fde4-b759-45ad-8c7e-45e1ec9d5f6e.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/b3c656c1-6e89-4491-b70d-2003eeb7fa72.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/c0f20d8b-f32b-40b5-bc5f-86fe17e90525.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/d7b6f571-25f9-44c4-812b-d040281b9d6a.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/db97a912-0690-46a1-80e7-ea6759b771ef.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/f542885d-c2a0-4a1f-9189-30a3995bcd61.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/fb22dfc2-87a5-40d5-b8c3-feb1e6df4047.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/fb6db36e-f813-4f25-92ea-afd7ed1ac961.root', \ - # '/store/relval/CMSSW_15_0_0/RelValTTbar_14TeV/GEN-SIM-RECO/141X_mcRun4_realistic_v3_STD_RegeneratedGS_Run4D110_noPU-v2/2580000/fc0a3df9-3f08-4355-9a91-12c1b3bd74ef.root' - ) + '/store/relval/CMSSW_15_1_0/RelValTTbar_14TeV/GEN-SIM-RECO/150X_mcRun4_realistic_v1_STD_RegeneratedGS_Run4D110_noPU-v1/2590000/f00daee7-b0bd-47ab-96fe-dfc16c78f923.root' + ) ) # Output From 15e3f19539363960c302b36f7a895741a0bf8066 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Mon, 27 Apr 2026 16:37:54 +0200 Subject: [PATCH 72/77] intermediate version --- DrawHits/fitResultsFromCanvases.py | 262 +++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 DrawHits/fitResultsFromCanvases.py diff --git a/DrawHits/fitResultsFromCanvases.py b/DrawHits/fitResultsFromCanvases.py new file mode 100644 index 0000000..403d33c --- /dev/null +++ b/DrawHits/fitResultsFromCanvases.py @@ -0,0 +1,262 @@ +import sys,os +import ROOT +from fnmatch import fnmatch +import argparse +import csv + +# +class MyColors: + ''' Simple class to create a sequence of colors from a predefined set + ''' + def __init__(self,colors=[1,2,4,6,7,8]): + # init with sorted list of ROOT color codes + assert colors + self.colors = colors + self.idx = None + + def next(self): + # return next color in sequence + if self.idx==None: + self.idx = 0 + return self.colors[self.idx] + self.idx += 1 + self.idx %= len(self.colors) + return self.colors[self.idx] + +def processPad(pad): + ''' Retrieve fit results from a single TPad + ''' + histo = None + for o in pad.GetListOfPrimitives(): + if o.InheritsFrom(ROOT.TH1.Class()) and o.GetDimension()==1: + assert histo==None + histo = o + + result = None + if histo: + print(histo.GetName()) + gaus = None + for f in histo.GetListOfFunctions(): + if f.GetName()=="gaus": + assert gaus==None + gaus = f + n = f.GetNpar() + assert n==3 + result = [ ] + for i in range(1,3): + result.append((f.GetParameter(i),f.GetParError(i))) + return result + +def processFile(rootfile): + ''' Retrieve fit results from a single root file generated by DrawHits + ''' + tf = ROOT.TFile(rootfile) + mainCnv = None + for k in tf.GetListOfKeys(): + o = tf.Get(k.GetName()) + if o.InheritsFrom(ROOT.TCanvas.Class()): + assert mainCnv==None + mainCnv = o + assert mainCnv + + pads = [ ] + for p in mainCnv.GetListOfPrimitives(): + if p.InheritsFrom(ROOT.TPad.Class()): + pads.append(p) + if len(pads)>=3: + break + assert len(pads)==3 + + results = [ ] + for p in pads: + result = processPad(p) + results.append(result) + + return results + +parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('--zones', '-z', help='zone name(s) (trailing part of input file names, with wildcard)', \ + type=str, default='*') +parser.add_argument('--csv', help='csv output file', type=str, default=None) +parser.add_argument('--output', '-o', help='output directory for graphic output', type=str, default=None) +parser.add_argument('--formats', help='comma-separated list of extensions for output files', \ + type=str, default="pdf,png") +parser.add_argument('directories', help='directories with stored canvases in root format', type=str, nargs='+') +args = parser.parse_args() +if args.output!=None: + assert os.path.isdir(args.output) +zones = [ x.strip() for x in args.zones.split(",") ] + + +ROOT.gStyle.SetOptStat(0) +allResults = { } +allFnGens = set() +newFnGens = { } +for d in args.directories: + assert os.path.isdir(d) + dn = os.path.basename(os.path.normpath(d)) + assert not dn in allResults + allResults[dn] = { } + dnResults = allResults[dn] + + fncode = None + for root,dirs,files in os.walk(d): + for f in files: + fname,fext = os.path.splitext(f) + if fext!=".root": + continue + fields = fname.split("_") + fngen = ( fields[0],"_".join(fields[2:]) ) + if not any([ fnmatch(fngen[1],x) for x in zones ]): + continue + if fncode!=None: + assert fields[1]==fncode + else: + fncode = fields[1] + results = processFile(os.path.join(root,f)) + print(results) + nNone = sum([ x==None for x in results ]) + assert nNone==0 or nNone==3 + if nNone==0: + #fngen = "_".join(fields[:1]+fields[2:]) + fngen = ( fields[0],"_".join(fields[2:]) ) + print(fngen) + allFnGens.add(fngen) + assert not fngen in dnResults + dnResults[fngen] = results +print(allFnGens) +sys.exit() + +mTypes = range(23,26) +parNames = [ 'mean', 'width' ] +dns = sorted(allResults.keys()) +nDns = len(dns) + +if args.csv!=None: + with open("tmpFitResults.csv","wt") as csvFile: + csvWriter = csv.writer(csvFile) + + hdrRow1 = [ 'Canvas' ] + hdrRow2 = [ '' ] + hdrRow3 = [ '' ] + for pn in parNames: + hdrRow1.append(pn) + hdrRow1.extend((nDns*len(mTypes)-1)*['']) + for mtype in mTypes: + hdrRow2.append("mType "+str(mtype)) + hdrRow2.extend((nDns-1)*['']) + for dn in dns: + hdrRow3.append(dn) + csvWriter.writerow(hdrRow1) + csvWriter.writerow(hdrRow2) + csvWriter.writerow(hdrRow3) + + for fnGen in sorted(allFnGens): + row = len(hdrRow1)*[ '' ] + row[0] = fnGen + idx = 1 + for ipn in range(len(parNames)): + for im in range(len(mTypes)): + for idn,dn in enumerate(dns): + dnResults = allResults[dn] + if fnGen in dnResults: + fnResults = dnResults[fnGen] + if fnGen=='cPullXW1_barrel': + print(ipn,im,idn,dn) + print(" ",fnResults[im][ipn]) + idx = 1 + idn + im*len(dns) + ipn*len(dns)*len(mTypes) + v = fnResults[im][ipn][0] + r = "{:4g}".format(v) + if "pull" in fnGen.lower(): + if parNames[ipn]=='mean': + r = '{:7.3f}'.format(v) + elif parNames[ipn]=='width': + r = '{:7.3f}'.format(v) + if "res" in fnGen.lower(): + if parNames[ipn]=='mean': + r = '{:7.2f}'.format(10000*v) + elif parNames[ipn]=='width': + r = '{:7.2f}'.format(10000*v) + #row[idx] = str(fnResults[im][ipn][0]) + row[idx] = r + csvWriter.writerow(row) + + csvFile.close() + +cnvs = { } +frames = [ ] +legs = [ ] +graphs = { } +for fnGen in sorted(allFnGens): + cnvs[fnGen] = { x:{ } for x in parNames } + graphs[fnGen] = { x:{ } for x in parNames } + for ipn,pn in enumerate(parNames): + cnv = ROOT.TCanvas(fnGen+"-"+pn,fnGen+"-"+pn,600,600) + cnv.SetBottomMargin(0.15) + cnvs[fnGen][pn] = cnv + graphs[fnGen][pn] = { x:{ } for x in mTypes } + frames.append(ROOT.TH1F("h"+fnGen[1:]+"-"+pn,"h"+fnGen[1:]+"-"+pn,nDns,-0.5,nDns-0.5)) + if pn=='mean': + #frames.append(cnv.DrawFrame(-0.5,-1,nDns-0.5,1)) + if "pull" in fnGen.lower(): + frames[-1].GetYaxis().SetTitle('mean (pull)') + elif "res" in fnGen.lower(): + frames[-1].GetYaxis().SetTitle('mean (residual) #mm') + elif pn=='width': + #frames.append(cnv.DrawFrame(-0.5,0,nDns-0.5,100)) + if "pull" in fnGen.lower(): + frames[-1].GetYaxis().SetTitle('sigma (pull)') + elif "res" in fnGen.lower(): + frames[-1].GetYaxis().SetTitle('sigma (residual) #mm') + for idn,dn in enumerate(dns): + frames[-1].GetXaxis().SetBinLabel(idn+1,dn) + frames[-1].GetXaxis().SetLabelSize(0.05) + ymin,ymax = 1.e30,-1.e30 + color = MyColors() + for im,mt in enumerate(mTypes): + graph = ROOT.TGraphErrors() + graph.SetName("g"+fnGen[1:]+"-"+pn+"-"+str(mt)) + graph.SetTitle("g"+fnGen[1:]+"-"+pn+"-"+str(mt)) + graph.SetLineWidth(2) + ic = color.next() + graph.SetLineColor(ic) + graph.SetMarkerStyle(im+20) + graph.SetMarkerColor(ic) + graphs[fnGen][pn][mt] = graph + for idn,dn in enumerate(dns): + dnResults = allResults[dn] + if fnGen in dnResults: + fnResults = dnResults[fnGen] + v,e = fnResults[im][ipn] + if "res" in fnGen.lower(): + v *= 10000 + e *= 10000 + graph.AddPointError(idn,v,0.,e) + ymin = min(ymin,v-e) + ymax = max(ymax,v+e) + if pn=='mean': + dy = ymax - ymin + ymin -= dy*1.01 + ymax += dy*1.04 + elif pn=='width': + ymin = 0. + ymax *= 1.10 + frames[-1].SetMinimum(ymin) + frames[-1].SetMaximum(ymax) + frames[-1].Draw() + leg = ROOT.TLegend(0.15,0.85,0.90,0.90) + leg.SetNColumns(3) + leg.SetBorderSize(0) + leg.SetFillStyle(0) + legs.append(leg) + for mt in mTypes: + leg.AddEntry(graphs[fnGen][pn][mt],"mType "+str(mt),"LP") + graphs[fnGen][pn][mt].Draw("PL") + leg.Draw() + cnv.Update() + if args.output!=None: + for fmt in [ x.strip() for x in args.formats.split(",") ]: + fnout = os.path.join(args.output,cnv.GetName()+"."+fmt) + cnv.SaveAs(fnout) + + From 8e7597b72891850a13768454c9f532d7b1bc3ff0 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 28 Apr 2026 09:18:04 +0200 Subject: [PATCH 73/77] updates to fitting tools --- DrawHits/FitHistogram.py | 274 +++++++++++++++++++++++++++++ DrawHits/fitRes.py | 272 +--------------------------- DrawHits/fitResultsFromCanvases.py | 104 ++++++----- 3 files changed, 335 insertions(+), 315 deletions(-) create mode 100644 DrawHits/FitHistogram.py diff --git a/DrawHits/FitHistogram.py b/DrawHits/FitHistogram.py new file mode 100644 index 0000000..70c0a9e --- /dev/null +++ b/DrawHits/FitHistogram.py @@ -0,0 +1,274 @@ +import ROOT + +class FitHistogram: + + def interpolate(y,y1,y2,x1=0.,x2=1.): + ''' Linear interpolation between two points (x1,y1) and (x2,y2) + to yield x corresponding to the target value y. + ''' + return x1 + (y-y1)/(y2-y1)*(x2-x1) + + def __init__(self,histogram): + self.hist = histogram + self.graph_ = None + self.cumulativeGraph_ = None + self.cumNormGraph_ = None + self.cumNormTGraph_ = None + self.cumNormSpline_ = None # spline corresponding to normalized cumulative graph + + def graph(self): + ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = bin contents. + Ignores under- / overflow. + ''' + if self.graph_==None: + self.graph_ = [ ] + + for i in range(self.hist.GetNbinsX()): + xbin = self.hist.GetBinLowEdge(i+1) + self.hist.GetBinWidth(i+1)/2. + self.graph_.append( (xbin,self.hist.GetBinContent(i+1)) ) + + return self.graph_ + + def cumulativeGraph(self): + ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = cumulated bin contents. + Ignores under- / overflow. + ''' + if self.cumulativeGraph_==None: + self.cumulativeGraph_ = [ ] + sum = 0. + for i in range(self.hist.GetNbinsX()): + xbin = self.hist.GetBinLowEdge(i+1) + self.hist.GetBinWidth(i+1)/2. + sum += self.hist.GetBinContent(i+1) + self.cumulativeGraph_.append( (xbin,sum) ) + + return self.cumulativeGraph_ + + def cumulativeNormGraph(self): + ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = cumulated bin contents. + Normalized to total histogram contents (including under- / overflow). + ''' + if self.cumNormGraph_==None: + cg = self.cumulativeGraph() + sum = self.hist.GetSumOfWeights() + self.cumNormGraph_ = [ ( x,y/sum ) for x,y in cg ] + + return self.cumNormGraph_ + + def cumulativeNormSpline(self): + ''' Create (TGraph and) TSpline3 from cumulativeNormGraph + ''' + if self.cumNormTGraph_==None: + self.cumNormTGraph_ = ROOT.TGraph() + for x,y in self.cumulativeNormGraph(): + self.cumNormTGraph_.SetPoint(self.cumNormTGraph_.GetN(),x,y) + + if self.cumNormSpline_==None: + self.cumNormSpline_ = ROOT.TSpline3(self.hist.GetName()+"-spline",self.cumNormTGraph_) + + return self.cumNormSpline_ + + + def intersects(self,value,cumulative=False,norm=False,direction=0): + ''' Calculate x-coordinates for intersection(s) of a graph defined by a list of (x,y) points sorted in x + with y==value. Uses linear interpolation. + Arguments: + value ....... target value + cumulative .. if true, use cumulative graph + norm ........ if true, use normalized cumulative graph + direction ... three possible values: 0 = any intersection, +1/-1 = consider only segments + with positive / negative slope. + ''' + # + # Get graph and do basic check + # + graph = None + if cumulative: + graph = self.cumulativeNormGraph() if norm else self.cumulativeGraph() + else: + assert norm==False + graph = self.graph() + + result = [ ] + if len(graph)<2: + return result + # + # loop over adjacent pairs of points + # + x1 = None + y1 = None + for x2,y2 in graph: + # + # start checking at 2nd point + # + if x1!=None: + assert x2>x1 + # + # value in interval? + # + if value>=min(y1,y2) and value<=max(y1,y2): + # check if dy is positive or negative, and compare with required sign of direction + if direction==0 or direction*(y2-y1)>0: + result.append(FitHistogram.interpolate(value,y2,y1,x2,x1)) + # + # move to next point + # + x1 = x2 + y1 = y2 + + return result + + def fwhm(self): + ''' Return lowest / highest x corresponding to ymax/2, and ymax/2 + ''' + # + # target y value (1/2 maximum) + # + y = self.hist.GetBinContent(self.hist.GetMaximumBin())/2. + # + # use first intersection with upward slope + # + xups = self.intersects(y,cumulative=False,direction=1) + print("xups",xups) + xlow = xups[0] if xups else None + # + # use last intersection with downward slope + # + xdowns = self.intersects(y,cumulative=False,direction=-1) + print("xdowns",xdowns) + xhigh = xdowns[-1] if xdowns else None + #dx = self.hist.GetBinWidth(1) + ### + ## preset result (low / high x values) + ## + #xlow = None + #xhigh = None + ## + ## loop over pairs of adjacent histogram bins + ## + #x1 = self.hist.GetBinLowEdge(1) + #y1 = self.hist.GetBinContent(1) + #for i in range(2,self.hist.GetNbinsX()): + # # check if target value between contents of neighbouring bins + # x2 = self.hist.GetBinLowEdge(i) + # y2 = self.hist.GetBinContent(i) + # first = None + # if y>=y1 and yy2: + # first = False + # + # if first!=None: + # # calculate interpolated x value + # x = FitHistogram.interpolate(y,y1,y2,x1,x2) + # # store lowest and highest x corresponding to y + # if first and xlow==None: + # xlow = x + # elif not first: + # xhigh = x + # # move to next bin + # x1 = x2 + # y1 = y2 + + # + # require result ( assumes that first and last bins are < ymax/2 ) and + # correct for bin width / 2 ( assumes that bin value corresponds to center of bin ) + assert xlow!=None and xhigh!=None + return (xlow,xhigh,y) + #return (xlow+dx,xhigh+dx,y) + + def quantile(self,prob): + ''' Return x-value to quantile q. + ''' + result = self.intersects(prob,cumulative=True,norm=True,direction=1) + #print(prob,result) + assert len(result)<2 + + return result[0] if result else None + + def findRootSpline(self,value,eps=0.001): + ''' Find position where spline derived from cumulative NormGraph= value. Assumes that the spline is \ + monotonously increasing. Tolerance is eps*value or cGraph[-1][1]=ymax: + print("findRootSpline: last value <= first value") + return None + # + # Check if inside values spanned by spline + # + if valueymax: + print("findRootSpline: required value outside range") + return None + # + # tolerance for distance between points + # + dxmax = eps*(ymax-ymin) + # + # loop with cutoff in case of non-convergence + # + found = False + for i in range(1000): + if (xh-xl)prob1 + result = ( None, None ) + xmin = self.hist.GetXaxis().GetXmin() + if prob1>0.: + xmin = self.findRootSpline(prob1) + if xmin==None: + return result + xmax = self.hist.GetXaxis().GetXmax() + if prob2<1.: + xmax = self.findRootSpline(prob2) + if xmin==None: + return result + + fitFunc = ROOT.TF1("mygaus","gaus(0)",xmin,xmax) + fitFunc.SetParameter(0,self.hist.GetMaximum()) + fitFunc.SetParameter(1,0.) + fitFunc.SetParLimits(1,-10.,10.) + fitFunc.SetParameter(2,self.hist.GetRMS()) + + fitPtr = self.hist.Fit(fitFunc,"S0") + #fitPtr = self.hist.Fit("gaus","S0","",xmin,xmax) + if ( not fitPtr.IsValid() ) or fitPtr.IsEmpty(): + return result + + #return fitPtr,self.hist.GetFunction("gaus") + return fitPtr,fitFunc + + diff --git a/DrawHits/fitRes.py b/DrawHits/fitRes.py index 3317cb7..9233ec1 100644 --- a/DrawHits/fitRes.py +++ b/DrawHits/fitRes.py @@ -1,279 +1,9 @@ import sys,os from math import sqrt,log import ROOT +import FitHistogram import argparse -class FitHistogram: - - def interpolate(y,y1,y2,x1=0.,x2=1.): - ''' Linear interpolation between two points (x1,y1) and (x2,y2) - to yield x corresponding to the target value y. - ''' - return x1 + (y-y1)/(y2-y1)*(x2-x1) - - def __init__(self,histogram): - self.hist = histogram - self.graph_ = None - self.cumulativeGraph_ = None - self.cumNormGraph_ = None - self.cumNormTGraph_ = None - self.cumNormSpline_ = None # spline corresponding to normalized cumulative graph - - def graph(self): - ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = bin contents. - Ignores under- / overflow. - ''' - if self.graph_==None: - self.graph_ = [ ] - - for i in range(self.hist.GetNbinsX()): - xbin = self.hist.GetBinLowEdge(i+1) + self.hist.GetBinWidth(i+1)/2. - self.graph_.append( (xbin,self.hist.GetBinContent(i+1)) ) - - return self.graph_ - - def cumulativeGraph(self): - ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = cumulated bin contents. - Ignores under- / overflow. - ''' - if self.cumulativeGraph_==None: - self.cumulativeGraph_ = [ ] - sum = 0. - for i in range(self.hist.GetNbinsX()): - xbin = self.hist.GetBinLowEdge(i+1) + self.hist.GetBinWidth(i+1)/2. - sum += self.hist.GetBinContent(i+1) - self.cumulativeGraph_.append( (xbin,sum) ) - - return self.cumulativeGraph_ - - def cumulativeNormGraph(self): - ''' Histogram converted to list of (x,y) coordinates with x = bin center and y = cumulated bin contents. - Normalized to total histogram contents (including under- / overflow). - ''' - if self.cumNormGraph_==None: - cg = self.cumulativeGraph() - sum = self.hist.GetSumOfWeights() - self.cumNormGraph_ = [ ( x,y/sum ) for x,y in cg ] - - return self.cumNormGraph_ - - def cumulativeNormSpline(self): - ''' Create (TGraph and) TSpline3 from cumulativeNormGraph - ''' - if self.cumNormTGraph_==None: - self.cumNormTGraph_ = ROOT.TGraph() - for x,y in self.cumulativeNormGraph(): - self.cumNormTGraph_.SetPoint(self.cumNormTGraph_.GetN(),x,y) - - if self.cumNormSpline_==None: - self.cumNormSpline_ = ROOT.TSpline3(self.hist.GetName()+"-spline",self.cumNormTGraph_) - - return self.cumNormSpline_ - - - def intersects(self,value,cumulative=False,norm=False,direction=0): - ''' Calculate x-coordinates for intersection(s) of a graph defined by a list of (x,y) points sorted in x - with y==value. Uses linear interpolation. - Arguments: - value ....... target value - cumulative .. if true, use cumulative graph - norm ........ if true, use normalized cumulative graph - direction ... three possible values: 0 = any intersection, +1/-1 = consider only segments - with positive / negative slope. - ''' - # - # Get graph and do basic check - # - graph = None - if cumulative: - graph = self.cumulativeNormGraph() if norm else self.cumulativeGraph() - else: - assert norm==False - graph = self.graph() - - result = [ ] - if len(graph)<2: - return result - # - # loop over adjacent pairs of points - # - x1 = None - y1 = None - for x2,y2 in graph: - # - # start checking at 2nd point - # - if x1!=None: - assert x2>x1 - # - # value in interval? - # - if value>=min(y1,y2) and value<=max(y1,y2): - # check if dy is positive or negative, and compare with required sign of direction - if direction==0 or direction*(y2-y1)>0: - result.append(FitHistogram.interpolate(value,y2,y1,x2,x1)) - # - # move to next point - # - x1 = x2 - y1 = y2 - - return result - - def fwhm(self): - ''' Return lowest / highest x corresponding to ymax/2, and ymax/2 - ''' - # - # target y value (1/2 maximum) - # - y = self.hist.GetBinContent(self.hist.GetMaximumBin())/2. - # - # use first intersection with upward slope - # - xups = self.intersects(y,cumulative=False,direction=1) - print("xups",xups) - xlow = xups[0] if xups else None - # - # use last intersection with downward slope - # - xdowns = self.intersects(y,cumulative=False,direction=-1) - print("xdowns",xdowns) - xhigh = xdowns[-1] if xdowns else None - #dx = self.hist.GetBinWidth(1) - ### - ## preset result (low / high x values) - ## - #xlow = None - #xhigh = None - ## - ## loop over pairs of adjacent histogram bins - ## - #x1 = self.hist.GetBinLowEdge(1) - #y1 = self.hist.GetBinContent(1) - #for i in range(2,self.hist.GetNbinsX()): - # # check if target value between contents of neighbouring bins - # x2 = self.hist.GetBinLowEdge(i) - # y2 = self.hist.GetBinContent(i) - # first = None - # if y>=y1 and yy2: - # first = False - # - # if first!=None: - # # calculate interpolated x value - # x = FitHistogram.interpolate(y,y1,y2,x1,x2) - # # store lowest and highest x corresponding to y - # if first and xlow==None: - # xlow = x - # elif not first: - # xhigh = x - # # move to next bin - # x1 = x2 - # y1 = y2 - - # - # require result ( assumes that first and last bins are < ymax/2 ) and - # correct for bin width / 2 ( assumes that bin value corresponds to center of bin ) - assert xlow!=None and xhigh!=None - return (xlow,xhigh,y) - #return (xlow+dx,xhigh+dx,y) - - def quantile(self,prob): - ''' Return x-value to quantile q. - ''' - result = self.intersects(prob,cumulative=True,norm=True,direction=1) - #print(prob,result) - assert len(result)<2 - - return result[0] if result else None - - def findRootSpline(self,value,eps=0.001): - ''' Find position where spline derived from cumulative NormGraph= value. Assumes that the spline is \ - monotonously increasing. Tolerance is eps*value or cGraph[-1][1]=ymax: - print("findRootSpline: last value <= first value") - return None - # - # Check if inside values spanned by spline - # - if valueymax: - print("findRootSpline: required value outside range") - return None - # - # tolerance for distance between points - # - dxmax = eps*(ymax-ymin) - # - # loop with cutoff in case of non-convergence - # - found = False - for i in range(1000): - if (xh-xl)prob1 - result = ( None, None ) - xmin = self.hist.GetXaxis().GetXmin() - if prob1>0.: - xmin = self.findRootSpline(prob1) - if xmin==None: - return result - xmax = self.hist.GetXaxis().GetXmax() - if prob2<1.: - xmax = self.findRootSpline(prob2) - if xmin==None: - return result - - fitFunc = ROOT.TF1("mygaus","gaus(0)",xmin,xmax) - fitFunc.SetParameter(0,self.hist.GetMaximum()) - fitFunc.SetParameter(1,0.) - fitFunc.SetParLimits(1,-10.,10.) - fitFunc.SetParameter(2,self.hist.GetRMS()) - - fitPtr = self.hist.Fit(fitFunc,"S0") - #fitPtr = self.hist.Fit("gaus","S0","",xmin,xmax) - if ( not fitPtr.IsValid() ) or fitPtr.IsEmpty(): - return result - - #return fitPtr,self.hist.GetFunction("gaus") - return fitPtr,fitFunc - class FitCanvas: diff --git a/DrawHits/fitResultsFromCanvases.py b/DrawHits/fitResultsFromCanvases.py index 403d33c..b3d2972 100644 --- a/DrawHits/fitResultsFromCanvases.py +++ b/DrawHits/fitResultsFromCanvases.py @@ -124,8 +124,8 @@ def processFile(rootfile): allFnGens.add(fngen) assert not fngen in dnResults dnResults[fngen] = results -print(allFnGens) -sys.exit() +#print(allFnGens) +#sys.exit() mTypes = range(23,26) parNames = [ 'mean', 'width' ] @@ -153,7 +153,7 @@ def processFile(rootfile): for fnGen in sorted(allFnGens): row = len(hdrRow1)*[ '' ] - row[0] = fnGen + row[0] = "_".join(fnGen) idx = 1 for ipn in range(len(parNames)): for im in range(len(mTypes)): @@ -187,71 +187,87 @@ def processFile(rootfile): frames = [ ] legs = [ ] graphs = { } -for fnGen in sorted(allFnGens): - cnvs[fnGen] = { x:{ } for x in parNames } - graphs[fnGen] = { x:{ } for x in parNames } +fnRoots = set( [ x[0] for x in allFnGens ] ) +fnZones = set( [ x[1] for x in allFnGens ] ) +for fnRoot in sorted(fnRoots): + cnvs[fnRoot] = { x:{ } for x in parNames } + graphs[fnRoot] = { x:{ } for x in parNames } for ipn,pn in enumerate(parNames): - cnv = ROOT.TCanvas(fnGen+"-"+pn,fnGen+"-"+pn,600,600) + cnv = ROOT.TCanvas(fnRoot+"-"+pn,fnRoot+"-"+pn,600,600) cnv.SetBottomMargin(0.15) - cnvs[fnGen][pn] = cnv - graphs[fnGen][pn] = { x:{ } for x in mTypes } - frames.append(ROOT.TH1F("h"+fnGen[1:]+"-"+pn,"h"+fnGen[1:]+"-"+pn,nDns,-0.5,nDns-0.5)) + cnvs[fnRoot][pn] = cnv + graphs[fnRoot][pn] = { } + for fnZone in fnZones: + graphs[fnRoot][pn][fnZone] = { } + for mt in mTypes: + graphs[fnRoot][pn][fnZone][mt] = { } + #graphs[fnRoot][pn] = { x:{ } for x in mTypes } + frames.append(ROOT.TH1F("h"+fnRoot[1:]+"-"+pn,"h"+fnRoot[1:]+"-"+pn,nDns,-0.5,nDns-0.5)) if pn=='mean': #frames.append(cnv.DrawFrame(-0.5,-1,nDns-0.5,1)) - if "pull" in fnGen.lower(): + if "pull" in fnRoot.lower(): frames[-1].GetYaxis().SetTitle('mean (pull)') - elif "res" in fnGen.lower(): + elif "res" in fnRoot.lower(): frames[-1].GetYaxis().SetTitle('mean (residual) #mm') elif pn=='width': #frames.append(cnv.DrawFrame(-0.5,0,nDns-0.5,100)) - if "pull" in fnGen.lower(): + if "pull" in fnRoot.lower(): frames[-1].GetYaxis().SetTitle('sigma (pull)') - elif "res" in fnGen.lower(): + elif "res" in fnRoot.lower(): frames[-1].GetYaxis().SetTitle('sigma (residual) #mm') for idn,dn in enumerate(dns): frames[-1].GetXaxis().SetBinLabel(idn+1,dn) frames[-1].GetXaxis().SetLabelSize(0.05) ymin,ymax = 1.e30,-1.e30 - color = MyColors() - for im,mt in enumerate(mTypes): - graph = ROOT.TGraphErrors() - graph.SetName("g"+fnGen[1:]+"-"+pn+"-"+str(mt)) - graph.SetTitle("g"+fnGen[1:]+"-"+pn+"-"+str(mt)) - graph.SetLineWidth(2) - ic = color.next() - graph.SetLineColor(ic) - graph.SetMarkerStyle(im+20) - graph.SetMarkerColor(ic) - graphs[fnGen][pn][mt] = graph - for idn,dn in enumerate(dns): - dnResults = allResults[dn] - if fnGen in dnResults: - fnResults = dnResults[fnGen] - v,e = fnResults[im][ipn] - if "res" in fnGen.lower(): - v *= 10000 - e *= 10000 - graph.AddPointError(idn,v,0.,e) - ymin = min(ymin,v-e) - ymax = max(ymax,v+e) + lstyle = MyColors([1,2,3]) + marker = 20 + for iz,fnZone in enumerate(sorted(fnZones)): + istyle = lstyle.next() + color = MyColors() + for im,mt in enumerate(mTypes): + graph = ROOT.TGraphErrors() + graph.SetName("g"+fnZone+"-"+pn+"-"+str(mt)) + graph.SetTitle("g"+fnZone+"-"+pn+"-"+str(mt)) + graph.SetLineWidth(2) + ic = color.next() + graph.SetLineColor(ic) + graph.SetLineStyle(istyle) + graph.SetMarkerStyle(marker) + marker += 1 + graph.SetMarkerColor(ic) + graphs[fnRoot][pn][fnZone][mt] = graph + fnGen = ( fnRoot, fnZone ) + for idn,dn in enumerate(dns): + dnResults = allResults[dn] + if fnGen in dnResults: + fnResults = dnResults[fnGen] + v,e = fnResults[im][ipn] + if "res" in fnRoot.lower(): + v *= 10000 + e *= 10000 + graph.AddPointError(idn+nDns*iz/50,v,0.,e) + ymin = min(ymin,v-e) + ymax = max(ymax,v+e) if pn=='mean': dy = ymax - ymin - ymin -= dy*1.01 - ymax += dy*1.04 + ymin -= dy*0.05 + ymax += dy*0.15 elif pn=='width': ymin = 0. - ymax *= 1.10 + ymax *= 1.15 frames[-1].SetMinimum(ymin) frames[-1].SetMaximum(ymax) frames[-1].Draw() - leg = ROOT.TLegend(0.15,0.85,0.90,0.90) - leg.SetNColumns(3) + leg = ROOT.TLegend(0.15,0.80,0.90,0.90) + leg.SetNColumns(4) leg.SetBorderSize(0) leg.SetFillStyle(0) legs.append(leg) - for mt in mTypes: - leg.AddEntry(graphs[fnGen][pn][mt],"mType "+str(mt),"LP") - graphs[fnGen][pn][mt].Draw("PL") + for fnZone in sorted(fnZones): + leg.AddEntry("",fnZone,"") + for mt in mTypes: + leg.AddEntry(graphs[fnRoot][pn][fnZone][mt],"mType "+str(mt),"LP") + graphs[fnRoot][pn][fnZone][mt].Draw("PL") leg.Draw() cnv.Update() if args.output!=None: From da0a027cdd7795926c66672129504b96bb29fb6b Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Tue, 28 Apr 2026 11:36:36 +0200 Subject: [PATCH 74/77] debugging --- DrawHits/FitHistogram.py | 5 +- DrawHits/fitResultsFromCanvases.py | 101 ++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 32 deletions(-) diff --git a/DrawHits/FitHistogram.py b/DrawHits/FitHistogram.py index 70c0a9e..01121ab 100644 --- a/DrawHits/FitHistogram.py +++ b/DrawHits/FitHistogram.py @@ -181,8 +181,9 @@ def quantile(self,prob): ''' result = self.intersects(prob,cumulative=True,norm=True,direction=1) #print(prob,result) - assert len(result)<2 - + if len(result)>1: + result = None + return result[0] if result else None def findRootSpline(self,value,eps=0.001): diff --git a/DrawHits/fitResultsFromCanvases.py b/DrawHits/fitResultsFromCanvases.py index b3d2972..a1a5ce8 100644 --- a/DrawHits/fitResultsFromCanvases.py +++ b/DrawHits/fitResultsFromCanvases.py @@ -1,5 +1,7 @@ import sys,os import ROOT +from FitHistogram import FitHistogram +from math import sqrt,log from fnmatch import fnmatch import argparse import csv @@ -23,7 +25,16 @@ def next(self): self.idx %= len(self.colors) return self.colors[self.idx] -def processPad(pad): +def fromQuantiles(fitHisto,isig): + xqs = [ ] + for sgn in [ -1, 0, 1 ]: + xqs.append(fitHisto.quantile(ROOT.TMath.Freq(sgn*isig))) + if None in xqs: + return None + + return [ ( xqs[1], 0. ), ( (xqs[2]-xqs[0])/2./isig, 0. ) ] + +def processPad(pad,algo='prefit'): ''' Retrieve fit results from a single TPad ''' histo = None @@ -31,23 +42,48 @@ def processPad(pad): if o.InheritsFrom(ROOT.TH1.Class()) and o.GetDimension()==1: assert histo==None histo = o - + if histo==None: + return None + #print(histo.GetName()) + result = None - if histo: - print(histo.GetName()) - gaus = None - for f in histo.GetListOfFunctions(): - if f.GetName()=="gaus": - assert gaus==None - gaus = f - n = f.GetNpar() - assert n==3 - result = [ ] - for i in range(1,3): - result.append((f.GetParameter(i),f.GetParError(i))) + fitHisto = FitHistogram(histo) + match algo: + case 'prefit': + gaus = None + for f in histo.GetListOfFunctions(): + if f.GetName()=="gaus": + assert gaus==None + gaus = f + n = f.GetNpar() + assert n==3 + result = [ ] + for i in range(1,3): + result.append((f.GetParameter(i),f.GetParError(i))) + case 'gaus': + fitPtr,fitFunc - fitHisto.fitGaus() + result = [ ] + for i in range(1,3): + result.append((f.GetParameter(i),f.GetParError(i))) + case 'fwhm': + xmin,xmax,y = fitHisto.fwhm() + result = [ ( (xmax-xmin)/2., 0. ), ( (xmax-xmin)/2/sqrt(2*log(2.)), 0. ) ] + + case 'q1sig': + result = fromQuantiles(fitHisto,1) + + case 'q2sig': + result = fromQuantiles(fitHisto,2) + + case 'q3sig': + result = fromQuantiles(fitHisto,3) + + case _: + raise ValueError("Unknown algorithm "+algo) + return result -def processFile(rootfile): +def processFile(rootfile,algo='prefit'): ''' Retrieve fit results from a single root file generated by DrawHits ''' tf = ROOT.TFile(rootfile) @@ -69,7 +105,8 @@ def processFile(rootfile): results = [ ] for p in pads: - result = processPad(p) + #print("Processing pad in",rootfile) + result = processPad(p,algo) results.append(result) return results @@ -79,8 +116,10 @@ def processFile(rootfile): type=str, default='*') parser.add_argument('--csv', help='csv output file', type=str, default=None) parser.add_argument('--output', '-o', help='output directory for graphic output', type=str, default=None) -parser.add_argument('--formats', help='comma-separated list of extensions for output files', \ +parser.add_argument('--formats', '-f', help='comma-separated list of extensions for output files', \ type=str, default="pdf,png") +parser.add_argument('--algorithm', '-a', help='algorithm used for fit results', type=str, \ + choices=[ 'prefit', 'gaus', 'fwhm', 'q1sig', 'q2sig', 'q3sig' ], default='prefit' ) parser.add_argument('directories', help='directories with stored canvases in root format', type=str, nargs='+') args = parser.parse_args() if args.output!=None: @@ -113,14 +152,14 @@ def processFile(rootfile): assert fields[1]==fncode else: fncode = fields[1] - results = processFile(os.path.join(root,f)) - print(results) + results = processFile(os.path.join(root,f),args.algorithm) nNone = sum([ x==None for x in results ]) - assert nNone==0 or nNone==3 + if nNone>0 and nNone<3: + print("***",fname,results) + #assert nNone==0 or nNone==3 if nNone==0: #fngen = "_".join(fields[:1]+fields[2:]) fngen = ( fields[0],"_".join(fields[2:]) ) - print(fngen) allFnGens.add(fngen) assert not fngen in dnResults dnResults[fngen] = results @@ -193,7 +232,8 @@ def processFile(rootfile): cnvs[fnRoot] = { x:{ } for x in parNames } graphs[fnRoot] = { x:{ } for x in parNames } for ipn,pn in enumerate(parNames): - cnv = ROOT.TCanvas(fnRoot+"-"+pn,fnRoot+"-"+pn,600,600) + cnvName = fnRoot+"-"+pn+"-"+args.algorithm + cnv = ROOT.TCanvas(cnvName,cnvName,600,600) cnv.SetBottomMargin(0.15) cnvs[fnRoot][pn] = cnv graphs[fnRoot][pn] = { } @@ -202,7 +242,7 @@ def processFile(rootfile): for mt in mTypes: graphs[fnRoot][pn][fnZone][mt] = { } #graphs[fnRoot][pn] = { x:{ } for x in mTypes } - frames.append(ROOT.TH1F("h"+fnRoot[1:]+"-"+pn,"h"+fnRoot[1:]+"-"+pn,nDns,-0.5,nDns-0.5)) + frames.append(ROOT.TH1F("h"+fnRoot[1:]+"-"+pn,fnRoot[1:]+"-"+pn+" ("+args.algorithm+")",nDns,-0.5,nDns-0.5)) if pn=='mean': #frames.append(cnv.DrawFrame(-0.5,-1,nDns-0.5,1)) if "pull" in fnRoot.lower(): @@ -241,13 +281,14 @@ def processFile(rootfile): dnResults = allResults[dn] if fnGen in dnResults: fnResults = dnResults[fnGen] - v,e = fnResults[im][ipn] - if "res" in fnRoot.lower(): - v *= 10000 - e *= 10000 - graph.AddPointError(idn+nDns*iz/50,v,0.,e) - ymin = min(ymin,v-e) - ymax = max(ymax,v+e) + if fnResults[im][ipn]!=None: + v,e = fnResults[im][ipn] + if "res" in fnRoot.lower(): + v *= 10000 + e *= 10000 + graph.AddPointError(idn+nDns*iz/50,v,0.,e) + ymin = min(ymin,v-e) + ymax = max(ymax,v+e) if pn=='mean': dy = ymax - ymin ymin -= dy*0.05 From 17f4b7f6e10bf21ac5d416331a74a309c0372001 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 29 Apr 2026 10:50:00 +0200 Subject: [PATCH 75/77] add arguments --- DrawHits/fitResultsFromCanvases.py | 217 ++++++++++++++++------------- 1 file changed, 124 insertions(+), 93 deletions(-) diff --git a/DrawHits/fitResultsFromCanvases.py b/DrawHits/fitResultsFromCanvases.py index a1a5ce8..c79d914 100644 --- a/DrawHits/fitResultsFromCanvases.py +++ b/DrawHits/fitResultsFromCanvases.py @@ -1,3 +1,7 @@ +# +# use canvases produced by drawHitsRDF to summarize means and widths for 1D residual or pull histograms +# by detector zone, module type, and algorithm +# import sys,os import ROOT from FitHistogram import FitHistogram @@ -67,7 +71,7 @@ def processPad(pad,algo='prefit'): result.append((f.GetParameter(i),f.GetParError(i))) case 'fwhm': xmin,xmax,y = fitHisto.fwhm() - result = [ ( (xmax-xmin)/2., 0. ), ( (xmax-xmin)/2/sqrt(2*log(2.)), 0. ) ] + result = [ ( (xmax+xmin)/2., 0. ), ( (xmax-xmin)/2/sqrt(2*log(2.)), 0. ) ] case 'q1sig': result = fromQuantiles(fitHisto,1) @@ -118,14 +122,24 @@ def processFile(rootfile,algo='prefit'): parser.add_argument('--output', '-o', help='output directory for graphic output', type=str, default=None) parser.add_argument('--formats', '-f', help='comma-separated list of extensions for output files', \ type=str, default="pdf,png") -parser.add_argument('--algorithm', '-a', help='algorithm used for fit results', type=str, \ - choices=[ 'prefit', 'gaus', 'fwhm', 'q1sig', 'q2sig', 'q3sig' ], default='prefit' ) +parser.add_argument('--mtypes', help='comma-separated list of module types', \ + type=str, default="23,24,25") +parser.add_argument('--names', help='comma-separated list of patterns to match file names', \ + type=str, default="*") +parser.add_argument('--algorithms', '-a', help='comma-separated list of algorithms used for fit results', \ + type=str, default='prefit' ) parser.add_argument('directories', help='directories with stored canvases in root format', type=str, nargs='+') args = parser.parse_args() if args.output!=None: assert os.path.isdir(args.output) zones = [ x.strip() for x in args.zones.split(",") ] - +reqFNames = [ x.strip() for x in args.names.split(",") ] +reqMTypes = [ int(x.strip()) for x in args.mtypes.split(",") ] +allAlgos = [ 'prefit', 'gaus', 'fwhm', 'q1sig', 'q2sig', 'q3sig' ] +reqAlgos = [ ] +for a in [ x.strip().lower() for x in args.algorithms.split(",") ]: + assert a in allAlgos + reqAlgos.append(a) ROOT.gStyle.SetOptStat(0) allResults = { } @@ -144,6 +158,8 @@ def processFile(rootfile,algo='prefit'): fname,fext = os.path.splitext(f) if fext!=".root": continue + if not any([ fnmatch(fname,x) for x in reqFNames ]): + continue fields = fname.split("_") fngen = ( fields[0],"_".join(fields[2:]) ) if not any([ fnmatch(fngen[1],x) for x in zones ]): @@ -152,75 +168,78 @@ def processFile(rootfile,algo='prefit'): assert fields[1]==fncode else: fncode = fields[1] - results = processFile(os.path.join(root,f),args.algorithm) - nNone = sum([ x==None for x in results ]) - if nNone>0 and nNone<3: - print("***",fname,results) - #assert nNone==0 or nNone==3 - if nNone==0: - #fngen = "_".join(fields[:1]+fields[2:]) - fngen = ( fields[0],"_".join(fields[2:]) ) - allFnGens.add(fngen) - assert not fngen in dnResults - dnResults[fngen] = results + dnResults[fngen] = { } + for algo in reqAlgos: + results = processFile(os.path.join(root,f),algo) + nNone = sum([ x==None for x in results ]) + if nNone>0 and nNone<3: + print("***",fname,results) + #assert nNone==0 or nNone==3 + if nNone==0: + #fngen = "_".join(fields[:1]+fields[2:]) + fngen = ( fields[0],"_".join(fields[2:]) ) + allFnGens.add(fngen) + #assert not fngen in dnResults + dnResults[fngen][algo] = results #print(allFnGens) #sys.exit() -mTypes = range(23,26) +allMTypes = range(23,26) +mTypes = reqMTypes parNames = [ 'mean', 'width' ] dns = sorted(allResults.keys()) nDns = len(dns) -if args.csv!=None: - with open("tmpFitResults.csv","wt") as csvFile: - csvWriter = csv.writer(csvFile) +#!# if args.csv!=None: +#!# with open("tmpFitResults.csv","wt") as csvFile: +#!# csvWriter = csv.writer(csvFile) - hdrRow1 = [ 'Canvas' ] - hdrRow2 = [ '' ] - hdrRow3 = [ '' ] - for pn in parNames: - hdrRow1.append(pn) - hdrRow1.extend((nDns*len(mTypes)-1)*['']) - for mtype in mTypes: - hdrRow2.append("mType "+str(mtype)) - hdrRow2.extend((nDns-1)*['']) - for dn in dns: - hdrRow3.append(dn) - csvWriter.writerow(hdrRow1) - csvWriter.writerow(hdrRow2) - csvWriter.writerow(hdrRow3) +#!# hdrRow1 = [ 'Canvas' ] +#!# hdrRow2 = [ '' ] +#!# hdrRow3 = [ '' ] +#!# for pn in parNames: +#!# hdrRow1.append(pn) +#!# hdrRow1.extend((nDns*len(mTypes)-1)*['']) +#!# for mtype in mTypes: +#!# hdrRow2.append("mType "+str(mtype)) +#!# hdrRow2.extend((nDns-1)*['']) +#!# for dn in dns: +#!# hdrRow3.append(dn) +#!# csvWriter.writerow(hdrRow1) +#!# csvWriter.writerow(hdrRow2) +#!# csvWriter.writerow(hdrRow3) - for fnGen in sorted(allFnGens): - row = len(hdrRow1)*[ '' ] - row[0] = "_".join(fnGen) - idx = 1 - for ipn in range(len(parNames)): - for im in range(len(mTypes)): - for idn,dn in enumerate(dns): - dnResults = allResults[dn] - if fnGen in dnResults: - fnResults = dnResults[fnGen] - if fnGen=='cPullXW1_barrel': - print(ipn,im,idn,dn) - print(" ",fnResults[im][ipn]) - idx = 1 + idn + im*len(dns) + ipn*len(dns)*len(mTypes) - v = fnResults[im][ipn][0] - r = "{:4g}".format(v) - if "pull" in fnGen.lower(): - if parNames[ipn]=='mean': - r = '{:7.3f}'.format(v) - elif parNames[ipn]=='width': - r = '{:7.3f}'.format(v) - if "res" in fnGen.lower(): - if parNames[ipn]=='mean': - r = '{:7.2f}'.format(10000*v) - elif parNames[ipn]=='width': - r = '{:7.2f}'.format(10000*v) - #row[idx] = str(fnResults[im][ipn][0]) - row[idx] = r - csvWriter.writerow(row) +#!# for fnGen in sorted(allFnGens): +#!# row = len(hdrRow1)*[ '' ] +#!# row[0] = "_".join(fnGen) +#!# idx = 1 +#!# for ipn in range(len(parNames)): +#!# for im in range(len(mTypes)): +#!# for idn,dn in enumerate(dns): +#!# dnResults = allResults[dn] +#!# if fnGen in dnResults: +#!# fnResults = dnResults[fnGen] +#!# if fnGen=='cPullXW1_barrel': +#!# print(ipn,im,idn,dn) +#!# print(" ",fnResults[im][ipn]) +#!# idx = 1 + idn + im*len(dns) + ipn*len(dns)*len(mTypes) +#!# v = fnResults[im][ipn][0] +#!# r = "{:4g}".format(v) +#!# if "pull" in fnGen.lower(): +#!# if parNames[ipn]=='mean': +#!# r = '{:7.3f}'.format(v) +#!# elif parNames[ipn]=='width': +#!# r = '{:7.3f}'.format(v) +#!# if "res" in fnGen.lower(): +#!# if parNames[ipn]=='mean': +#!# r = '{:7.2f}'.format(10000*v) +#!# elif parNames[ipn]=='width': +#!# r = '{:7.2f}'.format(10000*v) +#!# #row[idx] = str(fnResults[im][ipn][0]) +#!# row[idx] = r +#!# csvWriter.writerow(row) - csvFile.close() +#!# csvFile.close() cnvs = { } frames = [ ] @@ -232,7 +251,7 @@ def processFile(rootfile,algo='prefit'): cnvs[fnRoot] = { x:{ } for x in parNames } graphs[fnRoot] = { x:{ } for x in parNames } for ipn,pn in enumerate(parNames): - cnvName = fnRoot+"-"+pn+"-"+args.algorithm + cnvName = fnRoot+"-"+pn cnv = ROOT.TCanvas(cnvName,cnvName,600,600) cnv.SetBottomMargin(0.15) cnvs[fnRoot][pn] = cnv @@ -241,8 +260,11 @@ def processFile(rootfile,algo='prefit'): graphs[fnRoot][pn][fnZone] = { } for mt in mTypes: graphs[fnRoot][pn][fnZone][mt] = { } + for a in reqAlgos: + graphs[fnRoot][pn][fnZone][a] = { } + #graphs[fnRoot][pn] = { x:{ } for x in mTypes } - frames.append(ROOT.TH1F("h"+fnRoot[1:]+"-"+pn,fnRoot[1:]+"-"+pn+" ("+args.algorithm+")",nDns,-0.5,nDns-0.5)) + frames.append(ROOT.TH1F("h"+fnRoot[1:]+"-"+pn,fnRoot[1:]+"-"+pn,nDns,-0.5,nDns-0.5)) if pn=='mean': #frames.append(cnv.DrawFrame(-0.5,-1,nDns-0.5,1)) if "pull" in fnRoot.lower(): @@ -264,31 +286,35 @@ def processFile(rootfile,algo='prefit'): for iz,fnZone in enumerate(sorted(fnZones)): istyle = lstyle.next() color = MyColors() + style = iz + 1 for im,mt in enumerate(mTypes): - graph = ROOT.TGraphErrors() - graph.SetName("g"+fnZone+"-"+pn+"-"+str(mt)) - graph.SetTitle("g"+fnZone+"-"+pn+"-"+str(mt)) - graph.SetLineWidth(2) ic = color.next() - graph.SetLineColor(ic) - graph.SetLineStyle(istyle) - graph.SetMarkerStyle(marker) - marker += 1 - graph.SetMarkerColor(ic) - graphs[fnRoot][pn][fnZone][mt] = graph - fnGen = ( fnRoot, fnZone ) - for idn,dn in enumerate(dns): - dnResults = allResults[dn] - if fnGen in dnResults: - fnResults = dnResults[fnGen] - if fnResults[im][ipn]!=None: - v,e = fnResults[im][ipn] - if "res" in fnRoot.lower(): - v *= 10000 - e *= 10000 - graph.AddPointError(idn+nDns*iz/50,v,0.,e) - ymin = min(ymin,v-e) - ymax = max(ymax,v+e) + for ia,algo in enumerate(reqAlgos): + marker = ia + 20 + graph = ROOT.TGraphErrors() + graph.SetName("g"+fnZone+"-"+pn+"-"+str(mt)+"-"+algo) + graph.SetTitle("g"+fnZone+"-"+pn+"-"+str(mt)+"-"+algo) + graph.SetLineWidth(2) + #ic = color.next() + graph.SetLineColor(ic) + graph.SetLineStyle(istyle) + graph.SetMarkerStyle(marker) + #marker += 1 + graph.SetMarkerColor(ic) + graphs[fnRoot][pn][fnZone][mt][algo] = graph + fnGen = ( fnRoot, fnZone ) + for idn,dn in enumerate(dns): + dnResults = allResults[dn] + if fnGen in dnResults: + fnResults = dnResults[fnGen] + if ( algo in fnResults ) and fnResults[algo][im][ipn]!=None: + v,e = fnResults[algo][im][ipn] + if "res" in fnRoot.lower(): + v *= 10000 + e *= 10000 + graph.AddPointError(idn+nDns*iz/50,v,0.,e) + ymin = min(ymin,v-e) + ymax = max(ymax,v+e) if pn=='mean': dy = ymax - ymin ymin -= dy*0.05 @@ -299,16 +325,21 @@ def processFile(rootfile,algo='prefit'): frames[-1].SetMinimum(ymin) frames[-1].SetMaximum(ymax) frames[-1].Draw() - leg = ROOT.TLegend(0.15,0.80,0.90,0.90) + leg = ROOT.TLegend(0.10,0.80,0.90,0.90) leg.SetNColumns(4) leg.SetBorderSize(0) leg.SetFillStyle(0) legs.append(leg) for fnZone in sorted(fnZones): - leg.AddEntry("",fnZone,"") - for mt in mTypes: - leg.AddEntry(graphs[fnRoot][pn][fnZone][mt],"mType "+str(mt),"LP") - graphs[fnRoot][pn][fnZone][mt].Draw("PL") + for algo in reqAlgos: + leg.AddEntry("",fnZone+" "+algo,"") + for mt in allMTypes: + if mt in mTypes: + leg.AddEntry(graphs[fnRoot][pn][fnZone][mt][algo],"mType "+str(mt),"LP") + graphs[fnRoot][pn][fnZone][mt][algo].Draw("PL") + else: + leg.AddEntry(""," ","") + leg.Draw() cnv.Update() if args.output!=None: From 7c5281de8adf549bcf1728236e243e087ebde214 Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Thu, 30 Apr 2026 11:18:56 +0200 Subject: [PATCH 76/77] debugging --- DrawHits/fitResultsFromCanvases.py | 69 ++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/DrawHits/fitResultsFromCanvases.py b/DrawHits/fitResultsFromCanvases.py index c79d914..7b0f342 100644 --- a/DrawHits/fitResultsFromCanvases.py +++ b/DrawHits/fitResultsFromCanvases.py @@ -34,6 +34,7 @@ def fromQuantiles(fitHisto,isig): for sgn in [ -1, 0, 1 ]: xqs.append(fitHisto.quantile(ROOT.TMath.Freq(sgn*isig))) if None in xqs: + print("Quantiles failed!!!") return None return [ ( xqs[1], 0. ), ( (xqs[2]-xqs[0])/2./isig, 0. ) ] @@ -108,10 +109,15 @@ def processFile(rootfile,algo='prefit'): assert len(pads)==3 results = [ ] + #ctmp = ROOT.TCanvas("ctmp","ctmp",1200,800) for p in pads: - #print("Processing pad in",rootfile) + print("Processing pad in",rootfile,p.GetName(),"with algo",algo) + #p.Draw() + #ctmp.Update() result = processPad(p,algo) results.append(result) + print(result) + #input("Enter") return results @@ -128,6 +134,7 @@ def processFile(rootfile,algo='prefit'): type=str, default="*") parser.add_argument('--algorithms', '-a', help='comma-separated list of algorithms used for fit results', \ type=str, default='prefit' ) +parser.add_argument('--verbose', '-v', help='verbose output', action=store_true, default=False) parser.add_argument('directories', help='directories with stored canvases in root format', type=str, nargs='+') args = parser.parse_args() if args.output!=None: @@ -171,6 +178,7 @@ def processFile(rootfile,algo='prefit'): dnResults[fngen] = { } for algo in reqAlgos: results = processFile(os.path.join(root,f),algo) + print("processFile",os.path.join(root,f),algo,results) nNone = sum([ x==None for x in results ]) if nNone>0 and nNone<3: print("***",fname,results) @@ -181,8 +189,19 @@ def processFile(rootfile,algo='prefit'): allFnGens.add(fngen) #assert not fngen in dnResults dnResults[fngen][algo] = results + print("Algo =",algo) + +if args.verbose: + for dn in allResults: + print(dn) + for fngen in allResults[dn]: + print(" fngen",fngen,type(allResults[dn])) + for algo in allResults[dn][fngen]: + print(" ",algo) + for ir,r in enumerate(allResults[dn][fngen][algo]): + print(" ",ir,r) +#print(dnResults) #print(allFnGens) -#sys.exit() allMTypes = range(23,26) mTypes = reqMTypes @@ -258,10 +277,10 @@ def processFile(rootfile,algo='prefit'): graphs[fnRoot][pn] = { } for fnZone in fnZones: graphs[fnRoot][pn][fnZone] = { } - for mt in mTypes: + for mt in reqMTypes: graphs[fnRoot][pn][fnZone][mt] = { } for a in reqAlgos: - graphs[fnRoot][pn][fnZone][a] = { } + graphs[fnRoot][pn][fnZone][mt][a] = { } #graphs[fnRoot][pn] = { x:{ } for x in mTypes } frames.append(ROOT.TH1F("h"+fnRoot[1:]+"-"+pn,fnRoot[1:]+"-"+pn,nDns,-0.5,nDns-0.5)) @@ -282,15 +301,18 @@ def processFile(rootfile,algo='prefit'): frames[-1].GetXaxis().SetLabelSize(0.05) ymin,ymax = 1.e30,-1.e30 lstyle = MyColors([1,2,3]) - marker = 20 for iz,fnZone in enumerate(sorted(fnZones)): istyle = lstyle.next() - color = MyColors() + mstyle = MyColors(list(range(20,28))) style = iz + 1 - for im,mt in enumerate(mTypes): - ic = color.next() + for im,mt in enumerate(allMTypes): + if not mt in reqMTypes: + continue + color = MyColors() + marker = mstyle.next() for ia,algo in enumerate(reqAlgos): - marker = ia + 20 + ic = color.next() + #marker = ia + 20 graph = ROOT.TGraphErrors() graph.SetName("g"+fnZone+"-"+pn+"-"+str(mt)+"-"+algo) graph.SetTitle("g"+fnZone+"-"+pn+"-"+str(mt)+"-"+algo) @@ -309,10 +331,16 @@ def processFile(rootfile,algo='prefit'): fnResults = dnResults[fnGen] if ( algo in fnResults ) and fnResults[algo][im][ipn]!=None: v,e = fnResults[algo][im][ipn] + print("Results",fnRoot,pn,fnZone,mt,algo,dn,v) + print(" ",algo,fnResults[algo]) + print(" ",algo,im,fnResults[algo][im]) if "res" in fnRoot.lower(): v *= 10000 e *= 10000 graph.AddPointError(idn+nDns*iz/50,v,0.,e) + #if graph.GetName().startswith("gendcap-width-25-q") and \ + # graph.GetName().endswith("sig"): + # print("+++",graph.GetName(),fnRoot,pn,fnZone,mt,algo,dn,v) ymin = min(ymin,v-e) ymax = max(ymax,v+e) if pn=='mean': @@ -320,26 +348,29 @@ def processFile(rootfile,algo='prefit'): ymin -= dy*0.05 ymax += dy*0.15 elif pn=='width': - ymin = 0. + ymin -= (ymax-ymin)*0.05 ymax *= 1.15 frames[-1].SetMinimum(ymin) frames[-1].SetMaximum(ymax) frames[-1].Draw() - leg = ROOT.TLegend(0.10,0.80,0.90,0.90) - leg.SetNColumns(4) - leg.SetBorderSize(0) - leg.SetFillStyle(0) - legs.append(leg) + legArguments = [ ] for fnZone in sorted(fnZones): for algo in reqAlgos: - leg.AddEntry("",fnZone+" "+algo,"") + legArguments.append(("",fnZone+" "+algo,"")) for mt in allMTypes: if mt in mTypes: - leg.AddEntry(graphs[fnRoot][pn][fnZone][mt][algo],"mType "+str(mt),"LP") + legArguments.append((graphs[fnRoot][pn][fnZone][mt][algo],"mType "+str(mt),"LP")) graphs[fnRoot][pn][fnZone][mt][algo].Draw("PL") else: - leg.AddEntry(""," ","") - + legArguments.append((""," ","")) + + leg = ROOT.TLegend(0.10,0.90-0.02*len(legArguments)/4,0.90,0.90) + leg.SetNColumns(4) + leg.SetBorderSize(0) + leg.SetFillStyle(0) + legs.append(leg) + for largs in legArguments: + leg.AddEntry(*largs) leg.Draw() cnv.Update() if args.output!=None: From e642b883d5be7a8bff7a9279846f86c22c6f1b6d Mon Sep 17 00:00:00 2001 From: Wolfgang Adam Date: Wed, 6 May 2026 15:12:18 +0200 Subject: [PATCH 77/77] separate file for FitHistogram class --- DrawHits/FitHistogram.py | 235 ++++++++++++++++++++++++----- DrawHits/drawHitsResRDF.yaml | 5 + DrawHits/fitResultsFromCanvases.py | 22 +-- 3 files changed, 215 insertions(+), 47 deletions(-) diff --git a/DrawHits/FitHistogram.py b/DrawHits/FitHistogram.py index 01121ab..39470fa 100644 --- a/DrawHits/FitHistogram.py +++ b/DrawHits/FitHistogram.py @@ -1,7 +1,8 @@ import ROOT class FitHistogram: - + ''' Helper class to extract various quantities from a 1D histogram + ''' def interpolate(y,y1,y2,x1=0.,x2=1.): ''' Linear interpolation between two points (x1,y1) and (x2,y2) to yield x corresponding to the target value y. @@ -9,6 +10,8 @@ def interpolate(y,y1,y2,x1=0.,x2=1.): return x1 + (y-y1)/(y2-y1)*(x2-x1) def __init__(self,histogram): + ''' Store input histogram and prepare caches for various intermediate quantities + ''' self.hist = histogram self.graph_ = None self.cumulativeGraph_ = None @@ -128,46 +131,14 @@ def fwhm(self): # use first intersection with upward slope # xups = self.intersects(y,cumulative=False,direction=1) - print("xups",xups) + #print("xups",xups) xlow = xups[0] if xups else None # # use last intersection with downward slope # xdowns = self.intersects(y,cumulative=False,direction=-1) - print("xdowns",xdowns) + #print("xdowns",xdowns) xhigh = xdowns[-1] if xdowns else None - #dx = self.hist.GetBinWidth(1) - ### - ## preset result (low / high x values) - ## - #xlow = None - #xhigh = None - ## - ## loop over pairs of adjacent histogram bins - ## - #x1 = self.hist.GetBinLowEdge(1) - #y1 = self.hist.GetBinContent(1) - #for i in range(2,self.hist.GetNbinsX()): - # # check if target value between contents of neighbouring bins - # x2 = self.hist.GetBinLowEdge(i) - # y2 = self.hist.GetBinContent(i) - # first = None - # if y>=y1 and yy2: - # first = False - # - # if first!=None: - # # calculate interpolated x value - # x = FitHistogram.interpolate(y,y1,y2,x1,x2) - # # store lowest and highest x corresponding to y - # if first and xlow==None: - # xlow = x - # elif not first: - # xhigh = x - # # move to next bin - # x1 = x2 - # y1 = y2 # # require result ( assumes that first and last bins are < ymax/2 ) and @@ -179,6 +150,33 @@ def fwhm(self): def quantile(self,prob): ''' Return x-value to quantile q. ''' + # + # basic check - refuse to calculate quantile for probabilities beyond 1st / last non-empty bin + # + # use tail probability + # + nb = self.hist.GetNbinsX() + sumw = self.hist.GetSumOfWeights() + if prob<=0.5: + # check first non-empty bin from low -> high + cmax = prob*sumw + rng = range(1,nb+1) + else: + # check first non-empty bin from high -> low + cmax = (1-prob)*sumw + rng = range(nb,0,-1) + # find first non-empty bin + for ib in rng: + c = self.hist.GetBinContent(ib) + if c>1.e-10: + # return invalid result if first bin exceeds the threshold + if c>cmax: + #print("<<<",self.hist.GetName(),prob,nb,cmax,range,ib,c) + return None + break + # + # now determine quantile + # result = self.intersects(prob,cumulative=True,norm=True,direction=1) #print(prob,result) if len(result)>1: @@ -257,7 +255,7 @@ def fitGaus(self,prob1=0.,prob2=1.): xmax = self.findRootSpline(prob2) if xmin==None: return result - + fitFunc = ROOT.TF1("mygaus","gaus(0)",xmin,xmax) fitFunc.SetParameter(0,self.hist.GetMaximum()) fitFunc.SetParameter(1,0.) @@ -273,3 +271,168 @@ def fitGaus(self,prob1=0.,prob2=1.): return fitPtr,fitFunc +if __name__=="__main__": + # + # test of fitting for my canvases + # + import sys + from math import sqrt,log + from fnmatch import fnmatch + import argparse + + def fromQuantiles(fitHisto,isig): + xqs = [ ] + for sgn in [ -1, 0, 1 ]: + xqs.append(fitHisto.quantile(ROOT.TMath.Freq(sgn*isig))) + if None in xqs: + return None + return [ ( xqs[1], 0. ), ( (xqs[2]-xqs[0])/2./isig, 0. ) ] + + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('--list', '-l', help='list pads / histograms', action='store_true', default=False) + parser.add_argument('--algorithms', '-a', help='comma-separated list of algorithms used for fit results', \ + type=str, default='prefit' ) + parser.add_argument('--padName', help='pad name (fnmatch pattern)', type=str, default='*') + parser.add_argument('--histogramName', help='histogram name (fnmatch pattern)', type=str, default='*') + parser.add_argument('file', help='root file', type=str, nargs=1) + args = parser.parse_args() + + # + # select pad and histogram + # + mainPads = [ ] + tf = ROOT.TFile(args.file[0]) + + for k in tf.GetListOfKeys(): + oName = k.GetName() + o = tf.Get(oName) + if o.InheritsFrom(ROOT.TVirtualPad.Class()): + mainPads.append(o) + assert len(mainPads)==1 + + selectedPads = [ ] + for p in mainPads[0].GetListOfPrimitives(): + oName = p.GetName() + if args.list or fnmatch(oName,args.padName): + selectedPads.append(p) + if not args.list: + assert len(selectedPads)==1 + + selectedHistograms = [ ] + for p in selectedPads: + if args.list: + print("Pad ",p.GetName(),":") + for o in p.GetListOfPrimitives(): + if o.InheritsFrom(ROOT.TH1.Class()) and o.GetDimension()==1: + oName = o.GetName() + if args.list: + print(" Histogram 1D ",oName,type(o)) + if fnmatch(oName,args.histogramName): + selectedHistograms.append(o) + + if args.list: + sys.exit(0) + + selPad = selectedPads[0] + + assert len(selectedHistograms)==1 + + ROOT.gROOT.cd() + cnv = ROOT.TCanvas("c","c",800,800) + if selPad.GetLogy(): + cnv.SetLogy(1) + padHisto = selectedHistograms[0].Clone() + fitHisto = FitHistogram(padHisto) + padHisto.SetLineWidth(1) + padHisto.SetMarkerStyle(20) + padHisto.Draw("LP") + cnv.SetGridx(1) + cnv.SetGridy(1) + cnv.Update() + tf.Close() + + result = None + fitHisto = FitHistogram(padHisto) + + + # + # FWHM + # + xmin,xmax,y = fitHisto.fwhm() + result = [ ( (xmax+xmin)/2., 0. ), ( (xmax-xmin)/2/sqrt(2*log(2.)), 0. ) ] + print("FWHM",[ x[0] for x in result ]) + fwhmArrow = ROOT.TArrow() + fwhmArrow.SetLineColor(2) + fwhmArrow.SetLineWidth(3) + fwhmArrow.DrawArrow(xmin,y,xmax,y,0.005,"<>") + # + # prefit + # + gaus = None + for f in padHisto.GetListOfFunctions(): + if f.GetName()=="gaus": + assert gaus==None + gaus = f + #gaus = f.Clone() + n = gaus.GetNpar() + assert n==3 + result = [ ] + for i in range(1,3): + result.append((gaus.GetParameter(i),gaus.GetParError(i))) + gaus.SetLineColor(ROOT.kCyan) + #gaus.Draw() + print("Prefit",[ x[0] for x in result ]) + # + # gaus fit + # + fitPtr,fitFunc = fitHisto.fitGaus() + result = [ ] + if fitPtr!=None: + for i in range(1,3): + result.append((fitPtr.Parameter(i),fitPtr.ParError(i))) + if fitFunc!=None: + print(fitFunc.GetParameter(0),fitFunc.GetParameter(1),fitFunc.GetParameter(2)) + fitFunc.SetLineColor(ROOT.kMagenta) + fitFunc.SetLineWidth(3) + fitFunc.Draw("same") + print("Gaus fit",[ x[0] for x in result ]) + # + # quantiles (1 sigma equivalent) + # + quantLines = [ ] + quantColors = [ ROOT.kBlack, ROOT.kBlue, 8, ROOT.kRed ] + for i in range(4): + quantLine = ROOT.TLine() + #quantLine.SetLineColor(4-i) + quantLine.SetLineColor(quantColors[i]) + #quantLine.SetLineColor(4-i) + quantLine.SetLineWidth(3) + quantLine.SetLineStyle(2) + #quantLine.SetLineStyle(i+1) + quantLines.append(quantLine) + for isigma,sigma in enumerate([1,2,3]): + qs = [ ] + for sgn in [-1,0,1]: + p = ROOT.TMath.Freq(sgn*sigma) + qs.append(fitHisto.findRootSpline(p)) + #print(sigma,sgn,type(fitHisto)) + #print(sigma,sgn,p,qs[-1]) + #print(isigma,sigma,qs) + result = fromQuantiles(fitHisto,sigma) + if result!=None: + print("Sig",sigma,[ x[0] if x!=None else None for x in result ]) + else: + print("Sig",result) + + for iq in range(3): + il = 0 if iq==1 else isigma+1 + qlmax = padHisto.GetBinContent(padHisto.FindBin(qs[iq])) + quantLines[il].DrawLine(qs[iq],0.,qs[iq],qlmax) + #if iq==0: + # line = " from sigma = {:3.1f} quantile: ".format(sigma) + # line += "median = {:6.1f}um, half-width/sigma = {:6.1f}um".format(10000*qs[1], \ + # 10000*(qs[2]-qs[0])/2/sigma) + # print(line) + + cnv.Update() + diff --git a/DrawHits/drawHitsResRDF.yaml b/DrawHits/drawHitsResRDF.yaml index fb3d133..1ee9875 100644 --- a/DrawHits/drawHitsResRDF.yaml +++ b/DrawHits/drawHitsResRDF.yaml @@ -13,6 +13,11 @@ variables: rhLocalPosY: 'rhLocalPos.fCoordinates.fY' rhLocalErrX: 'rhLocalErr.fCoordinates.fX' rhLocalErrY: 'rhLocalErr.fCoordinates.fY' + localPosXMod90: 'floatMod(10000*localPos.fCoordinates.fX,90)' + localPosXMod100: 'floatMod(10000*localPos.fCoordinates.fX,100)' + localPosYMod500: 'floatMod(10*localPosY,50)/10.' + localPosYMod250: 'floatMod(10*localPosY,25)/10.' + localPosYMod15: 'floatMod(100*localPosY,15)/10' globRho2: 'globalDir.fCoordinates.fX*globalDir.fCoordinates.fX+globalDir.fCoordinates.fY*globalDir.fCoordinates.fY' globR2: 'globRho2+globalDir.fCoordinates.fZ*globalDir.fCoordinates.fZ' globPt: 'pabs*sqrt(globRho2/globR2)' diff --git a/DrawHits/fitResultsFromCanvases.py b/DrawHits/fitResultsFromCanvases.py index 7b0f342..e0ab0ae 100644 --- a/DrawHits/fitResultsFromCanvases.py +++ b/DrawHits/fitResultsFromCanvases.py @@ -134,7 +134,7 @@ def processFile(rootfile,algo='prefit'): type=str, default="*") parser.add_argument('--algorithms', '-a', help='comma-separated list of algorithms used for fit results', \ type=str, default='prefit' ) -parser.add_argument('--verbose', '-v', help='verbose output', action=store_true, default=False) +parser.add_argument('--verbose', '-v', help='verbose output', action='store_true', default=False) parser.add_argument('directories', help='directories with stored canvases in root format', type=str, nargs='+') args = parser.parse_args() if args.output!=None: @@ -178,18 +178,18 @@ def processFile(rootfile,algo='prefit'): dnResults[fngen] = { } for algo in reqAlgos: results = processFile(os.path.join(root,f),algo) - print("processFile",os.path.join(root,f),algo,results) + #print("processFile",os.path.join(root,f),algo,results) nNone = sum([ x==None for x in results ]) if nNone>0 and nNone<3: - print("***",fname,results) + print("*** 1 or 2 invalide results",fname,results) #assert nNone==0 or nNone==3 - if nNone==0: - #fngen = "_".join(fields[:1]+fields[2:]) - fngen = ( fields[0],"_".join(fields[2:]) ) - allFnGens.add(fngen) - #assert not fngen in dnResults - dnResults[fngen][algo] = results - print("Algo =",algo) + #!#if nNone==0: + #fngen = "_".join(fields[:1]+fields[2:]) + fngen = ( fields[0],"_".join(fields[2:]) ) + allFnGens.add(fngen) + #assert not fngen in dnResults + dnResults[fngen][algo] = results + print("Algo =",algo) if args.verbose: for dn in allResults: @@ -329,7 +329,7 @@ def processFile(rootfile,algo='prefit'): dnResults = allResults[dn] if fnGen in dnResults: fnResults = dnResults[fnGen] - if ( algo in fnResults ) and fnResults[algo][im][ipn]!=None: + if ( algo in fnResults ) and fnResults[algo][im]!=None: v,e = fnResults[algo][im][ipn] print("Results",fnRoot,pn,fnZone,mt,algo,dn,v) print(" ",algo,fnResults[algo])