################################################################################
#
# Copyright (c) 2011 The MadGraph Development team and Contributors
#
# This file is a part of the MadGraph 5 project, an application which
# automatically generates Feynman diagrams and matrix elements for arbitrary
# high-energy processes in the Standard Model and beyond.
#
# It is subject to the MadGraph license which should accompany this
# distribution.
#
# For more information, please visit: http://madgraph.phys.ucl.ac.be
#
################################################################################
"""
A user friendly interface to access all the function associated to MadWeight
"""
import logging
import os
import subprocess
import time
import glob
import math
import xml.sax.handler
import shutil
from cStringIO import StringIO
if __name__ == '__main__':
import sys
sys.path.append('/Users/omatt/Documents/eclipse/madweight/')
logger = logging.getLogger('cmdprint')
pjoin = os.path.join
try:
from madgraph import InvalidCmd, MadGraph5Error, MG5DIR
import madgraph.interface.extended_cmd as cmd
import madgraph.interface.common_run_interface as common_run
import madgraph.madweight.MW_info as MW_info
import madgraph.madweight.change_tf as change_tf
import madgraph.madweight.create_param as create_param
import madgraph.madweight.create_run as create_run
import madgraph.madweight.Cards as Cards
import madgraph.madweight.write_MadWeight as write_MadWeight
import madgraph.madweight.verif_event as verif_event
import madgraph.madweight.MW_driver as MW_driver
import madgraph.various.misc as misc
import madgraph.various.banner as banner
import madgraph.iolibs.files as files
MADEVENT = False
except ImportError, error:
logger.debug(error)
from internal import InvalidCmd, MadGraph5Error
import internal.extended_cmd as cmd
import internal.common_run_interface as common_run
import internal.madweight.MW_info as MW_info
import internal.madweight.change_tf as change_tf
import internal.madweight.create_param as create_param
import internal.madweight.create_run as create_run
import internal.madweight.Cards as Cards
import internal.madweight.write_MadWeight as write_MadWeight
import internal.madweight.verif_event as verif_event
import internal.madweight.MW_driver as MW_driver
import internal.misc as misc
import internal.banner as banner
import internal.files as files
MADEVENT = True
AlreadyRunning = common_run.AlreadyRunning
#===============================================================================
# CmdExtended
#===============================================================================
class CmdExtended(cmd.Cmd):
"""Particularisation of the cmd command for MadEvent"""
#suggested list of command
next_possibility = {
'start': [],
}
debug_output = 'MW5_debug'
error_debug = 'Please report this bug on https://bugs.launchpad.net/mg5amcnlo\n'
error_debug += 'with MadWeight in the title of the bug report.'
error_debug += 'More information is found in \'%(debug)s\'.\n'
error_debug += 'Please attach this file to your report.'
config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/mg5amcnlo\n'
keyboard_stop_msg = """stopping all operation
in order to quit madweight please enter exit"""
# Define the Error
InvalidCmd = InvalidCmd
ConfigurationError = MadGraph5Error
def __init__(self, *arg, **opt):
"""Init history and line continuation"""
# Tag allowing/forbiding question
self.force = False
# If possible, build an info line with current version number
# and date, from the VERSION text file
info = misc.get_pkg_info()
info_line = ""
if info and info.has_key('version') and info.has_key('date'):
len_version = len(info['version'])
len_date = len(info['date'])
if len_version + len_date < 30:
info_line = "#* VERSION %s %s %s *\n" % \
(info['version'],
(30 - len_version - len_date) * ' ',
info['date'])
else:
root_path = pjoin(os.path.dirname(__file__), os.path.pardir,os.path.pardir)
version = open(pjoin(root_path,'MGMEVersion.txt')).readline().strip()
info_line = "#* VERSION %s %s *\n" % \
(version, (24 - len(version)) * ' ')
# Create a header for the history file.
# Remember to fill in time at writeout time!
self.history_header = \
'#************************************************************\n' + \
'#* MadWeight 5 *\n' + \
'#* *\n' + \
"#* * * *\n" + \
"#* * * * * *\n" + \
"#* * * * * 5 * * * * *\n" + \
"#* * * * * *\n" + \
"#* * * *\n" + \
"#* *\n" + \
"#* *\n" + \
info_line + \
"#* *\n" + \
"#* The MadGraph Development Team - Please visit us at *\n" + \
"#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
'#* *\n' + \
'#************************************************************\n' + \
'#* *\n' + \
'#* Command File for MadWeight *\n' + \
'#* *\n' + \
'#* run as ./bin/madweight.py FILENAME *\n' + \
'#* *\n' + \
'#************************************************************\n'
if info_line:
info_line = info_line[1:]
logger.info(\
"************************************************************\n" + \
"* *\n" + \
"* W E L C O M E to M A D G R A P H 5 *\n" + \
"* M A D W E I G H T *\n" + \
"* *\n" + \
"* * * *\n" + \
"* * * * * *\n" + \
"* * * * * 5 * * * * *\n" + \
"* * * * * *\n" + \
"* * * *\n" + \
"* *\n" + \
info_line + \
"* *\n" + \
"* The MadGraph Development Team - Please visit us at *\n" + \
"* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
"* *\n" + \
"* Type 'help' for in-line help. *\n" + \
"* *\n" + \
"************************************************************")
cmd.Cmd.__init__(self, *arg, **opt)
class HelpToCmd(object):
def help_collect(self):
logger.info('collect [-refine]')
logger.info(' combine the results of the jobs launched on the cluster.')
logger.info(' This creates three type of output files:')
logger.info(' - weights.out [weight for event/card]')
logger.info(' - unnormalize-likelihood.out [-\sum ln(Weight)]')
logger.info(' - output.xml [additional information]')
logger.info('')
logger.info(' The option \'-refine\' is to be added if this is not the first')
logger.info(' cluster submission. Otherwise previous run submission will be lost.')
def help_define_transfer_fct(self):
"""help for define transfer_fct"""
logger.info(' Modify the current transfer functions')
logger.info(' If no argument provided a question showing the list of possibilities.')
logger.info(' will be ask. If the TF is provided as argument, no question is asked.')
class CompleteForCmd(object):
def complete_collect(self,text, line, begidx, endidx):
""" complete the collect command"""
args = self.split_arg(line[0:begidx])
return self.list_completion(text,['-refine','-f','--refine'], line)
def complete_define_transfer_fct(self, text, line, begidx, endidx):
""" complete the define_transfer_fct """
path = pjoin(self.me_dir, 'Source', 'MadWeight', 'transfer_function', 'data')
listdir=os.listdir(path)
args = self.split_arg(line[0:begidx])
if len(args) == 1:
possibilities = [content[3:-4] for content in listdir \
if (content.startswith('TF') and content.endswith('dat'))]
return self.list_completion(text, possibilities, line)
#===============================================================================
# MadWeightCmd
#===============================================================================
class MadWeightCmd(CmdExtended, HelpToCmd, CompleteForCmd, common_run.CommonRunCmd):
_set_options = []
prompt = 'MadWeight5>'
helporder = ['MadWeight Function', 'Documented commands', 'Advanced commands']
def remove_fct(self):
"""Not in help: remove fct"""
return None
do_decay_events = remove_fct
do_delphes = remove_fct
do_pgs = remove_fct
############################################################################
def __init__(self, me_dir = None, options={}, *completekey, **stdin):
""" add information to the cmd """
CmdExtended.__init__(self, *completekey, **stdin)
common_run.CommonRunCmd.__init__(self, me_dir, options)
self.configured = 0 # time at which the last option configuration occur
def do_quit(self, *args, **opts):
common_run.CommonRunCmd.do_quit(self, *args, **opts)
CmdExtended.do_quit(self, *args, **opts)
return True
def configure(self):
os.chdir(pjoin(self.me_dir))
self.__CMD__initpos = self.me_dir
time_mod = max([os.path.getctime(pjoin(self.me_dir,'Cards','run_card.dat')),
os.path.getctime(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))])
if self.configured > time_mod and \
hasattr(self,'MWparam') and hasattr(self,'run_card'):
return
self.configured = time.time()
self.MWparam = MW_info.MW_info(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
self.run_card = banner.RunCard(run_card)
if self.options['run_mode'] == 0:
self.exec_cmd('set run_mode 2 --no_save')
self.exec_cmd('set nb_core 1 --no_save')
if not self.options['cluster_temp_path']:
if self.options['run_mode'] == 2:
logger.info('Options cluster_temp_path is required for MW run. Trying to run with /tmp',
'$MG:color:BLACK')
self.exec_cmd('set cluster_temp_path /tmp --no_save')
elif self.options['cluster_type'] != 'condor':
raise Exception, 'cluster_temp_path needs to be define for MW. Please retry.'
def do_define_transfer_fct(self, line):
"""MadWeight Function:Define the current transfer function"""
with misc.chdir(self.me_dir):
self.configure()
args = self.split_arg(line)
path = pjoin(self.me_dir, 'Source', 'MadWeight', 'transfer_function', 'data')
listdir=os.listdir(path)
question = 'Please choose your transfer_function between\n'
possibilities = [content[3:-4] for content in listdir \
if (content.startswith('TF') and content.endswith('dat'))]
for i, tfname in enumerate(possibilities):
question += ' %s / %s\n' % (i, tfname)
possibilities += range(len(possibilities))
if args and args[0] in possibilities:
tfname = args[0]
else:
tfname = self.ask(question, 'dbl_gauss_pt_jet', possibilities)
if tfname.isdigit():
tfname = possibilities[int(tfname)]
P_dir, MW_dir = MW_info.detect_SubProcess(P_mode=1)
os.chdir('./Source/MadWeight/transfer_function')
change_tf.create_TF_main(tfname,0, MW_dir)
def do_treatcards(self, line):
"""MadWeight Function:create the various param_card // compile input for the run_card"""
self.configure()
args = self.split_arg(line)
create_param.Param_card(run_name=self.MWparam)
self.MWparam.update_nb_card()
Cards.create_include_file(self.MWparam)
create_run.update_cuts_status(self.MWparam)
def do_get_integration_channel(self, line):
"""MadWeight Function:analyze the cards/diagram to find an way to integrate efficiently"""
self.configure()
args = self.split_arg(line)
write_MadWeight.create_all_fortran_code(self.MWparam)
def do_compile(self, line, refine=False):
"""MadWeight Function:compile the code"""
self.configure()
misc.compile(arg=["../lib/libtools.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libblocks.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libTF.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libpdf.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libdhelas.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libmodel.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libgeneric.a"], cwd=pjoin(self.me_dir,'Source'))
misc.compile(arg=["../lib/libcernlib.a"], cwd=pjoin(self.me_dir,'Source'))
#
# here check validity of some parameters
if self.MWparam['mw_run']['integrator']=='m' and self.MWparam['mw_run']['montecarlo_perm']=='t':
raise Exception, 'Cannot use mint if monte carlo over permutations'
if self.MWparam['mw_run']['integrator']=='m' and self.MWparam['mw_run']['use_sobol']=='t':
raise Exception, 'sobol generator with mint not implemented'
for MW_dir in self.MWparam.MW_listdir:
logger.info('compile %s' %MW_dir)
pdir = pjoin(self.me_dir,'SubProcesses',MW_dir)
if refine and os.path.exists(pjoin(pdir, 'initialization.o')):
os.remove(pjoin(pdir, 'initialization.o'))
if refine and os.path.exists(pjoin(pdir, 'comp_madweight')):
os.remove(pjoin(pdir, 'comp_madweight'))
misc.compile(cwd=pdir)
if not os.path.exists(pjoin(pdir, 'comp_madweight')):
raise Exception, 'compilation fails'
logger.info('MadWeight code has been compiled.')
def do_check_events(self, line):
"""MadWeight Function: check that the events are valid
and write the events to MG mapping"""
self.configure()
evt_file = pjoin(self.me_dir,'Events','input.lhco')
if not os.path.exists(evt_file):
question = 'Which LHCO file do you want to use?'
default = ''
if os.path.exists('%s.gz' % evt_file):
input_file = '%s.gz' % evt_file
else:
input_file = self.ask(question, default, path_msg='valid path')
if not input_file:
raise self.InvalidCmd('Please specify a valid LHCO File')
if input_file.endswith('.gz'):
misc.gunzip(input_file, keep=True, stdout=evt_file)
else:
files.cp(input_file, evt_file)
verif_event.verif_event(self.MWparam)
def check_launch_jobs(self, args):
"""format the argument to retrun a list with two argument,
The first corresponding to the fact if we need te create the output dir
The second if we can launch the job on the cluster."""
if not args:
#use default
args[:] = [True, True]
return
else:
create_dir = True
launch = True
for arg in args:
if arg.count('=') !=1 :
logger.warning('command launch_jobs does not recognized argument %s. This argument is ignored' % arg)
restrict, value = arg.split('=')
if restrict == '--create_dir=':
if value in self.True:
create_dir = True
else:
create_dir = False
elif restrict == '--submit=':
if value in self.True:
launch = True
else:
launch = False
args[:] = [create_dir, launch]
return
def do_submit_jobs(self, line):
"""MadWeight Function:Submitting the jobs to the cluster"""
self.configure()
self.clean_old_run(keep_event=True)
args = self.split_arg(line)
self.check_launch_jobs(args)
# now args is of the type [True True]
create_dir, launch_jobs = args[0], args[1]
for nb_card in self.MWparam.actif_param:
for dirname in self.MWparam.MW_listdir:
nb_job = self.MWparam.nb_event_MW[dirname]
if self.MWparam['mw_run']['nb_event_by_node'] > 1:
nb_job = 1+ (nb_job-1) // self.MWparam['mw_run']['nb_event_by_node']
for event_sample in range(nb_job):
self.submit_job(dirname, nb_card, event_sample)
starttime = time.time()
#logger.info(' Waiting for submitted jobs to complete')
update_status = lambda i, r, f: self.update_status((i, r, f, 'madweight'),
starttime=starttime, level='madweight', update_results=False)
try:
self.cluster.wait(self.me_dir, update_status)
except Exception:
self.cluster.remove()
raise
except KeyboardInterrupt:
if not self.force:
ans = self.ask('Error detected. Do you want to clean the queue?',
default = 'y', choices=['y','n'])
else:
ans = 'y'
if ans == 'y':
self.cluster.remove()
raise
def submit_job(self, dirname, nb_card, sample_nb, evt_file=None, restrict_evt=[]):
"""launch on the cluster the job which creates the computation"""
input_files = [pjoin(self.me_dir, 'SubProcesses', dirname, 'comp_madweight'),
pjoin(self.me_dir, 'Cards', 'param_card_%i.dat' % nb_card),
self.get_pdf_input_filename(),
pjoin(self.me_dir, 'Cards', 'ident_card.dat'),
pjoin(self.me_dir, 'Cards', 'run_card.dat')
]
# add event_file:
if not evt_file:
evt_file = (sample_nb // self.MWparam['mw_run']['event_packing'])
evt = 'verif_%i.lhco' % evt_file
first_event = (sample_nb % self.MWparam['mw_run']['event_packing']) * self.MWparam['mw_run']['nb_event_by_node']
name = self.MWparam.name
input_files.append(pjoin(self.me_dir, 'SubProcesses', dirname, name, evt))
if restrict_evt:
restrict_path = pjoin(self.me_dir, 'SubProcesses', dirname, name,
'restrict%i_%i.dat' % (nb_card,evt_file))
input_files.append(restrict_path)
#open(restrict_path, 'w').write(' '.join(map(str, restrict_evt)))
# Need to add PDF (maybe also symfact, ...) ?
output_file = ['output_%s_%s.xml' % (nb_card, sample_nb)]
exe = pjoin(self.me_dir, 'bin', 'internal', 'madweight', 'MW_driver.py')
# expected args: card_nb, first_event, nb_event, evt, mw_int_points, log_level
args = [str(nb_card), str(first_event),
str(self.MWparam['mw_run']['nb_event_by_node']) ,evt,
str(self.MWparam['mw_run']['mw_int_points']),
self.MWparam['mw_run']['log_level'], str(sample_nb)]
cwd = pjoin(self.me_dir, 'SubProcesses', dirname, name)
# Ensure that the code is working ONLY if TEMP_CLUSTER_PATH is define
if self.options['run_mode'] == 0:
raise Exception , 'need to check the validity'
else:
# ensure that this is running with NO central disk !!!
if not self.options['cluster_temp_path'] and not self.options['cluster_type'] == 'condor':
raise self.ConfigurationError, 'MadWeight requires temp_cluster_path options to be define'
self.cluster.submit2(exe, args, cwd, input_files=input_files, output_files=output_file)
def check_collect(self, args):
""" """
if len(args) >1:
self.help_collect()
raise self.InvalidCmd, 'Invalid Command format'
elif len(args) == 1:
if args not in ['-refine', '--refine']:
args[0] = '-refine'
else:
self.help_collect()
raise self.InvalidCmd, 'Invalid Command format'
def do_collect(self, line):
"""MadWeight Function: making the collect of the results"""
self.configure()
args = self.split_arg(line)
self.check_collect(args)
xml_reader = MWParserXML()
name = self.MWparam.name
# 1. Concatanate the file. #############################################
out_dir = pjoin(self.me_dir, 'Events', name)
if '-refine' in args:
out_path = pjoin(out_dir, 'refine.xml')
else:
out_path = pjoin(out_dir, 'output.xml')
if os.path.exists(out_path):
logger.warning('Output file already exists. Current one will be tagged with _old suffix')
logger.warning('Run "collect -refine to instead update your current results."')
files.mv(pjoin(out_dir, 'output.xml'), pjoin(out_dir, 'output_old.xml'))
files.mv(pjoin(out_dir, 'weights.out'), pjoin(out_dir, 'weights.out'))
for MWdir in self.MWparam.MW_listdir:
out_dir = pjoin(self.me_dir, 'Events', name, MWdir)
files.mv(pjoin(out_dir, 'output.xml'), pjoin(out_dir, 'output_old.xml'))
out_dir = pjoin(self.me_dir, 'Events', name)
fsock = open(out_path, 'w')
fsock.write('\n\n')
# BANNER
for card in ['proc_card_mg5.dat','MadWeight_card.dat','transfer_card.dat','param_card.dat','run_card.dat']:
cname = card[:-4]
fsock.write('<%s>\n' % cname)
fsock.write(open(pjoin(self.me_dir,'Cards',card)).read().replace('<','!>'))
fsock.write('%s>\n' % cname)
fsock.write('\n')
at_least_one = False
for MWdir in self.MWparam.MW_listdir:
out_dir = pjoin(self.me_dir, 'Events', name, MWdir)
input_dir = pjoin(self.me_dir, 'SubProcesses', MWdir, name)
if not os.path.exists(out_dir):
os.mkdir(out_dir)
if '-refine' in args:
out_path = pjoin(out_dir, 'refine.xml')
else:
out_path = pjoin(out_dir, 'output.xml')
fsock2 = open(out_path,'w')
fsock.write('\n' % MWdir)
fsock2.write('\n' % MWdir)
for output in misc.glob('output_*_*.xml', input_dir):
at_least_one = True
text = open(output).read()
fsock2.write(text)
fsock.write(text)
os.remove(output)
fsock.write('\n')
fsock2.write('\n')
fsock2.close()
fsock.write('\n\n')
fsock.close()
# 2. Special treatment for refine mode
if '-refine' in args:
xml_reader2 = MWParserXML(self.MWparam['mw_run']['log_level'])
for MWdir in self.MWparam.MW_listdir:
out_dir = pjoin(self.me_dir, 'Events',name, MWdir)
ref_output = xml_reader2.read_file(pjoin(out_dir, 'refine.xml'))
xml_reader2 = MWParserXML(self.MWparam['mw_run']['log_level'])
base_output = xml_reader2.read_file(pjoin(out_dir, 'output.xml'))
base_output.refine(ref_output)
files.mv(pjoin(out_dir, 'output.xml'), pjoin(out_dir, 'output_old.xml'))
base_output.write(pjoin(out_dir, 'output.xml'), MWdir)
elif not at_least_one:
logger.warning("Nothing to collect restore _old file as current.")
out_dir = pjoin(self.me_dir, 'Events', name)
files.mv(pjoin(out_dir, 'output_old.xml'), pjoin(out_dir, 'output.xml'))
files.mv(pjoin(out_dir, 'weights_old.out'), pjoin(out_dir, 'weights.out'))
for MWdir in self.MWparam.MW_listdir:
out_dir = pjoin(self.me_dir, 'Events', name, MWdir)
files.mv(pjoin(out_dir, 'output.xml'), pjoin(out_dir, 'output_old.xml'))
# 3. Read the (final) log file for extracting data
total = {}
likelihood = {}
err_likelihood = {}
cards = set()
events = set()
tf_sets = set()
for MW_dir in self.MWparam.MW_listdir:
out_dir = pjoin(self.me_dir, 'Events', name, MW_dir)
xml_reader = MWParserXML()
data = xml_reader.read_file(pjoin(out_dir, 'output.xml'))
#
log_level = self.MWparam['mw_run']['log_level']
generator = ((int(i),j,int(k),data[i][j][k]) for i in data
for j in data[i]
for k in data[i][j])
for card, event, tf_set, obj in generator:
# update the full list of events/cards
cards.add(card)
events.add(event)
tf_sets.add(tf_set)
# now compute the associate value, error[square]
if (card,event, tf_set) in total:
value, error = total[(card, event, tf_set)]
else:
value, error = 0, 0
obj.calculate_total()
value, error = (value + obj.value, error + obj.error**2)
total[(card, event, tf_set)] = (value, error)
if tf_set == 1:
if value:
if card not in likelihood:
likelihood[card], err_likelihood[card] = 0, 0
likelihood[card] -= math.log(value)
err_likelihood[card] += error / value
else:
likelihood[card] = float('Inf')
err_likelihood[card] = float('nan')
# write the weights file:
fsock = open(pjoin(self.me_dir, 'Events', name, 'weights.out'), 'w')
logger.info('Write output file with weight information: %s' % fsock.name)
fsock.write('# Weight (un-normalize) for each card/event/set of transfer fct\n')
fsock.write('# format: LHCO_event_number card_id tf_set_id value integration_error\n')
events = list(events)
events.sort()
cards = list(cards)
cards.sort()
tf_sets = list(tf_sets)
tf_sets.sort()
for event in events:
for card in cards:
for tf_set in tf_sets:
try:
value, error = total[(card, event,tf_set)]
except KeyError:
continue
error = math.sqrt(error)
fsock.write('%s %s %s %s %s \n' % (event.replace('@', ' '), card, tf_set, value, error))
# write the likelihood file:
fsock = open(pjoin(self.me_dir, 'Events', name, 'un-normalized_likelihood.out'), 'w')
fsock.write('# Warning: this Likelihood needs a bin by bin normalization !\n')
fsock.write('# IF more than one set of transfer function are define. ONLY the first one is ')
fsock.write('# include in this file.')
fsock.write('# format: card_id value integration_error\n')
for card in cards:
value, error = likelihood[card], err_likelihood[card]
error = math.sqrt(error)
fsock.write('%s %s %s \n' % (card, value, error))
def do_clean(self, line):
"""MadWeight Function: syntax: clean [XXX]
clean the previous run XXX (the last one by default)"""
args = self.split_arg(line)
self.configure()
if len(args) == 0:
name = self.MWparam.name
else:
name = args[0]
ans = self.ask('Do you want to remove Events/%s directory?', 'y',['y','n'])
if ans == 'y':
try:
shutil.rmtree(pjoin(self.me_dir, 'Events', name))
except Exception, error:
logger.warning(error)
for Pdir in self.MWparam.MW_listdir:
try:
shutil.rmtree(pjoin(self.me_dir, 'SubProcesses', Pdir, name))
except Exception, error:
logger.warning(error)
def ask_edit_cards(self, cards, *arg, **opts):
super(MadWeightCmd, self).ask_edit_cards(cards, *arg, **opts)
self.configured = 0
self.configure()
def do_launch(self, line):
"""MadWeight Function:run the full suite of commands"""
args = self.split_arg(line)
#if not os.path.exists(pjoin(self.me_dir, 'Cards','transfer_card.dat')):
# self.exec_cmd('define_transfer_fct')
cards = ['param_card.dat', 'run_card.dat', 'madweight_card.dat',
'transfer_card.dat', 'input.lhco']
if not self.force:
self.ask_edit_cards(cards, mode='fixed', plot=False)
else:
self.configured = 0
self.configure()
with misc.chdir(self.me_dir):
if not os.path.exists(pjoin(self.me_dir, self.MWparam['mw_run']['inputfile'])):
raise self.InvalidCmd('Please specify a valid LHCO File')
if pjoin(self.me_dir, self.MWparam['mw_run']['inputfile']) not in \
[pjoin(self.me_dir, 'Events', 'input.lhco'), pjoin(self.me_dir, 'Events', 'input.lhco.gz')]:
zipped = self.MWparam['mw_run']['inputfile'].endswith('.gz')
if zipped:
files.cp(pjoin(self.me_dir, self.MWparam['mw_run']['inputfile']),
pjoin(self.me_dir, 'Events', 'input.lhco.gz'))
if os.path.exists(pjoin(self.me_dir, 'Events', 'input.lhco')):
os.remove(pjoin(self.me_dir, 'Events', 'input.lhco'))
else:
files.cp(pjoin(self.me_dir, self.MWparam['mw_run']['inputfile']),
pjoin(self.me_dir, 'Events', 'input.lhco'))
if not (os.path.exists(pjoin(self.me_dir, 'Events', 'input.lhco')) or \
os.path.exists(pjoin(self.me_dir, 'Events', 'input.lhco.gz'))):
raise self.InvalidCmd('Please specify a valid LHCO File')
self.exec_cmd('treatcards')
self.exec_cmd('get_integration_channel')
self.exec_cmd('compile')
self.exec_cmd('check_events')
self.exec_cmd('submit_jobs')
self.exec_cmd('collect')
def check_refine(self, args):
"""check the argument validity"""
if len(args) != 1:
raise self.InvalidCmd('refine requires a single argument')
try:
args[0] = float(args[0])
except Exception:
raise self.InvalidCmd('First argument of refine command should be a number')
if args[0] < 0 or args[0]>1:
raise self.InvalidCmd('The first argument should be a number between 0 and 1.')
def clean_old_run(self, keep_event=False):
for MWdir in self.MWparam.MW_listdir:
input_dir = pjoin(self.me_dir, 'SubProcesses', MWdir, self.MWparam.name)
if not os.path.exists(input_dir):
continue
for filename in os.listdir(input_dir):
if keep_event and filename.startswith('verif'):
continue
os.remove(pjoin(input_dir, filename))
def do_refine(self, line):
"""MadWeight Function:syntax: refine X
relaunch the computation of the weight which have a precision lower than X"""
args = self.split_arg(line)
self.check_refine(args)
self.configure()
self.clean_old_run(keep_event=True)
if not self.force:
cards = ['madweight_card.dat']
self.ask_edit_cards(cards, mode='fixed', plot=False)
self.exec_cmd("treatcards")
self.do_compile('', refine=True) # force re-compilation
nb_events_by_file = self.MWparam['mw_run']['nb_event_by_node'] * self.MWparam['mw_run']['event_packing']
asked_events = self.MWparam['mw_run']['nb_exp_events']
precision = args[0]
name = self.MWparam.name
allow_refine = []
# events/cards to refine
fsock = open(pjoin(self.me_dir, 'Events', name, 'weights.out'), 'r')
for line in fsock:
if '#' in line:
line = line.split('#')[0]
line = line.split()
if len(line) == 5:
lhco_nb, card_nb, tf_set, value, error = line
else:
continue
if tf_set != '1':
continue
if float(value) * precision < float(error):
allow_refine.append((int(card_nb), lhco_nb))
logger.info("%s selected jobs for the refinment." % len(allow_refine))
for MWdir in self.MWparam.MW_listdir:
# We need to know in which file are written all the relevant event
event_to_file = {}
for evt_nb in range(asked_events//nb_events_by_file +1):
evt = 'verif_%i.lhco' % evt_nb
for line in open(pjoin(self.me_dir, 'SubProcesses', MWdir, name, evt)):
split = line.split()
if len(split) == 3:
event_to_file[split[1]] = evt_nb
to_refine = {}
out_dir = pjoin(self.me_dir, 'Events',name, MWdir)
xml_reader = MWParserXML(keep_level='weight')
data = xml_reader.read_file(pjoin(out_dir, 'output.xml'))
generator = ((int(i),j,int(k),data[i][j][k]) for i in data
for j in data[i]
for k in data[i][j])
for card, event, tf_set, obj in generator:
if tf_set != 1:
continue
value, error = obj.value, obj.error
if value * precision < error:
if card not in to_refine:
to_refine[card] = []
if (card,event) in allow_refine:
to_refine[card].append(event)
if to_refine:
self.resubmit(MWdir, to_refine, event_to_file)
# control
starttime = time.time()
update_status = lambda i, r, f: self.update_status((i, r, f, 'madweight'),
starttime=starttime, level='madweight', update_results=False)
try:
self.cluster.wait(self.me_dir, update_status)
except Exception:
self.cluster.remove()
raise
except KeyboardInterrupt:
if not self.force:
ans = self.ask('Error detected. Do you want to clean the queue?',
default = 'y', choices=['y','n'])
else:
ans = 'y'
if ans == 'y':
self.cluster.remove()
raise
self.do_collect('-refine')
def resubmit(self, M_path, to_refine, event_to_file):
"""resubmit various jobs"""
for card, event_list in to_refine.items():
packets = {}
for event in event_list:
evt_nb_file = event_to_file[event]
if evt_nb_file in packets:
packets[evt_nb_file].append(event)
else:
packets[evt_nb_file] = [event]
# evt_file = (sample_nb // self.MWparam['mw_run']['event_packing'])
# open(restrict_path, 'w').write(' '.join(map(str, restrict_evt)))
max_evts = self.MWparam['mw_run']['nb_event_by_node']
for evt_nb, evt_list in packets.items():
restrict_path = pjoin(self.me_dir, 'SubProcesses', M_path, self.MWparam.name,
'restrict%i_%i.dat' % (card,evt_nb_file))
open(restrict_path, 'w').write(' '.join(map(str, evt_list)))
nb_weights = len(evt_list)
for i in range(1+ (nb_weights-1)//max_evts):
#sub_list = evt_list[max_evts * i: max_evts * (i+1)]
self.submit_job(M_path, card, i, evt_file=evt_nb,
restrict_evt=True)
#===============================================================================
# MadEventCmd
#===============================================================================
class MadWeightCmdShell(MadWeightCmd, cmd.CmdShell):
"""The command line processor of MadGraph"""
pass
class CollectObj(dict):
pass
#2 #############################################################################
def refine(self, other):
for card, CardDATA in other.items():
if card not in self:
self[card] = other[card]
continue
for event, obj2 in CardDATA.items():
self[card][event] = obj2
def write(self, out_path, MWdir):
""" """
fsock = open(out_path, 'w')
fsock.write('\n' % MWdir)
for card in self:
fsock.write('\n' % card)
for event in self[card].values():
event.write(fsock)
fsock.write('\n')
fsock.write('')
fsock.close()
#1 #################################################################################
class MWParserXML(xml.sax.handler.ContentHandler):
""" This class will organize in python obect the TF_param.dat file
(written in xml)
"""
#2 #############################################################################
def __init__(self, keep_level='weight'):
self.in_el = {'process': '', 'card':'', 'event':'', 'tfset':'' ,
'permutation':'', 'channel':'','full':''}
if keep_level in ['weight', 'event', 'debug']:
keep_level = 'tfset'
self.all_event = {}
self.keep_level = keep_level
self.buffer=''
self.output = CollectObj()
#2 #############################################################################
def startElement(self, name, attributes):
# if in lower level than needed skip the collection of data
if self.in_el[self.keep_level] != '' or name == 'log':
return
obj_class = {'event': MW_driver.Weight, 'permutation':MW_driver.Permutation,
'channel': MW_driver.Channel, 'tfset':MW_driver.TFsets}
if name == "process":
pass
elif name == 'card':
id = attributes['id']
if id not in self.output:
self.output[id] = {}
self.in_el[name] = self.output[id]
self.curr_card_id = id
elif name == 'event':
id = attributes['id']
value = float(attributes['value'])
error = float(attributes['error'])
card = self.curr_card_id
if ((card,id) in self.all_event):
data = self.all_event[(card,id)]
else:
data = MW_driver.Weight(id, self.keep_level)
self.all_event[(card,id)] = data
data.value = value
data.error = error
self.in_el['event'] = data
# assign it in the mother:
card = self.in_el['card']
card[id] = data
elif name == 'tfset':
id = attributes['id']
value = float(attributes['value'])
error = float(attributes['error'])
data = MW_driver.TFsets(id)
data.value = value
data.error = error
data.add('0', '', value, error, '')
#assign it to the mother:
event = self.in_el['event']
event[id] = data
self.in_el['tfset'] = data
elif name == 'permutation':
tfset = self.in_el['tfset']
id = attributes['id']
value = float(attributes['value'])
error = float(attributes['error'])
data = MW_driver.Permutation(id, '')
data.value = value
data.error = error
self.in_el['permutation'] = data
# assign it in the mother:
tfset[id] = data
elif name == 'channel':
id = attributes['id']
value = float(attributes['value'])
error = float(attributes['error'])
data = MW_driver.Channel(id, value, error)
self.in_el['channel'] = data
# assign it in the mother:
permutation = self.in_el['permutation']
permutation[id] = data
elif name in ['log','subprocess','br']:
pass
else:
raise Exception, name
if name != 'br':
self.text = StringIO()
def characters(self, content):
self.text.write(content)
def endElement(self, name):
if name == 'log':
data = self.in_el['event']
data.log = self.text.getvalue()
self.in_el[name] = ''
#2 #############################################################################
def read_file(self,filepos):
""" parse the file and fulfill the object """
self.output = CollectObj()
parser = xml.sax.make_parser( )
parser.setContentHandler(self)
parser.parse(filepos)
return self.output