From a38b04a17999c7889022d42fe988b94707bea0ee Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Tue, 12 Sep 2023 16:32:41 +0200 Subject: [PATCH 01/33] add calculation of neighbours for theta-module mered readout --- FCCSW_ecal/neighbours_theta.py | 43 +++ geometry/create_capacitance_file_theta.py | 338 ++++++++++++++++++ .../create_noise_file_chargePreAmp_theta.py | 334 +++++++++++++++++ 3 files changed, 715 insertions(+) create mode 100644 FCCSW_ecal/neighbours_theta.py create mode 100644 geometry/create_capacitance_file_theta.py create mode 100644 geometry/create_noise_file_chargePreAmp_theta.py diff --git a/FCCSW_ecal/neighbours_theta.py b/FCCSW_ecal/neighbours_theta.py new file mode 100644 index 0000000..31190c4 --- /dev/null +++ b/FCCSW_ecal/neighbours_theta.py @@ -0,0 +1,43 @@ +import os +from Gaudi.Configuration import * + +# Detector geometry +from Configurables import GeoSvc +geoservice = GeoSvc("GeoSvc") +# if FCC_DETECTORS is empty, this should use relative path to working directory +path_to_detector = os.environ.get("FCCDETECTORS", "") +print(path_to_detector) +detectors_to_use=[ + 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster_thetamodulemerged.xml', + #'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster.xml', +] + +# prefix all xmls with path_to_detector +geoservice.detectors = [os.path.join(path_to_detector, _det) for _det in detectors_to_use] +geoservice.OutputLevel = INFO + +# Geant4 service +# Configures the Geant simulation: geometry, physics list and user actions +from Configurables import CreateFCCeeCaloNeighbours +neighbours = CreateFCCeeCaloNeighbours("neighbours", + outputFileName = "neighbours_map_barrel_thetamodulemerged.root", + readoutNamesModuleTheta = ["ECalBarrelModuleThetaMerged"], +# readoutNamesModuleTheta = ["ECalBarrelModuleThetaMerged2"], + systemNamesModuleTheta = ["system"], + systemValuesModuleTheta = [4], + activeFieldNamesModuleTheta = ["layer"], + activeVolumesNumbers = [12], + #activeVolumesTheta = [1.2524, 1.2234, 1.1956, 1.1561, 1.1189, 1.0839, 1.0509, 0.9999, 0.9534, 0.91072], + readoutNamesVolumes = [], + connectBarrels = False, + OutputLevel = DEBUG) + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( TopAlg = [], + EvtSel = 'NONE', + EvtMax = 1, + # order is important, as GeoSvc is needed by G4SimSvc + ExtSvc = [geoservice, neighbours], + OutputLevel=INFO +) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py new file mode 100644 index 0000000..c446818 --- /dev/null +++ b/geometry/create_capacitance_file_theta.py @@ -0,0 +1,338 @@ +# execute script with +# python create_capacitance_file_theta.py + +from ROOT import TH1F, TF1, TF2, TCanvas, TLegend, TFile, gStyle +import ROOT +from math import ceil, sin, cos, atan, exp, log, tan, pi, sqrt, asin, degrees, radians + +ROOT.gROOT.SetBatch(ROOT.kTRUE) + +gStyle.SetPadTickY(1) + +debug = False +verbose = True + +#Dimensions +### FCCee +#ECalConstruction INFO ECAL cryostat: front: rmin (cm) = 210 rmax (cm) = 215 dz (cm) = 226 +#ECalConstruction INFO ECAL cryostat: back: rmin (cm) = 260 rmax (cm) = 270 dz (cm) = 226 +#ECalConstruction INFO ECAL cryostat: side: rmin (cm) = 215 rmax (cm) = 260 dz (cm) = 10 +#ECalConstruction INFO ECAL services: front: rmin (cm) = 215 rmax (cm) = 216 dz (cm) = 216 +#ECalConstruction INFO ECAL services: back: rmin (cm) = 256 rmax (cm) = 260 dz (cm) = 216 +#ECalConstruction INFO ECAL bath: material = LAr rmin (cm) = 216 rmax (cm) = 256 thickness in front of ECal (cm) = 1 thickness behind ECal (cm) = 4 +#ECalConstruction INFO ECAL calorimeter volume rmin (cm) = 216 rmax (cm) = 256 +#ECalConstruction INFO passive inner material = Lead and outer material = lArCaloSteel thickness of inner part (cm) = 0.14 thickness of outer part (cm) = 0.04 thickness of total (cm) = 0.2 rotation angle = 0.872665 +#ECalConstruction INFO number of passive plates = 1536 azim. angle difference = 0.00409062 +#ECalConstruction INFO distance at inner radius (cm) = 0.883573 distance at outer radius (cm) = 1.0472 +#ECalConstruction INFO readout material = PCB thickness of readout planes (cm) = 0.12 number of readout layers = 12 +#ECalConstruction INFO thickness of calorimeter (cm) = 40 length of passive or readout planes (cm) = 56.4964 +#ECalConstruction INFO active material = LAr active layers thickness at inner radius (cm) = 0.247949 thickness at outer radious (cm) = 0.479746 making 93.4857 % increase. +#ECalConstruction INFO active passive initial overlap (before subtraction) (cm) = 0.1 = 50 % + + +filename = "capacitances_perSource_ecalBarrelFCCee.root" +#filename = "capacitances_ecalBarrelFCCee_nLayer_%d_fromAnalytical.root"%numLayers + +# layer 2 require special care as it is separated in several cells and that the shield run beneath the etch: cell 2 signal pad top capa: 0.68 + 0.20 = 0.88, cell 2 signal pad bot: 0.56 + 0.21 = 0.77, cell 3: 0.34 + 2.4 = 2.74, cell 4: 1 + 0.25 = 1.25, cell 5: 1.85 + 0.28 = 2.13 + +activeTotal = 400.0 +inclinedTotal = 564.964 +tracesPerLayer = [6, 1, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7] # only one trace for strip layer because 4 cells instead of one +ncells_strip_layer = 4.0 +# careful, this is not really the radial spacing, it is, after dilution, the spacing in the parallel direction --> radial depth spacing will not be constant +readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 +#Detector +rmin = 2160 +Nplanes = 1536 +inclination_degree = 50 +angle = inclination_degree / 180. * pi #inclination angle inn radian +passiveThickness = 2.0 #mm +#Segmentation +deltaTheta = 0.00981748 +minTheta = 0.589 +maxTheta = pi-minTheta +numTheta = int(ceil((maxTheta-minTheta)/deltaTheta)) +if verbose: + print("minTheta = ", minTheta) + print("maxTheta = ", maxTheta) + print("numTheta = ", numTheta) + print("Nplanes = ", Nplanes) + print("rmin = ", rmin) + print("activeTotal = ", activeTotal) + print("readoutLayerRadialLengths = ", readoutLayerRadialLengths) + print("inclination (deg) = " , inclination_degree) + print("inclinedTotal = ", inclinedTotal) + print("passiveThickness = ", passiveThickness) + +#PCB dimensions [mm] +hhv = 0.1 +hs = 0.17 +t = 0.035 +w = 0.127 +ws = 0.250 +#hm = 0.250 +hm = 0.2075 +pcbThickness = 7 * t + 2 * hhv + 2 * hs + 2 * hm #mm +print("pcbThickness: %f"%pcbThickness) +#constants: +# distance from signal trace to shield (HS) - from impedance vs. trace width vs. distance to ground layer 2D plot (Z = 50 Ohm) +# trace width (W) - min value +# trace thickness (T) - min value +# distance from shield to the edge of PCB +#http://www.analog.com/media/en/training-seminars/design-handbooks/Basic-Linear-Design/Chapter12.pdf, page 40 +#signal trace +epsilonR = 4.4 # PCB +#conversion factor: 1 inch = 25.4 mm +inch2mm = 25.4 +#capa per length from maxwel +capa_per_mm = 0.123 # pF/mm +capa_per_mm_stripLayer = 0.062 # pF/mm +# multiplicative factor +# factor two because we merge two phi cells together, another factor 2 becasue we have two 1) signal pad / shield capa 2) HV plate / absorber capa per cell +nmult = 2 +nmult_trace = 1 # for the trace only the number of phi cell merged playes a role +epsilonRLAr = 1.5 # LAr at 88 K +epsilon0 = 8.854/1000. #pF/mm + + +# Fill the layer length, trace length, etc +readoutLayerParallelLengths = [] +real_radial_separation = [rmin] +real_radial_depth = [] +inclinations_wrt_radial_dir_at_middleRadialDepth = [] +trace_length = [] +numLayers = len(readoutLayerRadialLengths) +dilution_factor = inclinedTotal / activeTotal +trace_length_inner = 0 +trace_length_outer = 0 +outer = False +current_electrode_length = 0 +for idx in range(numLayers):# first pass to get all length parallel to the readout, real radial separation, inclination at the middle of the layer + readoutLayerRadialLengths[idx] *= 10 + parallel_length = readoutLayerRadialLengths[idx] * dilution_factor + # Tricky point: in the xml geo, you define 'radial'segmentation, but these depths will be the one parallel to the plates after scaling by the dilution factor --> even when setting constant radial depth, the geoemtry builder will make constant parallel length step, not constant radial steps + readoutLayerParallelLengths.append(parallel_length) + if outer: # prepare the starting trace length when starting to extract by the back of the PCB + trace_length_outer += parallel_length + if tracesPerLayer[idx] == 0 and tracesPerLayer[idx - 1] == 0: + outer = True + # sqrt(r**2+(L1+i*L2)**2+2*r*(L1+i*L2)*cos(alpha)) where L1 = 2.68, L2=12.09, r=192, alpha=50) + current_electrode_length += parallel_length + real_radial_separation.append(sqrt(rmin * rmin + current_electrode_length * current_electrode_length + 2 * rmin * current_electrode_length * cos(angle))) + real_radial_depth.append(real_radial_separation[idx+1] - real_radial_separation[idx]) + # treating the fact that radial angle decreases when radial depth increase + # angle comprise by lines from 1) Interaction point to inner right edge of a cell, 2) Interaction point to outer left edge of the considered cell (useful to get the plate angle with radial direction that changes with increasing R) + # based on scalene triangle sine law A/sin(a) = B/sin(b) = C/sin(c) (outer left edge aligned on the Y axis) + inclinations_wrt_radial_dir_at_middleRadialDepth.append(asin(rmin * sin(angle) / (real_radial_separation[idx] + ((real_radial_separation[idx+1] - real_radial_separation[idx]) / 2)))) + + +# second pass to get trace lengths +outer = False +for idx in range(numLayers): + if tracesPerLayer[idx] == 0 and tracesPerLayer[idx - 1] == 0: # we change direction + outer = True + if outer: + trace_length.append(trace_length_outer) + if idx == numLayers - 1: + trace_length_outer == 0 + continue + trace_length_outer -= readoutLayerParallelLengths[idx+1] + else: + trace_length.append(trace_length_inner) + trace_length_inner += readoutLayerParallelLengths[idx] + +print('Readout radial lengths originally asked: ', readoutLayerRadialLengths) +print('Readout parallel lengths: ', readoutLayerParallelLengths) +print("Real radial separation: ", real_radial_separation) +print("Real radial depth: ", real_radial_depth) +print("inclinations_wrt_radial_dir_at_middleRadialDepth: ", [degrees(inclinations) for inclinations in inclinations_wrt_radial_dir_at_middleRadialDepth]) +print("Signal trace length per layer: ", trace_length) + + +gStyle.SetOptStat(0) + +cImpedance = TCanvas("cImpedance","",600,800) +cImpedance.Divide(1,2) +cImpedance.cd(1) +fImpedance = TF2("fImpedance","60/sqrt([0])*log(1.9*(2*x+[1])/(0.8*y+[1]))",0.04,0.2,0.04,0.2) +fImpedance.SetTitle("Impedance vs trace width and distance to ground") +fImpedance.SetParameters(epsilonR, t) +fImpedance.Draw("colz") +fImpedance.GetXaxis().SetTitle("Distance to ground [mm]") +fImpedance.GetYaxis().SetTitle("Trace width [mm]") +cImpedance.cd(2) +fImpedance1D = TF1("fImpedance1D","60/sqrt([0])*log(1.9*(2*x+[1])/(0.8*[2]+[1]))",0.04,0.2) +fImpedance1D.SetTitle("Impedance vs distance to ground") +fImpedance1D.SetParameters(epsilonR, t, w) +fImpedance1D.Draw() +fImpedance1D.GetXaxis().SetTitle("Distance to ground [mm]") +fImpedance1D.GetYaxis().SetTitle("Impedance [#Omega]") + +#prepare the TH1 +hCapTrace = [] +hCapShield = [] +hCapDetector = [] +line_color_number = 1 +line_style_number = 1 +for i in range (0, len(readoutLayerRadialLengths)): + if line_color_number == 8: + line_color_number = 22 + if line_style_number == 8: + line_style_number = 1 + #traces + hCapTrace.append(TH1F()) + hCapTrace[i].SetBins(numTheta, minTheta, maxTheta) + hCapTrace[i].SetLineColor(line_color_number) + hCapTrace[i].SetLineStyle(line_style_number) + hCapTrace[i].SetLineWidth(2) + hCapTrace[i].SetTitle("Stripline capacitance; #theta; Capacitance [pF]") + hCapTrace[i].SetName("hCapacitance_traces"+str(i)) + #shields + hCapShield.append(TH1F()) + hCapShield[i].SetBins(numTheta, minTheta, maxTheta) + hCapShield[i].SetLineColor(line_color_number) + hCapShield[i].SetLineStyle(line_style_number) + hCapShield[i].SetLineWidth(2) + hCapShield[i].SetTitle("Signal pads - ground shields capacitance; #theta; Capacitance [pF]") + hCapShield[i].SetName("hCapacitance_shields"+str(i)) + #area + hCapDetector.append(TH1F()) + hCapDetector[i].SetBins(numTheta, minTheta, maxTheta) + hCapDetector[i].SetLineColor(line_color_number) + hCapDetector[i].SetLineStyle(line_style_number) + hCapDetector[i].SetLineWidth(2) + hCapDetector[i].SetTitle("Signal pad - absorber capacitance; #theta; Capacitance [pF]") + hCapDetector[i].SetName("hCapacitance_detector"+str(i)) + if line_color_number > 8: + line_color_number += 10 + else: + line_color_number += 1 + line_style_number += 1 + +cTrace = TCanvas("cTrace","",600,400) +cShield = TCanvas("cShield","",600,400) +cDetector = TCanvas("cDetector","",600,400) + +legend = TLegend(0.1,0.693,0.8,0.9) +#legend = TLegend(0.135,0.693,0.8,0.892) +legend.SetHeader("Longitudinal layers") +legend.SetNColumns(4) +capa_shield_max = 0 +capa_det_max = 0 +for i in range (0, len(readoutLayerParallelLengths)): + print("--------------") + for index in range(0, numTheta): + theta = minTheta + index * deltaTheta + thetaNext = minTheta + (index+1) * deltaTheta + eta = -log(tan(theta/2.0)) + deltaEta = abs( -log(tan((minTheta + (index+1) * deltaTheta)/2.0)) - eta) + if (debug): + print("theta = ", theta) + print("eta = ", eta) + print("delta eta = ", deltaEta) + + # take into account the inclination in eta + #traceLength = trace_length[i] / (sin(2. * atan(exp(-eta)))) + traceLength = trace_length[i] / sin(theta) + #print("Layer %d trace length %f"%(i+1, traceLength)) + #Trace capacitance (stripline) + logStripline = log(3.1 * hs / (0.8 * w + t)) + capacitanceTrace = nmult_trace * 1 / inch2mm * 1.41 * epsilonR / logStripline * traceLength + hCapTrace[i].SetBinContent(index+1, capacitanceTrace) + + #Shield capacitance (microstrip) + #cellLength = readoutLayerParallelLengths[i] / (sin(2. * atan(exp(-eta)))) + cellLength = readoutLayerParallelLengths[i] / sin(theta) + logMicrostrip = log(5.98 * hm / (0.8 * ws + t)) + # analytical formula + #capacitanceShield = nmult * cellLength * tracesPerLayer[i] * 1 / inch2mm * 0.67 * (epsilonR + 1.41) / logMicrostrip + # from maxwell + capacitanceShield = nmult * cellLength * tracesPerLayer[i] * capa_per_mm + if i == 1: #strip layer has smaller capacitance due to traces running beneath the anti-etch + capacitanceShield = nmult * cellLength * tracesPerLayer[i] * capa_per_mm_stripLayer + if capacitanceShield > capa_shield_max: + capa_shield_max = capacitanceShield + hCapShield[i].SetBinContent(index+1, capacitanceShield) + + ##Detector area (C = epsilon*A/d) + #area = ( radius[i] * ( 1 / (tan(2. * atan(exp(- (index + 1) * deltaEta)))) - 1 / (tan(2. * atan(exp(- index * deltaEta))) ) ) + # + radius[i + 1] * ( 1 / (tan(2. * atan(exp(- (index + 1) * deltaEta)))) - 1 / (tan(2. * atan(exp(- index * deltaEta))) ) ) + # ) / 2. * (radius[i+1] - radius[i]) + #distance = (radius[i+1] + radius[i]) / 2. * pi / Nplanes * cos (angle) - pcbThickness / 2. - passiveThickness / 2. + + #Detector area (C = epsilon*A/d) + area = abs( real_radial_separation[i] * ( 1 / tan(thetaNext) - 1 / tan(theta) ) + + real_radial_separation[i + 1] * ( 1 / tan(thetaNext) - 1 / tan(theta)) + ) / 2. * (real_radial_separation[i+1] - real_radial_separation[i]) + # get the cell size perpendicular to the plate direction from the cell size on the circle at given radius and the inclination w.r.t. radial dir, then remove the PCB and lead thickness (no need for any factor here because we are perpendicular to the PCB and lead plates) --> gives the LAr gap sizxe perpendicular + distance = (2 * pi * (real_radial_separation[i+1] + real_radial_separation[i]) / 2. / Nplanes * cos (inclinations_wrt_radial_dir_at_middleRadialDepth[i]) - pcbThickness - passiveThickness) / 2. # divided by two because two lar gap per cell + distance += hhv #the capa is between signal plate and absorber --> need to add distance between HV plate and signal pad + distance += t #the capa is between signal plate and absorber --> need to add distance between HV plate and signal pad + if (abs(theta - pi/2.)<1e-4): + print("LAr gap size (perpendicular) + hhv + t: %f mm"%distance) + capacitanceDetector = nmult * epsilon0 * epsilonRLAr * area / distance + if i == 1: #strip layer has smaller capacitance because it is divided in 4 smaller cells + capacitanceDetector /= ncells_strip_layer + hCapDetector[i].SetBinContent(index+1, capacitanceDetector) + if capacitanceDetector > capa_det_max: + capa_det_max = capacitanceDetector + if (abs(theta - pi/2.)<1e-4): + print("layer %d" %(i+1), "theta=%f" %theta, ": capacitanceTrace %.0f pF," %capacitanceTrace, "capacitanceShield %.0f pF" %capacitanceShield, "capacitanceDetector %.0f pF" %capacitanceDetector) + #, "distance %.1f mm" %distance + + #Draw + cTrace.cd() + if i == 0: + hCapTrace[i].Draw() + else: + hCapTrace[i].Draw("same") + legend.AddEntry(hCapTrace[i],"layer %d"%(i+1),"l") + cShield.cd() + if i == 0: + hCapShield[i].Draw() + else: + hCapShield[i].Draw("same") + cDetector.cd() + if i == 0: + hCapDetector[i].Draw() + else: + hCapDetector[i].Draw("same") + +maximum = capa_shield_max + +plots = TFile(filename,"RECREATE") + +for i in range (0, len(readoutLayerParallelLengths)): + hCapTrace[i].SetMinimum(0) + hCapTrace[i].SetMaximum(maximum*1.8) + hCapTrace[i].Write() + hCapShield[i].SetMinimum(0) + hCapShield[i].SetMaximum(capa_shield_max*1.5) + hCapShield[i].Write() + hCapDetector[i].SetMinimum(0) + hCapDetector[i].SetMaximum(capa_det_max*1.5) + hCapDetector[i].Write() + +cTrace.cd() +legend.Draw() +cTrace.Update() +cTrace.Write() +cTrace.Print("capa_trace.png") +cTrace.Print("capa_trace.pdf") +cShield.cd() +legend.Draw() +cShield.Update() +cShield.Write() +cShield.Print("capa_shield.png") +cShield.Print("capa_shield.pdf") +cDetector.cd() +legend.Draw() +cDetector.Update() +cDetector.Write() +cDetector.Print("capa_detector.png") +cDetector.Print("capa_detector.pdf") + +fImpedance.Write() +fImpedance1D.Write() + +#closeInput = raw_input("Press ENTER to exit") diff --git a/geometry/create_noise_file_chargePreAmp_theta.py b/geometry/create_noise_file_chargePreAmp_theta.py new file mode 100644 index 0000000..81df53c --- /dev/null +++ b/geometry/create_noise_file_chargePreAmp_theta.py @@ -0,0 +1,334 @@ +from ROOT import TH1F, TCanvas, TLegend, TFile, gStyle, gPad +import ROOT +import itertools +from datetime import date +import os, sys +from numpy import ones,vstack +from numpy.linalg import lstsq +from math import floor + +ROOT.gROOT.SetBatch(ROOT.kTRUE) +ROOT.gStyle.SetPadTickY(1) +ROOT.gStyle.SetOptTitle(0) + +def rescaleaxis(g, scale = 50e-12/1e-9): + """This function rescales the x-axis on a TGraph.""" + N = g.GetN() + x = g.GetX() + for i in range(N): + x[i] *= scale + g.GetHistogram().Delete() + g.SetHistogram(0) + return + +# you know the noise charge rms from Martin (as a function of capacitance): https://indico.cern.ch/event/1066234/contributions/4708987/attachments/2387716/4080914/20220209_Brieuc_Francois_Noble_Liquid_Calorimetry_forFCCee_FCCworkshop2022.pdf#page=7 +# you need to further get, for each layer, the collected charge corresponding to an energy deposit of 1 MeV in the cell (cell considered including the energy in absorber and PCB), the cell merging strategy does not matter yet here to first approximation because the 1 MeV current equivalent will be the same in any merging scenarios (the current will be shared in more gaps when merging many cells, but all these current will then be 'summed' before to reach the readout). Merging many cells will pay back later, when more signal will be collected per read out channel compared to merging less cells, for the same noise values + +# Retrieving a capa dependent function for the noise charge rms in terms of number of electrons: https://indico.cern.ch/event/1066234/contributions/4708987/attachments/2387716/4080914/20220209_Brieuc_Francois_Noble_Liquid_Calorimetry_forFCCee_FCCworkshop2022.pdf#page=7 +points_capa_noise = [(100, 4375), (500, 6750)] +x_coords, y_coords = zip(*points_capa_noise) +A = vstack([x_coords, ones(len(x_coords))]).T +m, c = lstsq(A, y_coords)[0] +#print("Line Solution is y = {m}x + {c}".format(m=m, c=c)) +def get_noise_charge_rms(capacitance): + return m * capacitance + c # number of electrons + +# Get the equivalent of 1 MeV energy deposit in a cell (absorber + Lar) in terms of number of electrons in the charge pre-amplifier + shaper +r_recomb = 0.04 +w_lar = 23.6 # eV needed to create a ion/electron pair +def get_ref_charge(SF, E_dep = 1 * pow(10, 6)): #E_dep en eV, choose 1 MeV + return E_dep * SF * (1 - r_recomb) / (2 * w_lar) # nA, the factor 2 comes from: Q_tot = I_0 * t_drift * 1/2 (rectangle --> triangle), t_drift cancels out from the formula to get I_0 which has v_drift/d_gap (Ramo Shockley). + # Assumption: shaping time is similar or bigger to drift time + +# what is this?? +SFfcc = [0.36504678560781667] * 1 + [0.09974087165838573] * 1 + [0.12392336840429007] * 1 + [0.1413266332223572] * 1 + [0.15415123193238958] * 1 + [0.1639900875460671] * 1 + [0.17156597031962592] * 1 + [0.17810674932424356] * 1 + [0.18340048249397345] * 1 + [0.18855877603870688] * 1 + [0.19307873042890955] * 1 + [0.21746137329706489] * 1 +nLayers = len(SFfcc) + +print("##########: ", get_ref_charge(0.16)) + +SF_rounded_forPrint = [] +for SF in SFfcc: + SF_rounded_forPrint.append(round(SF,2)) +print('SF:', SF_rounded_forPrint) + +#output_folder = "noise_capa_" + date.today().strftime("%y%m%d") +output_folder = "noise_vs_capa_chargePreAmp" + +#filename = "ecalBarrelFCCee_"+flagImpedance+"Ohm_"+flagTraces+"_"+str(flagsShieldsWidth)+"shieldWidth" +capa_filename = "capacitances_perSource_ecalBarrelFCCee.root" +if not os.path.exists(capa_filename): + print("Error: capacitance file does not exist, please run first python create_capacitance_file.py") + sys.exit(1) +fIn = TFile(capa_filename, "r") + +output_folder = "noise_capa_" + date.today().strftime("%y%m%d") +if not os.path.isdir(output_folder): + os.mkdir(output_folder) +fSaveAll = TFile(os.path.join(output_folder, "capacitances_ecalBarrelFCCee.root"),"RECREATE") +fSave = TFile(os.path.join(output_folder, "elecNoise_ecalBarrelFCCee.root"),"RECREATE") + +gStyle.SetOptStat(0) + +#TH1 with capacitances +hCapShield = [] +hCapTrace = [] +hCapDetector = [] +hCapTotal = [] +# electronic noise histograms +h_elecNoise_fcc = [] # default total noise shield + detector capacitance (without trace capacitance) -> to be used in FCCSW as noise estimation +h_elecNoise_all = [] # total noise shield + trace + detector capacitance +h_elecNoise_withTraceCap = [] # total noise without trace capacitance (as in ATLAS - trace cap. can be neglected): from shield + detector capacitance +h_elecNoise_shield = [] +h_elecNoise_trace = [] +h_elecNoise_detector = [] + +#Read graphs from files +for i in range (0, nLayers): + nameShield = "hCapacitance_shields"+str(i) + hCapShield.append(fIn.Get(nameShield)) + nameTrace = "hCapacitance_traces"+str(i) + hCapTrace.append(fIn.Get(nameTrace)) + nameDetector = "hCapacitance_detector"+str(i) + hCapDetector.append(fIn.Get(nameDetector)) + +index = 0 +nbins = hCapShield[index].GetNbinsX() +thetaMin = hCapShield[index].GetXaxis().GetBinLowEdge(1) +thetaMax = hCapShield[index].GetXaxis().GetBinUpEdge(nbins) +print("number of bins ", nbins, ", thetaMin ", thetaMin, ", thetaMax ", thetaMax) + +maximumCap = 0. +maximumNoise = 0. +maximumNoiseWithTrace = 0. + +line_color_number = 1 +line_style_number = 1 +for i in range (0, nLayers): + if line_color_number == 10: + line_color_number = 28 + if line_style_number > 10: + line_style_number = 1 + #Prepare electronic noise histograms + h_elecNoise_fcc.append( TH1F() ) + h_elecNoise_fcc[i].SetLineWidth(3) + h_elecNoise_fcc[i].SetLineColor(line_color_number) + h_elecNoise_fcc[i].SetLineStyle(line_style_number) + h_elecNoise_fcc[i].SetBins(nbins, thetaMin, thetaMax) + h_elecNoise_fcc[i].SetTitle("Default electronic noise: shield + detector capacitance; #theta; Electronic noise [MeV]") + h_elecNoise_fcc[i].SetName("h_elecNoise_fcc_"+str(i+1)) + + h_elecNoise_all.append( TH1F() ) + h_elecNoise_all[i].SetLineWidth(3) + h_elecNoise_all[i].SetLineColor(line_color_number) + h_elecNoise_all[i].SetLineStyle(line_style_number) + h_elecNoise_all[i].SetBins(nbins, thetaMin, thetaMax) + h_elecNoise_all[i].SetTitle("Total electronic noise: shield + trace + detector capacitance; #theta; Electronic noise [MeV]") + h_elecNoise_all[i].SetName("h_elecNoise_all_"+str(i+1)) + + h_elecNoise_withTraceCap.append( TH1F() ) + h_elecNoise_withTraceCap[i].SetLineWidth(3) + h_elecNoise_withTraceCap[i].SetLineColor(line_color_number) + h_elecNoise_withTraceCap[i].SetLineStyle(line_style_number) + h_elecNoise_withTraceCap[i].SetBins(nbins, thetaMin, thetaMax) + h_elecNoise_withTraceCap[i].SetTitle("Electronic noise with trace capacitance; #theta; Electronic noise [MeV]") + h_elecNoise_withTraceCap[i].SetName("h_elecNoise_withTraceCap_"+str(i+1)) + + h_elecNoise_shield.append( TH1F() ) + h_elecNoise_shield[i].SetLineWidth(3) + h_elecNoise_shield[i].SetLineColor(line_color_number) + h_elecNoise_shield[i].SetLineStyle(line_style_number) + h_elecNoise_shield[i].SetBins(nbins, thetaMin, thetaMax) + h_elecNoise_shield[i].SetTitle("Electronic noise - shields; #theta; Electronic noise [MeV]") + h_elecNoise_shield[i].SetName("h_elecNoise_shield_"+str(i+1)) + + h_elecNoise_trace.append( TH1F() ) + h_elecNoise_trace[i].SetLineWidth(3) + h_elecNoise_trace[i].SetLineColor(line_color_number) + h_elecNoise_trace[i].SetLineStyle(line_style_number) + h_elecNoise_trace[i].SetBins(nbins, thetaMin, thetaMax) + h_elecNoise_trace[i].SetTitle("Electronic noise -traces; #theta; Electronic noise [MeV]") + h_elecNoise_trace[i].SetName("h_elecNoise_trace_"+str(i+1)) + + h_elecNoise_detector.append( TH1F() ) + h_elecNoise_detector[i].SetLineWidth(3) + h_elecNoise_detector[i].SetLineColor(line_color_number) + h_elecNoise_detector[i].SetLineStyle(line_style_number) + h_elecNoise_detector[i].SetBins(nbins, thetaMin, thetaMax) + h_elecNoise_detector[i].SetTitle("Electronic noise - detector; #theta; Electronic noise [MeV]") + h_elecNoise_detector[i].SetName("h_elecNoise_detector_"+str(i+1)) + + #Total capacitance plot (shield + trace + detector) + hCapTotal.append( TH1F() ) + hCapTotal[i].SetBins(nbins, thetaMin, thetaMax) + hCapTotal[i].SetLineColor(line_color_number) + hCapTotal[i].SetLineStyle(line_style_number) + hCapTotal[i].SetLineWidth(3) + hCapTotal[i].SetTitle("Total capacitance; #theta; Capacitance [pF]") + hCapTotal[i].SetName("hCapacitance"+str(i)) + + ref_charge_1mev = get_ref_charge(SFfcc[i]) + if i != 0: + print(noise_charge_rms) + print(i, " ", ref_charge_1mev) + for ibin in range(0, nbins+1): + capShield = hCapShield[i].GetBinContent(ibin) + capTrace = hCapTrace[i].GetBinContent(ibin) + capDetector = hCapDetector[i].GetBinContent(ibin) + #total capacitance + #hCapTotal[i].SetBinContent( ibin, capShield + capTrace + capDetector ) + hCapTotal[i].SetBinContent( ibin, capShield + capDetector ) + # Compute the NOISE + noise_charge_rms = get_noise_charge_rms(capShield + capDetector) + noise = noise_charge_rms / (ref_charge_1mev) + noiseWithTrace = get_noise_charge_rms(capShield + capDetector + capTrace) / ref_charge_1mev + noiseShield = get_noise_charge_rms(capShield) / ref_charge_1mev + noiseTrace = get_noise_charge_rms(capTrace) / ref_charge_1mev + noiseDetector = get_noise_charge_rms(capDetector) / ref_charge_1mev + #find maximum for drawing of histograms + if noise > maximumNoise: + maximumNoise = noise + if noiseWithTrace > maximumNoiseWithTrace: + maximumNoiseWithTrace = noiseWithTrace + if (capShield + capDetector)>maximumCap: + maximumCap = (capShield + capDetector) + + #fill histogram + #default: without traces + h_elecNoise_fcc[i].SetBinContent(ibin, noise) + h_elecNoise_all[i].SetBinContent(ibin, noise) + h_elecNoise_withTraceCap[i].SetBinContent(ibin, noiseWithTrace) + h_elecNoise_shield[i].SetBinContent(ibin, noiseShield) + h_elecNoise_trace[i].SetBinContent(ibin, noiseTrace) + h_elecNoise_detector[i].SetBinContent(ibin, noiseDetector) + if ibin==floor((nbins+1)/2): + print("layer %d" %(i+1), "eta==0: capacitance %.0f pF," %( capShield + capTrace + capDetector ), "total elec. noise %.4f MeV" %noise, "elec. noise without trace cap. %.4f MeV" %noiseWithTrace) + line_color_number += 1 + line_style_number += 1 + +#print maximumCap, maximumNoise, maximumNoiseWithTrace + +cCapacitance = TCanvas("cCapacitance","Capacitance per cell",800,600) +cCapacitance.cd() +#legend = TLegend(0.135,0.573,0.466,0.872) +legend = TLegend(0.135,0.693,0.8,0.892) +legend.SetBorderSize(0) +legend.SetLineColor(0) +legend.SetLineStyle(0) +legend.SetLineWidth(0) +legend.SetFillColor(0) +legend.SetFillStyle(0) +legend.SetHeader("Longitudinal layers") +legend.SetNColumns(4) +for i, h in enumerate(hCapTotal): + h.SetMinimum(0) + h.SetMaximum(maximumCap*1.5) + h.GetYaxis().SetTitleOffset(1.4) + if i == 0: + h.Draw("") + else: + h.Draw("same") + legend.AddEntry(h,"Layer " + str(i+1),"l") + + +# Prepare "nice" plots & save all capacitances + noise +fSaveAll.cd() + +for h in hCapTotal: + h.SetMinimum(0.) + #h.SetMaximum(maximumCap*1.3) + h.GetYaxis().SetTitleOffset(1.4) + h.Write() + +legend.Draw() +cCapacitance.Update() +cCapacitance.Write() +cCapacitance.Print(os.path.join(output_folder, "cCapacitance.png")) + +#maximumCap = 1200. +#maximumNoise = 0.04 +#maximumNoiseWithTrace = 0.015 + +for h in itertools.chain(h_elecNoise_fcc, h_elecNoise_all): + h.SetMinimum(0.) + h.SetMaximum(maximumNoise*1.5) + h.GetYaxis().SetTitleOffset(1.4) + h.Write() + +for h in itertools.chain(h_elecNoise_withTraceCap, h_elecNoise_shield, h_elecNoise_trace, h_elecNoise_detector): + h.SetMinimum(0.) + h.SetMaximum(maximumNoiseWithTrace*1.5) + h.GetYaxis().SetTitleOffset(1.4) + h.Write() + +cNoise = TCanvas("cNoise","Electronic noise per cell",800,600) +cNoise.cd() +for i, h in enumerate(h_elecNoise_fcc): + if i == 0: + h.Draw("") + else: + h.Draw("same") + +legend.Draw() +cNoise.Update() +cNoise.Write() +cNoise.Print(os.path.join(output_folder, "cNoise.png")) + +cNoiseWithTrace = TCanvas("cNoiseWithTrace","Electronic noise with trace cap. per cell",800,600) +cNoiseWithTrace.cd() +for i, h in enumerate(h_elecNoise_withTraceCap): + if i == 0: + h.Draw("") + else: + h.Draw("same") + +legend.Draw() +cNoiseWithTrace.Update() +cNoiseWithTrace.Write() +cNoiseWithTrace.Print(os.path.join(output_folder, "cNoiseWithTrace.png")) + +legendP = TLegend(0.1,0.6,0.43,0.9) +legendP.SetHeader("Capacitance") + +cCapParts = TCanvas("cCapParts","",1200,1000) +cCapParts.Divide(3,4) +for i in range (0, nLayers): + cCapParts.cd(i+1) + if i < 7: + hCapTotal[i].SetMaximum(100) + else: + hCapTotal[i].SetMaximum(200) + + hCapTotal[i].SetTitle("Layer "+str(i+1)) + hCapTotal[i].GetXaxis().SetTitleSize(0.045) + hCapTotal[i].GetYaxis().SetTitleSize(0.045) + hCapTotal[i].GetYaxis().SetTitleOffset(1.15) + hCapTotal[i].SetLineColor(1) + hCapTotal[i].SetLineStyle(1) + hCapShield[i].SetLineColor(2) + hCapShield[i].SetLineStyle(2) + hCapTrace[i].SetLineColor(3) + hCapTrace[i].SetLineStyle(3) + hCapDetector[i].SetLineColor(4) + hCapDetector[i].SetLineStyle(4) + hCapTotal[i].Draw() + hCapShield[i].Draw("same") + #hCapTrace[i].Draw("same") + hCapDetector[i].Draw("same") + gPad.Update() + if i==0: + legendP.AddEntry(hCapTotal[i],"total cap.","l") + legendP.AddEntry(hCapShield[i],"shield cap.","l") + #legendP.AddEntry(hCapTrace[i],"trace cap.","l") + legendP.AddEntry(hCapDetector[i],"detector cap.","l") + legendP.Draw() + +cCapParts.Write() +cCapParts.Print(os.path.join(output_folder, "cCapParts.png")) + +#Save final noise plot (to be used in FCCSW) +fSave.cd() +for h in h_elecNoise_fcc: + h.Write() + +#closeInput = raw_input("Press ENTER to exit") + From ebcf565812f79234a7fea913d2543d01b1c533a6 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 13 Sep 2023 15:29:47 +0200 Subject: [PATCH 02/33] update scripts to create neighbours map and noise map --- FCCSW_ecal/noise_map.py | 46 ++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/FCCSW_ecal/noise_map.py b/FCCSW_ecal/noise_map.py index e1f5c90..4db53a9 100644 --- a/FCCSW_ecal/noise_map.py +++ b/FCCSW_ecal/noise_map.py @@ -1,33 +1,39 @@ from Gaudi.Configuration import * - # Detector geometry from Configurables import GeoSvc geoservice = GeoSvc("GeoSvc") # if FCC_DETECTORS is empty, this should use relative path to working directory +import os path_to_detector = os.environ.get("FCCDETECTORS", "") print(path_to_detector) detectors_to_use=[ - 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster.xml', +# 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster.xml', + 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster_thetamodulemerged.xml' ] # prefix all xmls with path_to_detector geoservice.detectors = [os.path.join(path_to_detector, _det) for _det in detectors_to_use] geoservice.OutputLevel = INFO -ecalBarrelReadoutName = "ECalBarrelPhiEta" +#ecalBarrelReadoutName = "ECalBarrelPhiEta" +ecalBarrelReadoutName = "ECalBarrelModuleThetaMerged" +#hcalBarrelReadoutName = "ECalBarrelPhiEta" +hcalBarrelReadoutName = "HCalBarrelReadout" #BarrelNoisePath = "/afs/cern.ch/user/b/brfranco/work/public/LAr_setups/230208/LAr_scripts/geometry/noise_capa_230301/elecNoise_ecalBarrelFCCee.root" BarrelNoisePath = os.environ['FCCBASEDIR']+"/LAr_scripts/data/elecNoise_ecalBarrelFCCee.root" ecalBarrelNoiseHistName = "h_elecNoise_fcc_" from Configurables import CellPositionsECalBarrelTool -# ATTENTION! -# The parameters have to be default in the tools, problem in Gaudi does not propagate the options through 2 tools -#ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel", -# readoutName = ecalBarrelReadoutName, -# OutputLevel = INFO) -#ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel") +ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel", + readoutName = ecalBarrelReadoutName +) +# OutputLevel = DEBUG) +#print(ECalBcells) -from Configurables import CreateFCChhCaloNoiseLevelMap, ReadNoiseFromFileTool -ECalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolECal", +#from Configurables import CreateFCChhCaloNoiseLevelMap, ReadNoiseFromFileTool +from Configurables import CreateFCCeeCaloNoiseLevelMap, ReadNoiseFromFileTool +ECalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolECal", + useSegmentation = False, + cellPositionsTool = ECalBcells, readoutName = ecalBarrelReadoutName, noiseFileName = BarrelNoisePath, elecNoiseHistoName = ecalBarrelNoiseHistName, @@ -38,8 +44,9 @@ scaleFactor = 1/1000., #MeV to GeV OutputLevel=DEBUG) -HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", - readoutName = ecalBarrelReadoutName, +HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", + useSegmentation = True, + readoutName = hcalBarrelReadoutName, noiseFileName = BarrelNoisePath, elecNoiseHistoName = ecalBarrelNoiseHistName, setNoiseOffset = False, @@ -49,20 +56,21 @@ scaleFactor = 1/1000., #MeV to GeV OutputLevel=DEBUG) -noisePerCell = CreateFCChhCaloNoiseLevelMap("noisePerCell", +#noisePerCell = CreateFCChhCaloNoiseLevelMap("noisePerCell", +noisePerCell = CreateFCCeeCaloNoiseLevelMap("noisePerCell", ECalBarrelNoiseTool = ECalNoiseTool, ecalBarrelSysId = 4, HCalBarrelNoiseTool = HCalNoiseTool, - readoutNamesPhiEta=[ecalBarrelReadoutName], - systemNamesPhiEta=["system"], - systemValuesPhiEta=[4], - activeFieldNamesPhiEta=["layer"], + readoutNamesModuleTheta=[ecalBarrelReadoutName], + systemNamesModuleTheta=["system"], + systemValuesModuleTheta=[4], + activeFieldNamesModuleTheta=["layer"], activeVolumesNumbers = [12], #activeVolumesEta = [1.2524, 1.2234, 1.1956, 1.1561, 1.1189, 1.0839, 1.0509, 0.9999, 0.9534, 0.91072], readoutNamesVolumes=[], outputFileName="cellNoise_map_electronicsNoiseLevel.root", OutputLevel=DEBUG) - +#noisePerCell.ECalBarrelNoiseTool.cellPositionsTool.readoutName = ecalBarrelReadoutName # ApplicationMgr from Configurables import ApplicationMgr From fd8fda209f0437bd64a4db0946628107bb437d1b Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 18 Sep 2023 14:39:33 +0200 Subject: [PATCH 03/33] update numPlanes --- geometry/create_capacitance_file_theta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index c446818..ef09b4e 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -43,7 +43,7 @@ readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 #Detector rmin = 2160 -Nplanes = 1536 +Nplanes = 1545 inclination_degree = 50 angle = inclination_degree / 180. * pi #inclination angle inn radian passiveThickness = 2.0 #mm From f6e7af413fe4b6b66698ef4e3d7c1e445edcbeb7 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 15:04:58 +0200 Subject: [PATCH 04/33] add event display tool for debugging --- FCCSW_ecal/displayV3.C | 1493 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1493 insertions(+) create mode 100644 FCCSW_ecal/displayV3.C diff --git a/FCCSW_ecal/displayV3.C b/FCCSW_ecal/displayV3.C new file mode 100644 index 0000000..74a22ad --- /dev/null +++ b/FCCSW_ecal/displayV3.C @@ -0,0 +1,1493 @@ +/******************************************************************************/ +// Simple event display for the LAr calorimeter with inclined modules +// Run with +// root +// .L displayV3.C+ +// display() +/******************************************************************************/ + + +/******************************************************************************/ +// dependencies +/******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + + +/******************************************************************************/ +// SETTINGS FOR THE DISPLAY +// - geometry file (and corresponding merging of theta cells/modules vs layer +// - data file +// - flags to draw or not elements of the event (particles, hits, ..) +// - minimum energy of particles, hits, cells, clusters +/******************************************************************************/ + +// G4 geometry file +std::string geomFile = "ECalBarrel.root"; + +// merging along theta and module directions and drawing options +//std::string evtFile = "output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_False_pMin_10000_MeV_ThetaMinMax_40_140_pdgId_11_pythiaFalse_NoiseFalse.root"; +//std::string evtFile = "test.root"; +//const std::vector mergedCells_Theta = {4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; +//const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; +//bool drawMergedCells = false; + +//std::string evtFile = "output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_False_pMin_10000_MeV_ThetaMinMax_40_140_pdgId_11_pythiaFalse_NoiseFalse_testmerge.root"; +//const std::vector mergedCells_Theta = {4, 8, 2, 1, 8, 4, 2, 1, 4, 2, 1, 8}; +//const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1}; +//bool drawMergedCells = true; + +// 50 electrons 100 GeV +std::string evtFile = "output_evts_50_100_GeV_ThetaMinMax_40_140_PhiMinMax_0_6.28318.root"; +// 1 pi0 50 GeV +// std::string evtFile = "output_evts_1_pdg_111_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +// 1 photon 50 GeV +// std::string evtFile = "output_evts_1_pdg_22_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +// 1 pi0 10 GeV +// std::string evtFile = "output_evts_1_pdg_111_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +// 1 photon 10 GeV +// std::string evtFile = "output_evts_1_pdg_22_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; + +const std::vector mergedCells_Theta = {4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; +const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + +bool drawParticles = true; +bool drawMCtracks = false; // does not work +bool drawHits = true; +bool drawCells = true; +bool drawMergedCells = false; +bool drawTopoClusters = true; + +// min particle energy (GeV) +float ParticleEnergyThreshold = 1.0; +// min hit and cell energy (GeV) +float HitEnergyThreshold = 0.0; +float CellEnergyThreshold = 0.0; +// min cluster energy (in GeV) +float TopoClusterEnergyThreshold = 2.; + + +/******************************************************************************/ +// GEOMETRICAL CONSTANTS +// They should match the geometry used in the geometry file and the readout +// used to produce the event file +/******************************************************************************/ + +// units +// G4 uses mm but Root uses cm.. +const double cm = 1.0; +const double mm = 0.1; +const std::string units = "cm"; + +// z extension of barrel +const double zMin = -3100.*mm; +const double zMax = 3100.*mm; + +// radial extension of barrel +const double rMin = 217.28*cm; +const double rMax = 257.33*cm; + +// nominal radial thickness of layers +const std::vector drNom( + { + 15.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm, + 35.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm + } +); + +// number of layers +const int nLayers = drNom.size(); + +// number of electrodes +const int nModules = 1545; + +// inclination angle of electrodes +const double alpha = 50*TMath::Pi()/180.; + +// grid in theta +// - size of cell +const double thetaGrid = 0.00981748/4; +// - theta of edge of first cell +const double thetaMin = 0.59027850 - thetaGrid/2.; +// - n(bins) +const int nThetaBins = 800; + + + +/******************************************************************************/ +// GEOMETRY HELPER FUNCTIONS AND DERIVED GEOMETRY PARAMETERS +/******************************************************************************/ + +// calculate length along electrode at r=r_out for electrode +// starting at r=r_in and inclined in phi by alpha +// for r_in>r_out, when the solution exists, it's always > 0 +double _L(double alpha, double r_in, double r_out) { + if (r_out > r_in) + return sqrt(r_out*r_out - r_in*r_in*sin(alpha)*sin(alpha)) - r_in*cos(alpha); + else + return r_in*cos(alpha) - sqrt(r_out*r_out - r_in*r_in*sin(alpha)*sin(alpha)); +} + +// calculate phi offset between point at r=r_out with respect +// to point at r=r_in if they are on the same electrode +// inclined in phi by alpha +double _phi(double alpha, double r_in, double r_out) { + double L = _L(alpha, r_in, r_out); + if (r_out > r_in) + return TMath::ASin(L/r_out * sin(alpha)); + else + return -TMath::ASin(L/r_out * sin(alpha)); +} + +// calculate radius of point on electrode starting at +// r=r_in, inclined in phi by alpha, and at distance L +// from beginning of electrode +double _r(double alpha, double r_in, double L) { + return sqrt((r_in+L*cos(alpha))*(r_in+L*cos(alpha))+(L*sin(alpha))*(L*sin(alpha))); +} + +// length of electrodes +static const double Ltot = _L(alpha, rMin, rMax); + +// phi separation of modules +const double gridPhi = TMath::TwoPi()/nModules; + +// r for electrode length = L/2 +static const double rAvg = _r(alpha, rMin, Ltot/2.0); + +// delta phi of point at L/2 +static const double dPhiAvg = _phi(alpha, rMin, rAvg); + +// phi edge of module 0 +static const double phiMin = -alpha - gridPhi/2.0; + +// other quantities, calculated by calcGeom +// radial position of each layer +std::vector r; +std::vector dr; +// length of electrode along each layer (dRnom/cos(alpha)) +std::vector dL; + +// calculate derived parameters of geometry depending on the main ones +// (such as radial/electrode length of each layer) +// and print them to screen +void calcGeom() { + + // print initial information + cout << "r(min) = " << rMin << " " << units << endl; + cout << "r(max) = " << rMax << " " << units << endl; + cout << "total thickness = " << rMax-rMin << " " << units << endl; + + // calculate total length + cout << "electrode length = " << Ltot << " " << units << endl << endl; + + // calculate length along electrode of each layer + cout << "n(layers) = " << nLayers << endl << endl; + std::vector L; + double sumL(0.0); + dL.clear(); + for (int i=0; i rMed; + for (int i=0; i> 11) & mask; +} + +// extract module number from cellID +ULong_t Module(ULong_t cellID) { + const ULong_t mask = (1<<11) -1; + return (cellID >> 19) & mask; +} + +// extract theta bin from cellID +ULong_t ThetaBin(ULong_t cellID) { + const ULong_t mask = (1<<10) -1; + return (cellID >> 30) & mask; +} + +// return the sign of a float +int sgn(float val) { + return (val > 0.) - (val < 0.); +} + + +/******************************************************************************/ +// HELPER FUNCTIONS related to the graphic system +/******************************************************************************/ + +void makeGui(); + +// derived TGLAnnotation class that overrides MouseEnter method +// to avoid editing of annotation +class TGLConstAnnotation : public TGLAnnotation +{ + public: + TGLConstAnnotation(TGLViewerBase *parent, const char *text, Float_t posx, Float_t posy) : + TGLAnnotation(parent, text, posx, posy) + { + ; + } + Bool_t MouseEnter(TGLOvlSelectRecord& /*rec*/) + { + fActive = kFALSE; + return kTRUE; + } +}; + + +/******************************************************************************/ +// ELEMENTS OF THE EVENT DISPLAY +/******************************************************************************/ + +Int_t eventId = 0; // Current event id +Int_t nEvents = 0; // Number of events in file +TEveStraightLineSet* particles = nullptr; +TEveTrackList* particlesMC = nullptr; +TEvePointSet* hits = nullptr; +TEvePointSet* cells = nullptr; +TEvePointSet* cells_merged = nullptr; +TEvePointSet* clusters = nullptr; +std::vector qs_rhoz; +std::vector qs_rhophi; +TEveElementList* topoclusters_rhoz = nullptr; +TEveElementList* topoclusters_rhophi = nullptr; +std::vector bs; +TEveElementList* topoclusters_3D = nullptr; + +TEveGeoShape* barrel = nullptr; +TEveViewer* rhoPhiView = nullptr; +TEveViewer* rhoZView = nullptr; +TGLViewer* rhoPhiGLView = nullptr; +TGLViewer* rhoZGLView = nullptr; +TEveScene* rhoPhiScene = nullptr; +TEveScene* rhoPhiEventScene = nullptr; +TEveScene* rhoZScene = nullptr; +TEveScene* rhoZEventScene = nullptr; +TEveProjectionManager* rhoPhiProjManager = nullptr; +TEveProjectionManager* rhoZProjManager = nullptr; + +TGLConstAnnotation* eventLabel = nullptr; + + +/******************************************************************************/ +// CLASS TO READ AN EVENT FROM THE EVENT FILE +// AND FILL THE EVENT DISPLAY OBJECTS +/******************************************************************************/ +class EventReader +{ + private: + TTreeReader* fReader = nullptr; + // 1a. - primary particles + TTreeReaderArray *genParticles_PDG = nullptr; + TTreeReaderArray *genParticles_generatorStatus = nullptr; + TTreeReaderArray *genParticles_simulatorStatus = nullptr; + TTreeReaderArray *genParticles_charge = nullptr; + TTreeReaderArray *genParticles_time = nullptr; + TTreeReaderArray *genParticles_mass = nullptr; + TTreeReaderArray *genParticles_vertex_x = nullptr; + TTreeReaderArray *genParticles_vertex_y = nullptr; + TTreeReaderArray *genParticles_vertex_z = nullptr; + //TTreeReaderArray *genParticles_endpoint_x = nullptr; + //TTreeReaderArray *genParticles_endpoint_y = nullptr; + //TTreeReaderArray *genParticles_endpoint_z = nullptr; + TTreeReaderArray *genParticles_momentum_x = nullptr; + TTreeReaderArray *genParticles_momentum_y = nullptr; + TTreeReaderArray *genParticles_momentum_z = nullptr; + + // 1a. - secondary particles + TTreeReaderArray *SimParticleSecondaries_PDG = nullptr; + //TTreeReaderArray *SimParticleSecondaries_generatorStatus = nullptr; + //TTreeReaderArray *SimParticleSecondaries_simulatorStatus = nullptr; + //TTreeReaderArray *SimParticleSecondaries_charge = nullptr; + //TTreeReaderArray *SimParticleSecondaries_time = nullptr; + TTreeReaderArray *SimParticleSecondaries_mass = nullptr; + TTreeReaderArray *SimParticleSecondaries_vertex_x = nullptr; + TTreeReaderArray *SimParticleSecondaries_vertex_y = nullptr; + TTreeReaderArray *SimParticleSecondaries_vertex_z = nullptr; + TTreeReaderArray *SimParticleSecondaries_endpoint_x = nullptr; + TTreeReaderArray *SimParticleSecondaries_endpoint_y = nullptr; + TTreeReaderArray *SimParticleSecondaries_endpoint_z = nullptr; + TTreeReaderArray *SimParticleSecondaries_momentum_x = nullptr; + TTreeReaderArray *SimParticleSecondaries_momentum_y = nullptr; + TTreeReaderArray *SimParticleSecondaries_momentum_z = nullptr; + + // 1b. hits + TTreeReaderArray *ECalBarrelPositionedHits_cellID = nullptr; + TTreeReaderArray *ECalBarrelPositionedHits_energy = nullptr; + TTreeReaderArray *ECalBarrelPositionedHits_position_x = nullptr; + TTreeReaderArray *ECalBarrelPositionedHits_position_y = nullptr; + TTreeReaderArray *ECalBarrelPositionedHits_position_z = nullptr; + + // 1c. - cells + TTreeReaderArray *ECalBarrelPositionedCells_cellID = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells_energy = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells_position_x = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells_position_y = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells_position_z = nullptr; + + // 1d. - cells with coarser merging + TTreeReaderArray *ECalBarrelPositionedCells2_cellID = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells2_energy = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells2_position_x = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells2_position_y = nullptr; + TTreeReaderArray *ECalBarrelPositionedCells2_position_z = nullptr; + + // 1e. - the corrected calo topo clusters + TTreeReaderArray *CorrectedCaloTopoClusters_energy = nullptr; + TTreeReaderArray *CorrectedCaloTopoClusters_position_x = nullptr; + TTreeReaderArray *CorrectedCaloTopoClusters_position_y = nullptr; + TTreeReaderArray *CorrectedCaloTopoClusters_position_z = nullptr; + TTreeReaderArray *CorrectedCaloTopoClusters_hits_begin = nullptr; + TTreeReaderArray *CorrectedCaloTopoClusters_hits_end = nullptr; + + // 1f. - cells in the topo clusters + TTreeReaderArray *PositionedCaloTopoClusterCells_cellID = nullptr; + TTreeReaderArray *PositionedCaloTopoClusterCells_energy = nullptr; + TTreeReaderArray *PositionedCaloTopoClusterCells_position_x = nullptr; + TTreeReaderArray *PositionedCaloTopoClusterCells_position_y = nullptr; + TTreeReaderArray *PositionedCaloTopoClusterCells_position_z = nullptr; + + public: + EventReader(TFile* f) + { + fReader = new TTreeReader("events", f); + nEvents = fReader->GetEntries(); + + // 1a. - primary particles + genParticles_PDG = new TTreeReaderArray(*fReader, "genParticles.PDG"); + genParticles_generatorStatus = new TTreeReaderArray(*fReader, "genParticles.generatorStatus"); + genParticles_simulatorStatus = new TTreeReaderArray(*fReader, "genParticles.simulatorStatus"); + genParticles_charge = new TTreeReaderArray(*fReader, "genParticles.charge"); + genParticles_time = new TTreeReaderArray(*fReader, "genParticles.time"); + genParticles_mass = new TTreeReaderArray(*fReader, "genParticles.mass"); + genParticles_vertex_x = new TTreeReaderArray(*fReader, "genParticles.vertex.x"); + genParticles_vertex_y = new TTreeReaderArray(*fReader, "genParticles.vertex.y"); + genParticles_vertex_z = new TTreeReaderArray(*fReader, "genParticles.vertex.z"); + //genParticles_endpoint_x = new TTreeReaderArray(*fReader, "genParticles.endpoint.x"); + //genParticles_endpoint_y = new TTreeReaderArray(*fReader, "genParticles.endpoint.y"); + //genParticles_endpoint_z = new TTreeReaderArray(*fReader, "genParticles.endpoint.z"); + genParticles_momentum_x = new TTreeReaderArray(*fReader, "genParticles.momentum.x"); + genParticles_momentum_y = new TTreeReaderArray(*fReader, "genParticles.momentum.y"); + genParticles_momentum_z = new TTreeReaderArray(*fReader, "genParticles.momentum.z"); + + // 1a. - secondary particles + if (fReader->GetTree()->FindBranch("SimParticleSecondaries.PDG")) { + SimParticleSecondaries_PDG = new TTreeReaderArray(*fReader, "SimParticleSecondaries.PDG"); + //SimParticleSecondaries_generatorStatus = new TTreeReaderArray(*fReader, "SimParticleSecondaries.generatorStatus"); + //SimParticleSecondaries_simulatorStatus = new TTreeReaderArray(*fReader, "SimParticleSecondaries.simulatorStatus"); + //SimParticleSecondaries_charge = new TTreeReaderArray(*fReader, "SimParticleSecondaries.charge"); + //SimParticleSecondaries_time = new TTreeReaderArray(*fReader, "SimParticleSecondaries.time"); + SimParticleSecondaries_mass = new TTreeReaderArray(*fReader, "SimParticleSecondaries.mass"); + SimParticleSecondaries_vertex_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.x"); + SimParticleSecondaries_vertex_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.y"); + SimParticleSecondaries_vertex_z = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.z"); + SimParticleSecondaries_endpoint_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.endpoint.x"); + SimParticleSecondaries_endpoint_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.endpoint.y"); + SimParticleSecondaries_endpoint_z = new TTreeReaderArray(*fReader, "SimParticleSecondaries.endpoint.z"); + SimParticleSecondaries_momentum_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.momentum.x"); + SimParticleSecondaries_momentum_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.momentum.y"); + SimParticleSecondaries_momentum_z = new TTreeReaderArray(*fReader, "SimParticleSecondaries.momentum.z"); + } + + // 1b. - hits + ECalBarrelPositionedHits_cellID = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.cellID"); + ECalBarrelPositionedHits_energy = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.energy"); + ECalBarrelPositionedHits_position_x = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.position.x"); + ECalBarrelPositionedHits_position_y = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.position.y"); + ECalBarrelPositionedHits_position_z = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.position.z"); + + // 1c. - cells + ECalBarrelPositionedCells_cellID = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.cellID"); + ECalBarrelPositionedCells_energy = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.energy"); + ECalBarrelPositionedCells_position_x = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.position.x"); + ECalBarrelPositionedCells_position_y = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.position.y"); + ECalBarrelPositionedCells_position_z = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.position.z"); + + // 1d. - cells with coarser merging + ECalBarrelPositionedCells2_cellID = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.cellID"); + ECalBarrelPositionedCells2_energy = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.energy"); + ECalBarrelPositionedCells2_position_x = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.position.x"); + ECalBarrelPositionedCells2_position_y = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.position.y"); + ECalBarrelPositionedCells2_position_z = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.position.z"); + + // 1e. - the corrected calo topo clusters + CorrectedCaloTopoClusters_energy = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.energy"); + CorrectedCaloTopoClusters_position_x = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.position.x"); + CorrectedCaloTopoClusters_position_y = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.position.y"); + CorrectedCaloTopoClusters_position_z = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.position.z"); + CorrectedCaloTopoClusters_hits_begin = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.hits_begin"); + CorrectedCaloTopoClusters_hits_end = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.hits_end"); + + // 1f. - cells in the topo clusters + PositionedCaloTopoClusterCells_cellID = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.cellID"); + PositionedCaloTopoClusterCells_energy = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.energy"); + PositionedCaloTopoClusterCells_position_x = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.position.x"); + PositionedCaloTopoClusterCells_position_y = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.position.y"); + PositionedCaloTopoClusterCells_position_z = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.position.z"); + + qs_rhoz.clear(); + qs_rhophi.clear(); + } + + ~EventReader() { + delete genParticles_PDG; + delete genParticles_generatorStatus; + delete genParticles_simulatorStatus; + delete genParticles_charge; + delete genParticles_time; + delete genParticles_mass; + delete genParticles_vertex_x; + delete genParticles_vertex_y; + delete genParticles_vertex_z; + //delete genParticles_endpoint_x; + //delete genParticles_endpoint_y; + //delete genParticles_endpoint_z; + delete genParticles_momentum_x; + delete genParticles_momentum_y; + delete genParticles_momentum_z; + + if (SimParticleSecondaries_PDG) { + delete SimParticleSecondaries_PDG; + // delete SimParticleSecondaries_generatorStatus; + // delete SimParticleSecondaries_simulatorStatus; + // delete SimParticleSecondaries_charge; + // delete SimParticleSecondaries_time; + delete SimParticleSecondaries_mass; + delete SimParticleSecondaries_vertex_x; + delete SimParticleSecondaries_vertex_y; + delete SimParticleSecondaries_vertex_z; + delete SimParticleSecondaries_endpoint_x; + delete SimParticleSecondaries_endpoint_y; + delete SimParticleSecondaries_endpoint_z; + delete SimParticleSecondaries_momentum_x; + delete SimParticleSecondaries_momentum_y; + delete SimParticleSecondaries_momentum_z; + } + delete ECalBarrelPositionedHits_cellID; + delete ECalBarrelPositionedHits_energy; + delete ECalBarrelPositionedHits_position_x; + delete ECalBarrelPositionedHits_position_y; + delete ECalBarrelPositionedHits_position_z; + delete ECalBarrelPositionedCells_cellID; + delete ECalBarrelPositionedCells_energy; + delete ECalBarrelPositionedCells_position_x; + delete ECalBarrelPositionedCells_position_y; + delete ECalBarrelPositionedCells_position_z; + delete ECalBarrelPositionedCells2_cellID; + delete ECalBarrelPositionedCells2_energy; + delete ECalBarrelPositionedCells2_position_x; + delete ECalBarrelPositionedCells2_position_y; + delete ECalBarrelPositionedCells2_position_z; + delete CorrectedCaloTopoClusters_energy; + delete CorrectedCaloTopoClusters_position_x; + delete CorrectedCaloTopoClusters_position_y; + delete CorrectedCaloTopoClusters_position_z; + delete CorrectedCaloTopoClusters_hits_begin; + delete CorrectedCaloTopoClusters_hits_end; + delete PositionedCaloTopoClusterCells_cellID; + delete PositionedCaloTopoClusterCells_energy; + delete PositionedCaloTopoClusterCells_position_x; + delete PositionedCaloTopoClusterCells_position_y; + delete PositionedCaloTopoClusterCells_position_z; + delete fReader; + } + + void loadEvent(int event = -1) { + if (event != -1) + eventId = event; + printf("Loading event %d.\n", eventId); + fReader->SetEntry(eventId); + + TString partType; + double pmax=0.0; + int ipmax=-1; + for (unsigned int i = 0; i < genParticles_generatorStatus->GetSize(); i ++) { + if ( (*genParticles_generatorStatus)[i] != 1 ) continue; + float _px = (*genParticles_momentum_x)[i]; + float _py = (*genParticles_momentum_y)[i]; + float _pz = (*genParticles_momentum_z)[i]; + float _p = sqrt( _px*_px + _py*_py + _pz*_pz ); + //cout << p << endl; + if (_p==0.) continue; + if (_p>pmax) { + pmax = _p; + ipmax = i; + } + } + int pdgID = (*genParticles_PDG)[ipmax]; + if (pdgID == 111) partType = "pi0"; + else if (pdgID == 22) partType = "y"; + else if (pdgID == 11) partType = "e-"; + else if (pdgID == -11) partType = "e+"; + else partType = "unknown"; + + // + // particles + // + if (drawParticles) { + cout << "Creating particles" << endl; + if (particles) { + // I haven't found a way to just delete the lines of the set + particles->Destroy(); + particles = nullptr; + } + if (particles == nullptr) { + particles = new TEveStraightLineSet("particles"); + particles->SetMainColor(kYellow); + particles->SetLineWidth(3); + gEve->AddElement(particles); + } + + if (drawMCtracks) { + if (particlesMC == nullptr) { + particlesMC = new TEveTrackList("particlesMC"); + TEveTrackPropagator* trkProp = particlesMC->GetPropagator(); + trkProp->SetMagField( 0.0 ); + particlesMC->SetMainColor(kYellow); + gEve->AddElement(particlesMC); + } + else + particlesMC->DestroyElements(); + } + + /* + int ipmax=-1; + for (unsigned int i = 0; i < genParticles_generatorStatus->GetSize(); i ++) { + if ( (*genParticles_generatorStatus)[i] != 1 ) continue; + float px = (*genParticles_momentum_x)[i]; + float py = (*genParticles_momentum_y)[i]; + float pz = (*genParticles_momentum_z)[i]; + float p = sqrt( px*px + py*py + pz*pz ); + //cout << p << endl; + if (p==0.) continue; + if (p>pmax) { + pmax = p; + ipmax = i; + } + + float m = (*genParticles_mass)[i]; + float px = (*genParticles_momentum_x)[i]; + float py = (*genParticles_momentum_y)[i]; + float pz = (*genParticles_momentum_z)[i]; + float m = (*genParticles_mass)[i]; + float p = sqrt( px*px + py*py + pz*pz ); + int pdgID = (*genParticles_PDG)[i]; + double t = (*genParticles_time)[i]; + double x1 = (*genParticles_vertex_x)[i] * mm; + double y1 = (*genParticles_vertex_y)[i] * mm; + double z1 = (*genParticles_vertex_z)[i] * mm; + double r1 = sqrt(x1*x1+y1*y1); + double sintheta = sqrt(px*px + py*py)/p; + double x2 = x1 + px/p * rMax / sintheta; + double y2 = y1 + py/p * rMax / sintheta; + double z2 = z1 + pz/p * rMax / sintheta; + double r2 = sqrt(x2*x2+y2*y2); + + particles->AddLine(x1,y1,z1, x2,y2,z2); + particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", + pdgID, + m, + p, + acos(pz/p), + atan2(py,px),)); + + if (drawMCtracks) { + TEveMCTrack mct; + mct.SetPdgCode( pdgID ); + mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); + mct.SetProductionVertex( x1, y1, z1, t ); + TEveTrack* track = new TEveTrack(&mct); + track->SetAttLineAttMarker(particlesMC); + particlesMC->AddElement(track); + } + } + if (drawMCtracks) particlesMC->MakeTracks(); + */ + + // handle differently the e/gamma vs pi0 particle guns (for pi0, need to look for the two photons in secondary particle list + // unfortunately cannot just use the latter to show particles since info about endpoint is broken (identical to vertex) + if (pdgID != 111) { + float m = (*genParticles_mass)[ipmax]; + float px = (*genParticles_momentum_x)[ipmax]; + float py = (*genParticles_momentum_y)[ipmax]; + float pz = (*genParticles_momentum_z)[ipmax]; + float p = sqrt( px*px + py*py + pz*pz ); + + double t = (*genParticles_time)[ipmax]; + double x1 = (*genParticles_vertex_x)[ipmax] * mm; + double y1 = (*genParticles_vertex_y)[ipmax] * mm; + double z1 = (*genParticles_vertex_z)[ipmax] * mm; + double r1 = sqrt(x1*x1+y1*y1); + double sintheta = sqrt(px*px + py*py)/p; + double x2 = x1 + px/p * rMax / sintheta; + double y2 = y1 + py/p * rMax / sintheta; + double z2 = z1 + pz/p * rMax / sintheta; + double r2 = sqrt(x2*x2+y2*y2); + + particles->AddLine(x1,y1,z1, x2,y2,z2); + particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", + pdgID, + m, + p, + acos(pz/p), + atan2(py,px))); + + } + else { + for (unsigned int i = 0; i < SimParticleSecondaries_PDG->GetSize(); i ++) { + int pdgID = (*SimParticleSecondaries_PDG)[i]; + // keep only photons + if (pdgID!=22) continue; + //if ( (*SimParticleSecondaries_generatorStatus)[i] != 1 ) continue; + float px = (*SimParticleSecondaries_momentum_x)[i]; + float py = (*SimParticleSecondaries_momentum_y)[i]; + float pz = (*SimParticleSecondaries_momentum_z)[i]; + float m = (*SimParticleSecondaries_mass)[i]; + float p = sqrt( px*px + py*py + pz*pz ); + float e = sqrt(p*p + m*m); + cout << "p = "<< p << endl; + if (pAddLine(x1,y1,z1, x2,y2,z2); + particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", + pdgID, + m, + p, + acos(pz/p), + atan2(py,px))); + } + } + } + + // + // hits + // + if (drawHits) { + cout << "Creating hits" << endl; + if (hits == nullptr) { + hits = new TEvePointSet(); + hits->SetName(Form("hits (E>%.1f GeV)",CellEnergyThreshold)); + hits->SetMarkerStyle(4); + hits->SetMarkerSize(1); + hits->SetMarkerColor(kRed); + gEve->AddElement(hits); + } + else + hits->Reset(); + for (unsigned int i = 0; i < ECalBarrelPositionedHits_position_x->GetSize(); i ++) { + float E = (*ECalBarrelPositionedHits_energy)[i]; + if (ESetNextPoint( (*ECalBarrelPositionedHits_position_x)[i] * mm , + (*ECalBarrelPositionedHits_position_y)[i] * mm , + (*ECalBarrelPositionedHits_position_z)[i] * mm ); + } + } + + // + // cells + // + if (drawCells) { + cout << "Creating cells" << endl; + if (cells == nullptr) { + cells = new TEvePointSet(); + cells->SetName(Form("cells (E>%.1f GeV)",CellEnergyThreshold)); + cells->SetMarkerStyle(4); + cells->SetMarkerSize(3); + cells->SetMarkerColor(kBlue); + gEve->AddElement(cells); + } + else + cells->Reset(); + for (unsigned int i = 0; i < ECalBarrelPositionedCells_position_x->GetSize(); i ++) { + float E = (*ECalBarrelPositionedCells_energy)[i]; + if (ESetNextPoint( (*ECalBarrelPositionedCells_position_x)[i] * mm , + (*ECalBarrelPositionedCells_position_y)[i] * mm , + (*ECalBarrelPositionedCells_position_z)[i] * mm ); + } + } + + // + // cells merged + // + if (drawMergedCells) { + cout << "Creating merged cells" << endl; + if (cells_merged == nullptr) { + cells_merged = new TEvePointSet(); + cells_merged->SetName("cells_merged"); + cells_merged->SetMarkerStyle(4); + cells_merged->SetMarkerSize(3); + cells_merged->SetMarkerColor(kBlue); + gEve->AddElement(cells_merged); + } + else + cells_merged->Reset(); + for (unsigned int i = 0; i < ECalBarrelPositionedCells2_position_x->GetSize(); i ++) { + float E = (*ECalBarrelPositionedCells2_energy)[i]; + // if (ESetNextPoint( (*ECalBarrelPositionedCells2_position_x)[i] * mm , + (*ECalBarrelPositionedCells2_position_y)[i] * mm , + (*ECalBarrelPositionedCells2_position_z)[i] * mm ); + } + } + + + // + // clusters + // + if (drawTopoClusters) { + cout << "Creating clusters" << endl; + + // centers of the clusters + if (clusters == nullptr) { + clusters = new TEvePointSet(); + clusters->SetName(Form("clusters (E>%.1f GeV)",TopoClusterEnergyThreshold)); + clusters->SetMarkerStyle(4); + clusters->SetMarkerSize(6); + clusters->SetMarkerColor(kGreen); + gEve->AddElement(clusters); + } + else + clusters->Reset(); + + for (unsigned int i = 0; i < CorrectedCaloTopoClusters_position_x->GetSize(); i ++) { + float E = (*CorrectedCaloTopoClusters_energy)[i]; + if (E < TopoClusterEnergyThreshold) continue; + clusters->SetNextPoint( (*CorrectedCaloTopoClusters_position_x)[i] * cm , + (*CorrectedCaloTopoClusters_position_y)[i] * cm , + (*CorrectedCaloTopoClusters_position_z)[i] * cm ); // why cluster positions are in cm and hits/cells in mm??? + } + + + // the DestroyElements method does not work for TExeQuadSet as for the TEvePointSet.. + // so I have to destroy and recreate the quad and box sets + for (auto qs : qs_rhoz) { + if (qs) + qs->Destroy(); + } + qs_rhoz.clear(); + + for (auto qs : qs_rhophi) { + if (qs) + qs->Destroy(); + } + qs_rhophi.clear(); + + for (auto _bs : bs) { + if (_bs) + _bs->Destroy(); + } + bs.clear(); + + TEveRGBAPalette *pal = new TEveRGBAPalette(0, 1000); + + // clusters in 3D + if (topoclusters_3D==nullptr) { + topoclusters_3D = new TEveElementList("Clusters in 3D (no E cut)"); + gEve->AddElement(topoclusters_3D); + } + else + topoclusters_3D->DestroyElements(); + + // clusters in 2D + if (topoclusters_rhoz==nullptr) { + topoclusters_rhoz = new TEveElementList(Form("Clusters in rho-z (E>%.1f GeV)",TopoClusterEnergyThreshold)); + // add to scene or manager? + rhoZProjManager->AddElement(topoclusters_rhoz); + //rhoZEventScene->AddElement(topoclusters_rhoz); + gEve->AddToListTree(topoclusters_rhoz,false); + } + else + topoclusters_rhoz->DestroyElements(); + + if (topoclusters_rhophi==nullptr) { + topoclusters_rhophi = new TEveElementList(Form("Clusters in rho-phi (E>%.1f GeV)",TopoClusterEnergyThreshold)); + // add to scene or manager? + rhoPhiProjManager->AddElement(topoclusters_rhophi); + //rhoPhiEventScene->AddElement(topoclusters_rhophi); + gEve->AddToListTree(topoclusters_rhophi,false); + } + else + topoclusters_rhophi->DestroyElements(); + + for (unsigned int i = 0; i < CorrectedCaloTopoClusters_energy->GetSize(); i ++) { + float energy = (*CorrectedCaloTopoClusters_energy)[i]; + float xcl = (*CorrectedCaloTopoClusters_position_x)[i]; + float ycl = (*CorrectedCaloTopoClusters_position_y)[i]; + float zcl = (*CorrectedCaloTopoClusters_position_z)[i]; + float rcl = sqrt(xcl*xcl + ycl*ycl); + float phicl = atan2(ycl, xcl); + float thetacl = atan2(rcl, zcl); + + if (energy < TopoClusterEnergyThreshold) { + qs_rhoz.push_back(nullptr); + qs_rhophi.push_back(nullptr); + } + else { + TEveQuadSet* aqs = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, Form("cluster %d", (int) i)); + aqs->SetMainTransparency(80); + // by calling SetOwnIds(kTRUE) the digit-set becomes + // the owner of the assigned objects and deletes + // them on destruction. + aqs->SetOwnIds(kTRUE); + aqs->SetPalette(pal); + aqs->SetTitle(Form("E = %f GeV\nR = %f cm\ntheta = %f\nphi = %f", + energy, + rcl, + thetacl, + phicl)); + qs_rhoz.push_back(aqs); + topoclusters_rhoz->AddElement(aqs); + + TEveQuadSet* aqs2 = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, Form("cluster %d", (int) i)); + aqs2->SetMainTransparency(80); + aqs2->SetOwnIds(kTRUE); + aqs2->SetPalette(pal); + aqs2->SetTitle(Form("E = %f GeV\nR = %f cm\ntheta = %f\nphi = %f", + energy, + rcl, + thetacl, + phicl)); + qs_rhophi.push_back(aqs2); + topoclusters_rhophi->AddElement(aqs2); + } + + TEveBoxSet* _bs = new TEveBoxSet(Form("cluster %d", (int) i),""); + _bs->Reset(TEveBoxSet::kBT_FreeBox, false, 32); + _bs->SetMainTransparency(80); + _bs->SetOwnIds(kTRUE); + _bs->SetPalette(pal); + _bs->SetTitle(Form("E = %f GeV\nR = %f cm\ntheta = %f\nphi = %f", + energy, + rcl, + thetacl, + phicl)); + bs.push_back(_bs); + topoclusters_3D->AddElement(_bs); + } + + // loop over cells and attach them to clusters + for (unsigned int i = 0; i < PositionedCaloTopoClusterCells_energy->GetSize(); i ++) { + int icl = -1; + for (unsigned int j = 0; j < CorrectedCaloTopoClusters_energy->GetSize(); j ++) { + if (i >= (*CorrectedCaloTopoClusters_hits_begin)[j] && i < (*CorrectedCaloTopoClusters_hits_end)[j]) { + icl = j; + break; + } + } + if (icl==-1) continue; // should never happen.. + ULong_t cellID = (*PositionedCaloTopoClusterCells_cellID)[i]; + int layer = (int) Layer(cellID); + float x_center = (*PositionedCaloTopoClusterCells_position_x)[i] * mm; + float y_center = (*PositionedCaloTopoClusterCells_position_y)[i] * mm; + float z_center = (*PositionedCaloTopoClusterCells_position_z)[i] * mm; + float r_center = sqrt(x_center*x_center + y_center*y_center); + float r_in = r[layer]; + float r_out = r[layer+1]; + float theta_center = atan2(r_center, z_center); + float phi_center = atan2(y_center, x_center); + float energy = (*PositionedCaloTopoClusterCells_energy)[i]; + + // cluster cells in rho-z projection + float verts[12]; + verts[0] = r_in/tan(theta_center - thetaGrid*mergedCells_Theta[layer]/2.); + verts[1] = r_in*sgn(y_center); + verts[3] = r_in/tan(theta_center + thetaGrid*mergedCells_Theta[layer]/2.); + verts[4] = r_in*sgn(y_center); + verts[6] = r_out/tan(theta_center + thetaGrid*mergedCells_Theta[layer]/2.); + verts[7] = r_out*sgn(y_center); + verts[9] = r_out/tan(theta_center - thetaGrid*mergedCells_Theta[layer]/2.); + verts[10] = r_out*sgn(y_center); + verts[2] = verts[5] = verts[8] = verts[11] = 0.; + if (qs_rhoz[icl]!=nullptr) { + qs_rhoz[icl]->AddQuad(verts); + qs_rhoz[icl]->QuadValue( (int) (1000 * energy) ); + qs_rhoz[icl]->QuadId( new TNamed(Form("Cell %lu", cellID), "Dong!") ); + } + // cluster cells in rho-phi projection + int module = (int) Module(cellID); + double Lin = _L(alpha, rMin, r[layer]); + double Lout = _L(alpha, rMin, r[layer+1]); + double deltaL = rMin*sin(gridPhi/2.0)*sin(alpha); + for (int j=0; jAddQuad(verts); + qs_rhophi[icl]->QuadValue( (int) (1000 * energy) ); + qs_rhophi[icl]->QuadId(new TNamed(Form("Cell %lu", cellID), "Dong!")); + } + } + + // cluster cells in 3D + float verts3D[24]; + for (int j=0; jAddBox(verts3D); + bs[icl]->DigitValue( (int) (1000 * energy) ); + //bs->BoxId(new TNamed(Form("Cell %lu", cellID), "Dong!")); + } + } + } + + if (eventLabel == nullptr) { + eventLabel = new TGLConstAnnotation(gEve->GetDefaultGLViewer(), Form("%s, %.1f GeV\nEvent %d", partType.Data(), pmax, eventId), 0.1, 0.9); + eventLabel->SetTextSize(0.05);// % of window diagonal + eventLabel->SetAllowClose(false); + } + else { + eventLabel->SetText(Form("%s, %.1f GeV\nEvent %d", partType.Data(), pmax, eventId)); + } + + TEveElement* top = (TEveElement*) gEve->GetCurrentEvent(); + // if nothing is drawn, top is null + if (top) { + rhoPhiEventScene->DestroyElements(); + rhoPhiProjManager->ImportElements(top, rhoPhiEventScene); + + // slow?? + //TEveRGBAPaletteOverlay *po = new TEveRGBAPaletteOverlay(pal, 0.55, 0.1, 0.4, 0.05); + //rhoPhiGLView->AddOverlayElement(po); + + rhoZEventScene->DestroyElements(); + rhoZProjManager->ImportElements(top, rhoZEventScene); + + //TEveRGBAPaletteOverlay *po2 = new TEveRGBAPaletteOverlay(pal, 0.55, 0.1, 0.4, 0.05); + //rhoZGLView->AddOverlayElement(po2); + } + + cout << "Done" << endl; + } +}; + + + +/******************************************************************************/ +// THE MAIN FUNCTION +/******************************************************************************/ + +EventReader* eventReader = nullptr; + +void display(int evt = 0) { + + // calculate the geometry parameters + calcGeom(); + + // create the eve manageer + TEveManager::Create(); + + // see palettes here: https://root.cern.ch/doc/master/classTColor.html + // gStyle->SetPalette(kAvocado); + gStyle->SetPalette(kSienna); + + // first tab + //gEve->GetDefaultGLViewer()->SetCurrentCamera(TGLViewer::kCameraPerspYOZ); + gEve->GetDefaultGLViewer()->SetGuideState(TGLUtil::kAxesOrigin, false, false, 0); + gEve->GetDefaultGLViewer()->DrawGuides(); + gEve->GetDefaultViewer()->SetElementName("3D view"); + //gEve->GetDefaultGLViewer()->GetClipSet()->SetClipType(TGLClip::EType(1)); + gEve->GetDefaultGLViewer()->CurrentCamera().RotateRad(-.7, 0.5); + + // Create the geometry and the readout + TEveElementList* geom = new TEveElementList("Geometry"); + TEveElementList* PCBs = new TEveElementList("PCBs"); + TEveElementList* actives = new TEveElementList("Active elements"); + TEveElementList* passives = new TEveElementList("Passive elements"); + TEveElementList* readout = new TEveElementList("Readout"); + bool useG4geom = true; + if (useG4geom) { + //auto fGeom = TFile::Open(geomFile.c_str(), "CACHEREAD"); + auto fGeom = TFile::Open(geomFile.c_str(), "READ"); + if (!fGeom) return; + TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) fGeom->Get("ECalBarrel_vol"); + barrel = TEveGeoShape::ImportShapeExtract(gse, 0); + barrel->SetMainTransparency(70); + fGeom->Close(); + delete fGeom; + barrel->SetPickableRecursively(kTRUE); + geom->AddElement(barrel); + TPRegexp re; + // hide bath as it slows down rendering a lot + re = TPRegexp("LAr_bath*"); + TEveElement* bath = barrel->FindChild(re); + bath->SetRnrSelfChildren(false, false); + // set transparency of the subvolumes + TEveElement::List_t matches; + re = TPRegexp("ECAL_Cryo*"); + barrel->FindChildren(matches, re); + for (auto a : matches) a->SetMainTransparency(70); + re = TPRegexp("services*"); + barrel->FindChildren(matches, re); + for (auto a : matches) a->SetMainTransparency(70); + // make lists of elements inside bath to turn on/off simultaneously + // not the correct way to go, volumes then appear twice.. + if (bath) { + TEveElementList* newbath = new TEveElementList("LAr_bath"); + barrel->AddElement(newbath); + TEveElement::List_t matches; + re = TPRegexp("PCB*"); + bath->FindChildren(matches, re); + for (auto a : matches) PCBs->AddElement(a); + newbath->AddElement(PCBs); + TEveElement::List_t matches2; + re = TPRegexp("active*"); + bath->FindChildren(matches2, re); + for (auto a : matches2) actives->AddElement(a); + newbath->AddElement(actives); + TEveElement::List_t matches3; + re = TPRegexp("passive*"); + bath->FindChildren(matches3, re); + for (auto a : matches3) passives->AddElement(a); + newbath->AddElement(passives); + barrel->RemoveElement(bath); + } + gEve->AddGlobalElement(geom); + gEve->AddToListTree(geom, true); + } + else { + // the barrel envelope + barrel = new TEveGeoShape("Barrel"); + barrel->SetShape(new TGeoTube(rMin, rMax, zMax)); + barrel->SetMainColor(kCyan); + barrel->SetMainTransparency(90); + barrel->SetNSegments(128); + // geom->AddElement(barrel); + gEve->AddGlobalElement(barrel); + // the barrel layers + TEveElementList* layers = new TEveElementList("layers"); + barrel->AddElement(layers); + TEveGeoShape* b; + for (int iLayer=0; iLayerSetShape(new TGeoTube(r[iLayer], r[iLayer+1], zMax)); + b->SetMainColor(kCyan); + b->SetMainTransparency(90); + b->SetNSegments(128); + layers->AddElement(b); + } + // the electrodes + TEveElementList* modules = new TEveElementList("modules"); + barrel->AddElement(modules); + for (int iModule=0; iModuleSetShape(new TGeoBBox(Ltot/2, 0.01, (zMax-zMin)/2.0)); + b->SetMainColor(kGray); + b->SetMainTransparency(95); + TGeoRotation* rot = new TGeoRotation(); + rot->SetAngles((alpha+iModule*gridPhi)*180./TMath::Pi(), 0., 0.); + TGeoCombiTrans* c1 = new TGeoCombiTrans(rAvg*cos(phi), rAvg*sin(phi), 0.0, rot); + b->SetTransMatrix(*c1); + modules->AddElement(b); + } + gEve->AddToListTree(barrel, true); + } + + gEve->AddToListTree(readout,true); + + // create second tab (R-phi view) + rhoPhiView = gEve->SpawnNewViewer("Projection Rho-Phi"); + // two scenes, for geometry and event + rhoPhiScene = gEve->SpawnNewScene("Rho-Phi geometry", "Scene holding projected geometry data for the RhoPhi view."); + rhoPhiView->AddScene(rhoPhiScene); + rhoPhiEventScene = gEve->SpawnNewScene("RhoPhi Event Data", "Scene holding projected event-data for the RhoPhi view."); + rhoPhiView->AddScene(rhoPhiEventScene); + rhoPhiGLView = rhoPhiView->GetGLViewer(); + // set camera orientation + rhoPhiGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); + // create 3D->2D projection manager for + rhoPhiProjManager = new TEveProjectionManager(); + rhoPhiProjManager->SetProjection(TEveProjection::kPT_RPhi); + rhoPhiScene->AddElement(rhoPhiProjManager); + auto axes = new TEveProjectionAxes(rhoPhiProjManager); + axes->SetElementName("Rho-Phi projection axes"); + rhoPhiScene->AddElement(axes); + //gEve->AddToListTree(axes, kTRUE); + //gEve->AddToListTree(rhoPhiProjManager, kTRUE); + if (useG4geom) { + rhoPhiProjManager->ImportElements(geom, rhoPhiScene); + // enable bath in 2D view + TEveElement* geomProj = rhoPhiProjManager->FindChild("Geometry [P]"); + TPRegexp re("ECalBarrel_*"); + TEveElement* barrelProj = geomProj->FindChild(re); + re = TPRegexp("LAr_bath*"); + TEveElement* bath = barrelProj->FindChild(re); + bath->SetRnrSelfChildren(false, true); + } + else + rhoPhiProjManager->ImportElements(barrel, rhoPhiScene); + + // the merged module grid + TEveStraightLineSet* gridmod = new TEveStraightLineSet("phi readout merged"); + gridmod->SetLineColor(kViolet+2); + gridmod->SetLineWidth(8); + for (int iLayer=0; iLayerAddLine(x1, y1, 0., x2, y2, 0.); + } + } + // add to proj manager or to scene? + //rhoPhiProjManager->AddElement(gridmod); + rhoPhiScene->AddElement(gridmod); + readout->AddElement(gridmod); + + // third tab (R-z view) + rhoZView = gEve->SpawnNewViewer("Projection Rho-Z"); + rhoZScene = gEve->SpawnNewScene("Rho-Z geometry", "Scene holding projected geometry data for the RhoZ view."); + rhoZView->AddScene(rhoZScene); + rhoZEventScene = gEve->SpawnNewScene("RhoZ Event Data", "Scene holding projected event-data for the RhoZ view."); + rhoZView->AddScene(rhoZEventScene); + rhoZGLView = rhoZView->GetGLViewer(); + rhoZGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); + + rhoZProjManager = new TEveProjectionManager(); + rhoZProjManager->SetProjection(TEveProjection::kPT_RhoZ); + rhoZScene->AddElement(rhoZProjManager); + auto axes2 = new TEveProjectionAxes(rhoZProjManager); + axes2->SetElementName("Rho-Z projection axes"); + rhoZScene->AddElement(axes2); + //gEve->AddToListTree(axes2, kTRUE); + //gEve->AddToListTree(rhoZProjManager, kTRUE); + if (useG4geom) { + rhoZProjManager->ImportElements(geom, rhoZScene); + // enable bath in 2D view + TEveElement* geomProj = rhoZProjManager->FindChild("Geometry [P]"); + TPRegexp re("ECalBarrel_*"); + TEveElement* barrelProj = geomProj->FindChild(re); + re = TPRegexp("LAr_bath*"); + TEveElement* bath = barrelProj->FindChild(re); + bath->SetRnrSelfChildren(false, true); + } + else + rhoZProjManager->ImportElements(barrel, rhoZScene); + + // the theta readout grid + TEveStraightLineSet* grid = new TEveStraightLineSet("theta readout"); + grid->SetLineColor(kViolet); + //grid->SetLineStyle(kDotted); + for (int iTheta=0; iTheta<=nThetaBins; iTheta++) { + double theta = thetaMin + iTheta*thetaGrid; + double r1 = rMin; + double r2 = rMax; + double z1 = r1*cos(theta)/sin(theta); + double z2 = r2*cos(theta)/sin(theta); + if (z1zMin) { + if (z2>zMax) { + z2 = zMax; + r2 = z2*sin(theta)/cos(theta); + } + if (z2AddLine(z1, r1, 0., z2, r2, 0.); + grid->AddLine(z1, -r1, 0., z2, -r2, 0.); + } + } + //rhoZProjManager->AddElement(grid); + rhoZScene->AddElement(grid); + readout->AddElement(grid); + + // the merged grid + TEveStraightLineSet* grid2 = new TEveStraightLineSet("theta readout merged"); + grid2->SetLineColor(kViolet+2); + grid2->SetLineWidth(8); + for (int iLayer=0; iLayerzMin) { + if (z2>zMax) { + z2 = zMax; + r2tmp = z2*sin(theta)/cos(theta); + } + if (z2AddLine(z1, r1, 0., + z2, r2tmp, 0.); + grid2->AddLine(z1, -r1, 0., + z2, -r2tmp, 0.); + } + } + } + //rhoZProjManager->AddElement(grid2); + rhoZScene->AddElement(grid2); + readout->AddElement(grid2); + + + gEve->Redraw3D(true); + + + makeGui(); + + // + // data + // + + // setup the reader + TFile* f = TFile::Open(evtFile.c_str(), "READ"); + eventReader = new EventReader(f); + + // load and display the requested event + eventReader->loadEvent(evt); + + // Set the 3D view as the active tab and rotate the camera + gEve->GetBrowser()->GetTabRight()->SetTab(0); + + // Draw + gEve->Redraw3D(true); +} + + +/******************************************************************************/ +// GUI +/******************************************************************************/ + +//______________________________________________________________________________ +// +// EvNavHandler class is needed to connect GUI signals. + +class EvNavHandler +{ +public: + void Fwd() + { + if (eventId < nEvents - 1) { + ++eventId; + eventReader->loadEvent(); + } else { + printf("Already at last event.\n"); + } + } + void Bck() + { + if (eventId > 0) { + --eventId; + eventReader->loadEvent(); + } else { + printf("Already at first event.\n"); + } + } +}; + +void makeGui() +{ + // Create minimal GUI for event navigation. + + TEveBrowser* browser = gEve->GetBrowser(); + browser->StartEmbedding(TRootBrowser::kLeft); + + TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600); + frmMain->SetWindowName("GUI"); + frmMain->SetCleanup(kDeepCleanup); + + TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain); + { + + TString icondir( Form("%s/icons/", gSystem->Getenv("ROOTSYS")) ); + TGPictureButton* b = 0; + EvNavHandler *fh = new EvNavHandler; + + b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoBack.gif")); + hf->AddFrame(b); + b->Connect("Clicked()", "EvNavHandler", fh, "Bck()"); + + b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoForward.gif")); + hf->AddFrame(b); + b->Connect("Clicked()", "EvNavHandler", fh, "Fwd()"); + } + frmMain->AddFrame(hf); + + frmMain->MapSubwindows(); + frmMain->Resize(); + frmMain->MapWindow(); + + browser->StopEmbedding(); + browser->SetTabTitle("Event Control", 0); +} From 16fab5a99d2cbc33644d2a3d89a7ba8771d6dd0d Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 15:08:02 +0200 Subject: [PATCH 05/33] add event display tool for debugging --- FCCSW_ecal/displayV3.C | 3 +++ 1 file changed, 3 insertions(+) diff --git a/FCCSW_ecal/displayV3.C b/FCCSW_ecal/displayV3.C index 74a22ad..daa9bd5 100644 --- a/FCCSW_ecal/displayV3.C +++ b/FCCSW_ecal/displayV3.C @@ -1,9 +1,12 @@ /******************************************************************************/ // Simple event display for the LAr calorimeter with inclined modules +// author: Giovanni Marchiori (giovanni.marchiori@cern.ch) +// // Run with // root // .L displayV3.C+ // display() +// /******************************************************************************/ From f3faab963c09b395376240c69b496221913fdb66 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 15:35:54 +0200 Subject: [PATCH 06/33] add comments --- geometry/create_capacitance_file_theta.py | 49 ++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index ef09b4e..a0eea4c 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -29,20 +29,58 @@ #ECalConstruction INFO active material = LAr active layers thickness at inner radius (cm) = 0.247949 thickness at outer radious (cm) = 0.479746 making 93.4857 % increase. #ECalConstruction INFO active passive initial overlap (before subtraction) (cm) = 0.1 = 50 % +# latest version +# Info: ECAL cryostat: front: rmin (cm) = 215.4 rmax (cm) = 216.78 dz (cm) = 310 +# Info: ECAL cryostat: back: rmin (cm) = 261.33 rmax (cm) = 271.6 dz (cm) = 310 +# Info: ECAL cryostat: side: rmin (cm) = 216.78 rmax (cm) = 261.33 dz (cm) = 3.38 +# Info: ECAL services: front: rmin (cm) = 216.78 rmax (cm) = 217.28 dz (cm) = 306.62 +# Info: ECAL services: back: rmin (cm) = 257.33 rmax (cm) = 261.33 dz (cm) = 306.62 +# Info: ECAL bath: material = LAr rmin (cm) = 217.28 rmax (cm) = 257.33 thickness in front of ECal (cm) = 0.5 thickness behind ECal (cm) = 4 +# Info: ECAL calorimeter volume rmin (cm) = 217.28 rmax (cm) = 257.33 +# Info: passive inner material = Lead +# and outer material = lArCaloSteel +# thickness of inner part at inner radius (cm) = 0.18 +# thickness of inner part at outer radius (cm) = 0.18 +# thickness of outer part (cm) = 0.01 +# thickness of total (cm) = 0.2 +# rotation angle = 0.872665 +# Info: number of passive plates = 1545 azim. angle difference = 0.00406679 +# Info: distance at inner radius (cm) = 0.883631 +# distance at outer radius (cm) = 1.04651 +# Info: readout material = PCB +# thickness of readout planes (cm) = 0.12 +# number of readout layers = 12 +# Info: thickness of calorimeter (cm) = 40.05 +# length of passive or readout planes (cm) = 56.586 filename = "capacitances_perSource_ecalBarrelFCCee.root" #filename = "capacitances_ecalBarrelFCCee_nLayer_%d_fromAnalytical.root"%numLayers # layer 2 require special care as it is separated in several cells and that the shield run beneath the etch: cell 2 signal pad top capa: 0.68 + 0.20 = 0.88, cell 2 signal pad bot: 0.56 + 0.21 = 0.77, cell 3: 0.34 + 2.4 = 2.74, cell 4: 1 + 0.25 = 1.25, cell 5: 1.85 + 0.28 = 2.13 -activeTotal = 400.0 -inclinedTotal = 564.964 +# 1*15mm + 11*35mm = 400 +# activeTotal = 400.0 +# inclinedTotal = 564.964 +# tracesPerLayer = [6, 1, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7] # only one trace for strip layer because 4 cells instead of one +# ncells_strip_layer = 4.0 +# careful, this is not really the radial spacing, it is, after dilution, the spacing in the parallel direction --> radial depth spacing will not be constant +# readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 +# Detector +# rmin = 2160 +# Nplanes = 1536 +# inclination_degree = 50 +# angle = inclination_degree / 180. * pi #inclination angle inn radian +# passiveThickness = 2.0 #mm + +# latest +activeTotal = 400.5 +inclinedTotal = 565.86 tracesPerLayer = [6, 1, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7] # only one trace for strip layer because 4 cells instead of one ncells_strip_layer = 4.0 # careful, this is not really the radial spacing, it is, after dilution, the spacing in the parallel direction --> radial depth spacing will not be constant readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 -#Detector -rmin = 2160 +# Detector +rmin = 2172.8 Nplanes = 1545 inclination_degree = 50 angle = inclination_degree / 180. * pi #inclination angle inn radian @@ -88,9 +126,10 @@ capa_per_mm = 0.123 # pF/mm capa_per_mm_stripLayer = 0.062 # pF/mm # multiplicative factor -# factor two because we merge two phi cells together, another factor 2 becasue we have two 1) signal pad / shield capa 2) HV plate / absorber capa per cell +# factor two because we merge two phi cells together, another factor 2 because we have two 1) signal pad / shield capa 2) HV plate / absorber capa per cell nmult = 2 nmult_trace = 1 # for the trace only the number of phi cell merged playes a role +# GM: should the above two be 4 and 2 since we merge 2 phi cells together? epsilonRLAr = 1.5 # LAr at 88 K epsilon0 = 8.854/1000. #pF/mm From 9e2463c9ac8e9533bdb3a2de308f4e7feb5a0caa Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 15:47:35 +0200 Subject: [PATCH 07/33] add comments --- geometry/create_capacitance_file_theta.py | 6 +++++- .../create_noise_file_chargePreAmp_theta.py | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index a0eea4c..394802b 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -1,5 +1,9 @@ +# calculate and save histograms of capacitance per source vs theta +# output is saved in ROOT file with given filename +# # execute script with # python create_capacitance_file_theta.py +# from ROOT import TH1F, TF1, TF2, TCanvas, TLegend, TFile, gStyle import ROOT @@ -53,7 +57,7 @@ # Info: thickness of calorimeter (cm) = 40.05 # length of passive or readout planes (cm) = 56.586 -filename = "capacitances_perSource_ecalBarrelFCCee.root" +filename = "capacitances_perSource_ecalBarrelFCCee_theta.root" #filename = "capacitances_ecalBarrelFCCee_nLayer_%d_fromAnalytical.root"%numLayers # layer 2 require special care as it is separated in several cells and that the shield run beneath the etch: cell 2 signal pad top capa: 0.68 + 0.20 = 0.88, cell 2 signal pad bot: 0.56 + 0.21 = 0.77, cell 3: 0.34 + 2.4 = 2.74, cell 4: 1 + 0.25 = 1.25, cell 5: 1.85 + 0.28 = 2.13 diff --git a/geometry/create_noise_file_chargePreAmp_theta.py b/geometry/create_noise_file_chargePreAmp_theta.py index 81df53c..0214a84 100644 --- a/geometry/create_noise_file_chargePreAmp_theta.py +++ b/geometry/create_noise_file_chargePreAmp_theta.py @@ -1,3 +1,16 @@ +# uses the output of create_capacitance_file_theta.py to create +# a TFile with noise vs theta for the different layers. +# The noise is derived based on https://indico.cern.ch/event/1066234/contributions/4708987/attachments/2387716/4080914/20220209_Brieuc_Francois_Noble_Liquid_Calorimetry_forFCCee_FCCworkshop2022.pdf#page=7 + +# execute script with +# python create_noise_file_chargePreAmp_theta.py + +# the input file name is configured with capa_filename +# noise and capacitances per layer are saved in root files +# capacitances_ecalBarrelFCCee_theta.root +# elecNoise_ecalBarrelFCCee_theta.root +# in folder noise_capa_ + from ROOT import TH1F, TCanvas, TLegend, TFile, gStyle, gPad import ROOT import itertools @@ -55,7 +68,7 @@ def get_ref_charge(SF, E_dep = 1 * pow(10, 6)): #E_dep en eV, choose 1 MeV output_folder = "noise_vs_capa_chargePreAmp" #filename = "ecalBarrelFCCee_"+flagImpedance+"Ohm_"+flagTraces+"_"+str(flagsShieldsWidth)+"shieldWidth" -capa_filename = "capacitances_perSource_ecalBarrelFCCee.root" +capa_filename = "capacitances_perSource_ecalBarrelFCCee_theta.root" if not os.path.exists(capa_filename): print("Error: capacitance file does not exist, please run first python create_capacitance_file.py") sys.exit(1) @@ -64,8 +77,8 @@ def get_ref_charge(SF, E_dep = 1 * pow(10, 6)): #E_dep en eV, choose 1 MeV output_folder = "noise_capa_" + date.today().strftime("%y%m%d") if not os.path.isdir(output_folder): os.mkdir(output_folder) -fSaveAll = TFile(os.path.join(output_folder, "capacitances_ecalBarrelFCCee.root"),"RECREATE") -fSave = TFile(os.path.join(output_folder, "elecNoise_ecalBarrelFCCee.root"),"RECREATE") +fSaveAll = TFile(os.path.join(output_folder, "capacitances_ecalBarrelFCCee_theta.root"),"RECREATE") +fSave = TFile(os.path.join(output_folder, "elecNoise_ecalBarrelFCCee_theta.root"),"RECREATE") gStyle.SetOptStat(0) From 9b0a94240adebef1824c248ecb92c75f7eb785d9 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 15:48:47 +0200 Subject: [PATCH 08/33] add noise file for theta readout --- data/elecNoise_ecalBarrelFCCee_theta.root | Bin 0 -> 20951 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/elecNoise_ecalBarrelFCCee_theta.root diff --git a/data/elecNoise_ecalBarrelFCCee_theta.root b/data/elecNoise_ecalBarrelFCCee_theta.root new file mode 100644 index 0000000000000000000000000000000000000000..d166cf85f22de3c3b6397b1b84edd523d53acf6e GIT binary patch literal 20951 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

