Newer
Older
#!/usr/bin/env python
#
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
#
# Run with
# faser_ntuple_maker.py [options]
#
# Options:
# --isMC - needed to reconstruct MC data
#
import sys
import time
import argparse
a = time.time()
parser = argparse.ArgumentParser(description="Run PHYS ntuple production")
parser.add_argument("path",
help="Fully qualified input path (directory or file)")
parser.add_argument("--slice", type=int, default=0,
help="Specify ordinal output file to produce")
parser.add_argument("--files", type=int, default=1,
help="Specify reco files per slice")
parser.add_argument("--merge", type=int, default=1,
help="Specify merged files per reco file (MC only)")
parser.add_argument("--last", type=int, default=0,
help="Specify last file in slice (normally --files)")
parser.add_argument("--outfile", default="",
help="Override output file name")
parser.add_argument("-v", "--verbose", action='store_true',
help="Turn on DEBUG output")
parser.add_argument("-n", "--nevents", type=int, default=-1,
help="Specify number of events to process (default: all)")
parser.add_argument("-t", "--tag", default="",
help="Specify tag (to append to output filename)")
parser.add_argument("--isMC", action='store_true',
help="Running on digitised MC rather than data")
parser.add_argument("--partial", action='store_true',
help="Allow partial input files")
parser.add_argument("-c", "--cond", default="",
help="Specify global conditions tag (default: OFLCOND-FASER-04)")

Deion Elgin Fellers
committed
parser.add_argument("--trigFilt", action='store_true',

Deion Elgin Fellers
committed
help="apply trigger event filter")

Deion Elgin Fellers
committed
parser.add_argument("--scintFilt", action='store_true',

Deion Elgin Fellers
committed
help="apply scintillator event filter")
parser.add_argument("--NoTrackFilt", action='store_true',
help="Don't apply track event filter (default: do)")

Deion Elgin Fellers
committed
parser.add_argument("--unblind", action='store_true',
help="Don't apply signal blinding (default: do)")

Deion Elgin Fellers
committed
parser.add_argument("--onlyblind", action='store_true',

Deion Elgin Fellers
committed
help="Only store events that were blinded (will override unblind arg)")
parser.add_argument("--grl", default="",
help="Specify GRL to apply")
parser.add_argument("--fluka", action='store_true',
help="Add FLUKA weights to ntuple")
parser.add_argument("--genie", action='store_true',
help="Add Genie weights to ntuple")
args = parser.parse_args()
from pathlib import Path
# Must figure out what we are doing here
filepath = Path(args.path)
filelist = []
# If this is a directory, need to create file list
if filepath.is_dir():
runstr = filepath.stem
# Make list of segments to search for
seglist = []
if args.merge > 1:
start = args.slice * args.files * args.merge
# Number of files to combine
if args.last > 0:
num = args.last
else:
num = args.files
# Make segment list
for i in range(start, start+num*args.merge, args.merge):
seg = f"{i:05d}-{(i+args.merge-1):05d}"
seglist.append(seg)
else:
start = args.slice * args.files
if args.last > 0:
end = start + args.last
else:
end = start + args.files
seglist = [f'{seg:05d}' for seg in range(start, end)]
for seg in seglist:
if args.isMC:
else:
searchstr = f"Faser-Physics-{runstr}-{seg}-*xAOD.root"
flist = list(filepath.glob(searchstr))
if len(flist) == 0:
print(f"Didn't find file {searchstr}!")
if args.partial: continue
sys.exit(1)
elif len(flist) > 1:
print(f"Found multiple matches for {searchstr}!")
print(flist)
sys.exit(1)
filestr = str(flist[0].resolve())
# Use proper EOS file path here?

Deion Elgin Fellers
committed
if filestr[:4] == '/eos':
filestr = f"root://eospublic.cern.ch/{filestr}"
filelist.append(filestr)
# End of loop over segments
firstfile = Path(filelist[0])
firststem = str(firstfile.stem)
firstfaser = firststem.split('-')[0]
firstshort = firststem.split('-')[1]
firstseg = firststem.split('-')[3]
if args.merge > 1:
firstseg2 = firststem.split('-')[4]
lastfile = Path(filelist[-1])
laststem = str(lastfile.stem)
lastseg = laststem.split('-')[3]
if args.merge > 1:
lastseg = laststem.split('-')[4]
print(f"Faser = {firstfaser}")
print(f"Short = {firstshort}")
print(f"Run = {runstr}")
print(f"First = {firstseg}")
print(f"Last = {lastseg}")

