Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879817
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Subscribers
None
View Options
Index: trunk/bin/agile-runmc
===================================================================
--- trunk/bin/agile-runmc (revision 756)
+++ trunk/bin/agile-runmc (revision 757)
@@ -1,528 +1,528 @@
#! /usr/bin/env python
"""Generate events and write to file or stdout
EXAMPLES:
%prog <gen> [-p<param> ...] [-P<pfile> ...] \\
[-n<nevts>] [-o<outfile>] [--sqrts=<energy>] \\
[--beams=<beamsstr>] \\
[--seed=<rngseed> | --randomize-seed]
%prog --list-gens
%prog --list-used-params
BEAM SPEC:
Beams can be specified in several different schemes. The
strings are compared case-insensitively. Energies are
specified in GeV. The energy must be explicitly specified,
either as part of the beam string (after a colon) or via
the --sqrts option.
* --beams=p:900,pbar:900
* --beams=ppbar:1960
* --beams=LHC:14000
* --beams=pp:14T
Beam particles:
* "proton", "2212", "p", "p+"
* "antiproton", "-2212", "pbar", "p-"
* "electron", "11", "e-"
* "positron", "-11", "e+"
Beam pair strings:
* pp: "LHC", "PP", "RHIC"
* ppbar: "TEVATRON", "TVT", "PPBAR"
* e+e-: "LEP", "E+E-", "EE"
ENVIRONMENT:
* AGILE_GEN_PATH
Colon-separated list of filesystem paths which get checked
in order when searching for generator libraries in the
Genser structure. The current directory and the AGILe install
path are also searched, after AGILE_GEN_PATH.
* AGILE_PARAM_PATH
Colon-separated list of filesystem paths which get checked
in order when searching for generator parameter files as
passed to the -P option. The current directory and the AGILe
install path are also searched, after AGILE_PARAM_PATH.
* AGILE_DEBUG
Enables debug output level if set
"""
import os, logging, re, sys
## Try to rename the process on Linux
try:
import ctypes
libc = ctypes.cdll.LoadLibrary('libc.so.6')
libc.prctl(15, 'agile-runmc', 0, 0, 0)
except Exception:
pass
## Try to bootstrap the Python path
import commands
try:
modname = sys.modules[__name__].__file__
binpath = os.path.dirname(modname)
agileconfigpath = os.path.join(binpath, "agile-config")
agilepypath = commands.getoutput(agileconfigpath + " --pythonpath")
sys.path.append(agilepypath)
except:
pass
import AGILe
## Randomly seed a random seed. Hmm.
import random, time
random.seed(time.time())
RANDRANDSEED = random.randint(0, 100000000)
## Parse command line arguments
from optparse import OptionParser, OptionGroup
parser = OptionParser(usage=__doc__)
parser.add_option("-n", "--nevts", help="Specify the number of events to generate",
dest="NEVTS", default="10")
parser.add_option("--list-gens", help="List the available generators",
action="store_true", dest="LISTGENS", default=False)
parser.add_option("--list-used-params", help="List the parameters passed to the generator by this command",
action="store_true", dest="LISTPARAMS", default=False)
parser.add_option("-o", "--out", help="Specify the file/pipe to write to. Use a '-' to write to stdout.",
dest="OUTFILE", default=None)
parser.add_option("-p", "--param", metavar="PNAME=PVAR", action="append", default=[],
help="Change a generator parameter PNAME to value PVAL",
dest="PARAMSTRS")
parser.add_option("-b", "--beams", help="Specify the beams. Super-flexible!",
dest="BEAMSTR", default=None)
parser.add_option("-s", "--seed", help="Specify the generator random number seed",
dest="RNGSEED", type="int", default=31415926)
parser.add_option("--randomize-seed", help="Randomize the generator random number seed",
action="store_const", const=RANDRANDSEED, dest="RNGSEED")
parser.add_option("-P", "--paramfile", metavar="PFILE", action="append", default=[],
help="Read a generator parameter file PFILE containing 'name = value' pairs",
dest="PARAMFILES")
parser.add_option("--filter", help="Remove particles without status == {1,2,4} from events",
action="store_true", dest="FILTER_EVENTS", default=False)
verbgroup = OptionGroup(parser, "Verbosity control")
verbgroup.add_option("-l", dest="NATIVE_LOG_STRS", action="append",
default=[], help="set a log level in the AGILe library")
-verbgroup.add_option("-Q", "--quiet", help="Suppress normal messages", dest="LOGLEVEL",
+verbgroup.add_option("-q", "--quiet", help="Suppress normal messages", dest="LOGLEVEL",
action="store_const", default=logging.INFO, const=logging.WARNING)
-verbgroup.add_option("-V", "--verbose", help="Add extra debug messages", dest="LOGLEVEL",
+verbgroup.add_option("-v", "--verbose", help="Add extra debug messages", dest="LOGLEVEL",
action="store_const", default=logging.INFO, const=logging.DEBUG)
parser.add_option_group(verbgroup)
opts, args = parser.parse_args()
## Change log level if AGILE_DEBUG env variable is set
if os.environ.has_key("AGILE_DEBUG"):
opts.LOGLEVEL = logging.DEBUG
## Configure logging
try:
logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
except:
pass
h = logging.StreamHandler()
h.setFormatter(logging.Formatter("%(message)s"))
logging.getLogger().setLevel(opts.LOGLEVEL)
if logging.getLogger().handlers:
logging.getLogger().handlers[0] = h
else:
logging.getLogger().addHandler(h)
## Control AGILe logger
for l in opts.NATIVE_LOG_STRS:
name, level = None, None
try:
name, level = l.split("=")
except:
name = "AGILe"
level = l
## Fix name
if name != "AGILe" and not name.startswith("AGILe."):
name = "AGILe." + name
try:
## Get right error type
LEVEL = level.upper()
if LEVEL == "TRACE":
level = AGILe.Log.TRACE
elif LEVEL == "DEBUG":
level = AGILe.Log.DEBUG
elif LEVEL == "INFO":
level = AGILe.Log.INFO
elif LEVEL == "WARNING" or LEVEL == "WARN":
level = AGILe.Log.WARN
elif LEVEL == "ERROR":
level = AGILe.Log.ERROR
else:
level = int(level)
logging.debug("Setting log level: %s %d" % (name, level))
## Set log level
AGILe.Log.setLogLevel(name, level)
except:
logging.warning("Couldn't process logging string '%s'" % l)
## Set up signal handling
import signal
RECVD_KILL_SIGNAL = None
def handleKillSignal(signum, frame):
"Declare us as having been signalled, and return to default handling behaviour"
global RECVD_KILL_SIGNAL
logging.critical("Signal handler called with signal " + str(signum))
RECVD_KILL_SIGNAL = signum
signal.signal(signum, signal.SIG_DFL)
## Signals to handle
signal.signal(signal.SIGTERM, handleKillSignal);
signal.signal(signal.SIGHUP, handleKillSignal);
signal.signal(signal.SIGINT, handleKillSignal);
signal.signal(signal.SIGUSR1, handleKillSignal);
signal.signal(signal.SIGUSR2, handleKillSignal);
try:
signal.signal(signal.SIGXCPU, handleKillSignal);
except:
pass
## Parse number-of-events string
if not opts.LISTGENS and not opts.LISTPARAMS:
try:
factor = 1
base = opts.NEVTS
suffix = opts.NEVTS[-1]
if suffix.upper() == "K":
factor = 1000
base = opts.NEVTS[:-1]
elif suffix == "M":
factor = 1000000
base = opts.NEVTS[:-1]
num = int(float(base) * factor)
logging.info("Generating %d events" % num)
opts.NEVTS = num
except:
logging.error("Invalid num events specification, '%s'" % opts.NEVTS)
sys.exit(1)
def readParamStrsFromFile(ppath):
paramstrs = []
pf = open(ppath, "r")
logging.debug("Reading param file '%s'" % ppath)
for line in pf:
sline = line.strip()
if len(sline) == 0 or sline[0] == "#":
continue
if re.match(r"@include \S+", sline.lower()):
incfile = sline.split()[1]
logging.info("Reading included parameters from %s" % incfile)
paramstrs += readParamFile(incfile)
else:
paramstrs.append(sline)
pf.close()
return paramstrs
def readParamFile(pfile):
global SEARCHPATH
## If a path has been given, don't use the search path
if "/" in pfile:
logging.debug("Trying to read param file '%s'" % pfile)
if os.access(pfile, os.R_OK):
return readParamStrsFromFile(pfile)
else:
raise Exception("Could not read param file '%s'" % pfile)
else:
for pdir in SEARCHPATH:
ppath = os.path.join(pdir, pfile)
logging.debug("Trying to read param file '%s'" % ppath)
if os.access(ppath, os.R_OK):
return readParamStrsFromFile(ppath)
raise Exception("Could not find param file '%s'" % pfile)
## Get parameter strings from file and CLI
PARAMSTRS = []
SEARCHPATH = ["."]
try:
SEARCHPATH += os.getenv("AGILE_PARAM_PATH").split(":")
except:
pass
try:
installdir = os.path.dirname(os.path.abspath(sys.argv[0]))
if os.path.basename(installdir) == "bin":
installdir = os.path.dirname(installdir)
agilesharedir = os.path.join(installdir, "share", "AGILe")
logging.debug("Adding %s to param file search path" % agilesharedir)
SEARCHPATH.append(agilesharedir)
## TODO: Deprecate and remove
rgsharedir = os.path.join(installdir, "share", "RivetGun")
logging.debug("Adding %s to param file search path" % rgsharedir)
SEARCHPATH.append(rgsharedir)
uninstalledsharedir = os.path.join(installdir, "data", "params")
logging.debug("Adding %s to param file search path" % uninstalledsharedir)
SEARCHPATH.append(uninstalledsharedir)
except:
pass
logging.debug("Searching for param files in dirs: %s" % str(SEARCHPATH))
try:
for pfile in opts.PARAMFILES:
PARAMSTRS += readParamFile(pfile)
except Exception, e:
logging.error(e)
sys.exit(2)
## Add CLI params
PARAMSTRS += opts.PARAMSTRS
## Interpret param strings
def getKeyVal(pstr):
mypstr = pstr.strip().replace("=", " ")
parts = mypstr.split()
if len(parts) != 2:
logging.error("Invalid param string: '%s'" % pstr)
sys.exit(1)
return parts
##
PARAMKEYS = []
PARAMS = {}
for pstr in PARAMSTRS:
k, v = getKeyVal(pstr)
PARAMS[k] = v
if not k in PARAMKEYS:
PARAMKEYS.append(k)
def _parse_energy(numstr):
import re
try:
e = float(numstr)
return e
except:
suffmatch = re.search(r"[^\d.]", numstr)
if not suffmatch:
raise ValueError("Bad energy string: %s" % numstr)
factor = base = None
suffstart = suffmatch.start()
if suffstart != -1:
base = numstr[:suffstart]
suffix = numstr[suffstart:]
if suffix.startswith("K"):
factor = 1e-6
elif suffix.startswith("M"):
factor = 1e-3
elif suffix.startswith("G"):
factor = 1
elif suffix.startswith("T"):
factor = 1e3
if factor is None or base is None:
raise ValueError("Bad energy string: %s" % numstr)
num = float(base) * factor
return num
## Parse a beam string
def _parseOneBeamStr(bstr):
if not ":" in bstr:
raise ValueError("Beam string must contain a colon to separate particle and energy parts")
name, energy = bstr.split(":")
energy = _parse_energy(energy)
pid = None
if name.lower() in ["proton", "2212", "p", "p+"]:
pid = AGILe.PROTON
elif name.lower() in ["antiproton", "-2212", "pbar", "p-"]:
pid = AGILe.ANTIPROTON
elif name.lower() in ["electron", "11", "e-"]:
pid = AGILe.ELECTRON
elif name.lower() in ["positron", "-11", "e+"]:
pid = AGILe.POSITRON
else:
raise Exception("Particle '%s' unknown" % name)
return pid, energy
## Choose beam string
## Defaults
#BEAMSTR = "LHC:14TeV"
BEAM1 = BEAM2 = "p"
MOM1 = MOM2 = "7000"
## Using params from file and command line
if PARAMS.has_key("RG:Beam1"):
BEAM1 = PARAMS["RG:Beam1"]
if PARAMS.has_key("RG:Beam2"):
BEAM2 = PARAMS["RG:Beam2"]
if PARAMS.has_key("RG:Mom1"):
MOM1 = PARAMS["RG:Mom1"]
if PARAMS.has_key("RG:Mom2"):
MOM2 = PARAMS["RG:Mom2"]
## Build beam string
BEAMSTR = "%s:%s,%s:%s" % (BEAM1, MOM1, BEAM2, MOM2)
## Override from params
if PARAMS.has_key("RG:Beams"):
BEAMSTR = PARAMS["RG:Beams"]
## Override from command line
if opts.BEAMSTR is not None:
BEAMSTR = opts.BEAMSTR
## Declare what we've got so far
logging.debug("Beam spec: " + BEAMSTR)
## Parse the beams string
try:
if "," in BEAMSTR:
beamAStr, beamBStr = BEAMSTR.split(",")
PID_A, E_A = _parseOneBeamStr(beamAStr)
PID_B, E_B = _parseOneBeamStr(beamBStr)
else:
if not ":" in BEAMSTR:
raise ValueError("Beams string must contain a colon to separate beam type and energy parts")
name, energyStr = BEAMSTR.split(":")
energy = _parse_energy(energyStr)
NAME = name.upper()
## If only a total energy is given, assume collision is symmetric
E_A, E_B = energy/2.0, energy/2.0
#
if NAME in ["LHC", "PP", "RHIC"]:
PID_A = AGILe.PROTON
PID_B = AGILe.PROTON
elif NAME in ["TEVATRON", "TVT", "PPBAR"]:
PID_A = AGILe.PROTON
PID_B = AGILe.ANTIPROTON
elif NAME in ["LEP", "E+E-", "EE"]:
PID_A = AGILe.ELECTRON
PID_B = AGILe.POSITRON
elif NAME in ["HERA", "EP"]:
PID_A = AGILe.ELECTRON
PID_B = AGILe.PROTON
## HERA uses asymmetric beams
## People seem to quote anything between 296 to 300 GeV for Run I
## These are the actual beam energies
if energy <= 300.0 and energy >= 295.0 :
E_A = 26.7
E_B = 820.0
## Again, people quote a variety of different cms energies
elif energy >= 318.0 and energy <= 320.0 :
E_A = 27.5
E_B = 920
else:
raise Exception("Unrecognised beams string, '%s'" % BEAMSTR)
except Exception, e:
logging.error("Beam parsing error: " + str(e))
sys.exit(1)
logging.debug("Beams: %s @ %2.1f GeV -> <- %s @ %2.1f GeV" % (str(PID_A), E_A, str(PID_B), E_B))
## List generators and exit, if requested
if opts.LISTGENS:
gens = AGILe.getAvailableGens()
if len(gens) > 0:
allgensstr = "\n".join(AGILe.getAvailableGens())
#logging.info(allgensstr)
print allgensstr
sys.exit(0)
## Determine the generator
GEN = None
## Override from params
if PARAMS.has_key("RG:Generator"):
GEN = PARAMS["RG:Generator"]
## Override from command line
if len(args) == 1:
GEN = args[0]
## Declare what we've got so far
logging.debug("Specified generator: " + str(GEN))
## Push beam and gen choices back into the params dictionary, for dumping
if PARAMS.has_key("RG:Beams"):
del PARAMS["RG:Beams"]
PARAMS["RG:Mom1"] = str(E_A)
PARAMS["RG:Mom2"] = str(E_B)
PARAMS["RG:Beam1"] = str(PID_A)
PARAMS["RG:Beam2"] = str(PID_B)
PARAMS["RG:Generator"] = str(GEN)
## List params and exit, if requested
if opts.LISTPARAMS:
for k in sorted(PARAMS.keys()):
print k, PARAMS[k]
sys.exit(0)
## No generator specified?
if GEN is None:
allgensstr = "\n ".join(AGILe.getAvailableGens())
msg = "No generator specified.\n"
if len(allgensstr) > 0:
msg += "Available generators:\n %s" % allgensstr
else:
msg += "No generators are available! Check your AGILE_GEN_PATH variable."
logging.error(msg)
sys.exit(1)
## Invalid generator specified
if GEN not in AGILe.getAvailableGens():
allgensstr = "\n ".join(AGILe.getAvailableGens())
msg = "Generator '%s' is not a valid choice.\n" % GEN
msg += "Available generators:\n %s" % allgensstr
logging.error(msg)
sys.exit(1)
## Valid generator specified -- hurrah!
logging.info("Generator is %s" % GEN)
AGILe.loadGenLibs(GEN)
gen = AGILe.createGen()
## Config and run generator
logging.debug("Generator name = %s" % gen.getName())
logging.info("Setting random seed = %d" % opts.RNGSEED)
gen.setSeed(opts.RNGSEED)
logging.info("Setting initial state: %s @ %2.1f GeV -> <- %s @ %2.1f GeV" % (str(PID_A), E_A, str(PID_B), E_B))
gen.setInitialState(PID_A, E_A, PID_B, E_B)
for pname in PARAMKEYS:
pval = PARAMS[pname]
if pname.startswith("RG:"):
logging.info("Skipping meta-param %s = %s" % (pname, pval))
continue
logging.info("Setting parameter %s = %s" % (pname,pval))
gen.setParam(pname,pval)
## Set up Run
OUT = ""
if opts.OUTFILE:
if opts.OUTFILE != "-" and not "." in opts.OUTFILE:
opts.OUTFILE += ".hepmc"
OUT = opts.OUTFILE
run = AGILe.Run(gen, OUT)
if opts.FILTER_EVENTS:
run.doFilter(True)
## Make and write events
for i in range(opts.NEVTS):
st = run.makeEvent()
logging.debug(run.eventSummary())
if not st:
logging.error("Writing events failed")
break
if RECVD_KILL_SIGNAL is not None:
logging.critical("Leaving event loop early due to signal " + str(RECVD_KILL_SIGNAL))
break
gen.finalize()
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 9:09 PM (22 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3806207
Default Alt Text
(17 KB)
Attached To
rAGILESVN agilesvn
Event Timeline
Log In to Comment