Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
faser_parser.py 7.15 KiB
#
# Copyright (C) 2022 CERN for the benefit of the ATLAS collaboration
# Copyright (C) 2022 CERN for the benefit of the FASER collaboration
#
# Parser function for particle gun samples
#

def float_or_none(arg):
    if arg is None or arg == "None":
        return None

    return float(arg)

def faser_pgparser():

    import sys
    import json
    import argparse

    parser = argparse.ArgumentParser(description="Run FASER ParticleGun Simulation")

    parser.add_argument("--conf", action='append',
                        help="Specify configuration file with default values")
    parser.add_argument("--geom", default="TI12MC",
                        help="Specify geomtery to simulation (default: TI12MC, alt: TestBeamMC)")

    parser.add_argument("--run", default=123456, type=int,
                        help="Run number to generate")
    parser.add_argument("--segment", default=00000, type=int,
                        help="Segment number to generate")
    parser.add_argument("--file_length", default=1000, type=int,
                        help="Total events per file segement")

    parser.add_argument("--short", default="PG_logE",
                        help="Short description for filename")
    parser.add_argument("--tag", default=None,
                        help="Generator tag (e.g.: g0000)")

    parser.add_argument("--pid", default=[-13, 13], type=int, nargs='*',
                        help="Specify PDG ID of particle (note plus/minus different) or list (e.g.: --pid -13 13)")
    parser.add_argument("--mass", default=105.66, type=float,
                        help="Specify particle mass (in MeV)")
    parser.add_argument("--radius", default=100., type=float, nargs="*",
                        help="Specify radius (in mm)")
    parser.add_argument("--angle", default=0.005, type=float_or_none,
                        help="Specify angular width (in Rad)")
    parser.add_argument("--zpos", default=None, type=float,
                        help="Specify z position of particles (in mm) (helpful to avoid FASERnu)")

    parser.add_argument("--pidd1", default=None, type=int, 
                        help="Specify PDG ID of daugther 1 for DIF generator")
    parser.add_argument("--pidd2", default=None, type=int, 
                        help="Specify PDG ID of daugther 2 for DIF generator")


    parser.add_argument("--sampler", default="log",
                        help="Specify energy sampling (log, lin, const, hist, hist2D)")
    parser.add_argument("--hist_name", default="",
                        help="Specify energy sampling name for hist sampler file.root:hist")
    
    parser.add_argument("--minE", default=10., type=float,
                        help="Minimum energy in GeV (for log or lin sampler)")
    parser.add_argument("--maxE", default=1000., type=float,
                        help="Maximum energy (or constant) in GeV")

    parser.add_argument("--nevts", default=-1, type=int,
                        help="Number of events to generate (for debugging)")
    parser.add_argument("--dump", action='store_true',
                        help="Write out full configuration")
    parser.add_argument("--noexec", action='store_true',
                        help="Exit after parsing configuration (no execution)")

    pg_args = parser.parse_args()

    # Get defaults
    if pg_args.conf is not None:
        for conf_fname in pg_args.conf:
            with open(conf_fname, 'r') as f:
                parser.set_defaults(**json.load(f))

        # Reload arguments to override config file with command line
        pg_args = parser.parse_args()

    # Print out configuration if requested
    if pg_args.dump:
        tmp_args = vars(pg_args).copy()
        del tmp_args['dump']  # Don't dump the dump value
        del tmp_args['conf']  # Don't dump the conf file name either
        del tmp_args['nevts'] # Debugging, not part of configuration
        del tmp_args['noexec'] # Debugging, not part of configuration
        print("Configuration:")
        print(json.dumps(tmp_args, indent=4, sort_keys=False))

    if pg_args.noexec:
        sys.exit(0)

    #
    # Add some derived quantities
    #

    # Create the file name also (could add gentag here)
    pg_args.outfile = f"FaserMC-{pg_args.short}-{pg_args.run:06}-{pg_args.segment:05}"

    if pg_args.tag:
        pg_args.outfile += f"-{pg_args.tag}"

    pg_args.outfile += "-HITS.root"

    return pg_args

# All done

#
# Parser function for Foresee samples
#
def faser_fsparser():

    import sys
    import json
    import argparse

    parser = argparse.ArgumentParser(description="Run FASER Foresee Simulation")

    parser.add_argument("--conf", action='append',
                        help="Specify configuration file with default values")
    parser.add_argument("--run", default=123456, type=int,
                        help="Run number to generate")
    parser.add_argument("--segment", default=00000, type=int,
                        help="Segment number to generate")
    parser.add_argument("--file_length", default=1000, type=int,
                        help="Total events per file segement")

    parser.add_argument("--model", help="Model name")
    parser.add_argument("--model_path", help="Path to model phase space file")

    parser.add_argument("--short", default="PG_logE",
                        help="Short description for filename")
    parser.add_argument("--tag", default=None,
                        help="Generator tag (g0000)")

    parser.add_argument("--pid", default=[-13, 13], type=int, nargs=2,
                        help="Specify PDG ID of daughter particles")
    parser.add_argument("--mass", default=105.66, type=float,
                        help="Specify particle mass (in MeV)")

    parser.add_argument("--nevts", default=-1, type=int,
                        help="Number of events to generate (for debugging)")
    parser.add_argument("--dump", action='store_true',
                        help="Write out full configuration")
    parser.add_argument("--noexec", action='store_true',
                        help="Exit after parsing configuration (no execution)")

    fs_args = parser.parse_args()

    # Get defaults
    if fs_args.conf is not None:
        for conf_fname in fs_args.conf:
            with open(conf_fname, 'r') as f:
                parser.set_defaults(**json.load(f))

        # Reload arguments to override config file with command line
        fs_args = parser.parse_args()

    # Print out configuration if requested
    if fs_args.dump:
        tmp_args = vars(fs_args).copy()
        del tmp_args['dump']  # Don't dump the dump value
        del tmp_args['conf']  # Don't dump the conf file name either
        del tmp_args['nevts'] # Debugging, not part of configuration
        del tmp_args['noexec'] # Debugging, not part of configuration
        print("Configuration:")
        print(json.dumps(tmp_args, indent=4, sort_keys=False))

    if fs_args.noexec:
        sys.exit(0)

    #
    # Add some derived quantities
    #

    # Create the file name also (could add gentag here)
    fs_args.outfile = f"FaserMC-{fs_args.short}-{fs_args.run:06}-{fs_args.segment:05}"

    if fs_args.tag:
        fs_args.outfile += f"-{fs_args.tag}"

    fs_args.outfile += "-HITS.root"

    return fs_args

# All done