Deion Elgin Fellers
committed
print(f"Tag = {args.tag}")
# Find any tags
tagstr = firststem.replace(f"{firstfaser}-{firstshort}-{runstr}-{firstseg}", "")
if args.merge > 1:
tagstr = tagstr.replace(f"-{firstseg2}", "")
tagstr = tagstr.replace("-xAOD", "")
# Build output name
outfile = f"{firstfaser}-{firstshort}-{runstr}-{firstseg}-{lastseg}"
# This will include the leading -
if len(tagstr) > 0:
outfile += f"{tagstr}"
if len(args.tag) > 0 and args.tag not in tagstr:
outfile += f"-{args.tag}"
outfile += "-PHYS.root"
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# If this is a single file, just process that
# Could be a url, so don't check if this is a file
else:
filelist.append(args.path)
# Build output name
filestem = str(filepath.stem)
# Remove -xAOD from end
if filestem[-5:] == "-xAOD":
filestem = filestem[:-5]
# Do we want to add a tag?
if len(args.tag) > 0 and args.tag not in filestem:
filestem += f"-{args.tag}"
outfile = f"{filestem}-PHYS.root"
# Print out what we found
if len(filelist) == 0:
printf("Found no files for {args.path}!")
sys.exit(1)
elif len(filelist) == 1:
print("Processing file:")
else:
print("Processing files:")
for f in filelist:
print(f)
# Override output file?
if len(args.outfile) > 0:
outfile = args.outfile
print("Output file:")
print(outfile)
print(f"Trigger Filter = {args.trigFilt}")
print(f"Scintillator Filter = {args.scintFilt}")
print(f"Track Filter = {not args.NoTrackFilt}")
print(f"Blind = {not args.unblind}")
print(f"OnlyBlinded = {args.onlyblind}")
print(f"GRL = {args.grl}")
# OK, lets run the job here
from AthenaCommon.Logging import log, logging
from AthenaCommon.Constants import DEBUG, VERBOSE, INFO
from AthenaCommon.Configurable import Configurable
from CalypsoConfiguration.AllConfigFlags import ConfigFlags
from CalypsoConfiguration.MainServicesConfig import MainServicesCfg
from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
Configurable.configurableRun3Behavior = True
# Configure
ConfigFlags.Input.Files = filelist
ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-04" # Always needed; must match FaserVersionS
else:
print(f"Setting ConfigFlags.IOVDb.GlobalTag = {args.cond}")
ConfigFlags.IOVDb.GlobalTag = args.cond
if args.isMC:
ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions
else:
ConfigFlags.IOVDb.DatabaseInstance = "CONDBR3" # Use data conditions
ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig
ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # FASER geometry
ConfigFlags.Common.isOnline = False
ConfigFlags.GeoModel.Align.Dynamic = False
ConfigFlags.Beam.NumberOfCollisions = 0.
ConfigFlags.Detector.GeometryFaserSCT = True
ConfigFlags.lock()
# Core components
acc = MainServicesCfg(ConfigFlags)
acc.merge(PoolReadCfg(ConfigFlags))
# Create kwargs for NtupleDumper
grl_kwargs = {}
if args.grl:
grl_kwargs['GoodRunsList'] = args.grl
grl_kwargs['ApplyGoodRunsList'] = True
mc_kwargs = {}
if args.genie:
mc_kwargs['UseGenieWeights'] = True
if args.fluka:
mc_kwargs['UseFlukaWeights'] = True
# algorithm
from NtupleDumper.NtupleDumperConfig import NtupleDumperAlgCfg
if args.isMC:
acc.merge(NtupleDumperAlgCfg(ConfigFlags, outfile, **mc_kwargs))
else:
acc.merge(NtupleDumperAlgCfg(ConfigFlags, outfile, DoBlinding=(not args.unblind), OnlyBlinded=args.onlyblind, DoScintFilter = args.scintFilt, DoTrackFilter = (not args.NoTrackFilt), DoTrigFilter = args.trigFilt, **grl_kwargs))
if not args.verbose:
from AthenaConfiguration.ComponentFactory import CompFactory
AthenaEventLoopMgr = CompFactory.AthenaEventLoopMgr()
AthenaEventLoopMgr.EventPrintoutInterval=1000
acc.addService(AthenaEventLoopMgr)
else:
nd = acc.getEventAlgo("NtupleDumperAlg")
nd.OutputLevel = VERBOSE
# Hack to avoid problem with our use of MC databases when isMC = False
if not args.isMC:
replicaSvc = acc.getService("DBReplicaSvc")
replicaSvc.COOLSQLiteVetoPattern = ""
replicaSvc.UseCOOLSQLite = True
replicaSvc.UseCOOLFrontier = False
replicaSvc.UseGeomSQLite = True
if args.verbose:
log.setLevel(VERBOSE)
acc.printConfig(withDetails=True)
ConfigFlags.dump()
else:
log.setLevel(INFO)
acc.getService("MessageSvc").Format = "% F%40W%S%7W%R%T %0W%M"
# Execute and finish
sc = acc.run(maxEvents=args.nevents)
b = time.time()
log.info(f"Finish execution in {b-a} seconds")
# Success should be 0
if sc.isSuccess():
log.info("Execution succeeded")
sys.exit(0)
else:
log.info("Execution failed, return 1")
sys.exit(1)