N6cbxyAH`UaEVe`Nq^1b3OOe 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 X{qxvGLYMWoP)g{;cJ?MZWN7?9RG&hF literal 0 HcmV?d00001 From 222adb0e10169380876e46e90a2f06bcb483eca2 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 16:40:30 +0200 Subject: [PATCH 09/33] restore noise_map and create new version for theta readout --- FCCSW_ecal/noise_map.py | 46 +++++++++------------ FCCSW_ecal/noise_map_theta.py | 77 +++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 FCCSW_ecal/noise_map_theta.py diff --git a/FCCSW_ecal/noise_map.py b/FCCSW_ecal/noise_map.py index 4db53a9..e1f5c90 100644 --- a/FCCSW_ecal/noise_map.py +++ b/FCCSW_ecal/noise_map.py @@ -1,39 +1,33 @@ from Gaudi.Configuration import * + # Detector geometry from Configurables import GeoSvc geoservice = GeoSvc("GeoSvc") # if FCC_DETECTORS is empty, this should use relative path to working directory -import os path_to_detector = os.environ.get("FCCDETECTORS", "") print(path_to_detector) detectors_to_use=[ -# 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster.xml', - 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster_thetamodulemerged.xml' + 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster.xml', ] # prefix all xmls with path_to_detector geoservice.detectors = [os.path.join(path_to_detector, _det) for _det in detectors_to_use] geoservice.OutputLevel = INFO -#ecalBarrelReadoutName = "ECalBarrelPhiEta" -ecalBarrelReadoutName = "ECalBarrelModuleThetaMerged" -#hcalBarrelReadoutName = "ECalBarrelPhiEta" -hcalBarrelReadoutName = "HCalBarrelReadout" +ecalBarrelReadoutName = "ECalBarrelPhiEta" #BarrelNoisePath = "/afs/cern.ch/user/b/brfranco/work/public/LAr_setups/230208/LAr_scripts/geometry/noise_capa_230301/elecNoise_ecalBarrelFCCee.root" BarrelNoisePath = os.environ['FCCBASEDIR']+"/LAr_scripts/data/elecNoise_ecalBarrelFCCee.root" ecalBarrelNoiseHistName = "h_elecNoise_fcc_" from Configurables import CellPositionsECalBarrelTool -ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel", - readoutName = ecalBarrelReadoutName -) -# OutputLevel = DEBUG) -#print(ECalBcells) +# ATTENTION! +# The parameters have to be default in the tools, problem in Gaudi does not propagate the options through 2 tools +#ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel", +# readoutName = ecalBarrelReadoutName, +# OutputLevel = INFO) +#ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel") -#from Configurables import CreateFCChhCaloNoiseLevelMap, ReadNoiseFromFileTool -from Configurables import CreateFCCeeCaloNoiseLevelMap, ReadNoiseFromFileTool -ECalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolECal", - useSegmentation = False, - cellPositionsTool = ECalBcells, +from Configurables import CreateFCChhCaloNoiseLevelMap, ReadNoiseFromFileTool +ECalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolECal", readoutName = ecalBarrelReadoutName, noiseFileName = BarrelNoisePath, elecNoiseHistoName = ecalBarrelNoiseHistName, @@ -44,9 +38,8 @@ scaleFactor = 1/1000., #MeV to GeV OutputLevel=DEBUG) -HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", - useSegmentation = True, - readoutName = hcalBarrelReadoutName, +HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", + readoutName = ecalBarrelReadoutName, noiseFileName = BarrelNoisePath, elecNoiseHistoName = ecalBarrelNoiseHistName, setNoiseOffset = False, @@ -56,21 +49,20 @@ scaleFactor = 1/1000., #MeV to GeV OutputLevel=DEBUG) -#noisePerCell = CreateFCChhCaloNoiseLevelMap("noisePerCell", -noisePerCell = CreateFCCeeCaloNoiseLevelMap("noisePerCell", +noisePerCell = CreateFCChhCaloNoiseLevelMap("noisePerCell", ECalBarrelNoiseTool = ECalNoiseTool, ecalBarrelSysId = 4, HCalBarrelNoiseTool = HCalNoiseTool, - readoutNamesModuleTheta=[ecalBarrelReadoutName], - systemNamesModuleTheta=["system"], - systemValuesModuleTheta=[4], - activeFieldNamesModuleTheta=["layer"], + readoutNamesPhiEta=[ecalBarrelReadoutName], + systemNamesPhiEta=["system"], + systemValuesPhiEta=[4], + activeFieldNamesPhiEta=["layer"], activeVolumesNumbers = [12], #activeVolumesEta = [1.2524, 1.2234, 1.1956, 1.1561, 1.1189, 1.0839, 1.0509, 0.9999, 0.9534, 0.91072], readoutNamesVolumes=[], outputFileName="cellNoise_map_electronicsNoiseLevel.root", OutputLevel=DEBUG) -#noisePerCell.ECalBarrelNoiseTool.cellPositionsTool.readoutName = ecalBarrelReadoutName + # ApplicationMgr from Configurables import ApplicationMgr diff --git a/FCCSW_ecal/noise_map_theta.py b/FCCSW_ecal/noise_map_theta.py new file mode 100644 index 0000000..1540283 --- /dev/null +++ b/FCCSW_ecal/noise_map_theta.py @@ -0,0 +1,77 @@ +from Gaudi.Configuration import * +# Detector geometry +from Configurables import GeoSvc +geoservice = GeoSvc("GeoSvc") +# if FCC_DETECTORS is empty, this should use relative path to working directory +import os +path_to_detector = os.environ.get("FCCDETECTORS", "") +print(path_to_detector) +detectors_to_use=[ + 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster_thetamodulemerged.xml' + ] +# prefix all xmls with path_to_detector +geoservice.detectors = [os.path.join(path_to_detector, _det) for _det in detectors_to_use] +geoservice.OutputLevel = INFO + +ecalBarrelReadoutName = "ECalBarrelModuleThetaMerged" +#hcalBarrelReadoutName = "ECalBarrelPhiEta" +hcalBarrelReadoutName = "HCalBarrelReadout" +BarrelNoisePath = os.environ['FCCBASEDIR']+"/LAr_scripts/data/elecNoise_ecalBarrelFCCee_theta.root" +ecalBarrelNoiseHistName = "h_elecNoise_fcc_" + +from Configurables import CellPositionsECalBarrelTool +ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel", + readoutName = ecalBarrelReadoutName +) +# OutputLevel = DEBUG) +#print(ECalBcells) + +from Configurables import CreateFCCeeCaloNoiseLevelMap, ReadNoiseFromFileTool +ECalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolECal", + useSegmentation = False, + cellPositionsTool = ECalBcells, + readoutName = ecalBarrelReadoutName, + noiseFileName = BarrelNoisePath, + elecNoiseHistoName = ecalBarrelNoiseHistName, + setNoiseOffset = False, + activeFieldName = "layer", + addPileup = False, + numRadialLayers = 12, + scaleFactor = 1/1000., #MeV to GeV + OutputLevel=DEBUG) + +HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", + useSegmentation = True, + readoutName = hcalBarrelReadoutName, + noiseFileName = BarrelNoisePath, + elecNoiseHistoName = ecalBarrelNoiseHistName, + setNoiseOffset = False, + activeFieldName = "layer", + addPileup = False, + numRadialLayers = 12, + scaleFactor = 1/1000., #MeV to GeV + OutputLevel=DEBUG) + +noisePerCell = CreateFCCeeCaloNoiseLevelMap("noisePerCell", + ECalBarrelNoiseTool = ECalNoiseTool, + ecalBarrelSysId = 4, + HCalBarrelNoiseTool = HCalNoiseTool, + readoutNamesModuleTheta=[ecalBarrelReadoutName], + systemNamesModuleTheta=["system"], + systemValuesModuleTheta=[4], + activeFieldNamesModuleTheta=["layer"], + activeVolumesNumbers = [12], + #activeVolumesEta = [1.2524, 1.2234, 1.1956, 1.1561, 1.1189, 1.0839, 1.0509, 0.9999, 0.9534, 0.91072], + readoutNamesVolumes=[], + outputFileName="cellNoise_map_electronicsNoiseLevel_thetamodulemerged.root", + OutputLevel=DEBUG) + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( TopAlg = [], + EvtSel = 'NONE', + EvtMax = 1, + # order is important, as GeoSvc is needed by G4SimSvc + ExtSvc = [geoservice, noisePerCell], + OutputLevel=INFO +) From 869e38dba0b411921b2ff67635cfae430b67ae1a Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 17:37:17 +0200 Subject: [PATCH 10/33] update gaudi steering file for thetamodule merged readout --- FCCSW_ecal/run_thetamodulemerged.py | 554 ++++++++++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 FCCSW_ecal/run_thetamodulemerged.py diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py new file mode 100644 index 0000000..74968ab --- /dev/null +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -0,0 +1,554 @@ +import os +import copy + +from GaudiKernel.SystemOfUnits import MeV, GeV, tesla + +use_pythia = False +addNoise = False + +# Input for simulations (momentum is expected in GeV!) +# Parameters for the particle gun simulations, dummy if use_pythia is set +# to True +# theta from 80 to 100 degrees corresponds to -0.17 < eta < 0.17 +# reminder: cell granularity in theta = 0.5625 degrees +# (in strips: 0.5625/4=0.14) + +momentum = 100 # in GeV +_pi = 3.14159 +#thetaMin = 40 # degrees +#thetaMax = 140 # degrees +thetaMin = 90 # degrees +thetaMax = 90 # degrees +phiMin = _pi/2. +phiMax = _pi/2. +#phiMin = _pi/2. - _pi*8/1545. +#phiMax = _pi/2. + _pi*8/1545. +#phiMin = 0 +#phiMax = 2 * _pi + +# particle type: 11 electron, 13 muon, 22 photon, 111 pi0, 211 pi+ +pdgCode = 11 +#pdgCode = 22 +#pdgCode = 111 + +magneticField = False + +from Gaudi.Configuration import * + +from Configurables import FCCDataSvc +podioevent = FCCDataSvc("EventDataSvc") + +################## Particle gun setup + +from Configurables import GenAlg +genAlg = GenAlg() +if use_pythia: + from Configurables import PythiaInterface + pythia8gentool = PythiaInterface() + pythia8gentool.pythiacard = os.path.join( + os.environ.get('PWD', ''), + "MCGeneration/ee_Zgamma_inclusive.cmd" + ) + #pythia8gentool.pythiacard = "MCGeneration/ee_Z_ee.cmd" + pythia8gentool.printPythiaStatistics = False + pythia8gentool.pythiaExtraSettings = [""] + genAlg.SignalProvider = pythia8gentool + # to smear the primary vertex position: + #from Configurables import GaussSmearVertex + #smeartool = GaussSmearVertex() + #smeartool.xVertexSigma = 0.5*units.mm + #smeartool.yVertexSigma = 0.5*units.mm + #smeartool.zVertexSigma = 40.0*units.mm + #smeartool.tVertexSigma = 180.0*units.picosecond + #genAlg.VertexSmearingTool = smeartool +else: + from Configurables import MomentumRangeParticleGun + pgun = MomentumRangeParticleGun("ParticleGun") + pgun.PdgCodes = [pdgCode] + pgun.MomentumMin = momentum * GeV + pgun.MomentumMax = momentum * GeV + pgun.PhiMin = phiMin + pgun.PhiMax = phiMax + pgun.ThetaMin = thetaMin * _pi / 180. + pgun.ThetaMax = thetaMax * _pi / 180. + genAlg.SignalProvider = pgun + +genAlg.hepmc.Path = "hepmc" + +from Configurables import HepMCToEDMConverter +hepmc_converter = HepMCToEDMConverter() +hepmc_converter.hepmc.Path="hepmc" +genParticlesOutputName = "genParticles" +hepmc_converter.GenParticles.Path = genParticlesOutputName +hepmc_converter.hepmcStatusList = [] +hepmc_converter.OutputLevel = INFO + +################## Simulation setup +# Detector geometry +from Configurables import GeoSvc +geoservice = GeoSvc("GeoSvc") +# if FCC_DETECTORS is empty, this should use relative path to working directory +path_to_detector = os.environ.get("FCCDETECTORS", "") +print(path_to_detector) +detectors_to_use=[ + 'Detector/DetFCCeeIDEA-LAr/compact/FCCee_DectMaster_thetamodulemerged.xml', +] +# prefix all xmls with path_to_detector +geoservice.detectors = [ + os.path.join(path_to_detector, _det) for _det in detectors_to_use +] +geoservice.OutputLevel = INFO + +# Geant4 service +# Configures the Geant simulation: geometry, physics list and user actions + +from Configurables import ( + SimG4FullSimActions, SimG4Alg, + SimG4PrimariesFromEdmTool, SimG4SaveParticleHistory +) +actions = SimG4FullSimActions() +# Uncomment if history from Geant4 decays is needed (e.g. to get the photons +# from pi0) and set actions=actions in SimG4Svc + uncomment saveHistTool +# in SimG4Alg +actions.enableHistory=True +actions.energyCut = 1.0 * GeV +saveHistTool = SimG4SaveParticleHistory("saveHistory") + +from Configurables import SimG4Svc +geantservice = SimG4Svc( + "SimG4Svc", + detector='SimG4DD4hepDetector', + physicslist="SimG4FtfpBert", + actions=actions +) + +# from Configurables import GeoToGdmlDumpSvc +# gdmldumpservice = GeoToGdmlDumpSvc("GeoToGdmlDumpSvc") + +# Fixed seed to have reproducible results, change it for each job if you +# split one production into several jobs +# Mind that if you leave Gaudi handle random seed and some job start within +# the same second (very likely) you will have duplicates +geantservice.randomNumbersFromGaudi = False +geantservice.seedValue = 4242 + +# Range cut +geantservice.g4PreInitCommands += ["/run/setCut 0.1 mm"] + +# Magnetic field +from Configurables import SimG4ConstantMagneticFieldTool +if magneticField == 1: + field = SimG4ConstantMagneticFieldTool( + "SimG4ConstantMagneticFieldTool", + FieldComponentZ=-2*tesla, + FieldOn=True, + IntegratorStepper="ClassicalRK4" + ) +else: + field = SimG4ConstantMagneticFieldTool( + "SimG4ConstantMagneticFieldTool", + FieldOn=False + ) + +# Geant4 algorithm +# Translates EDM to G4Event, passes the event to G4, writes out outputs +# via tools and a tool that saves the calorimeter hits + +# Detector readouts +# ECAL +ecalBarrelReadoutName = "ECalBarrelModuleThetaMerged" +ecalBarrelReadoutName2 = "ECalBarrelModuleThetaMerged2" +ecalEndcapReadoutName = "ECalEndcapPhiEta" +# HCAL +hcalBarrelReadoutName = "HCalBarrelReadout" +hcalEndcapReadoutName = "HCalEndcapReadout" + +# Configure saving of calorimeter hits +ecalBarrelHitsName = "ECalBarrelPositionedHits" +from Configurables import SimG4SaveCalHits +saveECalBarrelTool = SimG4SaveCalHits( + "saveECalBarrelHits", + readoutNames = [ecalBarrelReadoutName], + OutputLevel = INFO +) +saveECalBarrelTool.CaloHits.Path = ecalBarrelHitsName + +saveECalEndcapTool = SimG4SaveCalHits( + "saveECalEndcapHits", + readoutNames = [ecalEndcapReadoutName] +) +saveECalEndcapTool.CaloHits.Path = "ECalEndcapHits" + +saveHCalTool = SimG4SaveCalHits( + "saveHCalBarrelHits", + readoutNames = [hcalBarrelReadoutName] +) +saveHCalTool.CaloHits.Path = "HCalBarrelPositionedHits" + +#saveHCalEndcapTool = SimG4SaveCalHits("saveHCalEndcapHits", readoutNames = [hcalEndcapReadoutName]) +#saveHCalEndcapTool.CaloHits.Path = "HCalEndcapHits" + +# next, create the G4 algorithm, giving the list of names of tools ("XX/YY") +from Configurables import SimG4PrimariesFromEdmTool +particle_converter = SimG4PrimariesFromEdmTool("EdmConverter") +particle_converter.GenParticles.Path = genParticlesOutputName + +from Configurables import SimG4Alg +geantsim = SimG4Alg("SimG4Alg", + outputs= [ + saveECalBarrelTool, + saveHCalTool, + saveECalEndcapTool, + #saveHCalEndcapTool + saveHistTool + ], + eventProvider=particle_converter, + OutputLevel=INFO) + +############## Digitization (Merging hits into cells, EM scale calibration) +# EM scale calibration (sampling fraction) +from Configurables import CalibrateInLayersTool +calibEcalBarrel = CalibrateInLayersTool("CalibrateECalBarrel", + samplingFraction = [0.3632447480841956] * 1 + [0.13187261040190248] * 1 + [0.14349714292943705] * 1 + [0.150266118277841] * 1 + [0.15502683375826457] * 1 + [0.15954408786354762] * 1 + [0.16375302347299436] * 1 + [0.16840384714588075] * 1 + [0.17219540619311383] * 1 + [0.1755068643940401] * 1 + [0.17816980262822366] * 1 + [0.18131266048670405] * 1, + readoutName = ecalBarrelReadoutName, + layerFieldName = "layer") + +from Configurables import CalibrateCaloHitsTool +calibHcells = CalibrateCaloHitsTool("CalibrateHCal", invSamplingFraction="31.4") +calibEcalEndcap = CalibrateCaloHitsTool("CalibrateECalEndcap", invSamplingFraction="4.27") +calibHcalEndcap = CalibrateCaloHitsTool("CalibrateHCalEndcap", invSamplingFraction="31.7") + +# Create cells in ECal barrel +# 1. step - merge hits into cells with theta and module segmentation +# (module is a 'physical' cell i.e. lead + LAr + PCB + LAr +lead) +# 2. step - rewrite the cellId using the merged theta-module segmentation +# (merging several modules and severla theta readout cells). +# Add noise at this step if you derived the noise already assuming merged cells + +# Step 1: merge hits into cells according to initial segmentation +from Configurables import CreateCaloCells +EcalBarrelCellsName = "ECalBarrelCells" +createEcalBarrelCells = CreateCaloCells("CreateECalBarrelCells", + doCellCalibration=True, + calibTool = calibEcalBarrel, + addCellNoise=False, + filterCellNoise=False, + addPosition=True, + OutputLevel=INFO, + hits=ecalBarrelHitsName, + cells=EcalBarrelCellsName) + +# Step 2a: compute new cellID of cells based on new readout +# (merged module-theta segmentation with variable merging vs layer) +from Configurables import RedoSegmentation +resegmentEcalBarrel = RedoSegmentation("ReSegmentationEcal", + # old bitfield (readout) + oldReadoutName = ecalBarrelReadoutName, + # specify which fields are going to be altered (deleted/rewritten) + oldSegmentationIds = ["module", "theta"], + # new bitfield (readout), with new segmentation (merged modules and theta cells) + newReadoutName = ecalBarrelReadoutName2, + OutputLevel = INFO, + debugPrint = 200, + inhits = EcalBarrelCellsName, + outhits = "ECalBarrelCellsMerged") + +# Step 2b: merge new cells with same cellID together +# do not apply cell calibration again since cells were already +# calibrated in Step 1 +EcalBarrelCellsName2 = "ECalBarrelCells2" +createEcalBarrelCells2 = CreateCaloCells("CreateECalBarrelCells2", + doCellCalibration=False, + addCellNoise=False, + filterCellNoise=False, + OutputLevel=INFO, + hits="ECalBarrelCellsMerged", + cells=EcalBarrelCellsName2) + +# Add to Ecal barrel cells the position information +# (good for physics, all coordinates set properly) +from Configurables import CellPositionsECalBarrelTool +from Configurables import CreateCaloCellPositionsFCCee + +cellPositionEcalBarrelTool = CellPositionsECalBarrelTool( + "CellPositionsECalBarrel", + readoutName = ecalBarrelReadoutName, + OutputLevel = INFO +) +createEcalBarrelPositionedCells = CreateCaloCellPositionsFCCee( + "ECalBarrelPositionedCells", + OutputLevel = INFO +) +createEcalBarrelPositionedCells.positionsECalBarrelTool = cellPositionEcalBarrelTool +createEcalBarrelPositionedCells.hits.Path = EcalBarrelCellsName +createEcalBarrelPositionedCells.positionedHits.Path = "ECalBarrelPositionedCells" + +cellPositionEcalBarrelTool2= CellPositionsECalBarrelTool( + "CellPositionsECalBarrel2", + readoutName = ecalBarrelReadoutName2, + OutputLevel = INFO +) +createEcalBarrelPositionedCells2 = CreateCaloCellPositionsFCCee( + "ECalBarrelPositionedCells2", + OutputLevel = INFO +) +createEcalBarrelPositionedCells2.positionsECalBarrelTool = cellPositionEcalBarrelTool2 +createEcalBarrelPositionedCells2.hits.Path = EcalBarrelCellsName2 +createEcalBarrelPositionedCells2.positionedHits.Path = "ECalBarrelPositionedCells2" + +# Create cells in HCal +# 1. step - merge hits into cells with the default readout +createHcalBarrelCells = CreateCaloCells("CreateHCaloCells", + doCellCalibration=True, + calibTool=calibHcells, + addCellNoise = False, + filterCellNoise = False, + OutputLevel = INFO, + hits="HCalBarrelHits", + cells="HCalBarrelCells") + +# Create cells in ECal endcap +createEcalEndcapCells = CreateCaloCells("CreateEcalEndcapCaloCells", + doCellCalibration=True, + calibTool=calibEcalEndcap, + addCellNoise=False, + filterCellNoise=False, + OutputLevel=INFO) +createEcalEndcapCells.hits.Path="ECalEndcapHits" +createEcalEndcapCells.cells.Path="ECalEndcapCells" + +#createHcalEndcapCells = CreateCaloCells("CreateHcalEndcapCaloCells", +# doCellCalibration=True, +# calibTool=calibHcalEndcap, +# addCellNoise=False, +# filterCellNoise=False, +# OutputLevel=INFO) +#createHcalEndcapCells.hits.Path="HCalEndcapHits" +#createHcalEndcapCells.cells.Path="HCalEndcapCells" + + +#Empty cells for parts of calorimeter not implemented yet +from Configurables import CreateEmptyCaloCellsCollection +createemptycells = CreateEmptyCaloCellsCollection("CreateEmptyCaloCells") +createemptycells.cells.Path = "emptyCaloCells" + +# Produce sliding window clusters +from Configurables import CaloTowerTool +towers = CaloTowerTool("towers", + deltaEtaTower = 0.01, deltaPhiTower = 2*_pi/768., + radiusForPosition = 2160 + 40 / 2.0, + ## ecalBarrelReadoutName = ecalBarrelReadoutNamePhiEta, + ecalBarrelReadoutName = ecalBarrelReadoutName, + ecalEndcapReadoutName = ecalEndcapReadoutName, + ecalFwdReadoutName = "", + hcalBarrelReadoutName = hcalBarrelReadoutName, + hcalExtBarrelReadoutName = "", + hcalEndcapReadoutName = "", + hcalFwdReadoutName = "", + OutputLevel = INFO) +towers.ecalBarrelCells.Path = EcalBarrelCellsName +towers.ecalEndcapCells.Path = "ECalEndcapCells" +towers.ecalFwdCells.Path = "emptyCaloCells" +towers.hcalBarrelCells.Path = "emptyCaloCells" +towers.hcalExtBarrelCells.Path = "emptyCaloCells" +towers.hcalEndcapCells.Path = "emptyCaloCells" +towers.hcalFwdCells.Path = "emptyCaloCells" + +# Cluster variables +windE = 9 +windP = 17 +posE = 5 +posP = 11 +dupE = 7 +dupP = 13 +finE = 9 +finP = 17 +# Minimal energy to create a cluster in GeV (FCC-ee detectors have to reconstruct low energy particles) +threshold = 0.040 + +from Configurables import CreateCaloClustersSlidingWindow +createClusters = CreateCaloClustersSlidingWindow("CreateClusters", + towerTool = towers, + nEtaWindow = windE, nPhiWindow = windP, + nEtaPosition = posE, nPhiPosition = posP, + nEtaDuplicates = dupE, nPhiDuplicates = dupP, + nEtaFinal = finE, nPhiFinal = finP, + energyThreshold = threshold, + energySharingCorrection = False, + attachCells = True, + OutputLevel = INFO + ) +createClusters.clusters.Path = "CaloClusters" +createClusters.clusterCells.Path = "CaloClusterCells" + +createEcalBarrelPositionedCaloClusterCells = CreateCaloCellPositionsFCCee( + "ECalBarrelPositionedCaloClusterCells", + OutputLevel = INFO +) +createEcalBarrelPositionedCaloClusterCells.positionsECalBarrelTool = cellPositionEcalBarrelTool +createEcalBarrelPositionedCaloClusterCells.hits.Path = "CaloClusterCells" +createEcalBarrelPositionedCaloClusterCells.positionedHits.Path = "PositionedCaloClusterCells" + +from Configurables import CorrectCaloClusters +correctCaloClusters = CorrectCaloClusters("correctCaloClusters", + inClusters = createClusters.clusters.Path, + outClusters = "Corrected"+createClusters.clusters.Path, + numLayers = [12], + firstLayerIDs = [0], + lastLayerIDs = [11], + ## readoutNames = [ecalBarrelReadoutNamePhiEta], + readoutNames = [ecalBarrelReadoutName], + upstreamParameters = [[0.033955208567442975, -3.818122686176795, -146.59497297249345, 0.563447903447204, -3.7906629536351906, -8.569962044554627]], + upstreamFormulas = [['[0]+[1]/(x-[2])', '[0]+[1]/(x-[2])']], + downstreamParameters = [[-0.00357017357914002, 0.006624434345822984, 1.0065650241358008, -1.285181650875406, -0.0707783194915608, 12.907319280196257]], + downstreamFormulas = [['[0]+[1]*x', '[0]+[1]/sqrt(x)', '[0]+[1]/x']], + OutputLevel = INFO + ) + +# TOPO CLUSTERS PRODUCTION +from Configurables import ( + CaloTopoClusterInputTool, CaloTopoClusterFCCee, + TopoCaloNeighbours, TopoCaloNoisyCells +) +createTopoInput = CaloTopoClusterInputTool("CreateTopoInput", + ecalBarrelReadoutName = ecalBarrelReadoutName, + #ecalBarrelReadoutName = ecalBarrelReadoutName2, + ecalEndcapReadoutName = "", + ecalFwdReadoutName = "", + hcalBarrelReadoutName = "", + hcalExtBarrelReadoutName = "", + hcalEndcapReadoutName = "", + hcalFwdReadoutName = "", + OutputLevel = INFO) + +createTopoInput.ecalBarrelCells.Path = "ECalBarrelPositionedCells" +#createTopoInput.ecalBarrelCells.Path = "ECalBarrelPositionedCells2" +createTopoInput.ecalEndcapCells.Path = "emptyCaloCells" +createTopoInput.ecalFwdCells.Path = "emptyCaloCells" +createTopoInput.hcalBarrelCells.Path = "emptyCaloCells" +createTopoInput.hcalExtBarrelCells.Path = "emptyCaloCells" +createTopoInput.hcalEndcapCells.Path = "emptyCaloCells" +createTopoInput.hcalFwdCells.Path = "emptyCaloCells" + +readNeighboursMap = TopoCaloNeighbours("ReadNeighboursMap", + fileName = os.environ['FCCBASEDIR']+"/LAr_scripts/data/neighbours_map_barrel_thetamodulemerged.root", + OutputLevel = INFO) + +#Noise levels per cell +readNoisyCellsMap = TopoCaloNoisyCells("ReadNoisyCellsMap", + fileName = os.environ['FCCBASEDIR']+"/LAr_scripts/data/cellNoise_map_electronicsNoiseLevel_thetamodulemerged.root", + OutputLevel = INFO) + +createTopoClusters = CaloTopoClusterFCCee("CreateTopoClusters", + TopoClusterInput = createTopoInput, + #expects neighbours map from cellid->vec < neighbourIds > + neigboursTool = readNeighboursMap, + #tool to get noise level per cellid + noiseTool = readNoisyCellsMap, + #cell positions tools for all sub - systems + positionsECalBarrelTool = cellPositionEcalBarrelTool, + #positionsECalBarrelTool = cellPositionEcalBarrelTool2, + #positionsHCalBarrelTool = HCalBcells, + #positionsHCalExtBarrelTool = HCalExtBcells, + #positionsEMECTool = EMECcells, + #positionsHECTool = HECcells, + #positionsEMFwdTool = ECalFwdcells, + #positionsHFwdTool = HCalFwdcells, + seedSigma = 4, + neighbourSigma = 2, + lastNeighbourSigma = 0, + OutputLevel = INFO) +createTopoClusters.clusters.Path ="CaloTopoClusters" +createTopoClusters.clusterCells.Path = "CaloTopoClusterCells" + +createEcalBarrelPositionedCaloTopoClusterCells = CreateCaloCellPositionsFCCee( + "ECalBarrelPositionedCaloTopoClusterCells", + OutputLevel = INFO +) +#createEcalBarrelPositionedCaloTopoClusterCells.positionsECalBarrelTool = cellPositionEcalBarrelTool2 +createEcalBarrelPositionedCaloTopoClusterCells.positionsECalBarrelTool = cellPositionEcalBarrelTool +createEcalBarrelPositionedCaloTopoClusterCells.hits.Path = "CaloTopoClusterCells" +createEcalBarrelPositionedCaloTopoClusterCells.positionedHits.Path = "PositionedCaloTopoClusterCells" + +correctCaloTopoClusters = CorrectCaloClusters( + "correctCaloTopoClusters", + inClusters = createTopoClusters.clusters.Path, + outClusters = "Corrected"+createTopoClusters.clusters.Path, + numLayers = [12], + firstLayerIDs = [0], + lastLayerIDs = [11], + ## readoutNames = [ecalBarrelReadoutNamePhiEta], + readoutNames = [ecalBarrelReadoutName], + upstreamParameters = [[0.033955208567442975, -3.818122686176795, -146.59497297249345, 0.563447903447204, -3.7906629536351906, -8.569962044554627]], + upstreamFormulas = [['[0]+[1]/(x-[2])', '[0]+[1]/(x-[2])']], + downstreamParameters = [[-0.00357017357914002, 0.006624434345822984, 1.0065650241358008, -1.285181650875406, -0.0707783194915608, 12.907319280196257]], + downstreamFormulas = [['[0]+[1]*x', '[0]+[1]/sqrt(x)', '[0]+[1]/x']], + OutputLevel = INFO +) + +################ Output +from Configurables import PodioOutput +out = PodioOutput("out", + OutputLevel=INFO) + +#out.outputCommands = ["keep *"] +#out.outputCommands = ["keep *", "drop ECalBarrelHits", "drop HCal*", "drop ECalBarrelCellsStep*", "drop ECalBarrelPositionedHits", "drop emptyCaloCells", "drop CaloClusterCells"] +#out.outputCommands = ["keep *", "drop ECalBarrelHits", "drop HCal*", "drop ECalBarrelCellsStep*", "drop ECalBarrelPositionedHits", "drop emptyCaloCells", "drop CaloClusterCells", "drop %s"%EcalBarrelCellsName, "drop %s"%createEcalBarrelPositionedCells.positionedHits.Path] +#out.outputCommands = ["keep *", "drop ECalBarrelHits", "drop HCal*", "drop *ells*", "drop ECalBarrelPositionedHits", "drop emptyCaloCells"] +#out.outputCommands = ["keep *", "drop HCal*", "drop ECalBarrel*", "drop emptyCaloCells"] +out.outputCommands = ["keep *", "drop HCal*", "drop emptyCaloCells"] + +#Nevts = 1 +Nevts = 50 +import uuid +# out.filename = "root/output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_"+str(magneticField)+"_pMin_"+str(momentum*1000)+"_MeV"+"_ThetaMinMax_"+str(thetaMin)+"_"+str(thetaMax)+"_pdgId_"+str(pdgCode)+"_pythia"+str(use_pythia)+"_Noise"+str(addNoise)+".root" +out.filename = "./root_merge/output_evts_"+str(Nevts)+"_pdg_"+str(pdgCode)+"_"+str(momentum)+"_GeV"+"_ThetaMinMax_"+str(thetaMin)+"_"+str(thetaMax)+"_PhiMinMax_"+str(phiMin)+"_"+str(phiMax)+"_MagneticField_"+str(magneticField)+"_Noise"+str(addNoise)+".root" + +#CPU information +from Configurables import AuditorSvc, ChronoAuditor +chra = ChronoAuditor() +audsvc = AuditorSvc() +audsvc.Auditors = [chra] +genAlg.AuditExecute = True +hepmc_converter.AuditExecute = True +geantsim.AuditExecute = True +createEcalBarrelCells.AuditExecute = True +#createHcalBarrelCells.AuditExecute = True +createEcalBarrelPositionedCells.AuditExecute = True +createTopoClusters.AuditExecute = True +out.AuditExecute = True + +from Configurables import EventCounter +event_counter = EventCounter('event_counter') +event_counter.Frequency = 10 + +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg = [ + event_counter, + genAlg, + hepmc_converter, + geantsim, + createEcalBarrelCells, + createEcalBarrelPositionedCells, + resegmentEcalBarrel, + createEcalBarrelCells2, + createEcalBarrelPositionedCells2, + createEcalEndcapCells, + ## createHcalBarrelCells, + ## createHcalEndcapCells, + createemptycells, + ## createClusters, + ## createEcalBarrelPositionedCaloClusterCells, + ## correctCaloClusters, + createTopoClusters, + createEcalBarrelPositionedCaloTopoClusterCells, + correctCaloTopoClusters, + out + ], + EvtSel = 'NONE', + EvtMax = Nevts, + ExtSvc = [geoservice, podioevent, geantservice, audsvc], +# ExtSvc = [geoservice, podioevent, geantservice, gdmldumpservice, audsvc], + StopOnSignal = True, + ) From 6cdf856c5346faf46c6825ee6619a2bf1d5fdeb5 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 17:47:33 +0200 Subject: [PATCH 11/33] add little script to print neighbours --- FCCSW_ecal/printNeighbours.C | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 FCCSW_ecal/printNeighbours.C diff --git a/FCCSW_ecal/printNeighbours.C b/FCCSW_ecal/printNeighbours.C new file mode 100644 index 0000000..0023e22 --- /dev/null +++ b/FCCSW_ecal/printNeighbours.C @@ -0,0 +1,75 @@ +TTree* T = nullptr; +const std::string filename = "neighbours_map_barrel_thetamodulemerged.root"; +const std::string treename = "neighbours"; +ULong64_t cID; +std::vector *neighbours=0; + +// HELPER FUNCTIONS + +// extract layer number from cellID +ULong_t Layer(ULong_t cellID) { + const ULong_t mask = (1<<8) -1; + return (cellID >> 11) & mask; +} + +// extract module number from cellID +ULong_t Module(ULong_t cellID) { + const ULong_t mask = (1<<11) -1; + return (cellID >> 19) & mask; +} + +// extract theta bin from cellID +ULong_t ThetaBin(ULong_t cellID) { + const ULong_t mask = (1<<10) -1; + return (cellID >> 30) & mask; +} + +void printCell(ULong_t cellID) { + cout << "cellID: " << cellID << endl; + cout << "Layer: " << Layer(cellID) << endl; + cout << "Theta bin: " << ThetaBin(cellID) << endl; + cout << "Module: " << Module(cellID) << endl; + cout << endl; +} + +void LoadNeighboursMap() { + if (T==nullptr) { + TFile* f = TFile::Open(filename.c_str(),"READ"); + T = (TTree*) f->Get(treename.c_str()); + T->SetBranchAddress("cellId", &cID); + T->SetBranchAddress("neighbours", &neighbours); + } +} + +void printCellAndNeighbours(ULong64_t iEntry) { + T->GetEntry(iEntry); + cout << "=================================================" << endl; + cout << endl; + printCell(cID); + cout << "Neighbours: " << endl << endl; + for (unsigned int i=0; isize(); i++) { + printCell(neighbours->at(i)); + } + cout << "=================================================" << endl; +} + +void printNeighboursOfCell(ULong_t cellID) { + LoadNeighboursMap(); + for (ULong64_t iEntry=0; iEntryGetEntries(); iEntry++) { + T->GetEntry(iEntry); + if (cID == cellID) { + printCellAndNeighbours(iEntry); + return; + } + } + cout << "CellID not found" << endl; +} + + +void printNeighbours(int n=10) { + LoadNeighboursMap(); + for (int i=0; iUniform(T->GetEntries()); + printCellAndNeighbours(entry); + } +} From fb7e66c1ea7fe3b5e77f8ad852c3928492112775 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 18:12:54 +0200 Subject: [PATCH 12/33] take into account changes to seg class --- FCCSW_ecal/run_thetamodulemerged.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py index 74968ab..2be5c2c 100644 --- a/FCCSW_ecal/run_thetamodulemerged.py +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -267,10 +267,10 @@ # Add to Ecal barrel cells the position information # (good for physics, all coordinates set properly) -from Configurables import CellPositionsECalBarrelTool +from Configurables import CellPositionsECalBarrelModuleThetaSegTool from Configurables import CreateCaloCellPositionsFCCee -cellPositionEcalBarrelTool = CellPositionsECalBarrelTool( +cellPositionEcalBarrelTool = CellPositionsECalBarrelModuleThetaSegTool( "CellPositionsECalBarrel", readoutName = ecalBarrelReadoutName, OutputLevel = INFO @@ -283,7 +283,7 @@ createEcalBarrelPositionedCells.hits.Path = EcalBarrelCellsName createEcalBarrelPositionedCells.positionedHits.Path = "ECalBarrelPositionedCells" -cellPositionEcalBarrelTool2= CellPositionsECalBarrelTool( +cellPositionEcalBarrelTool2= CellPositionsECalBarrelModuleThetaSegTool( "CellPositionsECalBarrel2", readoutName = ecalBarrelReadoutName2, OutputLevel = INFO From 90bf8bde4d1ae15f992e939bfe7bc0da98674123 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 23:24:41 +0200 Subject: [PATCH 13/33] use proper cell positioning class --- FCCSW_ecal/noise_map_theta.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/FCCSW_ecal/noise_map_theta.py b/FCCSW_ecal/noise_map_theta.py index 1540283..154cead 100644 --- a/FCCSW_ecal/noise_map_theta.py +++ b/FCCSW_ecal/noise_map_theta.py @@ -19,11 +19,10 @@ BarrelNoisePath = os.environ['FCCBASEDIR']+"/LAr_scripts/data/elecNoise_ecalBarrelFCCee_theta.root" ecalBarrelNoiseHistName = "h_elecNoise_fcc_" -from Configurables import CellPositionsECalBarrelTool -ECalBcells = CellPositionsECalBarrelTool("CellPositionsECalBarrel", - readoutName = ecalBarrelReadoutName -) -# OutputLevel = DEBUG) +from Configurables import CellPositionsECalBarrelModuleThetaSegTool +ECalBcells = CellPositionsECalBarrelModuleThetaSegTool("CellPositionsECalBarrel", + readoutName = ecalBarrelReadoutName) +# OutputLevel = DEBUG) #print(ECalBcells) from Configurables import CreateFCCeeCaloNoiseLevelMap, ReadNoiseFromFileTool @@ -38,7 +37,7 @@ addPileup = False, numRadialLayers = 12, scaleFactor = 1/1000., #MeV to GeV - OutputLevel=DEBUG) + OutputLevel = INFO) HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", useSegmentation = True, @@ -50,7 +49,7 @@ addPileup = False, numRadialLayers = 12, scaleFactor = 1/1000., #MeV to GeV - OutputLevel=DEBUG) + OutputLevel = INFO) noisePerCell = CreateFCCeeCaloNoiseLevelMap("noisePerCell", ECalBarrelNoiseTool = ECalNoiseTool, @@ -62,9 +61,9 @@ activeFieldNamesModuleTheta=["layer"], activeVolumesNumbers = [12], #activeVolumesEta = [1.2524, 1.2234, 1.1956, 1.1561, 1.1189, 1.0839, 1.0509, 0.9999, 0.9534, 0.91072], - readoutNamesVolumes=[], - outputFileName="cellNoise_map_electronicsNoiseLevel_thetamodulemerged.root", - OutputLevel=DEBUG) + readoutNamesVolumes = [], + outputFileName = "cellNoise_map_electronicsNoiseLevel_thetamodulemerged.root", + OutputLevel = DEBUG) # ApplicationMgr from Configurables import ApplicationMgr @@ -74,4 +73,4 @@ # order is important, as GeoSvc is needed by G4SimSvc ExtSvc = [geoservice, noisePerCell], OutputLevel=INFO -) + ) From 9b15e7da6fd3b0f9f0042e299f0f2676e9c540e9 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 27 Sep 2023 23:38:12 +0200 Subject: [PATCH 14/33] remove warnings --- FCCSW_ecal/run_thetamodulemerged.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py index 2be5c2c..d06f79d 100644 --- a/FCCSW_ecal/run_thetamodulemerged.py +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -168,24 +168,24 @@ from Configurables import SimG4SaveCalHits saveECalBarrelTool = SimG4SaveCalHits( "saveECalBarrelHits", - readoutNames = [ecalBarrelReadoutName], + readoutName = ecalBarrelReadoutName, OutputLevel = INFO ) saveECalBarrelTool.CaloHits.Path = ecalBarrelHitsName saveECalEndcapTool = SimG4SaveCalHits( "saveECalEndcapHits", - readoutNames = [ecalEndcapReadoutName] + readoutName = ecalEndcapReadoutName ) saveECalEndcapTool.CaloHits.Path = "ECalEndcapHits" saveHCalTool = SimG4SaveCalHits( "saveHCalBarrelHits", - readoutNames = [hcalBarrelReadoutName] + readoutName = hcalBarrelReadoutName ) saveHCalTool.CaloHits.Path = "HCalBarrelPositionedHits" -#saveHCalEndcapTool = SimG4SaveCalHits("saveHCalEndcapHits", readoutNames = [hcalEndcapReadoutName]) +#saveHCalEndcapTool = SimG4SaveCalHits("saveHCalEndcapHits", readoutName = hcalEndcapReadoutName) #saveHCalEndcapTool.CaloHits.Path = "HCalEndcapHits" # next, create the G4 algorithm, giving the list of names of tools ("XX/YY") @@ -498,8 +498,8 @@ #out.outputCommands = ["keep *", "drop HCal*", "drop ECalBarrel*", "drop emptyCaloCells"] out.outputCommands = ["keep *", "drop HCal*", "drop emptyCaloCells"] -#Nevts = 1 -Nevts = 50 +Nevts = 1 +#Nevts = 50 import uuid # out.filename = "root/output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_"+str(magneticField)+"_pMin_"+str(momentum*1000)+"_MeV"+"_ThetaMinMax_"+str(thetaMin)+"_"+str(thetaMax)+"_pdgId_"+str(pdgCode)+"_pythia"+str(use_pythia)+"_Noise"+str(addNoise)+".root" out.filename = "./root_merge/output_evts_"+str(Nevts)+"_pdg_"+str(pdgCode)+"_"+str(momentum)+"_GeV"+"_ThetaMinMax_"+str(thetaMin)+"_"+str(thetaMax)+"_PhiMinMax_"+str(phiMin)+"_"+str(phiMax)+"_MagneticField_"+str(magneticField)+"_Noise"+str(addNoise)+".root" From aaad22c4ba02643a40807077ca17117226b5f06c Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Thu, 28 Sep 2023 16:15:00 +0200 Subject: [PATCH 15/33] small fix to theta range --- geometry/create_capacitance_file_theta.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index 394802b..ee5d717 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -90,8 +90,8 @@ angle = inclination_degree / 180. * pi #inclination angle inn radian passiveThickness = 2.0 #mm #Segmentation -deltaTheta = 0.00981748 -minTheta = 0.589 +deltaTheta = 0.009817477 +minTheta = 0.58905 maxTheta = pi-minTheta numTheta = int(ceil((maxTheta-minTheta)/deltaTheta)) if verbose: From 90ad9e3dc197aa10f5d512d426553bea1002a14a Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Thu, 28 Sep 2023 16:15:15 +0200 Subject: [PATCH 16/33] remove a warning --- geometry/create_noise_file_chargePreAmp_theta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geometry/create_noise_file_chargePreAmp_theta.py b/geometry/create_noise_file_chargePreAmp_theta.py index 0214a84..8bb5381 100644 --- a/geometry/create_noise_file_chargePreAmp_theta.py +++ b/geometry/create_noise_file_chargePreAmp_theta.py @@ -41,7 +41,7 @@ def rescaleaxis(g, scale = 50e-12/1e-9): points_capa_noise = [(100, 4375), (500, 6750)] x_coords, y_coords = zip(*points_capa_noise) A = vstack([x_coords, ones(len(x_coords))]).T -m, c = lstsq(A, y_coords)[0] +m, c = lstsq(A, y_coords,rcond=-1)[0] #print("Line Solution is y = {m}x + {c}".format(m=m, c=c)) def get_noise_charge_rms(capacitance): return m * capacitance + c # number of electrons From ca65a619dc9b0776924d3a42447e50f3d60132a6 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Fri, 29 Sep 2023 09:06:40 +0200 Subject: [PATCH 17/33] improve event display --- FCCSW_ecal/displayV3.C | 233 +++++++++++++++++++++++------------------ 1 file changed, 131 insertions(+), 102 deletions(-) diff --git a/FCCSW_ecal/displayV3.C b/FCCSW_ecal/displayV3.C index daa9bd5..4fdddad 100644 --- a/FCCSW_ecal/displayV3.C +++ b/FCCSW_ecal/displayV3.C @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -91,13 +92,13 @@ std::string geomFile = "ECalBarrel.root"; //bool drawMergedCells = true; // 50 electrons 100 GeV -std::string evtFile = "output_evts_50_100_GeV_ThetaMinMax_40_140_PhiMinMax_0_6.28318.root"; +// std::string evtFile = "output_evts_50_100_GeV_ThetaMinMax_40_140_PhiMinMax_0_6.28318.root"; // 1 pi0 50 GeV // std::string evtFile = "output_evts_1_pdg_111_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; // 1 photon 50 GeV // std::string evtFile = "output_evts_1_pdg_22_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; // 1 pi0 10 GeV -// std::string evtFile = "output_evts_1_pdg_111_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +std::string evtFile = "output_evts_1_pdg_111_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; // 1 photon 10 GeV // std::string evtFile = "output_evts_1_pdg_22_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; @@ -105,7 +106,7 @@ const std::vector mergedCells_Theta = {4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; bool drawParticles = true; -bool drawMCtracks = false; // does not work +bool drawMCtracks = true; // does not work bool drawHits = true; bool drawCells = true; bool drawMergedCells = false; @@ -366,13 +367,15 @@ TGLViewer* rhoPhiGLView = nullptr; TGLViewer* rhoZGLView = nullptr; TEveScene* rhoPhiScene = nullptr; TEveScene* rhoPhiEventScene = nullptr; +TEveScene* rhoPhiEventSceneManual = nullptr; TEveScene* rhoZScene = nullptr; TEveScene* rhoZEventScene = nullptr; +TEveScene* rhoZEventSceneManual = nullptr; TEveProjectionManager* rhoPhiProjManager = nullptr; TEveProjectionManager* rhoZProjManager = nullptr; TGLConstAnnotation* eventLabel = nullptr; - +TGTextEntry *textEntry = nullptr; /******************************************************************************/ // CLASS TO READ AN EVENT FROM THE EVENT FILE @@ -404,7 +407,7 @@ class EventReader //TTreeReaderArray *SimParticleSecondaries_generatorStatus = nullptr; //TTreeReaderArray *SimParticleSecondaries_simulatorStatus = nullptr; //TTreeReaderArray *SimParticleSecondaries_charge = nullptr; - //TTreeReaderArray *SimParticleSecondaries_time = nullptr; + TTreeReaderArray *SimParticleSecondaries_time = nullptr; TTreeReaderArray *SimParticleSecondaries_mass = nullptr; TTreeReaderArray *SimParticleSecondaries_vertex_x = nullptr; TTreeReaderArray *SimParticleSecondaries_vertex_y = nullptr; @@ -481,7 +484,7 @@ class EventReader //SimParticleSecondaries_generatorStatus = new TTreeReaderArray(*fReader, "SimParticleSecondaries.generatorStatus"); //SimParticleSecondaries_simulatorStatus = new TTreeReaderArray(*fReader, "SimParticleSecondaries.simulatorStatus"); //SimParticleSecondaries_charge = new TTreeReaderArray(*fReader, "SimParticleSecondaries.charge"); - //SimParticleSecondaries_time = new TTreeReaderArray(*fReader, "SimParticleSecondaries.time"); + SimParticleSecondaries_time = new TTreeReaderArray(*fReader, "SimParticleSecondaries.time"); SimParticleSecondaries_mass = new TTreeReaderArray(*fReader, "SimParticleSecondaries.mass"); SimParticleSecondaries_vertex_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.x"); SimParticleSecondaries_vertex_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.y"); @@ -556,7 +559,7 @@ class EventReader // delete SimParticleSecondaries_generatorStatus; // delete SimParticleSecondaries_simulatorStatus; // delete SimParticleSecondaries_charge; - // delete SimParticleSecondaries_time; + delete SimParticleSecondaries_time; delete SimParticleSecondaries_mass; delete SimParticleSecondaries_vertex_x; delete SimParticleSecondaries_vertex_y; @@ -598,9 +601,13 @@ class EventReader } void loadEvent(int event = -1) { - if (event != -1) - eventId = event; + + if (event != -1) eventId = event; + printf("Loading event %d.\n", eventId); + textEntry->SetTextColor(0xff0000); + textEntry->SetText(Form("Loading event %d...",eventId)); + fReader->SetEntry(eventId); TString partType; @@ -631,6 +638,7 @@ class EventReader // if (drawParticles) { cout << "Creating particles" << endl; + /* if (particles) { // I haven't found a way to just delete the lines of the set particles->Destroy(); @@ -642,13 +650,14 @@ class EventReader particles->SetLineWidth(3); gEve->AddElement(particles); } - + */ if (drawMCtracks) { if (particlesMC == nullptr) { particlesMC = new TEveTrackList("particlesMC"); TEveTrackPropagator* trkProp = particlesMC->GetPropagator(); - trkProp->SetMagField( 0.0 ); + trkProp->SetMagField( 0.01 ); particlesMC->SetMainColor(kYellow); + particlesMC->SetLineWidth(2); gEve->AddElement(particlesMC); } else @@ -728,7 +737,7 @@ class EventReader double y2 = y1 + py/p * rMax / sintheta; double z2 = z1 + pz/p * rMax / sintheta; double r2 = sqrt(x2*x2+y2*y2); - + /* particles->AddLine(x1,y1,z1, x2,y2,z2); particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", pdgID, @@ -736,7 +745,22 @@ class EventReader p, acos(pz/p), atan2(py,px))); + */ + if (drawMCtracks) { + TEveMCTrack mct; + mct.SetPdgCode( pdgID ); + mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); + mct.SetProductionVertex( x1, y1, z1, t ); + if (pdgID == 111) {mct.SetDaughter(0,1);mct.SetDaughter(1,2);} + TEveTrack* track = new TEveTrack(&mct, particlesMC->GetPropagator()); + track->SetAttLineAttMarker(particlesMC); + track->SetElementTitle(Form("p= %f\ntheta= %f\nphi = %f", + p, + acos(pz/p), + atan2(py,px))); + particlesMC->AddElement(track); + } } else { for (unsigned int i = 0; i < SimParticleSecondaries_PDG->GetSize(); i ++) { @@ -754,7 +778,7 @@ class EventReader if (pAddLine(x1,y1,z1, x2,y2,z2); particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", pdgID, @@ -779,8 +804,23 @@ class EventReader p, acos(pz/p), atan2(py,px))); + */ + if (drawMCtracks) { + TEveMCTrack mct; + mct.SetPdgCode( pdgID ); + mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); + mct.SetProductionVertex( x1, y1, z1, t ); + TEveTrack* track = new TEveTrack(&mct, particlesMC->GetPropagator()); + track->SetAttLineAttMarker(particlesMC); + track->SetElementTitle(Form("p= %f\ntheta= %f\nphi = %f", + p, + acos(pz/p), + atan2(py,px))); + particlesMC->AddElement(track); + } } } + if (drawMCtracks) particlesMC->MakeTracks(); } // @@ -923,8 +963,8 @@ class EventReader if (topoclusters_rhoz==nullptr) { topoclusters_rhoz = new TEveElementList(Form("Clusters in rho-z (E>%.1f GeV)",TopoClusterEnergyThreshold)); // add to scene or manager? - rhoZProjManager->AddElement(topoclusters_rhoz); - //rhoZEventScene->AddElement(topoclusters_rhoz); + // rhoZProjManager->AddElement(topoclusters_rhoz); + rhoZEventSceneManual->AddElement(topoclusters_rhoz); gEve->AddToListTree(topoclusters_rhoz,false); } else @@ -932,9 +972,9 @@ class EventReader if (topoclusters_rhophi==nullptr) { topoclusters_rhophi = new TEveElementList(Form("Clusters in rho-phi (E>%.1f GeV)",TopoClusterEnergyThreshold)); - // add to scene or manager? - rhoPhiProjManager->AddElement(topoclusters_rhophi); - //rhoPhiEventScene->AddElement(topoclusters_rhophi); + // add to scene or manager? -- scene that is not auto-projected! + // rhoPhiProjManager->AddElement(topoclusters_rhophi); + rhoPhiEventSceneManual->AddElement(topoclusters_rhophi); gEve->AddToListTree(topoclusters_rhophi,false); } else @@ -1130,6 +1170,10 @@ class EventReader } cout << "Done" << endl; + + textEntry->SetTextColor((Pixel_t)0x000000); + textEntry->SetText(Form("Event %d loaded", eventId)); + } }; @@ -1154,11 +1198,9 @@ void display(int evt = 0) { gStyle->SetPalette(kSienna); // first tab - //gEve->GetDefaultGLViewer()->SetCurrentCamera(TGLViewer::kCameraPerspYOZ); gEve->GetDefaultGLViewer()->SetGuideState(TGLUtil::kAxesOrigin, false, false, 0); gEve->GetDefaultGLViewer()->DrawGuides(); gEve->GetDefaultViewer()->SetElementName("3D view"); - //gEve->GetDefaultGLViewer()->GetClipSet()->SetClipType(TGLClip::EType(1)); gEve->GetDefaultGLViewer()->CurrentCamera().RotateRad(-.7, 0.5); // Create the geometry and the readout @@ -1180,11 +1222,9 @@ void display(int evt = 0) { barrel->SetPickableRecursively(kTRUE); geom->AddElement(barrel); TPRegexp re; - // hide bath as it slows down rendering a lot + // set transparency of the subvolumes of the bath re = TPRegexp("LAr_bath*"); TEveElement* bath = barrel->FindChild(re); - bath->SetRnrSelfChildren(false, false); - // set transparency of the subvolumes TEveElement::List_t matches; re = TPRegexp("ECAL_Cryo*"); barrel->FindChildren(matches, re); @@ -1193,7 +1233,6 @@ void display(int evt = 0) { barrel->FindChildren(matches, re); for (auto a : matches) a->SetMainTransparency(70); // make lists of elements inside bath to turn on/off simultaneously - // not the correct way to go, volumes then appear twice.. if (bath) { TEveElementList* newbath = new TEveElementList("LAr_bath"); barrel->AddElement(newbath); @@ -1213,6 +1252,8 @@ void display(int evt = 0) { for (auto a : matches3) passives->AddElement(a); newbath->AddElement(passives); barrel->RemoveElement(bath); + // hide elements inside bath by default because they are slow in 3D + newbath->SetRnrSelfChildren(true, false); } gEve->AddGlobalElement(geom); gEve->AddToListTree(geom, true); @@ -1266,28 +1307,19 @@ void display(int evt = 0) { rhoPhiView->AddScene(rhoPhiScene); rhoPhiEventScene = gEve->SpawnNewScene("RhoPhi Event Data", "Scene holding projected event-data for the RhoPhi view."); rhoPhiView->AddScene(rhoPhiEventScene); + rhoPhiEventSceneManual = gEve->SpawnNewScene("RhoPhi Event Data 2", "Scene holding hand-crafted event-data for the RhoPhi view."); + rhoPhiView->AddScene(rhoPhiEventSceneManual); rhoPhiGLView = rhoPhiView->GetGLViewer(); // set camera orientation rhoPhiGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); - // create 3D->2D projection manager for + // create 3D->2D projection manager for rho-phi rhoPhiProjManager = new TEveProjectionManager(); rhoPhiProjManager->SetProjection(TEveProjection::kPT_RPhi); - rhoPhiScene->AddElement(rhoPhiProjManager); auto axes = new TEveProjectionAxes(rhoPhiProjManager); axes->SetElementName("Rho-Phi projection axes"); rhoPhiScene->AddElement(axes); - //gEve->AddToListTree(axes, kTRUE); - //gEve->AddToListTree(rhoPhiProjManager, kTRUE); - if (useG4geom) { + if (useG4geom) rhoPhiProjManager->ImportElements(geom, rhoPhiScene); - // enable bath in 2D view - TEveElement* geomProj = rhoPhiProjManager->FindChild("Geometry [P]"); - TPRegexp re("ECalBarrel_*"); - TEveElement* barrelProj = geomProj->FindChild(re); - re = TPRegexp("LAr_bath*"); - TEveElement* bath = barrelProj->FindChild(re); - bath->SetRnrSelfChildren(false, true); - } else rhoPhiProjManager->ImportElements(barrel, rhoPhiScene); @@ -1308,8 +1340,7 @@ void display(int evt = 0) { gridmod->AddLine(x1, y1, 0., x2, y2, 0.); } } - // add to proj manager or to scene? - //rhoPhiProjManager->AddElement(gridmod); + // add to scene? rhoPhiScene->AddElement(gridmod); readout->AddElement(gridmod); @@ -1319,34 +1350,24 @@ void display(int evt = 0) { rhoZView->AddScene(rhoZScene); rhoZEventScene = gEve->SpawnNewScene("RhoZ Event Data", "Scene holding projected event-data for the RhoZ view."); rhoZView->AddScene(rhoZEventScene); + rhoZEventSceneManual = gEve->SpawnNewScene("RhoZ Event Data 2", "Scene holding hand-crafted event-data for the RhoZ view."); + rhoZView->AddScene(rhoZEventSceneManual); rhoZGLView = rhoZView->GetGLViewer(); rhoZGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); rhoZProjManager = new TEveProjectionManager(); rhoZProjManager->SetProjection(TEveProjection::kPT_RhoZ); - rhoZScene->AddElement(rhoZProjManager); auto axes2 = new TEveProjectionAxes(rhoZProjManager); axes2->SetElementName("Rho-Z projection axes"); rhoZScene->AddElement(axes2); - //gEve->AddToListTree(axes2, kTRUE); - //gEve->AddToListTree(rhoZProjManager, kTRUE); - if (useG4geom) { + if (useG4geom) rhoZProjManager->ImportElements(geom, rhoZScene); - // enable bath in 2D view - TEveElement* geomProj = rhoZProjManager->FindChild("Geometry [P]"); - TPRegexp re("ECalBarrel_*"); - TEveElement* barrelProj = geomProj->FindChild(re); - re = TPRegexp("LAr_bath*"); - TEveElement* bath = barrelProj->FindChild(re); - bath->SetRnrSelfChildren(false, true); - } else rhoZProjManager->ImportElements(barrel, rhoZScene); // the theta readout grid TEveStraightLineSet* grid = new TEveStraightLineSet("theta readout"); grid->SetLineColor(kViolet); - //grid->SetLineStyle(kDotted); for (int iTheta=0; iTheta<=nThetaBins; iTheta++) { double theta = thetaMin + iTheta*thetaGrid; double r1 = rMin; @@ -1366,7 +1387,6 @@ void display(int evt = 0) { grid->AddLine(z1, -r1, 0., z2, -r2, 0.); } } - //rhoZProjManager->AddElement(grid); rhoZScene->AddElement(grid); readout->AddElement(grid); @@ -1399,7 +1419,6 @@ void display(int evt = 0) { } } } - //rhoZProjManager->AddElement(grid2); rhoZScene->AddElement(grid2); readout->AddElement(grid2); @@ -1439,58 +1458,68 @@ void display(int evt = 0) { class EvNavHandler { public: - void Fwd() - { - if (eventId < nEvents - 1) { - ++eventId; - eventReader->loadEvent(); - } else { - printf("Already at last event.\n"); - } - } - void Bck() - { - if (eventId > 0) { - --eventId; - eventReader->loadEvent(); - } else { - printf("Already at first event.\n"); - } - } + void Fwd() + { + if (eventId < nEvents - 1) { + ++eventId; + eventReader->loadEvent(); + } else { + textEntry->SetTextColor(0xff0000); + textEntry->SetText("Already at last event"); + printf("Already at last event.\n"); + } + } + void Bck() + { + if (eventId > 0) { + --eventId; + eventReader->loadEvent(); + } else { + textEntry->SetTextColor(0xff0000); + textEntry->SetText("Already at first event"); + printf("Already at first event.\n"); + } + } }; void makeGui() { - // Create minimal GUI for event navigation. - - TEveBrowser* browser = gEve->GetBrowser(); - browser->StartEmbedding(TRootBrowser::kLeft); - - TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600); - frmMain->SetWindowName("GUI"); - frmMain->SetCleanup(kDeepCleanup); - - TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain); - { + // Create minimal GUI for event navigation. - TString icondir( Form("%s/icons/", gSystem->Getenv("ROOTSYS")) ); - TGPictureButton* b = 0; - EvNavHandler *fh = new EvNavHandler; + TEveBrowser* browser = gEve->GetBrowser(); + browser->StartEmbedding(TRootBrowser::kLeft); - b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoBack.gif")); - hf->AddFrame(b); - b->Connect("Clicked()", "EvNavHandler", fh, "Bck()"); - - b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoForward.gif")); - hf->AddFrame(b); - b->Connect("Clicked()", "EvNavHandler", fh, "Fwd()"); - } - frmMain->AddFrame(hf); - - frmMain->MapSubwindows(); - frmMain->Resize(); - frmMain->MapWindow(); - - browser->StopEmbedding(); - browser->SetTabTitle("Event Control", 0); + TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600); + frmMain->SetWindowName("GUI"); + frmMain->SetCleanup(kDeepCleanup); + + TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain); + { + + TString icondir( Form("%s/icons/", gSystem->Getenv("ROOTSYS")) ); + TGPictureButton* b = 0; + EvNavHandler *fh = new EvNavHandler; + + b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoBack.gif")); + hf->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 10, 2, 10, 10)); + b->Connect("Clicked()", "EvNavHandler", fh, "Bck()"); + + b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoForward.gif")); + hf->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 10, 10, 10)); + b->Connect("Clicked()", "EvNavHandler", fh, "Fwd()"); + + textEntry = new TGTextEntry(hf); + textEntry->SetEnabled(kFALSE); + hf->AddFrame(textEntry, new TGLayoutHints(kLHintsLeft | kLHintsCenterY | + kLHintsExpandX, 2, 10, 10, 10)); + + } + frmMain->AddFrame(hf); + + frmMain->MapSubwindows(); + frmMain->Resize(); + frmMain->MapWindow(); + + browser->StopEmbedding(); + browser->SetTabTitle("Event Control", 0); } From 7856ab31e7efb5fceeaf218c98454449a4fe514d Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Fri, 29 Sep 2023 15:52:25 +0200 Subject: [PATCH 18/33] update event display, add comments to the code --- FCCSW_ecal/displayV3.C | 301 +++++++----------- FCCSW_ecal/run_thetamodulemerged.py | 51 +-- .../create_noise_file_chargePreAmp_theta.py | 2 +- 3 files changed, 149 insertions(+), 205 deletions(-) diff --git a/FCCSW_ecal/displayV3.C b/FCCSW_ecal/displayV3.C index 4fdddad..14a45ba 100644 --- a/FCCSW_ecal/displayV3.C +++ b/FCCSW_ecal/displayV3.C @@ -93,20 +93,21 @@ std::string geomFile = "ECalBarrel.root"; // 50 electrons 100 GeV // std::string evtFile = "output_evts_50_100_GeV_ThetaMinMax_40_140_PhiMinMax_0_6.28318.root"; +// 1 electron 50 GeV +// std::string evtFile = "output_evts_1_pdg_11_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; // 1 pi0 50 GeV -// std::string evtFile = "output_evts_1_pdg_111_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +std::string evtFile = "output_evts_1_pdg_111_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; // 1 photon 50 GeV -// std::string evtFile = "output_evts_1_pdg_22_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +// std::string evtFile = "output_evts_1_pdg_22_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; // 1 pi0 10 GeV -std::string evtFile = "output_evts_1_pdg_111_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +// std::string evtFile = "output_evts_1_pdg_111_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; // 1 photon 10 GeV -// std::string evtFile = "output_evts_1_pdg_22_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795.root"; +// std::string evtFile = "output_evts_1_pdg_22_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; const std::vector mergedCells_Theta = {4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; bool drawParticles = true; -bool drawMCtracks = true; // does not work bool drawHits = true; bool drawCells = true; bool drawMergedCells = false; @@ -197,7 +198,8 @@ double _phi(double alpha, double r_in, double r_out) { // r=r_in, inclined in phi by alpha, and at distance L // from beginning of electrode double _r(double alpha, double r_in, double L) { - return sqrt((r_in+L*cos(alpha))*(r_in+L*cos(alpha))+(L*sin(alpha))*(L*sin(alpha))); + return sqrt( (r_in+L*cos(alpha)) * (r_in+L*cos(alpha)) + + (L*sin(alpha)) * (L*sin(alpha)) ); } // length of electrodes @@ -347,8 +349,7 @@ class TGLConstAnnotation : public TGLAnnotation Int_t eventId = 0; // Current event id Int_t nEvents = 0; // Number of events in file -TEveStraightLineSet* particles = nullptr; -TEveTrackList* particlesMC = nullptr; +TEveTrackList* particles = nullptr; TEvePointSet* hits = nullptr; TEvePointSet* cells = nullptr; TEvePointSet* cells_merged = nullptr; @@ -638,189 +639,107 @@ class EventReader // if (drawParticles) { cout << "Creating particles" << endl; - /* - if (particles) { - // I haven't found a way to just delete the lines of the set - particles->Destroy(); - particles = nullptr; - } if (particles == nullptr) { - particles = new TEveStraightLineSet("particles"); + particles = new TEveTrackList("particles"); + TEveTrackPropagator* trkProp = particles->GetPropagator(); + trkProp->SetMagField( 0.01 ); particles->SetMainColor(kYellow); - particles->SetLineWidth(3); + particles->SetLineWidth(2); gEve->AddElement(particles); } - */ - if (drawMCtracks) { - if (particlesMC == nullptr) { - particlesMC = new TEveTrackList("particlesMC"); - TEveTrackPropagator* trkProp = particlesMC->GetPropagator(); - trkProp->SetMagField( 0.01 ); - particlesMC->SetMainColor(kYellow); - particlesMC->SetLineWidth(2); - gEve->AddElement(particlesMC); - } - else - particlesMC->DestroyElements(); - } - - /* - int ipmax=-1; - for (unsigned int i = 0; i < genParticles_generatorStatus->GetSize(); i ++) { - if ( (*genParticles_generatorStatus)[i] != 1 ) continue; - float px = (*genParticles_momentum_x)[i]; - float py = (*genParticles_momentum_y)[i]; - float pz = (*genParticles_momentum_z)[i]; - float p = sqrt( px*px + py*py + pz*pz ); - //cout << p << endl; - if (p==0.) continue; - if (p>pmax) { - pmax = p; - ipmax = i; - } - - float m = (*genParticles_mass)[i]; - float px = (*genParticles_momentum_x)[i]; - float py = (*genParticles_momentum_y)[i]; - float pz = (*genParticles_momentum_z)[i]; - float m = (*genParticles_mass)[i]; - float p = sqrt( px*px + py*py + pz*pz ); - int pdgID = (*genParticles_PDG)[i]; - double t = (*genParticles_time)[i]; - double x1 = (*genParticles_vertex_x)[i] * mm; - double y1 = (*genParticles_vertex_y)[i] * mm; - double z1 = (*genParticles_vertex_z)[i] * mm; - double r1 = sqrt(x1*x1+y1*y1); - double sintheta = sqrt(px*px + py*py)/p; - double x2 = x1 + px/p * rMax / sintheta; - double y2 = y1 + py/p * rMax / sintheta; - double z2 = z1 + pz/p * rMax / sintheta; - double r2 = sqrt(x2*x2+y2*y2); - - particles->AddLine(x1,y1,z1, x2,y2,z2); - particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", - pdgID, - m, - p, - acos(pz/p), - atan2(py,px),)); - - if (drawMCtracks) { - TEveMCTrack mct; - mct.SetPdgCode( pdgID ); - mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); - mct.SetProductionVertex( x1, y1, z1, t ); - TEveTrack* track = new TEveTrack(&mct); - track->SetAttLineAttMarker(particlesMC); - particlesMC->AddElement(track); - } - } - if (drawMCtracks) particlesMC->MakeTracks(); - */ - - // handle differently the e/gamma vs pi0 particle guns (for pi0, need to look for the two photons in secondary particle list - // unfortunately cannot just use the latter to show particles since info about endpoint is broken (identical to vertex) - if (pdgID != 111) { - float m = (*genParticles_mass)[ipmax]; - float px = (*genParticles_momentum_x)[ipmax]; - float py = (*genParticles_momentum_y)[ipmax]; - float pz = (*genParticles_momentum_z)[ipmax]; - float p = sqrt( px*px + py*py + pz*pz ); - - double t = (*genParticles_time)[ipmax]; - double x1 = (*genParticles_vertex_x)[ipmax] * mm; - double y1 = (*genParticles_vertex_y)[ipmax] * mm; - double z1 = (*genParticles_vertex_z)[ipmax] * mm; - double r1 = sqrt(x1*x1+y1*y1); - double sintheta = sqrt(px*px + py*py)/p; - double x2 = x1 + px/p * rMax / sintheta; - double y2 = y1 + py/p * rMax / sintheta; - double z2 = z1 + pz/p * rMax / sintheta; - double r2 = sqrt(x2*x2+y2*y2); - /* - particles->AddLine(x1,y1,z1, x2,y2,z2); - particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", - pdgID, - m, - p, - acos(pz/p), - atan2(py,px))); - */ + else + particles->DestroyElements(); + + // handle differently the e/gamma vs pi0 particle guns + // (for pi0, need to look for the two photons in secondary particle list + // unfortunately cannot just use the latter to show particles since + // info about endpoint is broken (identical to vertex) + float m = (*genParticles_mass)[ipmax]; + float px = (*genParticles_momentum_x)[ipmax]; + float py = (*genParticles_momentum_y)[ipmax]; + float pz = (*genParticles_momentum_z)[ipmax]; + float p = sqrt( px*px + py*py + pz*pz ); - if (drawMCtracks) { - TEveMCTrack mct; - mct.SetPdgCode( pdgID ); - mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); - mct.SetProductionVertex( x1, y1, z1, t ); - if (pdgID == 111) {mct.SetDaughter(0,1);mct.SetDaughter(1,2);} - TEveTrack* track = new TEveTrack(&mct, particlesMC->GetPropagator()); - track->SetAttLineAttMarker(particlesMC); - track->SetElementTitle(Form("p= %f\ntheta= %f\nphi = %f", - p, - acos(pz/p), - atan2(py,px))); - particlesMC->AddElement(track); - } - } - else { + double t = (*genParticles_time)[ipmax]; + double x1 = (*genParticles_vertex_x)[ipmax] * mm; + double y1 = (*genParticles_vertex_y)[ipmax] * mm; + double z1 = (*genParticles_vertex_z)[ipmax] * mm; + double r1 = sqrt(x1*x1+y1*y1); + double sintheta = sqrt(px*px + py*py)/p; + double x2 = x1 + px/p * rMax / sintheta; + double y2 = y1 + py/p * rMax / sintheta; + double z2 = z1 + pz/p * rMax / sintheta; + double r2 = sqrt(x2*x2+y2*y2); + + TEveMCTrack mct; + mct.SetPdgCode( pdgID ); + mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); + mct.SetProductionVertex( x1, y1, z1, t ); + TEveTrack* track = new TEveTrack(&mct, particles->GetPropagator()); + track->SetAttLineAttMarker(particles); + track->SetElementTitle(Form("p = %.3f GeV\ntheta = %f\nphi = %f\nx = %f cm\ny = %f cm\nz= %f cm", + p, acos(pz/p), atan2(py,px), + x1/cm, y1/cm, z1/cm)); + particles->AddElement(track); + + // if the particle is a pi0, also draw the two photons, and set the endpoint + // of the pi0 track + if (pdgID == 111) { + bool decayVtxSet = false; for (unsigned int i = 0; i < SimParticleSecondaries_PDG->GetSize(); i ++) { - int pdgID = (*SimParticleSecondaries_PDG)[i]; + pdgID = (*SimParticleSecondaries_PDG)[i]; // keep only photons if (pdgID!=22) continue; //if ( (*SimParticleSecondaries_generatorStatus)[i] != 1 ) continue; - float px = (*SimParticleSecondaries_momentum_x)[i]; - float py = (*SimParticleSecondaries_momentum_y)[i]; - float pz = (*SimParticleSecondaries_momentum_z)[i]; - float m = (*SimParticleSecondaries_mass)[i]; - float p = sqrt( px*px + py*py + pz*pz ); + px = (*SimParticleSecondaries_momentum_x)[i]; + py = (*SimParticleSecondaries_momentum_y)[i]; + pz = (*SimParticleSecondaries_momentum_z)[i]; + m = (*SimParticleSecondaries_mass)[i]; + p = sqrt( px*px + py*py + pz*pz ); float e = sqrt(p*p + m*m); - cout << "p = "<< p << endl; + // cout << "p = "<< p << endl; if (pAddLine(x1,y1,z1, x2,y2,z2); - particles->SetElementTitle(Form("PDG = %d\nm = %f\np= %f\ntheta= %f\nphi = %f", - pdgID, - m, - p, - acos(pz/p), - atan2(py,px))); - */ - if (drawMCtracks) { - TEveMCTrack mct; - mct.SetPdgCode( pdgID ); - mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); - mct.SetProductionVertex( x1, y1, z1, t ); - TEveTrack* track = new TEveTrack(&mct, particlesMC->GetPropagator()); - track->SetAttLineAttMarker(particlesMC); - track->SetElementTitle(Form("p= %f\ntheta= %f\nphi = %f", - p, - acos(pz/p), - atan2(py,px))); - particlesMC->AddElement(track); + r2 = sqrt(x2*x2+y2*y2); + // cout << "x1 y1 z1 x2 y2 z2 = " + // << x1 << " " << y1 << " " << z1 << " " + // << x2 << " " << y2 << " " << z2 << endl; + // set pi0 decay point + if (!decayVtxSet) { + TEveVectorF v; v[0] = x1; v[1]=y1; v[2]=z1; + TEvePathMark mark(TEvePathMark::kDecay, v); + track->AddPathMark(mark); + decayVtxSet = true; } + TEveMCTrack mct; + mct.SetPdgCode( pdgID ); + mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); + mct.SetProductionVertex( x1, y1, z1, t ); + TEveTrack* track = new TEveTrack(&mct, particles->GetPropagator()); + track->SetAttLineAttMarker(particles); + track->SetElementTitle(Form("p = .3%f GeV\ntheta = %f\nphi = %f\nx = %f cm\ny = %f cm\nz= %f cm", + p, acos(pz/p), atan2(py,px), + x1/cm, y1/cm, z1/cm)); + + particles->AddElement(track); } } - if (drawMCtracks) particlesMC->MakeTracks(); + particles->MakeTracks(); } // @@ -923,9 +842,10 @@ class EventReader for (unsigned int i = 0; i < CorrectedCaloTopoClusters_position_x->GetSize(); i ++) { float E = (*CorrectedCaloTopoClusters_energy)[i]; if (E < TopoClusterEnergyThreshold) continue; + // cluster positions are in cm and hits/cells in mm ... clusters->SetNextPoint( (*CorrectedCaloTopoClusters_position_x)[i] * cm , (*CorrectedCaloTopoClusters_position_y)[i] * cm , - (*CorrectedCaloTopoClusters_position_z)[i] * cm ); // why cluster positions are in cm and hits/cells in mm??? + (*CorrectedCaloTopoClusters_position_z)[i] * cm ); } @@ -961,7 +881,8 @@ class EventReader // clusters in 2D if (topoclusters_rhoz==nullptr) { - topoclusters_rhoz = new TEveElementList(Form("Clusters in rho-z (E>%.1f GeV)",TopoClusterEnergyThreshold)); + topoclusters_rhoz = new TEveElementList(Form("Clusters in rho-z (E>%.1f GeV)", + TopoClusterEnergyThreshold)); // add to scene or manager? // rhoZProjManager->AddElement(topoclusters_rhoz); rhoZEventSceneManual->AddElement(topoclusters_rhoz); @@ -971,7 +892,8 @@ class EventReader topoclusters_rhoz->DestroyElements(); if (topoclusters_rhophi==nullptr) { - topoclusters_rhophi = new TEveElementList(Form("Clusters in rho-phi (E>%.1f GeV)",TopoClusterEnergyThreshold)); + topoclusters_rhophi = new TEveElementList(Form("Clusters in rho-phi (E>%.1f GeV)", + TopoClusterEnergyThreshold)); // add to scene or manager? -- scene that is not auto-projected! // rhoPhiProjManager->AddElement(topoclusters_rhophi); rhoPhiEventSceneManual->AddElement(topoclusters_rhophi); @@ -994,7 +916,8 @@ class EventReader qs_rhophi.push_back(nullptr); } else { - TEveQuadSet* aqs = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, Form("cluster %d", (int) i)); + TEveQuadSet* aqs = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, + Form("cluster %d", (int) i)); aqs->SetMainTransparency(80); // by calling SetOwnIds(kTRUE) the digit-set becomes // the owner of the assigned objects and deletes @@ -1009,7 +932,8 @@ class EventReader qs_rhoz.push_back(aqs); topoclusters_rhoz->AddElement(aqs); - TEveQuadSet* aqs2 = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, Form("cluster %d", (int) i)); + TEveQuadSet* aqs2 = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, + Form("cluster %d", (int) i)); aqs2->SetMainTransparency(80); aqs2->SetOwnIds(kTRUE); aqs2->SetPalette(pal); @@ -1040,7 +964,8 @@ class EventReader for (unsigned int i = 0; i < PositionedCaloTopoClusterCells_energy->GetSize(); i ++) { int icl = -1; for (unsigned int j = 0; j < CorrectedCaloTopoClusters_energy->GetSize(); j ++) { - if (i >= (*CorrectedCaloTopoClusters_hits_begin)[j] && i < (*CorrectedCaloTopoClusters_hits_end)[j]) { + if (i >= (*CorrectedCaloTopoClusters_hits_begin)[j] && + i < (*CorrectedCaloTopoClusters_hits_end)[j]) { icl = j; break; } @@ -1144,7 +1069,9 @@ class EventReader } if (eventLabel == nullptr) { - eventLabel = new TGLConstAnnotation(gEve->GetDefaultGLViewer(), Form("%s, %.1f GeV\nEvent %d", partType.Data(), pmax, eventId), 0.1, 0.9); + eventLabel = new TGLConstAnnotation(gEve->GetDefaultGLViewer(), + Form("%s, %.1f GeV\nEvent %d", + partType.Data(), pmax, eventId), 0.1, 0.9); eventLabel->SetTextSize(0.05);// % of window diagonal eventLabel->SetAllowClose(false); } @@ -1303,11 +1230,14 @@ void display(int evt = 0) { // create second tab (R-phi view) rhoPhiView = gEve->SpawnNewViewer("Projection Rho-Phi"); // two scenes, for geometry and event - rhoPhiScene = gEve->SpawnNewScene("Rho-Phi geometry", "Scene holding projected geometry data for the RhoPhi view."); + rhoPhiScene = gEve->SpawnNewScene("Rho-Phi geometry", + "Scene holding projected geometry data for the RhoPhi view."); rhoPhiView->AddScene(rhoPhiScene); - rhoPhiEventScene = gEve->SpawnNewScene("RhoPhi Event Data", "Scene holding projected event-data for the RhoPhi view."); + rhoPhiEventScene = gEve->SpawnNewScene("RhoPhi Event Data", + "Scene holding projected event-data for the RhoPhi view."); rhoPhiView->AddScene(rhoPhiEventScene); - rhoPhiEventSceneManual = gEve->SpawnNewScene("RhoPhi Event Data 2", "Scene holding hand-crafted event-data for the RhoPhi view."); + rhoPhiEventSceneManual = gEve->SpawnNewScene("RhoPhi Event Data 2", + "Scene holding hand-crafted event-data for the RhoPhi view."); rhoPhiView->AddScene(rhoPhiEventSceneManual); rhoPhiGLView = rhoPhiView->GetGLViewer(); // set camera orientation @@ -1346,11 +1276,14 @@ void display(int evt = 0) { // third tab (R-z view) rhoZView = gEve->SpawnNewViewer("Projection Rho-Z"); - rhoZScene = gEve->SpawnNewScene("Rho-Z geometry", "Scene holding projected geometry data for the RhoZ view."); + rhoZScene = gEve->SpawnNewScene("Rho-Z geometry", + "Scene holding projected geometry data for the RhoZ view."); rhoZView->AddScene(rhoZScene); - rhoZEventScene = gEve->SpawnNewScene("RhoZ Event Data", "Scene holding projected event-data for the RhoZ view."); + rhoZEventScene = gEve->SpawnNewScene("RhoZ Event Data", + "Scene holding projected event-data for the RhoZ view."); rhoZView->AddScene(rhoZEventScene); - rhoZEventSceneManual = gEve->SpawnNewScene("RhoZ Event Data 2", "Scene holding hand-crafted event-data for the RhoZ view."); + rhoZEventSceneManual = gEve->SpawnNewScene("RhoZ Event Data 2", + "Scene holding hand-crafted event-data for the RhoZ view."); rhoZView->AddScene(rhoZEventSceneManual); rhoZGLView = rhoZView->GetGLViewer(); rhoZGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py index d06f79d..c31b9ea 100644 --- a/FCCSW_ecal/run_thetamodulemerged.py +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -13,7 +13,12 @@ # reminder: cell granularity in theta = 0.5625 degrees # (in strips: 0.5625/4=0.14) -momentum = 100 # in GeV +#Nevts = 20000 +#Nevts = 50 +Nevts = 1 +#momentum = 100 # in GeV +momentum = 50 # in GeV +#momentum = 10 # in GeV _pi = 3.14159 #thetaMin = 40 # degrees #thetaMax = 140 # degrees @@ -21,8 +26,6 @@ thetaMax = 90 # degrees phiMin = _pi/2. phiMax = _pi/2. -#phiMin = _pi/2. - _pi*8/1545. -#phiMax = _pi/2. + _pi*8/1545. #phiMin = 0 #phiMax = 2 * _pi @@ -31,8 +34,14 @@ #pdgCode = 22 #pdgCode = 111 +# Set to true if history from Geant4 decays is needed (e.g. to get the +# photons from pi0) +saveG4Hist = False +if (pdgCode == 111): saveG4Hist = True + magneticField = False + from Gaudi.Configuration import * from Configurables import FCCDataSvc @@ -101,18 +110,16 @@ # Geant4 service # Configures the Geant simulation: geometry, physics list and user actions - from Configurables import ( SimG4FullSimActions, SimG4Alg, SimG4PrimariesFromEdmTool, SimG4SaveParticleHistory ) actions = SimG4FullSimActions() -# Uncomment if history from Geant4 decays is needed (e.g. to get the photons -# from pi0) and set actions=actions in SimG4Svc + uncomment saveHistTool -# in SimG4Alg -actions.enableHistory=True -actions.energyCut = 1.0 * GeV -saveHistTool = SimG4SaveParticleHistory("saveHistory") + +if saveG4Hist: + actions.enableHistory=True + actions.energyCut = 1.0 * GeV + saveHistTool = SimG4SaveParticleHistory("saveHistory") from Configurables import SimG4Svc geantservice = SimG4Svc( @@ -185,7 +192,10 @@ ) saveHCalTool.CaloHits.Path = "HCalBarrelPositionedHits" -#saveHCalEndcapTool = SimG4SaveCalHits("saveHCalEndcapHits", readoutName = hcalEndcapReadoutName) +#saveHCalEndcapTool = SimG4SaveCalHits( +# "saveHCalEndcapHits", +# readoutName = hcalEndcapReadoutName +#) #saveHCalEndcapTool.CaloHits.Path = "HCalEndcapHits" # next, create the G4 algorithm, giving the list of names of tools ("XX/YY") @@ -194,14 +204,17 @@ particle_converter.GenParticles.Path = genParticlesOutputName from Configurables import SimG4Alg +outputTools = [ + saveECalBarrelTool, + saveHCalTool, + saveECalEndcapTool, + #saveHCalEndcapTool +] +if saveG4Hist: + outputTools += [saveHistTool] + geantsim = SimG4Alg("SimG4Alg", - outputs= [ - saveECalBarrelTool, - saveHCalTool, - saveECalEndcapTool, - #saveHCalEndcapTool - saveHistTool - ], + outputs = outputTools, eventProvider=particle_converter, OutputLevel=INFO) @@ -498,8 +511,6 @@ #out.outputCommands = ["keep *", "drop HCal*", "drop ECalBarrel*", "drop emptyCaloCells"] out.outputCommands = ["keep *", "drop HCal*", "drop emptyCaloCells"] -Nevts = 1 -#Nevts = 50 import uuid # out.filename = "root/output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_"+str(magneticField)+"_pMin_"+str(momentum*1000)+"_MeV"+"_ThetaMinMax_"+str(thetaMin)+"_"+str(thetaMax)+"_pdgId_"+str(pdgCode)+"_pythia"+str(use_pythia)+"_Noise"+str(addNoise)+".root" out.filename = "./root_merge/output_evts_"+str(Nevts)+"_pdg_"+str(pdgCode)+"_"+str(momentum)+"_GeV"+"_ThetaMinMax_"+str(thetaMin)+"_"+str(thetaMax)+"_PhiMinMax_"+str(phiMin)+"_"+str(phiMax)+"_MagneticField_"+str(magneticField)+"_Noise"+str(addNoise)+".root" diff --git a/geometry/create_noise_file_chargePreAmp_theta.py b/geometry/create_noise_file_chargePreAmp_theta.py index 8bb5381..f0aa258 100644 --- a/geometry/create_noise_file_chargePreAmp_theta.py +++ b/geometry/create_noise_file_chargePreAmp_theta.py @@ -53,7 +53,7 @@ def get_ref_charge(SF, E_dep = 1 * pow(10, 6)): #E_dep en eV, choose 1 MeV return E_dep * SF * (1 - r_recomb) / (2 * w_lar) # nA, the factor 2 comes from: Q_tot = I_0 * t_drift * 1/2 (rectangle --> triangle), t_drift cancels out from the formula to get I_0 which has v_drift/d_gap (Ramo Shockley). # Assumption: shaping time is similar or bigger to drift time -# what is this?? +# Sampling fraction in each layer SFfcc = [0.36504678560781667] * 1 + [0.09974087165838573] * 1 + [0.12392336840429007] * 1 + [0.1413266332223572] * 1 + [0.15415123193238958] * 1 + [0.1639900875460671] * 1 + [0.17156597031962592] * 1 + [0.17810674932424356] * 1 + [0.18340048249397345] * 1 + [0.18855877603870688] * 1 + [0.19307873042890955] * 1 + [0.21746137329706489] * 1 nLayers = len(SFfcc) From c7100cf7a12404610eaa47fcd82c1241da9a47f1 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Fri, 29 Sep 2023 15:52:32 +0200 Subject: [PATCH 19/33] update event display, add comments to the code --- data/elecNoise_ecalBarrelFCCee_theta.root | Bin 20951 -> 20714 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/elecNoise_ecalBarrelFCCee_theta.root b/data/elecNoise_ecalBarrelFCCee_theta.root index d166cf85f22de3c3b6397b1b84edd523d53acf6e..1133c922237aba87b381c4e16bf7442c451603d3 100644 GIT binary patch delta 12585 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 RpIbbDRl)ad$@5M*{U7%ZC=&nx delta 13008 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 Date: Fri, 29 Sep 2023 16:22:09 +0200 Subject: [PATCH 20/33] update sampling fractions in scripts using theta-module merged readout for latest detector with 1545 modules --- FCCSW_ecal/run_thetamodulemerged.py | 6 +++--- geometry/create_noise_file_chargePreAmp_theta.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py index c31b9ea..61b0372 100644 --- a/FCCSW_ecal/run_thetamodulemerged.py +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -222,9 +222,9 @@ # EM scale calibration (sampling fraction) from Configurables import CalibrateInLayersTool calibEcalBarrel = CalibrateInLayersTool("CalibrateECalBarrel", - samplingFraction = [0.3632447480841956] * 1 + [0.13187261040190248] * 1 + [0.14349714292943705] * 1 + [0.150266118277841] * 1 + [0.15502683375826457] * 1 + [0.15954408786354762] * 1 + [0.16375302347299436] * 1 + [0.16840384714588075] * 1 + [0.17219540619311383] * 1 + [0.1755068643940401] * 1 + [0.17816980262822366] * 1 + [0.18131266048670405] * 1, - readoutName = ecalBarrelReadoutName, - layerFieldName = "layer") + samplingFraction = [0.35920833517910844] * 1 + [0.13624356500953932] * 1 + [0.14386554236870444] * 1 + [0.14928465075470942] * 1 + [0.15373827173933277] * 1 + [0.1590691464263249] * 1 + [0.1616598353661629] * 1 + [0.16611800053971013] * 1 + [0.169986924691829] * 1 + [0.1727827697437898] * 1 + [0.175009158726329] * 1 + [0.1767637635193861] * 1, + readoutName = ecalBarrelReadoutName, + layerFieldName = "layer") from Configurables import CalibrateCaloHitsTool calibHcells = CalibrateCaloHitsTool("CalibrateHCal", invSamplingFraction="31.4") diff --git a/geometry/create_noise_file_chargePreAmp_theta.py b/geometry/create_noise_file_chargePreAmp_theta.py index f0aa258..f8851ce 100644 --- a/geometry/create_noise_file_chargePreAmp_theta.py +++ b/geometry/create_noise_file_chargePreAmp_theta.py @@ -54,7 +54,8 @@ def get_ref_charge(SF, E_dep = 1 * pow(10, 6)): #E_dep en eV, choose 1 MeV # Assumption: shaping time is similar or bigger to drift time # Sampling fraction in each layer -SFfcc = [0.36504678560781667] * 1 + [0.09974087165838573] * 1 + [0.12392336840429007] * 1 + [0.1413266332223572] * 1 + [0.15415123193238958] * 1 + [0.1639900875460671] * 1 + [0.17156597031962592] * 1 + [0.17810674932424356] * 1 + [0.18340048249397345] * 1 + [0.18855877603870688] * 1 + [0.19307873042890955] * 1 + [0.21746137329706489] * 1 +# numbers updated for latest model with 1545 modules +SFfcc = [0.35920833517910844] * 1 + [0.13624356500953932] * 1 + [0.14386554236870444] * 1 + [0.14928465075470942] * 1 + [0.15373827173933277] * 1 + [0.1590691464263249] * 1 + [0.1616598353661629] * 1 + [0.16611800053971013] * 1 + [0.169986924691829] * 1 + [0.1727827697437898] * 1 + [0.175009158726329] * 1 + [0.1767637635193861] * 1 nLayers = len(SFfcc) print("##########: ", get_ref_charge(0.16)) From 4de268ee45bde84e3ce57384ee532e1580b541aa Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Fri, 29 Sep 2023 16:47:47 +0200 Subject: [PATCH 21/33] move ReadNoiseFromFileTool for theta-based readout to new tool in FCCee subdirectory --- FCCSW_ecal/noise_map_theta.py | 26 +++++++++++----------- data/elecNoise_ecalBarrelFCCee_theta.root | Bin 20714 -> 20800 bytes 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/FCCSW_ecal/noise_map_theta.py b/FCCSW_ecal/noise_map_theta.py index 154cead..b832a7c 100644 --- a/FCCSW_ecal/noise_map_theta.py +++ b/FCCSW_ecal/noise_map_theta.py @@ -25,19 +25,19 @@ # OutputLevel = DEBUG) #print(ECalBcells) -from Configurables import CreateFCCeeCaloNoiseLevelMap, ReadNoiseFromFileTool -ECalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolECal", - useSegmentation = False, - cellPositionsTool = ECalBcells, - readoutName = ecalBarrelReadoutName, - noiseFileName = BarrelNoisePath, - elecNoiseHistoName = ecalBarrelNoiseHistName, - setNoiseOffset = False, - activeFieldName = "layer", - addPileup = False, - numRadialLayers = 12, - scaleFactor = 1/1000., #MeV to GeV - OutputLevel = INFO) +from Configurables import CreateFCCeeCaloNoiseLevelMap, ReadNoiseFromFileTool, ReadNoiseVsThetaFromFileTool +ECalNoiseTool = ReadNoiseVsThetaFromFileTool("ReadNoiseFromFileToolECal", + useSegmentation = False, + cellPositionsTool = ECalBcells, + readoutName = ecalBarrelReadoutName, + noiseFileName = BarrelNoisePath, + elecNoiseHistoName = ecalBarrelNoiseHistName, + setNoiseOffset = False, + activeFieldName = "layer", + addPileup = False, + numRadialLayers = 12, + scaleFactor = 1/1000., #MeV to GeV + OutputLevel = INFO) HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", useSegmentation = True, diff --git a/data/elecNoise_ecalBarrelFCCee_theta.root b/data/elecNoise_ecalBarrelFCCee_theta.root index 1133c922237aba87b381c4e16bf7442c451603d3..5279adc3aa72def9340ad101deb5d9e264427bb3 100644 GIT binary patch delta 11593 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 delta 11506 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 From 10ed2a3bc0a90e897818b285bcc477a0e813be75 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Fri, 6 Oct 2023 11:15:28 +0200 Subject: [PATCH 22/33] add code to dump GDML file of detector model and convert it to ROOT filefor EVE display --- FCCSW_ecal/displayV3.C | 80 ++++++++++++++++++++++++++++- FCCSW_ecal/run_thetamodulemerged.py | 12 +++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/FCCSW_ecal/displayV3.C b/FCCSW_ecal/displayV3.C index 14a45ba..fe1576e 100644 --- a/FCCSW_ecal/displayV3.C +++ b/FCCSW_ecal/displayV3.C @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -154,7 +157,7 @@ const std::vector drNom( const int nLayers = drNom.size(); // number of electrodes -const int nModules = 1545; +const int nModules = 1536; // inclination angle of electrodes const double alpha = 50*TMath::Pi()/180.; @@ -319,6 +322,81 @@ int sgn(float val) { } +/******************************************************************************/ +// DISPLAY DETECTOR STORED IN GDML (AND OPTIONALLY CONVERT TO ROOT EVE FORMAT) +/******************************************************************************/ + +void displayGDMLModel(bool larOnly=false, int dim=3, bool dumpToRoot=false) +{ + TEveManager::Create(); + + TFile::SetCacheFileDir("."); + gGeoManager = TGeoManager::Import("GeantDetector.gdml"); + gGeoManager->DefaultColors(); + gGeoManager->SetNsegments(200); // has no effect in tube rendering in OpenGL (overridden by OGL) + // makes the code crash.. + //gGeoManager->SetDefaultUnits(TGeoManager::kRootUnits); + //gGeoManager->SetDefaultUnits(TGeoManager::kG4Units); + + if (larOnly) { + // only Lar + TGeoVolume* vol = gGeoManager->GetVolume("ECalBarrel_vol"); + vol->SetFillColorAlpha(kBlue, 0.05); + vol->SetTransparency(90); + TObjArray* nodes = gGeoManager->GetTopVolume()->GetNodes(); + TObjArrayIter nodeIter(nodes); + TGeoNode* barrel = nullptr; + while (TGeoNode* node = (TGeoNode*) nodeIter.Next()) { + TString name(node->GetName()); + //cout << name << endl; + if (name.BeginsWith("ECalBarrel_vol_14")) { + barrel = node; + break; + } + } + if (barrel == nullptr) { + cout << "Could not find ECalBarrel volume in GDML" << endl; + return; + } + TEveGeoTopNode* inn = new TEveGeoTopNode(gGeoManager, barrel); + inn->SetVisOption(1); + inn->SetVisLevel(3); + gEve->AddGlobalElement(inn); + gEve->AddToListTree(inn, true); + inn->ExpandIntoListTreesRecursively(); + inn->SetCSGExportNSeg(2000); + if (dumpToRoot) inn->SaveExtract("ECalBarrel.root", "ECalBarrel_vol", false); + } + else { + // full detector + auto tn = new TEveGeoTopNode(gGeoManager, gGeoManager->GetTopNode()); + tn->SetVisLevel(3); + gEve->AddGlobalElement(tn); + gEve->AddToListTree(tn, true); + tn->ExpandIntoListTreesRecursively(); + if (dumpToRoot) tn->SaveExtract("FCCDetector.root", "world", false); + } + + gEve->FullRedraw3D(kTRUE); + + // EClipType not exported to CINT (see TGLUtil.h): + // 0 - no clip, 1 - clip plane, 2 - clip box + auto v = gEve->GetDefaultGLViewer(); + + if (dim==3) { + // 3d view + v->GetClipSet()->SetClipType(TGLClip::EType(1)); + v->CurrentCamera().RotateRad(-.7, 0.5); + } + else { + // 2d view + v->GetClipSet()->SetClipType(TGLClip::EType(0)); + v->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); + } + v->DoDraw(); +} + + /******************************************************************************/ // HELPER FUNCTIONS related to the graphic system /******************************************************************************/ diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py index 61b0372..6aadf85 100644 --- a/FCCSW_ecal/run_thetamodulemerged.py +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -5,6 +5,7 @@ use_pythia = False addNoise = False +dumpGDML = False # Input for simulations (momentum is expected in GeV!) # Parameters for the particle gun simulations, dummy if use_pythia is set @@ -130,7 +131,9 @@ ) # from Configurables import GeoToGdmlDumpSvc -# gdmldumpservice = GeoToGdmlDumpSvc("GeoToGdmlDumpSvc") +if dumpGDML: + from Configurables import GeoToGdmlDumpSvc + gdmldumpservice = GeoToGdmlDumpSvc("GeoToGdmlDumpSvc") # Fixed seed to have reproducible results, change it for each job if you # split one production into several jobs @@ -533,6 +536,10 @@ event_counter = EventCounter('event_counter') event_counter.Frequency = 10 +ExtSvc = [geoservice, podioevent, geantservice, audsvc] +if dumpGDML: + ExtSvc += [gdmldumpservice] + from Configurables import ApplicationMgr ApplicationMgr( TopAlg = [ @@ -559,7 +566,6 @@ ], EvtSel = 'NONE', EvtMax = Nevts, - ExtSvc = [geoservice, podioevent, geantservice, audsvc], -# ExtSvc = [geoservice, podioevent, geantservice, gdmldumpservice, audsvc], + ExtSvc = ExtSvc, StopOnSignal = True, ) From 23f72ef062edb1eef93d1ae3240051a36c4adf9c Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Sat, 7 Oct 2023 20:23:47 +0200 Subject: [PATCH 23/33] update sampling and leakage corrections --- FCCSW_ecal/run_thetamodulemerged.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/FCCSW_ecal/run_thetamodulemerged.py b/FCCSW_ecal/run_thetamodulemerged.py index 6aadf85..914cb9d 100644 --- a/FCCSW_ecal/run_thetamodulemerged.py +++ b/FCCSW_ecal/run_thetamodulemerged.py @@ -16,7 +16,8 @@ #Nevts = 20000 #Nevts = 50 -Nevts = 1 +#Nevts = 1 +Nevts=1000 #momentum = 100 # in GeV momentum = 50 # in GeV #momentum = 10 # in GeV @@ -225,7 +226,7 @@ # EM scale calibration (sampling fraction) from Configurables import CalibrateInLayersTool calibEcalBarrel = CalibrateInLayersTool("CalibrateECalBarrel", - samplingFraction = [0.35920833517910844] * 1 + [0.13624356500953932] * 1 + [0.14386554236870444] * 1 + [0.14928465075470942] * 1 + [0.15373827173933277] * 1 + [0.1590691464263249] * 1 + [0.1616598353661629] * 1 + [0.16611800053971013] * 1 + [0.169986924691829] * 1 + [0.1727827697437898] * 1 + [0.175009158726329] * 1 + [0.1767637635193861] * 1, + samplingFraction = [0.36599110182660616] * 1 + [0.1366222373338866] * 1 + [0.1452035173747207] * 1 + [0.1504319190969367] * 1 + [0.15512713637727382] * 1 + [0.1592916726494782] * 1 + [0.16363478857307595] * 1 + [0.1674697333180323] * 1 + [0.16998205747422343] * 1 + [0.1739146363733975] * 1 + [0.17624609543603845] * 1 + [0.1768613530850488] * 1, readoutName = ecalBarrelReadoutName, layerFieldName = "layer") @@ -414,9 +415,11 @@ lastLayerIDs = [11], ## readoutNames = [ecalBarrelReadoutNamePhiEta], readoutNames = [ecalBarrelReadoutName], - upstreamParameters = [[0.033955208567442975, -3.818122686176795, -146.59497297249345, 0.563447903447204, -3.7906629536351906, -8.569962044554627]], + #upstreamParameters = [[0.02729094887360858, -1.378665489864182, -68.40424543618059, 3.6930827214130053, -5528.714729126099, -1630.7911298009794]], + upstreamParameters = [[0.02729094887360858, -1.378665489864182, -68.40424543618059, 3.6930827214130053, -5528.714729126099, -1630.7911298009794]], upstreamFormulas = [['[0]+[1]/(x-[2])', '[0]+[1]/(x-[2])']], - downstreamParameters = [[-0.00357017357914002, 0.006624434345822984, 1.0065650241358008, -1.285181650875406, -0.0707783194915608, 12.907319280196257]], + #downstreamParameters = [[-0.0032351643028483354, 0.006597484738888312, 0.8972024981692965, -1.0207168610322181, 0.017878133854084398, 9.108099243443101]], + downstreamParameters = [[-0.0032351643028483354, 0.006597484738888312, 0.8972024981692965, -1.0207168610322181, 0.017878133854084398, 9.108099243443101]], downstreamFormulas = [['[0]+[1]*x', '[0]+[1]/sqrt(x)', '[0]+[1]/x']], OutputLevel = INFO ) @@ -495,9 +498,11 @@ lastLayerIDs = [11], ## readoutNames = [ecalBarrelReadoutNamePhiEta], readoutNames = [ecalBarrelReadoutName], - upstreamParameters = [[0.033955208567442975, -3.818122686176795, -146.59497297249345, 0.563447903447204, -3.7906629536351906, -8.569962044554627]], + #upstreamParameters = [[0.02729094887360858, -1.378665489864182, -68.40424543618059, 3.6930827214130053, -5528.714729126099, -1630.7911298009794]], + upstreamParameters = [[0.02729094887360858, -1.378665489864182, -68.40424543618059, 3.6930827214130053, -5528.714729126099, -1630.7911298009794]], upstreamFormulas = [['[0]+[1]/(x-[2])', '[0]+[1]/(x-[2])']], - downstreamParameters = [[-0.00357017357914002, 0.006624434345822984, 1.0065650241358008, -1.285181650875406, -0.0707783194915608, 12.907319280196257]], + #downstreamParameters = [[-0.0032351643028483354, 0.006597484738888312, 0.8972024981692965, -1.0207168610322181, 0.017878133854084398, 9.108099243443101]], + downstreamParameters = [[-0.0032351643028483354, 0.006597484738888312, 0.8972024981692965, -1.0207168610322181, 0.017878133854084398, 9.108099243443101]], downstreamFormulas = [['[0]+[1]*x', '[0]+[1]/sqrt(x)', '[0]+[1]/x']], OutputLevel = INFO ) From dc8137b4a52420995eec8f3e38561c7e52ccb46d Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 9 Oct 2023 23:51:40 +0200 Subject: [PATCH 24/33] update sampling fraction for latest model with 1536 modules --- geometry/create_noise_file_chargePreAmp_theta.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geometry/create_noise_file_chargePreAmp_theta.py b/geometry/create_noise_file_chargePreAmp_theta.py index f8851ce..f79307e 100644 --- a/geometry/create_noise_file_chargePreAmp_theta.py +++ b/geometry/create_noise_file_chargePreAmp_theta.py @@ -54,8 +54,8 @@ def get_ref_charge(SF, E_dep = 1 * pow(10, 6)): #E_dep en eV, choose 1 MeV # Assumption: shaping time is similar or bigger to drift time # Sampling fraction in each layer -# numbers updated for latest model with 1545 modules -SFfcc = [0.35920833517910844] * 1 + [0.13624356500953932] * 1 + [0.14386554236870444] * 1 + [0.14928465075470942] * 1 + [0.15373827173933277] * 1 + [0.1590691464263249] * 1 + [0.1616598353661629] * 1 + [0.16611800053971013] * 1 + [0.169986924691829] * 1 + [0.1727827697437898] * 1 + [0.175009158726329] * 1 + [0.1767637635193861] * 1 +# numbers updated for latest model with 1536 modules +SFfcc = [0.36599110182660616] * 1 + [0.1366222373338866] * 1 + [0.1452035173747207] * 1 + [0.1504319190969367] * 1 + [0.15512713637727382] * 1 + [0.1592916726494782] * 1 + [0.16363478857307595] * 1 + [0.1674697333180323] * 1 + [0.16998205747422343] * 1 + [0.1739146363733975] * 1 + [0.17624609543603845] * 1 + [0.1768613530850488] * 1 nLayers = len(SFfcc) print("##########: ", get_ref_charge(0.16)) From 4807a7016f77e7e327cfe603dc18a020215c857c Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 9 Oct 2023 23:52:00 +0200 Subject: [PATCH 25/33] update sampling fraction for latest model with 1536 modules --- geometry/create_capacitance_file_theta.py | 45 ++++++++++++----------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index ee5d717..59b4670 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -34,28 +34,29 @@ #ECalConstruction INFO active passive initial overlap (before subtraction) (cm) = 0.1 = 50 % # latest version -# Info: ECAL cryostat: front: rmin (cm) = 215.4 rmax (cm) = 216.78 dz (cm) = 310 -# Info: ECAL cryostat: back: rmin (cm) = 261.33 rmax (cm) = 271.6 dz (cm) = 310 -# Info: ECAL cryostat: side: rmin (cm) = 216.78 rmax (cm) = 261.33 dz (cm) = 3.38 -# Info: ECAL services: front: rmin (cm) = 216.78 rmax (cm) = 217.28 dz (cm) = 306.62 -# Info: ECAL services: back: rmin (cm) = 257.33 rmax (cm) = 261.33 dz (cm) = 306.62 -# Info: ECAL bath: material = LAr rmin (cm) = 217.28 rmax (cm) = 257.33 thickness in front of ECal (cm) = 0.5 thickness behind ECal (cm) = 4 -# Info: ECAL calorimeter volume rmin (cm) = 217.28 rmax (cm) = 257.33 -# Info: passive inner material = Lead -# and outer material = lArCaloSteel -# thickness of inner part at inner radius (cm) = 0.18 -# thickness of inner part at outer radius (cm) = 0.18 -# thickness of outer part (cm) = 0.01 -# thickness of total (cm) = 0.2 -# rotation angle = 0.872665 -# Info: number of passive plates = 1545 azim. angle difference = 0.00406679 -# Info: distance at inner radius (cm) = 0.883631 -# distance at outer radius (cm) = 1.04651 -# Info: readout material = PCB -# thickness of readout planes (cm) = 0.12 -# number of readout layers = 12 -# Info: thickness of calorimeter (cm) = 40.05 -# length of passive or readout planes (cm) = 56.586 +# Debug: Number of layers: 12 total thickness 40 +# Info: ECAL cryostat: front: rmin (cm) = 215.4 rmax (cm) = 216.78 dz (cm) = 310 +# Info: ECAL cryostat: back: rmin (cm) = 261.33 rmax (cm) = 271.6 dz (cm) = 310 +# Info: ECAL cryostat: side: rmin (cm) = 216.78 rmax (cm) = 261.33 dz (cm) = 3.38 +# Info: ECAL services: front: rmin (cm) = 216.78 rmax (cm) = 217.28 dz (cm) = 306.62 +# Info: ECAL services: back: rmin (cm) = 257.33 rmax (cm) = 261.33 dz (cm) = 306.62 +# Info: ECAL bath: material = LAr rmin (cm) = 217.28 rmax (cm) = 257.33 thickness in front of ECal (cm) = 0.5 thickness behind ECal (cm) = 4 +# Info: ECAL calorimeter volume rmin (cm) = 217.28 rmax (cm) = 257.33 +# Info: passive inner material = Lead +# and outer material = lArCaloSteel +# thickness of inner part at inner radius (cm) = 0.18 +# thickness of inner part at outer radius (cm) = 0.18 +# thickness of outer part (cm) = 0.01 +# thickness of total (cm) = 0.2 +# rotation angle = 0.872665 +# Info: number of passive plates = 1536 azim. angle difference = 0.00409062 +# Info: distance at inner radius (cm) = 0.888809 +# distance at outer radius (cm) = 1.05264 +# Info: readout material = PCB +# thickness of readout planes (cm) = 0.12 +# number of readout layers = 12 +# Info: thickness of calorimeter (cm) = 40.05 +# length of passive or readout planes (cm) = 56.586 filename = "capacitances_perSource_ecalBarrelFCCee_theta.root" #filename = "capacitances_ecalBarrelFCCee_nLayer_%d_fromAnalytical.root"%numLayers From af589b08b7ebc291bf1228b44b7b18b214508913 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 9 Oct 2023 23:52:58 +0200 Subject: [PATCH 26/33] add property for including or not diagonal neighbours --- FCCSW_ecal/neighbours_theta.py | 1 + 1 file changed, 1 insertion(+) diff --git a/FCCSW_ecal/neighbours_theta.py b/FCCSW_ecal/neighbours_theta.py index 31190c4..c58ce82 100644 --- a/FCCSW_ecal/neighbours_theta.py +++ b/FCCSW_ecal/neighbours_theta.py @@ -28,6 +28,7 @@ activeFieldNamesModuleTheta = ["layer"], activeVolumesNumbers = [12], #activeVolumesTheta = [1.2524, 1.2234, 1.1956, 1.1561, 1.1189, 1.0839, 1.0509, 0.9999, 0.9534, 0.91072], + includeDiagonalCells = False, readoutNamesVolumes = [], connectBarrels = False, OutputLevel = DEBUG) From 97489d2a574cb094a4114132a376349a0b431ae4 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 16 Oct 2023 21:47:20 +0200 Subject: [PATCH 27/33] move event display to its own package --- FCCSW_ecal/displayV3.C | 1536 ---------------------------------------- 1 file changed, 1536 deletions(-) delete mode 100644 FCCSW_ecal/displayV3.C diff --git a/FCCSW_ecal/displayV3.C b/FCCSW_ecal/displayV3.C deleted file mode 100644 index fe1576e..0000000 --- a/FCCSW_ecal/displayV3.C +++ /dev/null @@ -1,1536 +0,0 @@ -/******************************************************************************/ -// Simple event display for the LAr calorimeter with inclined modules -// author: Giovanni Marchiori (giovanni.marchiori@cern.ch) -// -// Run with -// root -// .L displayV3.C+ -// display() -// -/******************************************************************************/ - - -/******************************************************************************/ -// dependencies -/******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace std; - - -/******************************************************************************/ -// SETTINGS FOR THE DISPLAY -// - geometry file (and corresponding merging of theta cells/modules vs layer -// - data file -// - flags to draw or not elements of the event (particles, hits, ..) -// - minimum energy of particles, hits, cells, clusters -/******************************************************************************/ - -// G4 geometry file -std::string geomFile = "ECalBarrel.root"; - -// merging along theta and module directions and drawing options -//std::string evtFile = "output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_False_pMin_10000_MeV_ThetaMinMax_40_140_pdgId_11_pythiaFalse_NoiseFalse.root"; -//std::string evtFile = "test.root"; -//const std::vector mergedCells_Theta = {4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; -//const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; -//bool drawMergedCells = false; - -//std::string evtFile = "output_fullCalo_SimAndDigi_withTopoCluster_MagneticField_False_pMin_10000_MeV_ThetaMinMax_40_140_pdgId_11_pythiaFalse_NoiseFalse_testmerge.root"; -//const std::vector mergedCells_Theta = {4, 8, 2, 1, 8, 4, 2, 1, 4, 2, 1, 8}; -//const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1}; -//bool drawMergedCells = true; - -// 50 electrons 100 GeV -// std::string evtFile = "output_evts_50_100_GeV_ThetaMinMax_40_140_PhiMinMax_0_6.28318.root"; -// 1 electron 50 GeV -// std::string evtFile = "output_evts_1_pdg_11_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; -// 1 pi0 50 GeV -std::string evtFile = "output_evts_1_pdg_111_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; -// 1 photon 50 GeV -// std::string evtFile = "output_evts_1_pdg_22_50_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; -// 1 pi0 10 GeV -// std::string evtFile = "output_evts_1_pdg_111_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; -// 1 photon 10 GeV -// std::string evtFile = "output_evts_1_pdg_22_10_GeV_ThetaMinMax_90_90_PhiMinMax_1.570795_1.570795_MagneticField_False_NoiseFalse.root"; - -const std::vector mergedCells_Theta = {4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; -const std::vector mergedModules = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - -bool drawParticles = true; -bool drawHits = true; -bool drawCells = true; -bool drawMergedCells = false; -bool drawTopoClusters = true; - -// min particle energy (GeV) -float ParticleEnergyThreshold = 1.0; -// min hit and cell energy (GeV) -float HitEnergyThreshold = 0.0; -float CellEnergyThreshold = 0.0; -// min cluster energy (in GeV) -float TopoClusterEnergyThreshold = 2.; - - -/******************************************************************************/ -// GEOMETRICAL CONSTANTS -// They should match the geometry used in the geometry file and the readout -// used to produce the event file -/******************************************************************************/ - -// units -// G4 uses mm but Root uses cm.. -const double cm = 1.0; -const double mm = 0.1; -const std::string units = "cm"; - -// z extension of barrel -const double zMin = -3100.*mm; -const double zMax = 3100.*mm; - -// radial extension of barrel -const double rMin = 217.28*cm; -const double rMax = 257.33*cm; - -// nominal radial thickness of layers -const std::vector drNom( - { - 15.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm, - 35.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm, 35.*mm - } -); - -// number of layers -const int nLayers = drNom.size(); - -// number of electrodes -const int nModules = 1536; - -// inclination angle of electrodes -const double alpha = 50*TMath::Pi()/180.; - -// grid in theta -// - size of cell -const double thetaGrid = 0.00981748/4; -// - theta of edge of first cell -const double thetaMin = 0.59027850 - thetaGrid/2.; -// - n(bins) -const int nThetaBins = 800; - - - -/******************************************************************************/ -// GEOMETRY HELPER FUNCTIONS AND DERIVED GEOMETRY PARAMETERS -/******************************************************************************/ - -// calculate length along electrode at r=r_out for electrode -// starting at r=r_in and inclined in phi by alpha -// for r_in>r_out, when the solution exists, it's always > 0 -double _L(double alpha, double r_in, double r_out) { - if (r_out > r_in) - return sqrt(r_out*r_out - r_in*r_in*sin(alpha)*sin(alpha)) - r_in*cos(alpha); - else - return r_in*cos(alpha) - sqrt(r_out*r_out - r_in*r_in*sin(alpha)*sin(alpha)); -} - -// calculate phi offset between point at r=r_out with respect -// to point at r=r_in if they are on the same electrode -// inclined in phi by alpha -double _phi(double alpha, double r_in, double r_out) { - double L = _L(alpha, r_in, r_out); - if (r_out > r_in) - return TMath::ASin(L/r_out * sin(alpha)); - else - return -TMath::ASin(L/r_out * sin(alpha)); -} - -// calculate radius of point on electrode starting at -// r=r_in, inclined in phi by alpha, and at distance L -// from beginning of electrode -double _r(double alpha, double r_in, double L) { - return sqrt( (r_in+L*cos(alpha)) * (r_in+L*cos(alpha)) - + (L*sin(alpha)) * (L*sin(alpha)) ); -} - -// length of electrodes -static const double Ltot = _L(alpha, rMin, rMax); - -// phi separation of modules -const double gridPhi = TMath::TwoPi()/nModules; - -// r for electrode length = L/2 -static const double rAvg = _r(alpha, rMin, Ltot/2.0); - -// delta phi of point at L/2 -static const double dPhiAvg = _phi(alpha, rMin, rAvg); - -// phi edge of module 0 -static const double phiMin = -alpha - gridPhi/2.0; - -// other quantities, calculated by calcGeom -// radial position of each layer -std::vector r; -std::vector dr; -// length of electrode along each layer (dRnom/cos(alpha)) -std::vector dL; - -// calculate derived parameters of geometry depending on the main ones -// (such as radial/electrode length of each layer) -// and print them to screen -void calcGeom() { - - // print initial information - cout << "r(min) = " << rMin << " " << units << endl; - cout << "r(max) = " << rMax << " " << units << endl; - cout << "total thickness = " << rMax-rMin << " " << units << endl; - - // calculate total length - cout << "electrode length = " << Ltot << " " << units << endl << endl; - - // calculate length along electrode of each layer - cout << "n(layers) = " << nLayers << endl << endl; - std::vector L; - double sumL(0.0); - dL.clear(); - for (int i=0; i rMed; - for (int i=0; i> 11) & mask; -} - -// extract module number from cellID -ULong_t Module(ULong_t cellID) { - const ULong_t mask = (1<<11) -1; - return (cellID >> 19) & mask; -} - -// extract theta bin from cellID -ULong_t ThetaBin(ULong_t cellID) { - const ULong_t mask = (1<<10) -1; - return (cellID >> 30) & mask; -} - -// return the sign of a float -int sgn(float val) { - return (val > 0.) - (val < 0.); -} - - -/******************************************************************************/ -// DISPLAY DETECTOR STORED IN GDML (AND OPTIONALLY CONVERT TO ROOT EVE FORMAT) -/******************************************************************************/ - -void displayGDMLModel(bool larOnly=false, int dim=3, bool dumpToRoot=false) -{ - TEveManager::Create(); - - TFile::SetCacheFileDir("."); - gGeoManager = TGeoManager::Import("GeantDetector.gdml"); - gGeoManager->DefaultColors(); - gGeoManager->SetNsegments(200); // has no effect in tube rendering in OpenGL (overridden by OGL) - // makes the code crash.. - //gGeoManager->SetDefaultUnits(TGeoManager::kRootUnits); - //gGeoManager->SetDefaultUnits(TGeoManager::kG4Units); - - if (larOnly) { - // only Lar - TGeoVolume* vol = gGeoManager->GetVolume("ECalBarrel_vol"); - vol->SetFillColorAlpha(kBlue, 0.05); - vol->SetTransparency(90); - TObjArray* nodes = gGeoManager->GetTopVolume()->GetNodes(); - TObjArrayIter nodeIter(nodes); - TGeoNode* barrel = nullptr; - while (TGeoNode* node = (TGeoNode*) nodeIter.Next()) { - TString name(node->GetName()); - //cout << name << endl; - if (name.BeginsWith("ECalBarrel_vol_14")) { - barrel = node; - break; - } - } - if (barrel == nullptr) { - cout << "Could not find ECalBarrel volume in GDML" << endl; - return; - } - TEveGeoTopNode* inn = new TEveGeoTopNode(gGeoManager, barrel); - inn->SetVisOption(1); - inn->SetVisLevel(3); - gEve->AddGlobalElement(inn); - gEve->AddToListTree(inn, true); - inn->ExpandIntoListTreesRecursively(); - inn->SetCSGExportNSeg(2000); - if (dumpToRoot) inn->SaveExtract("ECalBarrel.root", "ECalBarrel_vol", false); - } - else { - // full detector - auto tn = new TEveGeoTopNode(gGeoManager, gGeoManager->GetTopNode()); - tn->SetVisLevel(3); - gEve->AddGlobalElement(tn); - gEve->AddToListTree(tn, true); - tn->ExpandIntoListTreesRecursively(); - if (dumpToRoot) tn->SaveExtract("FCCDetector.root", "world", false); - } - - gEve->FullRedraw3D(kTRUE); - - // EClipType not exported to CINT (see TGLUtil.h): - // 0 - no clip, 1 - clip plane, 2 - clip box - auto v = gEve->GetDefaultGLViewer(); - - if (dim==3) { - // 3d view - v->GetClipSet()->SetClipType(TGLClip::EType(1)); - v->CurrentCamera().RotateRad(-.7, 0.5); - } - else { - // 2d view - v->GetClipSet()->SetClipType(TGLClip::EType(0)); - v->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); - } - v->DoDraw(); -} - - -/******************************************************************************/ -// HELPER FUNCTIONS related to the graphic system -/******************************************************************************/ - -void makeGui(); - -// derived TGLAnnotation class that overrides MouseEnter method -// to avoid editing of annotation -class TGLConstAnnotation : public TGLAnnotation -{ - public: - TGLConstAnnotation(TGLViewerBase *parent, const char *text, Float_t posx, Float_t posy) : - TGLAnnotation(parent, text, posx, posy) - { - ; - } - Bool_t MouseEnter(TGLOvlSelectRecord& /*rec*/) - { - fActive = kFALSE; - return kTRUE; - } -}; - - -/******************************************************************************/ -// ELEMENTS OF THE EVENT DISPLAY -/******************************************************************************/ - -Int_t eventId = 0; // Current event id -Int_t nEvents = 0; // Number of events in file -TEveTrackList* particles = nullptr; -TEvePointSet* hits = nullptr; -TEvePointSet* cells = nullptr; -TEvePointSet* cells_merged = nullptr; -TEvePointSet* clusters = nullptr; -std::vector qs_rhoz; -std::vector qs_rhophi; -TEveElementList* topoclusters_rhoz = nullptr; -TEveElementList* topoclusters_rhophi = nullptr; -std::vector bs; -TEveElementList* topoclusters_3D = nullptr; - -TEveGeoShape* barrel = nullptr; -TEveViewer* rhoPhiView = nullptr; -TEveViewer* rhoZView = nullptr; -TGLViewer* rhoPhiGLView = nullptr; -TGLViewer* rhoZGLView = nullptr; -TEveScene* rhoPhiScene = nullptr; -TEveScene* rhoPhiEventScene = nullptr; -TEveScene* rhoPhiEventSceneManual = nullptr; -TEveScene* rhoZScene = nullptr; -TEveScene* rhoZEventScene = nullptr; -TEveScene* rhoZEventSceneManual = nullptr; -TEveProjectionManager* rhoPhiProjManager = nullptr; -TEveProjectionManager* rhoZProjManager = nullptr; - -TGLConstAnnotation* eventLabel = nullptr; -TGTextEntry *textEntry = nullptr; - -/******************************************************************************/ -// CLASS TO READ AN EVENT FROM THE EVENT FILE -// AND FILL THE EVENT DISPLAY OBJECTS -/******************************************************************************/ -class EventReader -{ - private: - TTreeReader* fReader = nullptr; - // 1a. - primary particles - TTreeReaderArray *genParticles_PDG = nullptr; - TTreeReaderArray *genParticles_generatorStatus = nullptr; - TTreeReaderArray *genParticles_simulatorStatus = nullptr; - TTreeReaderArray *genParticles_charge = nullptr; - TTreeReaderArray *genParticles_time = nullptr; - TTreeReaderArray *genParticles_mass = nullptr; - TTreeReaderArray *genParticles_vertex_x = nullptr; - TTreeReaderArray *genParticles_vertex_y = nullptr; - TTreeReaderArray *genParticles_vertex_z = nullptr; - //TTreeReaderArray *genParticles_endpoint_x = nullptr; - //TTreeReaderArray *genParticles_endpoint_y = nullptr; - //TTreeReaderArray *genParticles_endpoint_z = nullptr; - TTreeReaderArray *genParticles_momentum_x = nullptr; - TTreeReaderArray *genParticles_momentum_y = nullptr; - TTreeReaderArray *genParticles_momentum_z = nullptr; - - // 1a. - secondary particles - TTreeReaderArray *SimParticleSecondaries_PDG = nullptr; - //TTreeReaderArray *SimParticleSecondaries_generatorStatus = nullptr; - //TTreeReaderArray *SimParticleSecondaries_simulatorStatus = nullptr; - //TTreeReaderArray *SimParticleSecondaries_charge = nullptr; - TTreeReaderArray *SimParticleSecondaries_time = nullptr; - TTreeReaderArray *SimParticleSecondaries_mass = nullptr; - TTreeReaderArray *SimParticleSecondaries_vertex_x = nullptr; - TTreeReaderArray *SimParticleSecondaries_vertex_y = nullptr; - TTreeReaderArray *SimParticleSecondaries_vertex_z = nullptr; - TTreeReaderArray *SimParticleSecondaries_endpoint_x = nullptr; - TTreeReaderArray *SimParticleSecondaries_endpoint_y = nullptr; - TTreeReaderArray *SimParticleSecondaries_endpoint_z = nullptr; - TTreeReaderArray *SimParticleSecondaries_momentum_x = nullptr; - TTreeReaderArray *SimParticleSecondaries_momentum_y = nullptr; - TTreeReaderArray *SimParticleSecondaries_momentum_z = nullptr; - - // 1b. hits - TTreeReaderArray *ECalBarrelPositionedHits_cellID = nullptr; - TTreeReaderArray *ECalBarrelPositionedHits_energy = nullptr; - TTreeReaderArray *ECalBarrelPositionedHits_position_x = nullptr; - TTreeReaderArray *ECalBarrelPositionedHits_position_y = nullptr; - TTreeReaderArray *ECalBarrelPositionedHits_position_z = nullptr; - - // 1c. - cells - TTreeReaderArray *ECalBarrelPositionedCells_cellID = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells_energy = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells_position_x = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells_position_y = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells_position_z = nullptr; - - // 1d. - cells with coarser merging - TTreeReaderArray *ECalBarrelPositionedCells2_cellID = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells2_energy = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells2_position_x = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells2_position_y = nullptr; - TTreeReaderArray *ECalBarrelPositionedCells2_position_z = nullptr; - - // 1e. - the corrected calo topo clusters - TTreeReaderArray *CorrectedCaloTopoClusters_energy = nullptr; - TTreeReaderArray *CorrectedCaloTopoClusters_position_x = nullptr; - TTreeReaderArray *CorrectedCaloTopoClusters_position_y = nullptr; - TTreeReaderArray *CorrectedCaloTopoClusters_position_z = nullptr; - TTreeReaderArray *CorrectedCaloTopoClusters_hits_begin = nullptr; - TTreeReaderArray *CorrectedCaloTopoClusters_hits_end = nullptr; - - // 1f. - cells in the topo clusters - TTreeReaderArray *PositionedCaloTopoClusterCells_cellID = nullptr; - TTreeReaderArray *PositionedCaloTopoClusterCells_energy = nullptr; - TTreeReaderArray *PositionedCaloTopoClusterCells_position_x = nullptr; - TTreeReaderArray *PositionedCaloTopoClusterCells_position_y = nullptr; - TTreeReaderArray *PositionedCaloTopoClusterCells_position_z = nullptr; - - public: - EventReader(TFile* f) - { - fReader = new TTreeReader("events", f); - nEvents = fReader->GetEntries(); - - // 1a. - primary particles - genParticles_PDG = new TTreeReaderArray(*fReader, "genParticles.PDG"); - genParticles_generatorStatus = new TTreeReaderArray(*fReader, "genParticles.generatorStatus"); - genParticles_simulatorStatus = new TTreeReaderArray(*fReader, "genParticles.simulatorStatus"); - genParticles_charge = new TTreeReaderArray(*fReader, "genParticles.charge"); - genParticles_time = new TTreeReaderArray(*fReader, "genParticles.time"); - genParticles_mass = new TTreeReaderArray(*fReader, "genParticles.mass"); - genParticles_vertex_x = new TTreeReaderArray(*fReader, "genParticles.vertex.x"); - genParticles_vertex_y = new TTreeReaderArray(*fReader, "genParticles.vertex.y"); - genParticles_vertex_z = new TTreeReaderArray(*fReader, "genParticles.vertex.z"); - //genParticles_endpoint_x = new TTreeReaderArray(*fReader, "genParticles.endpoint.x"); - //genParticles_endpoint_y = new TTreeReaderArray(*fReader, "genParticles.endpoint.y"); - //genParticles_endpoint_z = new TTreeReaderArray(*fReader, "genParticles.endpoint.z"); - genParticles_momentum_x = new TTreeReaderArray(*fReader, "genParticles.momentum.x"); - genParticles_momentum_y = new TTreeReaderArray(*fReader, "genParticles.momentum.y"); - genParticles_momentum_z = new TTreeReaderArray(*fReader, "genParticles.momentum.z"); - - // 1a. - secondary particles - if (fReader->GetTree()->FindBranch("SimParticleSecondaries.PDG")) { - SimParticleSecondaries_PDG = new TTreeReaderArray(*fReader, "SimParticleSecondaries.PDG"); - //SimParticleSecondaries_generatorStatus = new TTreeReaderArray(*fReader, "SimParticleSecondaries.generatorStatus"); - //SimParticleSecondaries_simulatorStatus = new TTreeReaderArray(*fReader, "SimParticleSecondaries.simulatorStatus"); - //SimParticleSecondaries_charge = new TTreeReaderArray(*fReader, "SimParticleSecondaries.charge"); - SimParticleSecondaries_time = new TTreeReaderArray(*fReader, "SimParticleSecondaries.time"); - SimParticleSecondaries_mass = new TTreeReaderArray(*fReader, "SimParticleSecondaries.mass"); - SimParticleSecondaries_vertex_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.x"); - SimParticleSecondaries_vertex_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.y"); - SimParticleSecondaries_vertex_z = new TTreeReaderArray(*fReader, "SimParticleSecondaries.vertex.z"); - SimParticleSecondaries_endpoint_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.endpoint.x"); - SimParticleSecondaries_endpoint_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.endpoint.y"); - SimParticleSecondaries_endpoint_z = new TTreeReaderArray(*fReader, "SimParticleSecondaries.endpoint.z"); - SimParticleSecondaries_momentum_x = new TTreeReaderArray(*fReader, "SimParticleSecondaries.momentum.x"); - SimParticleSecondaries_momentum_y = new TTreeReaderArray(*fReader, "SimParticleSecondaries.momentum.y"); - SimParticleSecondaries_momentum_z = new TTreeReaderArray(*fReader, "SimParticleSecondaries.momentum.z"); - } - - // 1b. - hits - ECalBarrelPositionedHits_cellID = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.cellID"); - ECalBarrelPositionedHits_energy = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.energy"); - ECalBarrelPositionedHits_position_x = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.position.x"); - ECalBarrelPositionedHits_position_y = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.position.y"); - ECalBarrelPositionedHits_position_z = new TTreeReaderArray(*fReader, "ECalBarrelPositionedHits.position.z"); - - // 1c. - cells - ECalBarrelPositionedCells_cellID = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.cellID"); - ECalBarrelPositionedCells_energy = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.energy"); - ECalBarrelPositionedCells_position_x = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.position.x"); - ECalBarrelPositionedCells_position_y = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.position.y"); - ECalBarrelPositionedCells_position_z = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells.position.z"); - - // 1d. - cells with coarser merging - ECalBarrelPositionedCells2_cellID = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.cellID"); - ECalBarrelPositionedCells2_energy = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.energy"); - ECalBarrelPositionedCells2_position_x = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.position.x"); - ECalBarrelPositionedCells2_position_y = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.position.y"); - ECalBarrelPositionedCells2_position_z = new TTreeReaderArray(*fReader, "ECalBarrelPositionedCells2.position.z"); - - // 1e. - the corrected calo topo clusters - CorrectedCaloTopoClusters_energy = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.energy"); - CorrectedCaloTopoClusters_position_x = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.position.x"); - CorrectedCaloTopoClusters_position_y = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.position.y"); - CorrectedCaloTopoClusters_position_z = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.position.z"); - CorrectedCaloTopoClusters_hits_begin = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.hits_begin"); - CorrectedCaloTopoClusters_hits_end = new TTreeReaderArray(*fReader, "CorrectedCaloTopoClusters.hits_end"); - - // 1f. - cells in the topo clusters - PositionedCaloTopoClusterCells_cellID = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.cellID"); - PositionedCaloTopoClusterCells_energy = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.energy"); - PositionedCaloTopoClusterCells_position_x = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.position.x"); - PositionedCaloTopoClusterCells_position_y = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.position.y"); - PositionedCaloTopoClusterCells_position_z = new TTreeReaderArray(*fReader, "PositionedCaloTopoClusterCells.position.z"); - - qs_rhoz.clear(); - qs_rhophi.clear(); - } - - ~EventReader() { - delete genParticles_PDG; - delete genParticles_generatorStatus; - delete genParticles_simulatorStatus; - delete genParticles_charge; - delete genParticles_time; - delete genParticles_mass; - delete genParticles_vertex_x; - delete genParticles_vertex_y; - delete genParticles_vertex_z; - //delete genParticles_endpoint_x; - //delete genParticles_endpoint_y; - //delete genParticles_endpoint_z; - delete genParticles_momentum_x; - delete genParticles_momentum_y; - delete genParticles_momentum_z; - - if (SimParticleSecondaries_PDG) { - delete SimParticleSecondaries_PDG; - // delete SimParticleSecondaries_generatorStatus; - // delete SimParticleSecondaries_simulatorStatus; - // delete SimParticleSecondaries_charge; - delete SimParticleSecondaries_time; - delete SimParticleSecondaries_mass; - delete SimParticleSecondaries_vertex_x; - delete SimParticleSecondaries_vertex_y; - delete SimParticleSecondaries_vertex_z; - delete SimParticleSecondaries_endpoint_x; - delete SimParticleSecondaries_endpoint_y; - delete SimParticleSecondaries_endpoint_z; - delete SimParticleSecondaries_momentum_x; - delete SimParticleSecondaries_momentum_y; - delete SimParticleSecondaries_momentum_z; - } - delete ECalBarrelPositionedHits_cellID; - delete ECalBarrelPositionedHits_energy; - delete ECalBarrelPositionedHits_position_x; - delete ECalBarrelPositionedHits_position_y; - delete ECalBarrelPositionedHits_position_z; - delete ECalBarrelPositionedCells_cellID; - delete ECalBarrelPositionedCells_energy; - delete ECalBarrelPositionedCells_position_x; - delete ECalBarrelPositionedCells_position_y; - delete ECalBarrelPositionedCells_position_z; - delete ECalBarrelPositionedCells2_cellID; - delete ECalBarrelPositionedCells2_energy; - delete ECalBarrelPositionedCells2_position_x; - delete ECalBarrelPositionedCells2_position_y; - delete ECalBarrelPositionedCells2_position_z; - delete CorrectedCaloTopoClusters_energy; - delete CorrectedCaloTopoClusters_position_x; - delete CorrectedCaloTopoClusters_position_y; - delete CorrectedCaloTopoClusters_position_z; - delete CorrectedCaloTopoClusters_hits_begin; - delete CorrectedCaloTopoClusters_hits_end; - delete PositionedCaloTopoClusterCells_cellID; - delete PositionedCaloTopoClusterCells_energy; - delete PositionedCaloTopoClusterCells_position_x; - delete PositionedCaloTopoClusterCells_position_y; - delete PositionedCaloTopoClusterCells_position_z; - delete fReader; - } - - void loadEvent(int event = -1) { - - if (event != -1) eventId = event; - - printf("Loading event %d.\n", eventId); - textEntry->SetTextColor(0xff0000); - textEntry->SetText(Form("Loading event %d...",eventId)); - - fReader->SetEntry(eventId); - - TString partType; - double pmax=0.0; - int ipmax=-1; - for (unsigned int i = 0; i < genParticles_generatorStatus->GetSize(); i ++) { - if ( (*genParticles_generatorStatus)[i] != 1 ) continue; - float _px = (*genParticles_momentum_x)[i]; - float _py = (*genParticles_momentum_y)[i]; - float _pz = (*genParticles_momentum_z)[i]; - float _p = sqrt( _px*_px + _py*_py + _pz*_pz ); - //cout << p << endl; - if (_p==0.) continue; - if (_p>pmax) { - pmax = _p; - ipmax = i; - } - } - int pdgID = (*genParticles_PDG)[ipmax]; - if (pdgID == 111) partType = "pi0"; - else if (pdgID == 22) partType = "y"; - else if (pdgID == 11) partType = "e-"; - else if (pdgID == -11) partType = "e+"; - else partType = "unknown"; - - // - // particles - // - if (drawParticles) { - cout << "Creating particles" << endl; - if (particles == nullptr) { - particles = new TEveTrackList("particles"); - TEveTrackPropagator* trkProp = particles->GetPropagator(); - trkProp->SetMagField( 0.01 ); - particles->SetMainColor(kYellow); - particles->SetLineWidth(2); - gEve->AddElement(particles); - } - else - particles->DestroyElements(); - - // handle differently the e/gamma vs pi0 particle guns - // (for pi0, need to look for the two photons in secondary particle list - // unfortunately cannot just use the latter to show particles since - // info about endpoint is broken (identical to vertex) - float m = (*genParticles_mass)[ipmax]; - float px = (*genParticles_momentum_x)[ipmax]; - float py = (*genParticles_momentum_y)[ipmax]; - float pz = (*genParticles_momentum_z)[ipmax]; - float p = sqrt( px*px + py*py + pz*pz ); - - double t = (*genParticles_time)[ipmax]; - double x1 = (*genParticles_vertex_x)[ipmax] * mm; - double y1 = (*genParticles_vertex_y)[ipmax] * mm; - double z1 = (*genParticles_vertex_z)[ipmax] * mm; - double r1 = sqrt(x1*x1+y1*y1); - double sintheta = sqrt(px*px + py*py)/p; - double x2 = x1 + px/p * rMax / sintheta; - double y2 = y1 + py/p * rMax / sintheta; - double z2 = z1 + pz/p * rMax / sintheta; - double r2 = sqrt(x2*x2+y2*y2); - - TEveMCTrack mct; - mct.SetPdgCode( pdgID ); - mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); - mct.SetProductionVertex( x1, y1, z1, t ); - TEveTrack* track = new TEveTrack(&mct, particles->GetPropagator()); - track->SetAttLineAttMarker(particles); - track->SetElementTitle(Form("p = %.3f GeV\ntheta = %f\nphi = %f\nx = %f cm\ny = %f cm\nz= %f cm", - p, acos(pz/p), atan2(py,px), - x1/cm, y1/cm, z1/cm)); - particles->AddElement(track); - - // if the particle is a pi0, also draw the two photons, and set the endpoint - // of the pi0 track - if (pdgID == 111) { - bool decayVtxSet = false; - for (unsigned int i = 0; i < SimParticleSecondaries_PDG->GetSize(); i ++) { - pdgID = (*SimParticleSecondaries_PDG)[i]; - // keep only photons - if (pdgID!=22) continue; - //if ( (*SimParticleSecondaries_generatorStatus)[i] != 1 ) continue; - px = (*SimParticleSecondaries_momentum_x)[i]; - py = (*SimParticleSecondaries_momentum_y)[i]; - pz = (*SimParticleSecondaries_momentum_z)[i]; - m = (*SimParticleSecondaries_mass)[i]; - p = sqrt( px*px + py*py + pz*pz ); - float e = sqrt(p*p + m*m); - // cout << "p = "<< p << endl; - if (pAddPathMark(mark); - decayVtxSet = true; - } - TEveMCTrack mct; - mct.SetPdgCode( pdgID ); - mct.SetMomentum( px, py, pz, sqrt(p*p + m*m) ); - mct.SetProductionVertex( x1, y1, z1, t ); - TEveTrack* track = new TEveTrack(&mct, particles->GetPropagator()); - track->SetAttLineAttMarker(particles); - track->SetElementTitle(Form("p = .3%f GeV\ntheta = %f\nphi = %f\nx = %f cm\ny = %f cm\nz= %f cm", - p, acos(pz/p), atan2(py,px), - x1/cm, y1/cm, z1/cm)); - - particles->AddElement(track); - } - } - particles->MakeTracks(); - } - - // - // hits - // - if (drawHits) { - cout << "Creating hits" << endl; - if (hits == nullptr) { - hits = new TEvePointSet(); - hits->SetName(Form("hits (E>%.1f GeV)",CellEnergyThreshold)); - hits->SetMarkerStyle(4); - hits->SetMarkerSize(1); - hits->SetMarkerColor(kRed); - gEve->AddElement(hits); - } - else - hits->Reset(); - for (unsigned int i = 0; i < ECalBarrelPositionedHits_position_x->GetSize(); i ++) { - float E = (*ECalBarrelPositionedHits_energy)[i]; - if (ESetNextPoint( (*ECalBarrelPositionedHits_position_x)[i] * mm , - (*ECalBarrelPositionedHits_position_y)[i] * mm , - (*ECalBarrelPositionedHits_position_z)[i] * mm ); - } - } - - // - // cells - // - if (drawCells) { - cout << "Creating cells" << endl; - if (cells == nullptr) { - cells = new TEvePointSet(); - cells->SetName(Form("cells (E>%.1f GeV)",CellEnergyThreshold)); - cells->SetMarkerStyle(4); - cells->SetMarkerSize(3); - cells->SetMarkerColor(kBlue); - gEve->AddElement(cells); - } - else - cells->Reset(); - for (unsigned int i = 0; i < ECalBarrelPositionedCells_position_x->GetSize(); i ++) { - float E = (*ECalBarrelPositionedCells_energy)[i]; - if (ESetNextPoint( (*ECalBarrelPositionedCells_position_x)[i] * mm , - (*ECalBarrelPositionedCells_position_y)[i] * mm , - (*ECalBarrelPositionedCells_position_z)[i] * mm ); - } - } - - // - // cells merged - // - if (drawMergedCells) { - cout << "Creating merged cells" << endl; - if (cells_merged == nullptr) { - cells_merged = new TEvePointSet(); - cells_merged->SetName("cells_merged"); - cells_merged->SetMarkerStyle(4); - cells_merged->SetMarkerSize(3); - cells_merged->SetMarkerColor(kBlue); - gEve->AddElement(cells_merged); - } - else - cells_merged->Reset(); - for (unsigned int i = 0; i < ECalBarrelPositionedCells2_position_x->GetSize(); i ++) { - float E = (*ECalBarrelPositionedCells2_energy)[i]; - // if (ESetNextPoint( (*ECalBarrelPositionedCells2_position_x)[i] * mm , - (*ECalBarrelPositionedCells2_position_y)[i] * mm , - (*ECalBarrelPositionedCells2_position_z)[i] * mm ); - } - } - - - // - // clusters - // - if (drawTopoClusters) { - cout << "Creating clusters" << endl; - - // centers of the clusters - if (clusters == nullptr) { - clusters = new TEvePointSet(); - clusters->SetName(Form("clusters (E>%.1f GeV)",TopoClusterEnergyThreshold)); - clusters->SetMarkerStyle(4); - clusters->SetMarkerSize(6); - clusters->SetMarkerColor(kGreen); - gEve->AddElement(clusters); - } - else - clusters->Reset(); - - for (unsigned int i = 0; i < CorrectedCaloTopoClusters_position_x->GetSize(); i ++) { - float E = (*CorrectedCaloTopoClusters_energy)[i]; - if (E < TopoClusterEnergyThreshold) continue; - // cluster positions are in cm and hits/cells in mm ... - clusters->SetNextPoint( (*CorrectedCaloTopoClusters_position_x)[i] * cm , - (*CorrectedCaloTopoClusters_position_y)[i] * cm , - (*CorrectedCaloTopoClusters_position_z)[i] * cm ); - } - - - // the DestroyElements method does not work for TExeQuadSet as for the TEvePointSet.. - // so I have to destroy and recreate the quad and box sets - for (auto qs : qs_rhoz) { - if (qs) - qs->Destroy(); - } - qs_rhoz.clear(); - - for (auto qs : qs_rhophi) { - if (qs) - qs->Destroy(); - } - qs_rhophi.clear(); - - for (auto _bs : bs) { - if (_bs) - _bs->Destroy(); - } - bs.clear(); - - TEveRGBAPalette *pal = new TEveRGBAPalette(0, 1000); - - // clusters in 3D - if (topoclusters_3D==nullptr) { - topoclusters_3D = new TEveElementList("Clusters in 3D (no E cut)"); - gEve->AddElement(topoclusters_3D); - } - else - topoclusters_3D->DestroyElements(); - - // clusters in 2D - if (topoclusters_rhoz==nullptr) { - topoclusters_rhoz = new TEveElementList(Form("Clusters in rho-z (E>%.1f GeV)", - TopoClusterEnergyThreshold)); - // add to scene or manager? - // rhoZProjManager->AddElement(topoclusters_rhoz); - rhoZEventSceneManual->AddElement(topoclusters_rhoz); - gEve->AddToListTree(topoclusters_rhoz,false); - } - else - topoclusters_rhoz->DestroyElements(); - - if (topoclusters_rhophi==nullptr) { - topoclusters_rhophi = new TEveElementList(Form("Clusters in rho-phi (E>%.1f GeV)", - TopoClusterEnergyThreshold)); - // add to scene or manager? -- scene that is not auto-projected! - // rhoPhiProjManager->AddElement(topoclusters_rhophi); - rhoPhiEventSceneManual->AddElement(topoclusters_rhophi); - gEve->AddToListTree(topoclusters_rhophi,false); - } - else - topoclusters_rhophi->DestroyElements(); - - for (unsigned int i = 0; i < CorrectedCaloTopoClusters_energy->GetSize(); i ++) { - float energy = (*CorrectedCaloTopoClusters_energy)[i]; - float xcl = (*CorrectedCaloTopoClusters_position_x)[i]; - float ycl = (*CorrectedCaloTopoClusters_position_y)[i]; - float zcl = (*CorrectedCaloTopoClusters_position_z)[i]; - float rcl = sqrt(xcl*xcl + ycl*ycl); - float phicl = atan2(ycl, xcl); - float thetacl = atan2(rcl, zcl); - - if (energy < TopoClusterEnergyThreshold) { - qs_rhoz.push_back(nullptr); - qs_rhophi.push_back(nullptr); - } - else { - TEveQuadSet* aqs = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, - Form("cluster %d", (int) i)); - aqs->SetMainTransparency(80); - // by calling SetOwnIds(kTRUE) the digit-set becomes - // the owner of the assigned objects and deletes - // them on destruction. - aqs->SetOwnIds(kTRUE); - aqs->SetPalette(pal); - aqs->SetTitle(Form("E = %f GeV\nR = %f cm\ntheta = %f\nphi = %f", - energy, - rcl, - thetacl, - phicl)); - qs_rhoz.push_back(aqs); - topoclusters_rhoz->AddElement(aqs); - - TEveQuadSet* aqs2 = new TEveQuadSet(TEveQuadSet::kQT_FreeQuad, false, 32, - Form("cluster %d", (int) i)); - aqs2->SetMainTransparency(80); - aqs2->SetOwnIds(kTRUE); - aqs2->SetPalette(pal); - aqs2->SetTitle(Form("E = %f GeV\nR = %f cm\ntheta = %f\nphi = %f", - energy, - rcl, - thetacl, - phicl)); - qs_rhophi.push_back(aqs2); - topoclusters_rhophi->AddElement(aqs2); - } - - TEveBoxSet* _bs = new TEveBoxSet(Form("cluster %d", (int) i),""); - _bs->Reset(TEveBoxSet::kBT_FreeBox, false, 32); - _bs->SetMainTransparency(80); - _bs->SetOwnIds(kTRUE); - _bs->SetPalette(pal); - _bs->SetTitle(Form("E = %f GeV\nR = %f cm\ntheta = %f\nphi = %f", - energy, - rcl, - thetacl, - phicl)); - bs.push_back(_bs); - topoclusters_3D->AddElement(_bs); - } - - // loop over cells and attach them to clusters - for (unsigned int i = 0; i < PositionedCaloTopoClusterCells_energy->GetSize(); i ++) { - int icl = -1; - for (unsigned int j = 0; j < CorrectedCaloTopoClusters_energy->GetSize(); j ++) { - if (i >= (*CorrectedCaloTopoClusters_hits_begin)[j] && - i < (*CorrectedCaloTopoClusters_hits_end)[j]) { - icl = j; - break; - } - } - if (icl==-1) continue; // should never happen.. - ULong_t cellID = (*PositionedCaloTopoClusterCells_cellID)[i]; - int layer = (int) Layer(cellID); - float x_center = (*PositionedCaloTopoClusterCells_position_x)[i] * mm; - float y_center = (*PositionedCaloTopoClusterCells_position_y)[i] * mm; - float z_center = (*PositionedCaloTopoClusterCells_position_z)[i] * mm; - float r_center = sqrt(x_center*x_center + y_center*y_center); - float r_in = r[layer]; - float r_out = r[layer+1]; - float theta_center = atan2(r_center, z_center); - float phi_center = atan2(y_center, x_center); - float energy = (*PositionedCaloTopoClusterCells_energy)[i]; - - // cluster cells in rho-z projection - float verts[12]; - verts[0] = r_in/tan(theta_center - thetaGrid*mergedCells_Theta[layer]/2.); - verts[1] = r_in*sgn(y_center); - verts[3] = r_in/tan(theta_center + thetaGrid*mergedCells_Theta[layer]/2.); - verts[4] = r_in*sgn(y_center); - verts[6] = r_out/tan(theta_center + thetaGrid*mergedCells_Theta[layer]/2.); - verts[7] = r_out*sgn(y_center); - verts[9] = r_out/tan(theta_center - thetaGrid*mergedCells_Theta[layer]/2.); - verts[10] = r_out*sgn(y_center); - verts[2] = verts[5] = verts[8] = verts[11] = 0.; - if (qs_rhoz[icl]!=nullptr) { - qs_rhoz[icl]->AddQuad(verts); - qs_rhoz[icl]->QuadValue( (int) (1000 * energy) ); - qs_rhoz[icl]->QuadId( new TNamed(Form("Cell %lu", cellID), "Dong!") ); - } - // cluster cells in rho-phi projection - int module = (int) Module(cellID); - double Lin = _L(alpha, rMin, r[layer]); - double Lout = _L(alpha, rMin, r[layer+1]); - double deltaL = rMin*sin(gridPhi/2.0)*sin(alpha); - for (int j=0; jAddQuad(verts); - qs_rhophi[icl]->QuadValue( (int) (1000 * energy) ); - qs_rhophi[icl]->QuadId(new TNamed(Form("Cell %lu", cellID), "Dong!")); - } - } - - // cluster cells in 3D - float verts3D[24]; - for (int j=0; jAddBox(verts3D); - bs[icl]->DigitValue( (int) (1000 * energy) ); - //bs->BoxId(new TNamed(Form("Cell %lu", cellID), "Dong!")); - } - } - } - - if (eventLabel == nullptr) { - eventLabel = new TGLConstAnnotation(gEve->GetDefaultGLViewer(), - Form("%s, %.1f GeV\nEvent %d", - partType.Data(), pmax, eventId), 0.1, 0.9); - eventLabel->SetTextSize(0.05);// % of window diagonal - eventLabel->SetAllowClose(false); - } - else { - eventLabel->SetText(Form("%s, %.1f GeV\nEvent %d", partType.Data(), pmax, eventId)); - } - - TEveElement* top = (TEveElement*) gEve->GetCurrentEvent(); - // if nothing is drawn, top is null - if (top) { - rhoPhiEventScene->DestroyElements(); - rhoPhiProjManager->ImportElements(top, rhoPhiEventScene); - - // slow?? - //TEveRGBAPaletteOverlay *po = new TEveRGBAPaletteOverlay(pal, 0.55, 0.1, 0.4, 0.05); - //rhoPhiGLView->AddOverlayElement(po); - - rhoZEventScene->DestroyElements(); - rhoZProjManager->ImportElements(top, rhoZEventScene); - - //TEveRGBAPaletteOverlay *po2 = new TEveRGBAPaletteOverlay(pal, 0.55, 0.1, 0.4, 0.05); - //rhoZGLView->AddOverlayElement(po2); - } - - cout << "Done" << endl; - - textEntry->SetTextColor((Pixel_t)0x000000); - textEntry->SetText(Form("Event %d loaded", eventId)); - - } -}; - - - -/******************************************************************************/ -// THE MAIN FUNCTION -/******************************************************************************/ - -EventReader* eventReader = nullptr; - -void display(int evt = 0) { - - // calculate the geometry parameters - calcGeom(); - - // create the eve manageer - TEveManager::Create(); - - // see palettes here: https://root.cern.ch/doc/master/classTColor.html - // gStyle->SetPalette(kAvocado); - gStyle->SetPalette(kSienna); - - // first tab - gEve->GetDefaultGLViewer()->SetGuideState(TGLUtil::kAxesOrigin, false, false, 0); - gEve->GetDefaultGLViewer()->DrawGuides(); - gEve->GetDefaultViewer()->SetElementName("3D view"); - gEve->GetDefaultGLViewer()->CurrentCamera().RotateRad(-.7, 0.5); - - // Create the geometry and the readout - TEveElementList* geom = new TEveElementList("Geometry"); - TEveElementList* PCBs = new TEveElementList("PCBs"); - TEveElementList* actives = new TEveElementList("Active elements"); - TEveElementList* passives = new TEveElementList("Passive elements"); - TEveElementList* readout = new TEveElementList("Readout"); - bool useG4geom = true; - if (useG4geom) { - //auto fGeom = TFile::Open(geomFile.c_str(), "CACHEREAD"); - auto fGeom = TFile::Open(geomFile.c_str(), "READ"); - if (!fGeom) return; - TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) fGeom->Get("ECalBarrel_vol"); - barrel = TEveGeoShape::ImportShapeExtract(gse, 0); - barrel->SetMainTransparency(70); - fGeom->Close(); - delete fGeom; - barrel->SetPickableRecursively(kTRUE); - geom->AddElement(barrel); - TPRegexp re; - // set transparency of the subvolumes of the bath - re = TPRegexp("LAr_bath*"); - TEveElement* bath = barrel->FindChild(re); - TEveElement::List_t matches; - re = TPRegexp("ECAL_Cryo*"); - barrel->FindChildren(matches, re); - for (auto a : matches) a->SetMainTransparency(70); - re = TPRegexp("services*"); - barrel->FindChildren(matches, re); - for (auto a : matches) a->SetMainTransparency(70); - // make lists of elements inside bath to turn on/off simultaneously - if (bath) { - TEveElementList* newbath = new TEveElementList("LAr_bath"); - barrel->AddElement(newbath); - TEveElement::List_t matches; - re = TPRegexp("PCB*"); - bath->FindChildren(matches, re); - for (auto a : matches) PCBs->AddElement(a); - newbath->AddElement(PCBs); - TEveElement::List_t matches2; - re = TPRegexp("active*"); - bath->FindChildren(matches2, re); - for (auto a : matches2) actives->AddElement(a); - newbath->AddElement(actives); - TEveElement::List_t matches3; - re = TPRegexp("passive*"); - bath->FindChildren(matches3, re); - for (auto a : matches3) passives->AddElement(a); - newbath->AddElement(passives); - barrel->RemoveElement(bath); - // hide elements inside bath by default because they are slow in 3D - newbath->SetRnrSelfChildren(true, false); - } - gEve->AddGlobalElement(geom); - gEve->AddToListTree(geom, true); - } - else { - // the barrel envelope - barrel = new TEveGeoShape("Barrel"); - barrel->SetShape(new TGeoTube(rMin, rMax, zMax)); - barrel->SetMainColor(kCyan); - barrel->SetMainTransparency(90); - barrel->SetNSegments(128); - // geom->AddElement(barrel); - gEve->AddGlobalElement(barrel); - // the barrel layers - TEveElementList* layers = new TEveElementList("layers"); - barrel->AddElement(layers); - TEveGeoShape* b; - for (int iLayer=0; iLayerSetShape(new TGeoTube(r[iLayer], r[iLayer+1], zMax)); - b->SetMainColor(kCyan); - b->SetMainTransparency(90); - b->SetNSegments(128); - layers->AddElement(b); - } - // the electrodes - TEveElementList* modules = new TEveElementList("modules"); - barrel->AddElement(modules); - for (int iModule=0; iModuleSetShape(new TGeoBBox(Ltot/2, 0.01, (zMax-zMin)/2.0)); - b->SetMainColor(kGray); - b->SetMainTransparency(95); - TGeoRotation* rot = new TGeoRotation(); - rot->SetAngles((alpha+iModule*gridPhi)*180./TMath::Pi(), 0., 0.); - TGeoCombiTrans* c1 = new TGeoCombiTrans(rAvg*cos(phi), rAvg*sin(phi), 0.0, rot); - b->SetTransMatrix(*c1); - modules->AddElement(b); - } - gEve->AddToListTree(barrel, true); - } - - gEve->AddToListTree(readout,true); - - // create second tab (R-phi view) - rhoPhiView = gEve->SpawnNewViewer("Projection Rho-Phi"); - // two scenes, for geometry and event - rhoPhiScene = gEve->SpawnNewScene("Rho-Phi geometry", - "Scene holding projected geometry data for the RhoPhi view."); - rhoPhiView->AddScene(rhoPhiScene); - rhoPhiEventScene = gEve->SpawnNewScene("RhoPhi Event Data", - "Scene holding projected event-data for the RhoPhi view."); - rhoPhiView->AddScene(rhoPhiEventScene); - rhoPhiEventSceneManual = gEve->SpawnNewScene("RhoPhi Event Data 2", - "Scene holding hand-crafted event-data for the RhoPhi view."); - rhoPhiView->AddScene(rhoPhiEventSceneManual); - rhoPhiGLView = rhoPhiView->GetGLViewer(); - // set camera orientation - rhoPhiGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); - // create 3D->2D projection manager for rho-phi - rhoPhiProjManager = new TEveProjectionManager(); - rhoPhiProjManager->SetProjection(TEveProjection::kPT_RPhi); - auto axes = new TEveProjectionAxes(rhoPhiProjManager); - axes->SetElementName("Rho-Phi projection axes"); - rhoPhiScene->AddElement(axes); - if (useG4geom) - rhoPhiProjManager->ImportElements(geom, rhoPhiScene); - else - rhoPhiProjManager->ImportElements(barrel, rhoPhiScene); - - // the merged module grid - TEveStraightLineSet* gridmod = new TEveStraightLineSet("phi readout merged"); - gridmod->SetLineColor(kViolet+2); - gridmod->SetLineWidth(8); - for (int iLayer=0; iLayerAddLine(x1, y1, 0., x2, y2, 0.); - } - } - // add to scene? - rhoPhiScene->AddElement(gridmod); - readout->AddElement(gridmod); - - // third tab (R-z view) - rhoZView = gEve->SpawnNewViewer("Projection Rho-Z"); - rhoZScene = gEve->SpawnNewScene("Rho-Z geometry", - "Scene holding projected geometry data for the RhoZ view."); - rhoZView->AddScene(rhoZScene); - rhoZEventScene = gEve->SpawnNewScene("RhoZ Event Data", - "Scene holding projected event-data for the RhoZ view."); - rhoZView->AddScene(rhoZEventScene); - rhoZEventSceneManual = gEve->SpawnNewScene("RhoZ Event Data 2", - "Scene holding hand-crafted event-data for the RhoZ view."); - rhoZView->AddScene(rhoZEventSceneManual); - rhoZGLView = rhoZView->GetGLViewer(); - rhoZGLView->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); - - rhoZProjManager = new TEveProjectionManager(); - rhoZProjManager->SetProjection(TEveProjection::kPT_RhoZ); - auto axes2 = new TEveProjectionAxes(rhoZProjManager); - axes2->SetElementName("Rho-Z projection axes"); - rhoZScene->AddElement(axes2); - if (useG4geom) - rhoZProjManager->ImportElements(geom, rhoZScene); - else - rhoZProjManager->ImportElements(barrel, rhoZScene); - - // the theta readout grid - TEveStraightLineSet* grid = new TEveStraightLineSet("theta readout"); - grid->SetLineColor(kViolet); - for (int iTheta=0; iTheta<=nThetaBins; iTheta++) { - double theta = thetaMin + iTheta*thetaGrid; - double r1 = rMin; - double r2 = rMax; - double z1 = r1*cos(theta)/sin(theta); - double z2 = r2*cos(theta)/sin(theta); - if (z1zMin) { - if (z2>zMax) { - z2 = zMax; - r2 = z2*sin(theta)/cos(theta); - } - if (z2AddLine(z1, r1, 0., z2, r2, 0.); - grid->AddLine(z1, -r1, 0., z2, -r2, 0.); - } - } - rhoZScene->AddElement(grid); - readout->AddElement(grid); - - // the merged grid - TEveStraightLineSet* grid2 = new TEveStraightLineSet("theta readout merged"); - grid2->SetLineColor(kViolet+2); - grid2->SetLineWidth(8); - for (int iLayer=0; iLayerzMin) { - if (z2>zMax) { - z2 = zMax; - r2tmp = z2*sin(theta)/cos(theta); - } - if (z2AddLine(z1, r1, 0., - z2, r2tmp, 0.); - grid2->AddLine(z1, -r1, 0., - z2, -r2tmp, 0.); - } - } - } - rhoZScene->AddElement(grid2); - readout->AddElement(grid2); - - - gEve->Redraw3D(true); - - - makeGui(); - - // - // data - // - - // setup the reader - TFile* f = TFile::Open(evtFile.c_str(), "READ"); - eventReader = new EventReader(f); - - // load and display the requested event - eventReader->loadEvent(evt); - - // Set the 3D view as the active tab and rotate the camera - gEve->GetBrowser()->GetTabRight()->SetTab(0); - - // Draw - gEve->Redraw3D(true); -} - - -/******************************************************************************/ -// GUI -/******************************************************************************/ - -//______________________________________________________________________________ -// -// EvNavHandler class is needed to connect GUI signals. - -class EvNavHandler -{ -public: - void Fwd() - { - if (eventId < nEvents - 1) { - ++eventId; - eventReader->loadEvent(); - } else { - textEntry->SetTextColor(0xff0000); - textEntry->SetText("Already at last event"); - printf("Already at last event.\n"); - } - } - void Bck() - { - if (eventId > 0) { - --eventId; - eventReader->loadEvent(); - } else { - textEntry->SetTextColor(0xff0000); - textEntry->SetText("Already at first event"); - printf("Already at first event.\n"); - } - } -}; - -void makeGui() -{ - // Create minimal GUI for event navigation. - - TEveBrowser* browser = gEve->GetBrowser(); - browser->StartEmbedding(TRootBrowser::kLeft); - - TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600); - frmMain->SetWindowName("GUI"); - frmMain->SetCleanup(kDeepCleanup); - - TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain); - { - - TString icondir( Form("%s/icons/", gSystem->Getenv("ROOTSYS")) ); - TGPictureButton* b = 0; - EvNavHandler *fh = new EvNavHandler; - - b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoBack.gif")); - hf->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 10, 2, 10, 10)); - b->Connect("Clicked()", "EvNavHandler", fh, "Bck()"); - - b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoForward.gif")); - hf->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 10, 10, 10)); - b->Connect("Clicked()", "EvNavHandler", fh, "Fwd()"); - - textEntry = new TGTextEntry(hf); - textEntry->SetEnabled(kFALSE); - hf->AddFrame(textEntry, new TGLayoutHints(kLHintsLeft | kLHintsCenterY | - kLHintsExpandX, 2, 10, 10, 10)); - - } - frmMain->AddFrame(hf); - - frmMain->MapSubwindows(); - frmMain->Resize(); - frmMain->MapWindow(); - - browser->StopEmbedding(); - browser->SetTabTitle("Event Control", 0); -} From db9b4a038437364274e1bcc851b883b9b9539a54 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Tue, 17 Oct 2023 12:22:20 +0200 Subject: [PATCH 28/33] update README for theta-based segmentation and fix capacitance calculation --- geometry/README.md | 5 ++ geometry/create_capacitance_file_theta.py | 71 +++++++---------------- 2 files changed, 26 insertions(+), 50 deletions(-) diff --git a/geometry/README.md b/geometry/README.md index 3a8c500..aa63e40 100644 --- a/geometry/README.md +++ b/geometry/README.md @@ -5,4 +5,9 @@ Upon detector geometry change, the noise values, noise maps and neighbor maps (u - `create_noise_file_chargePreAmp.py` uses the output of `create_capacitance_file.py` to create a TFile with noise vs eta for the different layers. The noise is derived based on [this](https://indico.cern.ch/event/1066234/contributions/4708987/attachments/2387716/4080914/20220209_Brieuc_Francois_Noble_Liquid_Calorimetry_forFCCee_FCCworkshop2022.pdf#page=7). - you then have to go to `../FCCSW_ecal` to run `neighbours.py` and `noise_map.py` (make sure you modify `BarrelNoisePath` in the latter script to point to your new noise values) +If using the theta-module segmentation (with inclined modules and merging of cells along theta and/or module directions) then the following scripts should be used instead: +- `create_capacitance_file_theta.py` +- `create_noise_file_chargePreAmp_theta.py` +- you then have to go to `../FCCSW_ecal` to run `neighbours_theta.py` and `noise_map_theta.py` + NB: At the moment those files are provided from `/eos/user/b/brfranco/rootfile_storage/` (which has restricted writing permissions) as explained in the main README. This should probably be updated to take them from e.g. a public cern box link but meanwhile you can just point `TopoCaloNeighbours` and `TopoCaloNoisyCells` to the local updated files or contact Brieuc so that he updates the files directly there. diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index 59b4670..936ef60 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -17,23 +17,7 @@ verbose = True #Dimensions -### FCCee -#ECalConstruction INFO ECAL cryostat: front: rmin (cm) = 210 rmax (cm) = 215 dz (cm) = 226 -#ECalConstruction INFO ECAL cryostat: back: rmin (cm) = 260 rmax (cm) = 270 dz (cm) = 226 -#ECalConstruction INFO ECAL cryostat: side: rmin (cm) = 215 rmax (cm) = 260 dz (cm) = 10 -#ECalConstruction INFO ECAL services: front: rmin (cm) = 215 rmax (cm) = 216 dz (cm) = 216 -#ECalConstruction INFO ECAL services: back: rmin (cm) = 256 rmax (cm) = 260 dz (cm) = 216 -#ECalConstruction INFO ECAL bath: material = LAr rmin (cm) = 216 rmax (cm) = 256 thickness in front of ECal (cm) = 1 thickness behind ECal (cm) = 4 -#ECalConstruction INFO ECAL calorimeter volume rmin (cm) = 216 rmax (cm) = 256 -#ECalConstruction INFO passive inner material = Lead and outer material = lArCaloSteel thickness of inner part (cm) = 0.14 thickness of outer part (cm) = 0.04 thickness of total (cm) = 0.2 rotation angle = 0.872665 -#ECalConstruction INFO number of passive plates = 1536 azim. angle difference = 0.00409062 -#ECalConstruction INFO distance at inner radius (cm) = 0.883573 distance at outer radius (cm) = 1.0472 -#ECalConstruction INFO readout material = PCB thickness of readout planes (cm) = 0.12 number of readout layers = 12 -#ECalConstruction INFO thickness of calorimeter (cm) = 40 length of passive or readout planes (cm) = 56.4964 -#ECalConstruction INFO active material = LAr active layers thickness at inner radius (cm) = 0.247949 thickness at outer radious (cm) = 0.479746 making 93.4857 % increase. -#ECalConstruction INFO active passive initial overlap (before subtraction) (cm) = 0.1 = 50 % - -# latest version +### FCCee, latest version, with LAr gap size adjusted to obtain 1536 modules (default gives 1545) # Debug: Number of layers: 12 total thickness 40 # Info: ECAL cryostat: front: rmin (cm) = 215.4 rmax (cm) = 216.78 dz (cm) = 310 # Info: ECAL cryostat: back: rmin (cm) = 261.33 rmax (cm) = 271.6 dz (cm) = 310 @@ -64,20 +48,6 @@ # layer 2 require special care as it is separated in several cells and that the shield run beneath the etch: cell 2 signal pad top capa: 0.68 + 0.20 = 0.88, cell 2 signal pad bot: 0.56 + 0.21 = 0.77, cell 3: 0.34 + 2.4 = 2.74, cell 4: 1 + 0.25 = 1.25, cell 5: 1.85 + 0.28 = 2.13 # 1*15mm + 11*35mm = 400 -# activeTotal = 400.0 -# inclinedTotal = 564.964 -# tracesPerLayer = [6, 1, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7] # only one trace for strip layer because 4 cells instead of one -# ncells_strip_layer = 4.0 -# careful, this is not really the radial spacing, it is, after dilution, the spacing in the parallel direction --> radial depth spacing will not be constant -# readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 -# Detector -# rmin = 2160 -# Nplanes = 1536 -# inclination_degree = 50 -# angle = inclination_degree / 180. * pi #inclination angle inn radian -# passiveThickness = 2.0 #mm - -# latest activeTotal = 400.5 inclinedTotal = 565.86 tracesPerLayer = [6, 1, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7] # only one trace for strip layer because 4 cells instead of one @@ -86,7 +56,7 @@ readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 # Detector rmin = 2172.8 -Nplanes = 1545 +Nplanes = 1536 inclination_degree = 50 angle = inclination_degree / 180. * pi #inclination angle inn radian passiveThickness = 2.0 #mm @@ -127,14 +97,16 @@ epsilonR = 4.4 # PCB #conversion factor: 1 inch = 25.4 mm inch2mm = 25.4 -#capa per length from maxwel +#capa per length from maxwel1 capa_per_mm = 0.123 # pF/mm capa_per_mm_stripLayer = 0.062 # pF/mm -# multiplicative factor -# factor two because we merge two phi cells together, another factor 2 because we have two 1) signal pad / shield capa 2) HV plate / absorber capa per cell -nmult = 2 -nmult_trace = 1 # for the trace only the number of phi cell merged playes a role -# GM: should the above two be 4 and 2 since we merge 2 phi cells together? +# multiplicative factors +# factor two because we merge two phi cells together +numberOfMergedCellsInPhi = 2 +# for the trace, another factor 2 because we have two HV plate / absorber capa per cell +nmultTrace = 2 +# for the shield, where we use maxwell, the extra factor 2 (two signal pad / shield capa) is already accounted for +nmultShield = 1 epsilonRLAr = 1.5 # LAr at 88 K epsilon0 = 8.854/1000. #pF/mm @@ -154,7 +126,7 @@ for idx in range(numLayers):# first pass to get all length parallel to the readout, real radial separation, inclination at the middle of the layer readoutLayerRadialLengths[idx] *= 10 parallel_length = readoutLayerRadialLengths[idx] * dilution_factor - # Tricky point: in the xml geo, you define 'radial'segmentation, but these depths will be the one parallel to the plates after scaling by the dilution factor --> even when setting constant radial depth, the geoemtry builder will make constant parallel length step, not constant radial steps + # Tricky point: in the xml geo, you define 'radial'segmentation, but these depths will be the one parallel to the plates after scaling by the dilution factor --> even when setting constant radial depth, the geometry builder will make constant parallel length step, not constant radial steps readoutLayerParallelLengths.append(parallel_length) if outer: # prepare the starting trace length when starting to extract by the back of the PCB trace_length_outer += parallel_length @@ -275,25 +247,24 @@ print("eta = ", eta) print("delta eta = ", deltaEta) - # take into account the inclination in eta - #traceLength = trace_length[i] / (sin(2. * atan(exp(-eta)))) + # take into account the inclination in theta traceLength = trace_length[i] / sin(theta) #print("Layer %d trace length %f"%(i+1, traceLength)) #Trace capacitance (stripline) logStripline = log(3.1 * hs / (0.8 * w + t)) - capacitanceTrace = nmult_trace * 1 / inch2mm * 1.41 * epsilonR / logStripline * traceLength + # analytical formula + capacitanceTrace = nmultTrace * numberOfMergedCellsInPhi * 1 / inch2mm * 1.41 * epsilonR / logStripline * traceLength hCapTrace[i].SetBinContent(index+1, capacitanceTrace) #Shield capacitance (microstrip) - #cellLength = readoutLayerParallelLengths[i] / (sin(2. * atan(exp(-eta)))) cellLength = readoutLayerParallelLengths[i] / sin(theta) logMicrostrip = log(5.98 * hm / (0.8 * ws + t)) - # analytical formula - #capacitanceShield = nmult * cellLength * tracesPerLayer[i] * 1 / inch2mm * 0.67 * (epsilonR + 1.41) / logMicrostrip - # from maxwell - capacitanceShield = nmult * cellLength * tracesPerLayer[i] * capa_per_mm + # analytical formula (nmultShield = 2) + #capacitanceShield = nmultShield * numberOfMergedCellsInPhi * cellLength * tracesPerLayer[i] * 1 / inch2mm * 0.67 * (epsilonR + 1.41) / logMicrostrip + # from maxwell (nmultShield = 1) + capacitanceShield = nmultShield * numberOfMergedCellsInPhi * cellLength * tracesPerLayer[i] * capa_per_mm if i == 1: #strip layer has smaller capacitance due to traces running beneath the anti-etch - capacitanceShield = nmult * cellLength * tracesPerLayer[i] * capa_per_mm_stripLayer + capacitanceShield = numberOfMergedCellsInPhi * cellLength * tracesPerLayer[i] * capa_per_mm_stripLayer if capacitanceShield > capa_shield_max: capa_shield_max = capacitanceShield hCapShield[i].SetBinContent(index+1, capacitanceShield) @@ -308,13 +279,13 @@ area = abs( real_radial_separation[i] * ( 1 / tan(thetaNext) - 1 / tan(theta) ) + real_radial_separation[i + 1] * ( 1 / tan(thetaNext) - 1 / tan(theta)) ) / 2. * (real_radial_separation[i+1] - real_radial_separation[i]) - # get the cell size perpendicular to the plate direction from the cell size on the circle at given radius and the inclination w.r.t. radial dir, then remove the PCB and lead thickness (no need for any factor here because we are perpendicular to the PCB and lead plates) --> gives the LAr gap sizxe perpendicular + # get the cell size perpendicular to the plate direction from the cell size on the circle at given radius and the inclination w.r.t. radial dir, then remove the PCB and lead thickness (no need for any factor here because we are perpendicular to the PCB and lead plates) --> gives the LAr gap size perpendicular distance = (2 * pi * (real_radial_separation[i+1] + real_radial_separation[i]) / 2. / Nplanes * cos (inclinations_wrt_radial_dir_at_middleRadialDepth[i]) - pcbThickness - passiveThickness) / 2. # divided by two because two lar gap per cell distance += hhv #the capa is between signal plate and absorber --> need to add distance between HV plate and signal pad distance += t #the capa is between signal plate and absorber --> need to add distance between HV plate and signal pad if (abs(theta - pi/2.)<1e-4): print("LAr gap size (perpendicular) + hhv + t: %f mm"%distance) - capacitanceDetector = nmult * epsilon0 * epsilonRLAr * area / distance + capacitanceDetector = numberOfMergedCellsInPhi * epsilon0 * epsilonRLAr * area / distance if i == 1: #strip layer has smaller capacitance because it is divided in 4 smaller cells capacitanceDetector /= ncells_strip_layer hCapDetector[i].SetBinContent(index+1, capacitanceDetector) From 23b93aa7cf2f95a495cb9a1d28a6f77a0d05f7d4 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Thu, 19 Oct 2023 17:12:05 +0200 Subject: [PATCH 29/33] set readout use for topoclustering in default scripts not using the theta-module readout --- FCCSW_ecal/runClueAndTopoAndSlidingWindowAndCaloSim.py | 1 + FCCSW_ecal/runTopoAndSlidingWindowAndCaloSim.py | 1 + 2 files changed, 2 insertions(+) diff --git a/FCCSW_ecal/runClueAndTopoAndSlidingWindowAndCaloSim.py b/FCCSW_ecal/runClueAndTopoAndSlidingWindowAndCaloSim.py index 31dd4cc..5af9853 100644 --- a/FCCSW_ecal/runClueAndTopoAndSlidingWindowAndCaloSim.py +++ b/FCCSW_ecal/runClueAndTopoAndSlidingWindowAndCaloSim.py @@ -373,6 +373,7 @@ #positionsHECTool = HECcells, #positionsEMFwdTool = ECalFwdcells, #positionsHFwdTool = HCalFwdcells, + readoutName = ecalBarrelReadoutNamePhiEta, seedSigma = 4, neighbourSigma = 2, lastNeighbourSigma = 0, diff --git a/FCCSW_ecal/runTopoAndSlidingWindowAndCaloSim.py b/FCCSW_ecal/runTopoAndSlidingWindowAndCaloSim.py index 043d66e..a4f3ba2 100644 --- a/FCCSW_ecal/runTopoAndSlidingWindowAndCaloSim.py +++ b/FCCSW_ecal/runTopoAndSlidingWindowAndCaloSim.py @@ -399,6 +399,7 @@ #positionsHECTool = HECcells, #positionsEMFwdTool = ECalFwdcells, #positionsHFwdTool = HCalFwdcells, + readoutName = ecalBarrelReadoutNamePhiEta, seedSigma = 4, neighbourSigma = 2, lastNeighbourSigma = 0, From 08c4b8dda37c4de03388cfc9d04375b604ed2f9c Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 23 Oct 2023 10:06:57 +0200 Subject: [PATCH 30/33] update traces per layer to version where we read out everything from the back --- geometry/create_capacitance_file_theta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index 936ef60..dbb99da 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -50,7 +50,7 @@ # 1*15mm + 11*35mm = 400 activeTotal = 400.5 inclinedTotal = 565.86 -tracesPerLayer = [6, 1, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7] # only one trace for strip layer because 4 cells instead of one +tracesPerLayer = [0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] # only one trace for strip layer because 4 cells instead of one. Version where we extract all channels from the back ncells_strip_layer = 4.0 # careful, this is not really the radial spacing, it is, after dilution, the spacing in the parallel direction --> radial depth spacing will not be constant readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 From 34a50be6a3df98ad06901f176f28fb31a425cc59 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Tue, 24 Oct 2023 10:15:45 +0200 Subject: [PATCH 31/33] fix crash --- FCCSW_ecal/noise_map_theta.py | 1 - 1 file changed, 1 deletion(-) diff --git a/FCCSW_ecal/noise_map_theta.py b/FCCSW_ecal/noise_map_theta.py index b832a7c..8f7638d 100644 --- a/FCCSW_ecal/noise_map_theta.py +++ b/FCCSW_ecal/noise_map_theta.py @@ -40,7 +40,6 @@ OutputLevel = INFO) HCalNoiseTool = ReadNoiseFromFileTool("ReadNoiseFromFileToolHCal", - useSegmentation = True, readoutName = hcalBarrelReadoutName, noiseFileName = BarrelNoisePath, elecNoiseHistoName = ecalBarrelNoiseHistName, From dc99d4a8b97024ffd9fcc5b51e78ac7ad5a77445 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 25 Oct 2023 00:03:59 +0200 Subject: [PATCH 32/33] fix capacitance calculation for arbbitrary merging of cells --- geometry/create_capacitance_file_theta.py | 30 ++++++++++------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index dbb99da..c1ed740 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -51,7 +51,8 @@ activeTotal = 400.5 inclinedTotal = 565.86 tracesPerLayer = [0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] # only one trace for strip layer because 4 cells instead of one. Version where we extract all channels from the back -ncells_strip_layer = 4.0 +nMergedThetaCells = [4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4] +nMergedModules = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] # careful, this is not really the radial spacing, it is, after dilution, the spacing in the parallel direction --> radial depth spacing will not be constant readoutLayerRadialLengths = [1.500000] * 1 + [3.500000] * 11 # Detector @@ -61,7 +62,7 @@ angle = inclination_degree / 180. * pi #inclination angle inn radian passiveThickness = 2.0 #mm #Segmentation -deltaTheta = 0.009817477 +deltaTheta = 0.009817477/4. minTheta = 0.58905 maxTheta = pi-minTheta numTheta = int(ceil((maxTheta-minTheta)/deltaTheta)) @@ -97,16 +98,15 @@ epsilonR = 4.4 # PCB #conversion factor: 1 inch = 25.4 mm inch2mm = 25.4 -#capa per length from maxwel1 -capa_per_mm = 0.123 # pF/mm -capa_per_mm_stripLayer = 0.062 # pF/mm +# capa per length from maxwel1 (pF/mm) +# strip layer has smaller capacitance due to traces running beneath the anti-etch +capa_per_mm = [0.123, 0.062, 0.123, 0.123, 0.123, 0.123, 0.123, 0.123, 0.123, 0.123, 0.123, 0.123] # multiplicative factors -# factor two because we merge two phi cells together -numberOfMergedCellsInPhi = 2 -# for the trace, another factor 2 because we have two HV plate / absorber capa per cell +# for the trace, factor 2 because we have two HV plate / absorber capa per cell nmultTrace = 2 # for the shield, where we use maxwell, the extra factor 2 (two signal pad / shield capa) is already accounted for nmultShield = 1 +# dielectric constants epsilonRLAr = 1.5 # LAr at 88 K epsilon0 = 8.854/1000. #pF/mm @@ -250,21 +250,19 @@ # take into account the inclination in theta traceLength = trace_length[i] / sin(theta) #print("Layer %d trace length %f"%(i+1, traceLength)) - #Trace capacitance (stripline) + #Trace capacitance (stripline) - not used since already accounted for elsewhere logStripline = log(3.1 * hs / (0.8 * w + t)) # analytical formula - capacitanceTrace = nmultTrace * numberOfMergedCellsInPhi * 1 / inch2mm * 1.41 * epsilonR / logStripline * traceLength + capacitanceTrace = nmultTrace * 1 / inch2mm * 1.41 * epsilonR / logStripline * traceLength hCapTrace[i].SetBinContent(index+1, capacitanceTrace) #Shield capacitance (microstrip) cellLength = readoutLayerParallelLengths[i] / sin(theta) logMicrostrip = log(5.98 * hm / (0.8 * ws + t)) # analytical formula (nmultShield = 2) - #capacitanceShield = nmultShield * numberOfMergedCellsInPhi * cellLength * tracesPerLayer[i] * 1 / inch2mm * 0.67 * (epsilonR + 1.41) / logMicrostrip + #capacitanceShield = nmultShield * nMergedModules[i] * cellLength * tracesPerLayer[i] * 1 / inch2mm * 0.67 * (epsilonR + 1.41) / logMicrostrip # from maxwell (nmultShield = 1) - capacitanceShield = nmultShield * numberOfMergedCellsInPhi * cellLength * tracesPerLayer[i] * capa_per_mm - if i == 1: #strip layer has smaller capacitance due to traces running beneath the anti-etch - capacitanceShield = numberOfMergedCellsInPhi * cellLength * tracesPerLayer[i] * capa_per_mm_stripLayer + capacitanceShield = nmultShield * nMergedModules[i] * nMergedThetaCells[i] * cellLength * tracesPerLayer[i] * capa_per_mm[i] if capacitanceShield > capa_shield_max: capa_shield_max = capacitanceShield hCapShield[i].SetBinContent(index+1, capacitanceShield) @@ -285,9 +283,7 @@ distance += t #the capa is between signal plate and absorber --> need to add distance between HV plate and signal pad if (abs(theta - pi/2.)<1e-4): print("LAr gap size (perpendicular) + hhv + t: %f mm"%distance) - capacitanceDetector = numberOfMergedCellsInPhi * epsilon0 * epsilonRLAr * area / distance - if i == 1: #strip layer has smaller capacitance because it is divided in 4 smaller cells - capacitanceDetector /= ncells_strip_layer + capacitanceDetector = nMergedModules[i] * nMergedThetaCells[i] * 2 * epsilon0 * epsilonRLAr * area / distance # factor 2 is because there are 2 LAr gaps for each cell hCapDetector[i].SetBinContent(index+1, capacitanceDetector) if capacitanceDetector > capa_det_max: capa_det_max = capacitanceDetector From a32414795585608b0a6a6987d3f2cef60b9444a7 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Wed, 25 Oct 2023 10:14:01 +0200 Subject: [PATCH 33/33] fix double counting of merged theta cells impact on shield capacitance --- geometry/create_capacitance_file_theta.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geometry/create_capacitance_file_theta.py b/geometry/create_capacitance_file_theta.py index c1ed740..2888eeb 100644 --- a/geometry/create_capacitance_file_theta.py +++ b/geometry/create_capacitance_file_theta.py @@ -262,7 +262,9 @@ # analytical formula (nmultShield = 2) #capacitanceShield = nmultShield * nMergedModules[i] * cellLength * tracesPerLayer[i] * 1 / inch2mm * 0.67 * (epsilonR + 1.41) / logMicrostrip # from maxwell (nmultShield = 1) - capacitanceShield = nmultShield * nMergedModules[i] * nMergedThetaCells[i] * cellLength * tracesPerLayer[i] * capa_per_mm[i] + # dont multiply by nMergedThetaCells: the shield/pad capa is reasonably independent of the cell size and the fact that there is some merging + # done for theta cells is already taken into account by the tracesPerLayer + capacitanceShield = nmultShield * nMergedModules[i] * cellLength * tracesPerLayer[i] * capa_per_mm[i] if capacitanceShield > capa_shield_max: capa_shield_max = capacitanceShield hCapShield[i].SetBinContent(index+1, capacitanceShield)