diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_logE-101302.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_logE-101302.json index 8ae524dc0453e65117e33137ce2ddb081226887f..76ba19e1146b9107c3365cc5c5dd867ff26e6c94 100644 --- a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_logE-101302.json +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_logE-101302.json @@ -9,5 +9,5 @@ "sampler": "log", "segment": 0, "short": "MDC_PG_muon_fasernu_logE", - "zpos": -5000.0 + "zpos": -4000.0 } diff --git a/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py b/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py index 607ce904658f777b0403a5b452b58b4160f66b0e..b48bbf861ed4bbac6e0a6fb6cc9fd95da5049138 100755 --- a/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py +++ b/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py @@ -113,6 +113,14 @@ if __name__ == '__main__': #if args.zpos: # ConfigFlags.Sim.Gun["z"] = args.zpos + doShiftLOS = (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or + ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift) + + if doShiftLOS: + pgConfig = ConfigFlags.Sim.Gun + pgConfig["McEventKey"] = "BeamTruthEvent_ATLASCoord" + ConfigFlags.Sim.Gun = pgConfig + # # MDC geometry configuration # @@ -153,26 +161,22 @@ if __name__ == '__main__': # Shift LOS # - if (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or - ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift): - - MCEventKey = "BeamTruthEventShifted" + if doShiftLOS: import McParticleEvent.Pythonizations from GeneratorUtils.ShiftLOSConfig import ShiftLOSCfg - cfg.merge(ShiftLOSCfg(ConfigFlags, OutputMCEventKey = MCEventKey, + + cfg.merge(ShiftLOSCfg(ConfigFlags, xcross = ConfigFlags.Sim.Beam.xangle, ycross = ConfigFlags.Sim.Beam.yangle, xshift = ConfigFlags.Sim.Beam.xshift, yshift = ConfigFlags.Sim.Beam.yshift)) - else: - MCEventKey = "BeamTruthEvent" # # Add the G4FaserAlg # from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg - cfg.merge(G4FaserAlgCfg(ConfigFlags, InputTruthCollection = MCEventKey)) + cfg.merge(G4FaserAlgCfg(ConfigFlags)) # # Dump config # diff --git a/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py b/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py index c9f9154ef986e4216e07a38f0114f8bd1511b230..20970fdf37f5fb28f102949e5ef35cd1372f193c 100755 --- a/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py +++ b/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py @@ -124,6 +124,14 @@ if __name__ == '__main__': # Pass this in one go to ConfigFlags ConfigFlags.Sim.Gun = sg_dict + doShiftLOS = (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or + ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift) + + if doShiftLOS: + pgConfig = ConfigFlags.Sim.Gun + pgConfig["McEventKey"] = "BeamTruthEvent_ATLASCoord" + ConfigFlags.Sim.Gun = pgConfig + # # MDC geometry configuration # @@ -164,26 +172,22 @@ if __name__ == '__main__': # Shift LOS # - if (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or - ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift): - - MCEventKey = "BeamTruthEventShifted" + if doShiftLOS: import McParticleEvent.Pythonizations from GeneratorUtils.ShiftLOSConfig import ShiftLOSCfg - cfg.merge(ShiftLOSCfg(ConfigFlags, OutputMCEventKey = MCEventKey, + + cfg.merge(ShiftLOSCfg(ConfigFlags, xcross = ConfigFlags.Sim.Beam.xangle, ycross = ConfigFlags.Sim.Beam.yangle, xshift = ConfigFlags.Sim.Beam.xshift, yshift = ConfigFlags.Sim.Beam.yshift)) - else: - MCEventKey = "BeamTruthEvent" # # Add the G4FaserAlg # from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg - cfg.merge(G4FaserAlgCfg(ConfigFlags, InputTruthCollection = MCEventKey)) + cfg.merge(G4FaserAlgCfg(ConfigFlags)) # # Dump config # diff --git a/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py index f9003eeceda4528ce2a7af132971c5e1e5447cd2..942340f12c97db7e80850e0ede3be55d44bda54d 100755 --- a/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py +++ b/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py @@ -191,7 +191,7 @@ itemList = [ "xAOD::EventInfo#*" # if args.isMC: # Add truth records here? - itemList.extend( ["McEventCollection#*"] ) + itemList.extend( ["McEventCollection#*", "TrackerSimDataCollection#*"] ) acc.merge(OutputStreamCfg(ConfigFlags, "xAOD", itemList)) diff --git a/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh b/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh index 60c39ca370330fcad5432523d33740722b754a8f..b04d56aa9d13f3bac39f02213e0f47625714c689 100755 --- a/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh +++ b/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh @@ -124,7 +124,7 @@ fi cd "$file_stem" # # Run job -if [[ -z "$rtag" ]]; then +if [[ -z "$tag" ]]; then faserMDC_reco.py "--nevents=$nevents" "$file_path" else faserMDC_reco.py "--nevents=$nevents" "--reco=$tag" "$file_path" diff --git a/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py b/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py index 323adda69d9228ecdbde65431b09bf42a579745d..12de492f4070237b59dda273673b994bbc275d37 100755 --- a/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py +++ b/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py @@ -127,6 +127,7 @@ if __name__ == '__main__': # Skip events # ConfigFlags.Exec.SkipEvents = args.skip + ConfigFlags.Exec.MaxEvents = args.nevents # # Output file name # @@ -153,6 +154,9 @@ if __name__ == '__main__': # import sys # ConfigFlags.fillFromArgs(sys.argv[1:]) + doShiftLOS = (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or + ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift) + # # MDC geometry configuration # @@ -178,7 +182,11 @@ if __name__ == '__main__': if ConfigFlags.Input.Files[0].endswith(".events") or ConfigFlags.Input.Files[0].endswith(".hepmc"): from HEPMCReader.HepMCReaderConfig import HepMCReaderCfg - cfg.merge(HepMCReaderCfg(ConfigFlags)) + + if doShiftLOS: + cfg.merge(HepMCReaderCfg(ConfigFlags, McEventKey = "BeamTruthEvent_ATLASCoord")) + else: + cfg.merge(HepMCReaderCfg(ConfigFlags)) from McEventSelector.McEventSelectorConfig import McEventSelectorCfg cfg.merge(McEventSelectorCfg(ConfigFlags)) @@ -189,6 +197,11 @@ if __name__ == '__main__': from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg cfg.merge(PoolReadCfg(ConfigFlags)) + if doShiftLOS: + from SGComps.AddressRemappingConfig import InputOverwriteCfg + # Rename old truth collection to add ATLAS coord to can still use BeamTruthEvent for the one in FASER Coords + cfg.merge(InputOverwriteCfg("McEventCollection", "BeamTruthEvent", "McEventCollection", "BeamTruthEvent_ATLASCoord")) + # # Output file # @@ -198,26 +211,22 @@ if __name__ == '__main__': # # Shift LOS # - if (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or - ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift): + if doShiftLOS: - MCEventKey = "BeamTruthEventShifted" import McParticleEvent.Pythonizations from GeneratorUtils.ShiftLOSConfig import ShiftLOSCfg - cfg.merge(ShiftLOSCfg(ConfigFlags, OutputMCEventKey = MCEventKey, + cfg.merge(ShiftLOSCfg(ConfigFlags, xcross = ConfigFlags.Sim.Beam.xangle, ycross = ConfigFlags.Sim.Beam.yangle, xshift = ConfigFlags.Sim.Beam.xshift, yshift = ConfigFlags.Sim.Beam.yshift)) - else: - MCEventKey = "BeamTruthEvent" # # Add the G4FaserAlg # from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg - cfg.merge(G4FaserAlgCfg(ConfigFlags, InputTruthCollection = MCEventKey)) + cfg.merge(G4FaserAlgCfg(ConfigFlags)) # # Dump config # @@ -235,10 +244,11 @@ if __name__ == '__main__': # Execute and finish # - if args.verbose: - cfg.foreach_component("*").OutputLevel = "DEBUG" - else: - cfg.foreach_component("*").OutputLevel = "INFO" + # This fails with ShiftLOSCfg... + #if args.verbose: + # cfg.foreach_component("*").OutputLevel = "DEBUG" + #else: + # cfg.foreach_component("*").OutputLevel = "INFO" sc = cfg.run(maxEvents=args.nevents) diff --git a/Control/CalypsoExample/Simulation/scripts/submit_faserMDC_simulate.sh b/Control/CalypsoExample/Simulation/scripts/submit_faserMDC_simulate.sh index e00adfd50005e3d3600a7a5df55a45039f89e391..3c175d72519eda6d9f973c84ea3c2b1af00b7dba 100755 --- a/Control/CalypsoExample/Simulation/scripts/submit_faserMDC_simulate.sh +++ b/Control/CalypsoExample/Simulation/scripts/submit_faserMDC_simulate.sh @@ -2,7 +2,10 @@ # Used with a condor file to submit to vanilla universe # # Usage: -# submit_faserMDC_simluate.sh input_file output_file [release_directory] [working_directory] [skip] [nevts] +# submit_faserMDC_simluate.sh [--shift] input_file output_file [release_directory] [working_directory] [skip] [nevts] +# +# Options: +# --shift - apply crossing angle (and FASER shift) # # input_file - full file name (with path) # output_file - full output file name @@ -22,6 +25,24 @@ SECONDS=0 # # Parse command-line options +while [ -n "$1" ] +do + case "$1" in + -s | --shift) + echo "Applying crossing-angle shift" + xangle=1 + shift;; # This 'eats' the argument + + -*) + echo "Unknown option $1" + shift;; + + *) break;; # Not an option, don't shift + esac +done + +# +# Parse command-line arguments infile=${1} outfile=${2} release_directory=${3} @@ -143,8 +164,11 @@ cd "${file_stem}" # Run job #if [[ -z "$tag" ]]; then #fi -faserMDC_simulate.py --skip "$skip_events" -n "$nevts" "$infile" "$outfile" - +if [[ -z "$xangle" ]]; then + faserMDC_simulate.py --skip "$skip_events" -n "$nevts" "$infile" "$outfile" +else + faserMDC_simulate.py --yangle -0.000150 --yshift 12.0 --skip "$skip_events" -n "$nevts" "$infile" "$outfile" +fi # # Print out ending time date diff --git a/Generators/FaserParticleGun/python/RadialPosSampler.py b/Generators/FaserParticleGun/python/RadialPosSampler.py index 814235e363a8ef5fb03df7a266676ff80247c672..6fcd6829b29ea474d5c7380526d3c46bab9c6871 100644 --- a/Generators/FaserParticleGun/python/RadialPosSampler.py +++ b/Generators/FaserParticleGun/python/RadialPosSampler.py @@ -34,6 +34,7 @@ class RadialPosSampler(Sampler): @property def r(self): "r position sampler" + fwhm = 2*self.radius sig = fwhm/(2 * sqrt(2 * log(2))) @@ -44,8 +45,6 @@ class RadialPosSampler(Sampler): y = random.gauss(0, self.radius) return sqrt(x**2 + y**2) - # return random.gauss(0, sig) - @property def phi(self): "phi position sampler" @@ -62,7 +61,7 @@ class RadialPosSampler(Sampler): return ROOT.TLorentzVector(x, y, z, t) if __name__ == "__main__": -# test when run from command line + # test when run from command line import numpy as np import matplotlib.pyplot as plt @@ -70,8 +69,8 @@ if __name__ == "__main__": xlist = [] ylist = [] - r = RadialPosSampler(r = 1, x = 10, y = -10, z = 10) - for i in range (10000): + r = RadialPosSampler(r = -10, x = 0, y = 0, z = 10) + for i in range (100000): res = r.shoot() xlist.append(res.X()) ylist.append(res.Y()) @@ -81,10 +80,13 @@ if __name__ == "__main__": plt.figure(figsize = (5,5)) plt.subplot(2,2,1) - plt.scatter(xarr, yarr, marker = "*") + plt.hist2d(xarr, yarr) plt.subplot(2,2,2) plt.hist(yarr) plt.subplot(2,2,3) plt.hist(xarr) + plt.subplot(2,2,4) + plt.hist(np.sqrt(xarr**2 + yarr**2)) plt.tight_layout() plt.show() + diff --git a/Generators/ForeseeGenerator/python/Validate.py b/Generators/ForeseeGenerator/python/Validate.py index 9c6be63475b6e066ece1ceac0aea059b8837a0dc..399d85ae788903d7f2829af6bd3239a69ddb0527 100644 --- a/Generators/ForeseeGenerator/python/Validate.py +++ b/Generators/ForeseeGenerator/python/Validate.py @@ -4,6 +4,7 @@ from GeneratorModules.EvgenAnalysisAlg import EvgenAnalysisAlg import ROOT as R import numpy as np import os +from math import sqrt def fix(): "Python Fixes for HepMC" @@ -63,9 +64,10 @@ class HistSvc(object): class EvgenValidation(EvgenAnalysisAlg): "Gen-level validation" - def __init__(self, name = "EvgenValidation", ndaughters = 2, outname = "validation.root"): + def __init__(self, name = "EvgenValidation", ndaughters = 2, outname = "validation.root", mother_stored = False): super(EvgenValidation, self).__init__(name=name) self.hists = HistSvc() + self.mother_stored = mother_stored self.ndaughters = ndaughters self.outname = outname @@ -80,7 +82,7 @@ class EvgenValidation(EvgenAnalysisAlg): def initialize(self): # All daughters - self.hists.add("PIDs", 60, -30, 30) + self.hists.add("PIDs", 600, -300, 300) # Daughter i tbins, pbins = self.binning() @@ -92,26 +94,30 @@ class EvgenValidation(EvgenAnalysisAlg): self.hists.add(f"Theta_d{i}", 20, 0, 0.001) self.hists.add(f"Phi_d{i}", 16, -3.2, 3.2) self.hists.add(f"ThetaVsP_d{i}", arrayX = tbins, arrayY = pbins) - self.hists.add(f"Mass_d{i}", 200, 0, 0.01) + self.hists.add(f"Mass_d{i}", 5000, 0, 1) # Mother - self.hists.add("E_M", 100, 0, 10000) - self.hists.add("P_M", 100, 0, 10000) - self.hists.add("Pz_M", 100, 0, 10000) - self.hists.add("Pt_M", 100, 0, 1) - self.hists.add("Theta_M", 20, 0, 0.001) + self.hists.add("E_M", 1000, 0, 10000) + self.hists.add("P_M", 1000, 0, 10000) + self.hists.add("Pz_M", 1000, 0, 10000) + self.hists.add("Pt_M", 1000, 0, 1) + self.hists.add("Theta_M", 200, 0, 0.02) self.hists.add("Phi_M", 16, -3.2, 3.2) - self.hists.add("Mass_M", 200, 0, 1) + self.hists.add("Mass_M", 200, 0, 2) self.hists.add("ThetaVsP_M", arrayX = tbins, arrayY = pbins) # Vertex - self.hists.add("Vtx_X", 50, -100, 100) - self.hists.add("Vtx_Y", 50, -100, 100) - # For fluka - #self.hists.add("Vtx_X", 100, -3000, 3000) - #self.hists.add("Vtx_Y", 100, -3000, 3000) - self.hists.add("Vtx_Z", 50, -1500, 0) - self.hists.add("Vtx_XY", 50, -100, 100, 50, -100, 100) + self.hists.add("Vtx_X_LLP", 50, -100, 100) + self.hists.add("Vtx_Y_LLP", 50, -100, 100) + self.hists.add("Vtx_Z_LLP", 500, -5000, 0) + self.hists.add("Vtx_R_LLP", 20, 0, 200) + self.hists.add("Vtx_XY_LLP", 50, -100, 100, 50, -100, 100) + + self.hists.add("Vtx_X_All", 50, -100, 100) + self.hists.add("Vtx_Y_All", 50, -100, 100) + self.hists.add("Vtx_Z_All", 500, -5000, 0) + self.hists.add("Vtx_R_All", 20, 0, 200) + self.hists.add("Vtx_XY_All", 50, -100, 100, 50, -100, 100) return StatusCode.Success @@ -137,40 +143,61 @@ class EvgenValidation(EvgenAnalysisAlg): self.hists["PIDs"].Fill(p.pdg_id(), self.weight) return - def fillVertex(self, v): - self.hists["Vtx_X"].Fill(v.x(), self.weight) - self.hists["Vtx_Y"].Fill(v.y(), self.weight) - self.hists["Vtx_Z"].Fill(v.z(), self.weight) - self.hists["Vtx_XY"].Fill(v.x(), v.y(), self.weight) + def fillVertex(self, label, v): + self.hists[f"Vtx_X_{label}"].Fill(v.x(), self.weight) + self.hists[f"Vtx_Y_{label}"].Fill(v.y(), self.weight) + self.hists[f"Vtx_Z_{label}"].Fill(v.z(), self.weight) + self.hists[f"Vtx_XY_{label}"].Fill(v.x(), v.y(), self.weight) + self.hists[f"Vtx_R_{label}"].Fill(sqrt(v.x()**2 + v.y()**2), self.weight) return def execute(self): evt = self.events()[0] - self.weight = evt.weights()[0] + self.weight = evt.weights()[0] if evt.weights() else 1 - # Loop over all particles in events (assuming mother not stored) + # Loop over all particles in events momenta = [] + vertices = [] mother = HepMC.FourVector(0,0,0,0) llp_vtx = None + for i, p in enumerate(evt.particles): - #p.print() + print("--- ", i) + p.print() self.fillDaughter(p) - momenta.append(p.momentum()) - mother += p.momentum() - if i == 0: + + if self.mother_stored: + if i == 0: + mother = p.momentum() + else: + momenta.append(p.momentum()) + else: + momenta.append(p.momentum()) + mother += p.momentum() + + if i == 0 and p.production_vertex(): #p.production_vertex().print() llp_vtx = p.production_vertex().point3d() + if p.production_vertex(): + vertices.append(p.production_vertex().point3d()) + # Fill daughter plots for i in range(self.ndaughters): + if i >= len(momenta): continue self.fillKin(f"d{i}", momenta[i]) # Fill mother plots self.fillKin("M", mother, mass = True) - # Fill vertex plots - self.fillVertex(llp_vtx) + # Fill all vertices + for v in vertices: + self.fillVertex("All", v) + + # Fill LLP vertex plots + if llp_vtx: + self.fillVertex("LLP", llp_vtx) return StatusCode.Success @@ -184,7 +211,8 @@ if __name__ == "__main__": import argparse, sys parser = argparse.ArgumentParser(description="Run gen-level validation") parser.add_argument("file", nargs="+", help = "full path to imput file") - parser.add_argument("--ndaugthers", "-d", default = 2, type = int, help = "Number of daugthers to plot") + parser.add_argument("--ndaughters", "-d", default = 2, type = int, help = "Number of daugthers to plot") + parser.add_argument("--mother_stored", "-m", default = False, action = "store_true", help = "Is mother stored in input?") parser.add_argument("--output", "-o", default = "validation.root", help = "Name of output file") parser.add_argument("--mcEventKey", "-k", default = "BeamTruthEvent", help = "Name of MC collection") parser.add_argument("--nevents", "-n", default = -1, type = int, help = "Number of events to process") @@ -218,7 +246,7 @@ if __name__ == "__main__": fix() acc = ComponentAccumulator() - valid = EvgenValidation("EvgenValidation", ndaughters = args.ndaugthers, outname = args.output) + valid = EvgenValidation("EvgenValidation", ndaughters = args.ndaughters, outname = args.output, mother_stored = args.mother_stored) valid.McEventKey = args.mcEventKey acc.addEventAlgo(valid) cfg.merge(acc) diff --git a/Generators/ForeseeGenerator/share/convert_hepmc_to_evnt.py b/Generators/ForeseeGenerator/share/convert_hepmc_to_evnt.py new file mode 100644 index 0000000000000000000000000000000000000000..382ad439e5ec1a7d31699c482fd0f17758f18f9c --- /dev/null +++ b/Generators/ForeseeGenerator/share/convert_hepmc_to_evnt.py @@ -0,0 +1,62 @@ +def getNEvents(fname, maxEvents): + "Work out how many events are in the file" + + n = 0 + with open(fname) as f: + n = sum(1 for l in f if l.startswith("E ")) + + if maxEvents != -1 and n > maxEvents: + n = maxEvents + + print ("Setting Maximum events to", n) + return n + + +if __name__ == "__main__": + + import sys + + from AthenaCommon.Logging import log + from AthenaCommon.Constants import DEBUG + log.setLevel(DEBUG) + + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior = 1 + + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + ConfigFlags.Input.RunNumber = [12345] + ConfigFlags.Input.OverrideRunNumber = True + ConfigFlags.Input.LumiBlockNumber = [1] + + ConfigFlags.Input.isMC = True + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" # Always needed; must match FaserVersion + ConfigFlags.GeoModel.FaserVersion = "FASER-01" # Default FASER geometry + ConfigFlags.Detector.EnableFaserSCT = True + + ConfigFlags.Output.EVNTFileName = "myEVNT.pool.root" + + ConfigFlags.Exec.MaxEvents= -1 + + import sys + ConfigFlags.fillFromArgs(sys.argv[1:]) + + + ConfigFlags.Exec.MaxEvents = getNEvents(ConfigFlags.Input.Files[0], ConfigFlags.Exec.MaxEvents) + + ConfigFlags.lock() + + from CalypsoConfiguration.MainServicesConfig import MainServicesCfg + cfg = MainServicesCfg(ConfigFlags) + + from HEPMCReader.HepMCReaderConfig import HepMCReaderCfg + cfg.merge(HepMCReaderCfg(ConfigFlags)) + + from McEventSelector.McEventSelectorConfig import McEventSelectorCfg + cfg.merge(McEventSelectorCfg(ConfigFlags)) + + itemList = [ "EventInfo#McEventInfo", "McEventCollection#*" ] + from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg + cfg.merge(OutputStreamCfg(ConfigFlags, "EVNT", itemList, disableEventTag = True)) + + sc = cfg.run() + sys.exit(not sc.isSuccess()) diff --git a/Generators/ForeseeGenerator/share/plot_validation.py b/Generators/ForeseeGenerator/share/plot_validation.py index 8d5a04701c82deedadada27fc76d11fa4a6a8d30..8429978bc6a091abd853456d1a10fa3d33ab200d 100644 --- a/Generators/ForeseeGenerator/share/plot_validation.py +++ b/Generators/ForeseeGenerator/share/plot_validation.py @@ -14,6 +14,8 @@ def plot(f, name, xtitle, ytitle, xlo = None, xhi = None, ylo = None, yhi = None if ylo is not None and yhi is not None: h.SetAxisRange(ylo, yhi, "Y") + elif not logy: + h.SetMinimum(0) if isinstance(r, tuple): h.Rebin2D(r[0], r[1]) @@ -49,7 +51,7 @@ def plot(f, name, xtitle, ytitle, xlo = None, xhi = None, ylo = None, yhi = None h.Draw(d) return h -def plotn(f, configs, x, y, outname = "valplot"): +def plotn(f, args, configs, x, y, outname): c = R.TCanvas() c.Divide(x, y) @@ -62,61 +64,88 @@ def plotn(f, configs, x, y, outname = "valplot"): c.cd(i+1) c._objs.append(plot(f, *cfg)) - c.Print(f"{outname}.eps") + c.Print(f"{args.output}/{outname}.eps") return if __name__ == "__main__": + R.gROOT.SetBatch(True) R.gStyle.SetOptStat(0) - fname = "validation.root" - f = R.TFile.Open(fname) - - config = [Hist("P_d0", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5), - Hist("Theta_d0", xtitle = "#theta [rad]", ndiv = -4), - Hist("Mass_d0", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.001, ndiv = 4), - Hist("Pt_d0", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5), - Hist("Phi_d0", xtitle = "#phi [rad]"), - Hist("ThetaVsP_d0", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz") + import argparse, sys, os + parser = argparse.ArgumentParser(description="Run gen-level validation plotting") + parser.add_argument("file", help = "full path to imput file") + parser.add_argument("--output", "-o", default = "valplot", help = "Name of output directory") + parser.add_argument("--ndaughters", "-d", default = 2, type = int, help = "Number of daugthers to plot") + args = parser.parse_args() + + if not os.path.exists(args.output): + os.mkdir(args.output) + + print (args.file) + f = R.TFile.Open(args.file) + + for i in range(args.ndaughters): + config = [Hist(f"P_d{i}", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5), + Hist(f"Theta_d{i}", xtitle = "#theta [rad]", ndiv = -4), + Hist(f"Mass_d{i}", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.1, ndiv = 4), + Hist(f"Pt_d{i}", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5), + Hist(f"Phi_d{i}", xtitle = "#phi [rad]"), + Hist(f"ThetaVsP_d{i}", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz") + ] + + plotn(f, args, config, 3, 2, f"daug{i}") + + config = [Hist("P_M", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, xlo = 0, xhi = 10000, r=10), + Hist("Theta_M", xtitle = "#theta [rad]", ndiv = -4, r = 10), + Hist("Mass_M", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 1., ndiv = 5), + Hist("Pt_M", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 50), + Hist("Phi_M", xtitle = "#phi [rad]", r = 2), + Hist("ThetaVsP_M", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz") ] - plotn(f, config, 3, 2, "daug0") + plotn(f, args, config, 3, 2, "mother") - config = [Hist("P_d1", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5), - Hist("Theta_d1", xtitle = "#theta [rad]", ndiv = -4), - Hist("Mass_d1", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.001, ndiv = 4), - Hist("Pt_d1", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5), - Hist("Phi_d1", xtitle = "#phi [rad]"), - Hist("ThetaVsP_d1", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz") + plotn(f, args, Hist("PIDs", xtitle="PDG Id"), 1, 1, "pid") + + +# config = [Hist("ThetaVsP_M", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz"), +# Hist("ThetaVsP_d0", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz"), +# Hist("ThetaVsP_d1", ytitle = "p^{0} [GeV]", xtitle = "#theta [rad]", logx = True, logy = True, d = "colz") +# ] +# +# plotn(f, args, config, 2, 2, "twod") + + config = [Hist("Vtx_X_LLP", xtitle = "x [mm]", r = 5), + Hist("Vtx_Y_LLP", xtitle = "y [mm]", r = 5), + Hist("Vtx_Z_LLP", xtitle = "z [mm]", r = 5, ndiv = 5), + Hist("Vtx_XY_LLP", xtitle = "x [mm]", ytitle = "y [mm]", d = "colz", r = (5,5)), + Hist("Vtx_R_LLP", xtitle = "r [mm]", r = 5, ndiv = 5) ] - plotn(f, config, 3, 2, "daug1") + plotn(f, args, config, 3, 2, "vtx_llp") - config = [Hist("P_M", logy = True, xtitle = "p^{0} [GeV]", ndiv = 5, r = 5), - Hist("Theta_M", xtitle = "#theta [rad]", ndiv = -4), - Hist("Mass_M", xtitle = "m^{0} [GeV]", xlo = 0, xhi = 0.05), - Hist("Pt_M", logy = True, xtitle = "p_{T}^{0} [GeV]", ndiv = 10, r = 5), - Hist("Phi_M", xtitle = "#phi [rad]"), - Hist("ThetaVsP_M", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz") - ] - plotn(f, config, 3, 2, "mother") + config = [Hist("Vtx_X_All", xtitle = "x [mm]", r = 5), + Hist("Vtx_Y_All", xtitle = "y [mm]", r = 5), + Hist("Vtx_Z_All", xtitle = "z [mm]", r = 5, ndiv = 5), + Hist("Vtx_XY_All", xtitle = "x [mm]", ytitle = "y [mm]", d = "colz", r = (5,5)), + Hist("Vtx_R_All", xtitle = "r [mm]", r = 5, ndiv = 5) + ] - plotn(f, Hist("PIDs", xtitle="PDG Id"), 1, 1, "pid") + plotn(f, args, config, 3, 2, "vtx_all") - config = [Hist("ThetaVsP_M", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz"), - Hist("ThetaVsP_d0", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz"), - Hist("ThetaVsP_d1", xtitle = "p^{0} [GeV]", ytitle = "#theta [rad]", logx = True, logy = True, d = "colz") - ] - plotn(f, config, 2, 2, "twod") +# config = [Hist("Vtx_X", xtitle = "x [mm]", r = 5), +# Hist("Vtx_Y", xtitle = "y [mm]", r = 5), +# Hist("Vtx_Z", xtitle = "z [mm]", r = 5, ndiv = 5), +# Hist("Vtx_XY", xtitle = "x [mm]", ytitle = "y [mm]", d = "colz", r = (5,5)), +# Hist("Vtx_R", xtitle = "r [mm]", r = 5, ndiv = 5) +# ] +# +# plotn(f, args, config, 3, 2, "vtx") - config = [Hist("Vtx_X", xtitle = "x [mm]", r = 5), - Hist("Vtx_Y", xtitle = "y [mm]", r = 5), - Hist("Vtx_Z", xtitle = "z [mm]", r = 5), - Hist("Vtx_XY", xtitle = "x [mm]", ytitle = "y [mm]", d = "colz", r = (5,5)) - ] - plotn(f, config, 2, 2, "vtx") + diff --git a/Generators/GeneratorUtils/python/ShiftLOSConfig.py b/Generators/GeneratorUtils/python/ShiftLOSConfig.py index 4d7f02d59d93591aa6c0e26156ce9a07e10e445d..ffc5c79b926b1674ac43d9e8947bfbbe1750da16 100644 --- a/Generators/GeneratorUtils/python/ShiftLOSConfig.py +++ b/Generators/GeneratorUtils/python/ShiftLOSConfig.py @@ -14,9 +14,10 @@ def ShiftLOSCfg(ConfigFlags, **kwargs) : import McParticleEvent.Pythonizations cfg = ComponentAccumulator() + shift = ShiftLOS(name = kwargs.setdefault("name", "ShiftLOS")) - shift.InputMCEventKey = kwargs.setdefault("InputMCEventKey", "BeamTruthEvent") - shift.OutputMCEventKey = kwargs.setdefault("OutputMCEventKey", "BeamTruthEventShifted") + shift.InputMCEventKey = kwargs.setdefault("InputMCEventKey", "BeamTruthEvent_ATLASCoord") + shift.OutputMCEventKey = kwargs.setdefault("OutputMCEventKey", "BeamTruthEvent") shift.xcross = kwargs.setdefault("xcross", 0) shift.ycross = kwargs.setdefault("ycross", 0) shift.xshift = kwargs.setdefault("xshift", 0) diff --git a/Generators/HEPMCReader/python/HepMCReaderConfig.py b/Generators/HEPMCReader/python/HepMCReaderConfig.py index 72081a86f237a8a99154a61bf7d7713f12282d06..510b63c5ea51b6d69d2ae36c3d477c0123c69495 100644 --- a/Generators/HEPMCReader/python/HepMCReaderConfig.py +++ b/Generators/HEPMCReader/python/HepMCReaderConfig.py @@ -2,21 +2,74 @@ # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -# import sys +import sys, tempfile, pathlib from AthenaConfiguration.MainServicesConfig import AthSequencer from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory from TruthIO.TruthIOConf import HepMCReadFromFile +def get_file_skip_events(ConfigFlags): + "Create a file with events from ConfigFlags.Exec.SkipEvents to ConfigFlags.Exec.SkipEvents + ConfigFlags.Exec.MaxEvents" -def HepMCReaderCfg(ConfigFlags, **kwargs) : - cfg = ComponentAccumulator(AthSequencer("AthBeginSeq", Sequential = True)) + usetemp = True + #usetemp = False + + skip = ConfigFlags.Exec.SkipEvents + fname = ConfigFlags.Input.Files[0] + evtMax = ConfigFlags.Exec.MaxEvents + + if skip == 0: + return fname + + print(f"get_file_skip_events skipping {skip} events with max {evtMax}") + + if usetemp: + fout = tempfile.NamedTemporaryFile("w", delete = False) + foutname = fout.name + else: + infile = pathlib.Path(fname) + # Put this in current working directory + if evtMax > 0: + end = skip+evtMax + else: + end = 'all' + + foutname = f"{infile.stem}=evts{skip}-{end}.{infile.suffix}" + #foutname, fext = ".".join(fname.split('.')[:-1]), fname.split('.')[-1] + #foutname = f"{foutname}-evts{skip}-{skip+evtMax}{fext}" + fout = open(foutname, "w") + fout.write("HepMC::Version 2.06.09\nHepMC::IO_GenEvent-START_EVENT_LISTING\n") + ievt = 0 + with open(fname) as fin: + for l in fin: + if l.startswith("E "): + ievt += 1 + + if evtMax > 0 and ievt > skip + evtMax: + break + + if ievt > skip: + #print(f"Writing event {ievt}") + fout.write(l) + # else: + # print(f"Skipping event {ievt}") + + fout.write("HepMC::IO_GenEvent-END_EVENT_LISTING\n") + fout.close() + + #print(f"Wrote to file {foutname}") + + return foutname + + +def HepMCReaderCfg(ConfigFlags, **kwargs) : + cfg = ComponentAccumulator(AthSequencer("AthBeginSeq", Sequential = True)) from TruthIO.TruthIOConf import HepMCReadFromFile hepmc = CompFactory.HepMCReadFromFile(name = kwargs.setdefault("name", "FASERHepMCReader")) - hepmc.InputFile = ConfigFlags.Input.Files[0] + hepmc.InputFile = get_file_skip_events(ConfigFlags) # ConfigFlags.Input.Files[0] hepmc.McEventKey = kwargs.setdefault("McEventKey", "BeamTruthEvent") cfg.addEventAlgo(hepmc, sequenceName = "AthBeginSeq", primary = True) # to run *before* G4 diff --git a/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py b/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py old mode 100644 new mode 100755 index 156f20d22770b1aef4a0daf8ea117833e1b2cdef..998b40c286837a3436e6fc714f4977b355ccdd9d --- a/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py +++ b/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py @@ -58,11 +58,21 @@ if __name__ == '__main__': import sys ConfigFlags.fillFromArgs(sys.argv[1:]) + doShiftLOS = (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or + ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift) + # from math import atan # from AthenaCommon.SystemOfUnits import GeV, TeV, cm, m # from AthenaCommon.PhysicalConstants import pi # import ParticleGun as PG -# ConfigFlags.Sim.Gun = {"Generator" : "SingleParticle", "pid" : 11, "energy" : PG.LogSampler(10*GeV, 1*TeV), "theta" : PG.GaussianSampler(0, atan((10*cm)/(7*m)), oneside = True), "phi" : [0, 2*pi], "mass" : 0.511, "radius" : -10*cm, "randomSeed" : 12345} +# ConfigFlags.Sim.Gun = {"Generator" : "SingleParticle", "pid" : 11, "energy" : PG.LogSampler(10*GeV, 1*TeV), "theta" : +# PG.GaussianSampler(0, atan((10*cm)/(7*m)), oneside = True), "phi" : [0, 2*pi], "mass" : 0.511, "radius" : -10*cm, "randomSeed" : 12345} + + if doShiftLOS: + pgConfig = ConfigFlags.Sim.Gun + pgConfig["McEventKey"] = "BeamTruthEvent_ATLASCoord" + ConfigFlags.Sim.Gun = pgConfig + # # By being a little clever, we can steer the geometry setup from the command line using GeoModel.FaserVersion @@ -97,12 +107,16 @@ if __name__ == '__main__': print("Input.Files = ",ConfigFlags.Input.Files) # -# If so, and only one file that ends in .events read as HepMC +# If so, and only one file that ends in .events or .hepmc read as HepMC # if len(ConfigFlags.Input.Files) == 1 and (ConfigFlags.Input.Files[0].endswith(".events") or ConfigFlags.Input.Files[0].endswith(".hepmc")): from HEPMCReader.HepMCReaderConfig import HepMCReaderCfg - cfg.merge(HepMCReaderCfg(ConfigFlags)) + + if doShiftLOS: + cfg.merge(HepMCReaderCfg(ConfigFlags, McEventKey = "BeamTruthEvent_ATLASCoord")) + else: + cfg.merge(HepMCReaderCfg(ConfigFlags)) from McEventSelector.McEventSelectorConfig import McEventSelectorCfg cfg.merge(McEventSelectorCfg(ConfigFlags)) @@ -113,6 +127,12 @@ if __name__ == '__main__': else: from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg cfg.merge(PoolReadCfg(ConfigFlags)) + + if doShiftLOS: + from SGComps.AddressRemappingConfig import InputOverwriteCfg + # Rename old truth collection to add ATLAS coord to can still use BeamTruthEvent for the one in FASER Coords + cfg.merge(InputOverwriteCfg("McEventCollection", "BeamTruthEvent", "McEventCollection", "BeamTruthEvent_ATLASCoord")) + # # If not, configure the particle gun as requested, or using defaults # @@ -122,6 +142,7 @@ if __name__ == '__main__': # from FaserParticleGun.FaserParticleGunConfig import FaserParticleGunCfg cfg.merge(FaserParticleGunCfg(ConfigFlags)) + from McEventSelector.McEventSelectorConfig import McEventSelectorCfg cfg.merge(McEventSelectorCfg(ConfigFlags)) @@ -135,23 +156,21 @@ if __name__ == '__main__': # Shift LOS # - if (ConfigFlags.Sim.Beam.xangle or ConfigFlags.Sim.Beam.yangle or - ConfigFlags.Sim.Beam.xshift or ConfigFlags.Sim.Beam.yshift): - - MCEventKey = "BeamTruthEventShifted" + if doShiftLOS: + import McParticleEvent.Pythonizations from GeneratorUtils.ShiftLOSConfig import ShiftLOSCfg - cfg.merge(ShiftLOSCfg(ConfigFlags, OutputMCEventKey = MCEventKey, + cfg.merge(ShiftLOSCfg(ConfigFlags, xcross = ConfigFlags.Sim.Beam.xangle, ycross = ConfigFlags.Sim.Beam.yangle, xshift = ConfigFlags.Sim.Beam.xshift, yshift = ConfigFlags.Sim.Beam.yshift)) - else: - MCEventKey = "BeamTruthEvent" # # Add the G4FaserAlg # from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg - cfg.merge(G4FaserAlgCfg(ConfigFlags, InputTruthCollection = MCEventKey)) + cfg.merge(G4FaserAlgCfg(ConfigFlags)) + + #cfg.getEventAlgo("OutputStreamHITS").ItemList += ["McEventCollection#BeamTruthEvent_ATLASCoord"] # # Dump config #