1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """A user friendly command line interface to access MadGraph5_aMC@NLO features.
16 Uses the cmd package for command interpretation and tab completion.
17 """
18 from __future__ import division
19
20 import atexit
21 import collections
22 import cmath
23 import glob
24 import logging
25 import math
26 import optparse
27 import os
28 import pydoc
29 import random
30 import re
31 import signal
32 import shutil
33 import stat
34 import subprocess
35 import sys
36 import traceback
37 import time
38 import tarfile
39 import StringIO
40 import shutil
41 import copy
42 import xml.dom.minidom as minidom
43
44 try:
45 import readline
46 GNU_SPLITTING = ('GNU' in readline.__doc__)
47 except:
48 GNU_SPLITTING = True
49
50 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
51 root_path = os.path.split(root_path)[0]
52 sys.path.insert(0, os.path.join(root_path,'bin'))
53
54
55 pjoin = os.path.join
56
57 logger = logging.getLogger('madevent.stdout')
58 logger_stderr = logging.getLogger('madevent.stderr')
59
60 try:
61 import madgraph
62
63
64 except ImportError:
65
66 MADEVENT = True
67 import internal.extended_cmd as cmd
68 import internal.common_run_interface as common_run
69 import internal.banner as banner_mod
70 import internal.misc as misc
71 from internal import InvalidCmd, MadGraph5Error, ReadWrite
72 import internal.files as files
73 import internal.gen_crossxhtml as gen_crossxhtml
74 import internal.gen_ximprove as gen_ximprove
75 import internal.save_load_object as save_load_object
76 import internal.cluster as cluster
77 import internal.check_param_card as check_param_card
78 import internal.sum_html as sum_html
79 import internal.combine_runs as combine_runs
80 import internal.lhe_parser as lhe_parser
81 import internal.histograms as histograms
82 from internal.files import ln
83 else:
84
85 MADEVENT = False
86 import madgraph.interface.extended_cmd as cmd
87 import madgraph.interface.common_run_interface as common_run
88 import madgraph.iolibs.files as files
89 import madgraph.iolibs.save_load_object as save_load_object
90 import madgraph.madevent.gen_crossxhtml as gen_crossxhtml
91 import madgraph.madevent.gen_ximprove as gen_ximprove
92 import madgraph.madevent.sum_html as sum_html
93 import madgraph.various.banner as banner_mod
94 import madgraph.various.cluster as cluster
95 import madgraph.various.misc as misc
96 import madgraph.madevent.combine_runs as combine_runs
97 import madgraph.various.lhe_parser as lhe_parser
98 import madgraph.various.histograms as histograms
99
100 import models.check_param_card as check_param_card
101 from madgraph.iolibs.files import ln
102 from madgraph import InvalidCmd, MadGraph5Error, MG5DIR, ReadWrite
109
112
114
115 MadEventAlreadyRunning = common_run.MadEventAlreadyRunning
116
117
118
119
120 -class CmdExtended(common_run.CommonRunCmd):
121 """Particularisation of the cmd command for MadEvent"""
122
123
124 next_possibility = {
125 'start': [],
126 }
127
128 debug_output = 'ME5_debug'
129 error_debug = 'Please report this bug on https://bugs.launchpad.net/mg5amcnlo\n'
130 error_debug += 'More information is found in \'%(debug)s\'.\n'
131 error_debug += 'Please attach this file to your report.'
132
133 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/mg5amcnlo\n'
134
135
136 keyboard_stop_msg = """stopping all operation
137 in order to quit MadGraph5_aMC@NLO please enter exit"""
138
139
140 InvalidCmd = InvalidCmd
141 ConfigurationError = MadGraph5Error
142
143 - def __init__(self, me_dir, options, *arg, **opt):
144 """Init history and line continuation"""
145
146
147 self.force = False
148
149
150
151 info = misc.get_pkg_info()
152 info_line = ""
153 if info and info.has_key('version') and info.has_key('date'):
154 len_version = len(info['version'])
155 len_date = len(info['date'])
156 if len_version + len_date < 30:
157 info_line = "#* VERSION %s %s %s *\n" % \
158 (info['version'],
159 (30 - len_version - len_date) * ' ',
160 info['date'])
161 else:
162 version = open(pjoin(root_path,'MGMEVersion.txt')).readline().strip()
163 info_line = "#* VERSION %s %s *\n" % \
164 (version, (24 - len(version)) * ' ')
165
166
167
168 self.history_header = \
169 '#************************************************************\n' + \
170 '#* MadGraph5_aMC@NLO/MadEvent *\n' + \
171 '#* *\n' + \
172 "#* * * *\n" + \
173 "#* * * * * *\n" + \
174 "#* * * * * 5 * * * * *\n" + \
175 "#* * * * * *\n" + \
176 "#* * * *\n" + \
177 "#* *\n" + \
178 "#* *\n" + \
179 info_line + \
180 "#* *\n" + \
181 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
182 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
183 '#* *\n' + \
184 '#************************************************************\n' + \
185 '#* *\n' + \
186 '#* Command File for MadEvent *\n' + \
187 '#* *\n' + \
188 '#* run as ./bin/madevent.py filename *\n' + \
189 '#* *\n' + \
190 '#************************************************************\n'
191
192 if info_line:
193 info_line = info_line[1:]
194
195 logger.info(\
196 "************************************************************\n" + \
197 "* *\n" + \
198 "* W E L C O M E to *\n" + \
199 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
200 "* M A D E V E N T *\n" + \
201 "* *\n" + \
202 "* * * *\n" + \
203 "* * * * * *\n" + \
204 "* * * * * 5 * * * * *\n" + \
205 "* * * * * *\n" + \
206 "* * * *\n" + \
207 "* *\n" + \
208 info_line + \
209 "* *\n" + \
210 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
211 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
212 "* *\n" + \
213 "* Type 'help' for in-line help. *\n" + \
214 "* *\n" + \
215 "************************************************************")
216 super(CmdExtended, self).__init__(me_dir, options, *arg, **opt)
217
219 """return the history header"""
220 return self.history_header % misc.get_time_info()
221
223 """action to perform to close nicely on a keyboard interupt"""
224 try:
225 if hasattr(self, 'cluster'):
226 logger.info('rm jobs on queue')
227 self.cluster.remove()
228 if hasattr(self, 'results'):
229 self.update_status('Stop by the user', level=None, makehtml=False, error=True)
230 self.add_error_log_in_html(KeyboardInterrupt)
231 except:
232 pass
233
234 - def postcmd(self, stop, line):
235 """ Update the status of the run for finishing interactive command """
236
237 stop = super(CmdExtended, self).postcmd(stop, line)
238
239 self.force = False
240
241 if not self.use_rawinput:
242 return stop
243
244 if self.results and not self.results.current:
245 return stop
246
247 arg = line.split()
248 if len(arg) == 0:
249 return stop
250 if isinstance(self.results.status, str) and self.results.status.startswith('Error'):
251 return stop
252 if isinstance(self.results.status, str) and self.results.status == 'Stop by the user':
253 self.update_status('%s Stop by the user' % arg[0], level=None, error=True)
254 return stop
255 elif not self.results.status:
256 return stop
257 elif str(arg[0]) in ['exit','quit','EOF']:
258 return stop
259
260 try:
261 self.update_status('Command \'%s\' done.<br> Waiting for instruction.' % arg[0],
262 level=None, error=True)
263 except Exception:
264 misc.sprint('update_status fails')
265 pass
266
267
273
287
288
290 """If a ME run is currently running add a link in the html output"""
291
292 if isinstance(error, ZeroResult):
293 self.add_error_log_in_html(error)
294 logger.warning('Zero result detected: %s' % error)
295
296 try:
297 if not self.banner:
298 self.banner = banner_mod.Banner()
299 if 'slha' not in self.banner:
300 self.banner.add(pjoin(self.me_dir,'Cards','param_card.dat'))
301 if 'mgruncard' not in self.banner:
302 self.banner.add(pjoin(self.me_dir,'Cards','run_card.dat'))
303 if 'mg5proccard' not in self.banner:
304 proc_card = pjoin(self.me_dir,'Cards','proc_card_mg5.dat')
305 if os.path.exists(proc_card):
306 self.banner.add(proc_card)
307
308 out_dir = pjoin(self.me_dir, 'Events', self.run_name)
309 if not os.path.isdir(out_dir):
310 os.mkdir(out_dir)
311 output_path = pjoin(out_dir, '%s_%s_banner.txt' % \
312 (self.run_name, self.run_tag))
313 self.banner.write(output_path)
314 except Exception:
315 if __debug__:
316 raise
317 else:
318 pass
319 else:
320 self.add_error_log_in_html()
321 cmd.Cmd.nice_error_handling(self, error, line)
322 try:
323 debug_file = open(self.debug_output, 'a')
324 debug_file.write(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')))
325 debug_file.close()
326 except:
327 pass
328
334 """ The Series of help routine for the MadEventCmd"""
335
337 logger.info("syntax: pythia [RUN] [--run_options]")
338 logger.info("-- run pythia on RUN (current one by default)")
339 self.run_options_help([('-f','answer all question by default'),
340 ('--tag=', 'define the tag for the pythia run'),
341 ('--no_default', 'not run if pythia_card not present')])
342
344 logger.info("syntax: pythia8 [RUN] [--run_options]")
345 logger.info("-- run pythia8 on RUN (current one by default)")
346 self.run_options_help([('-f','answer all question by default'),
347 ('--tag=', 'define the tag for the pythia8 run'),
348 ('--no_default', 'not run if pythia8_card not present')])
349
351 logger.info("syntax: banner_run Path|RUN [--run_options]")
352 logger.info("-- Reproduce a run following a given banner")
353 logger.info(" One of the following argument is require:")
354 logger.info(" Path should be the path of a valid banner.")
355 logger.info(" RUN should be the name of a run of the current directory")
356 self.run_options_help([('-f','answer all question by default'),
357 ('--name=X', 'Define the name associated with the new run')])
358
360 logger.info("syntax: open FILE ")
361 logger.info("-- open a file with the appropriate editor.")
362 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
363 logger.info(' the path to the last created/used directory is used')
364 logger.info(' The program used to open those files can be chosen in the')
365 logger.info(' configuration file ./input/mg5_configuration.txt')
366
367
369 if data:
370 logger.info('-- local options:')
371 for name, info in data:
372 logger.info(' %s : %s' % (name, info))
373
374 logger.info("-- session options:")
375 logger.info(" Note that those options will be kept for the current session")
376 logger.info(" --cluster : Submit to the cluster. Current cluster: %s" % self.options['cluster_type'])
377 logger.info(" --multicore : Run in multi-core configuration")
378 logger.info(" --nb_core=X : limit the number of core to use to X.")
379
380
382 logger.info("syntax: generate_events [run_name] [options]",)
383 logger.info("-- Launch the full chain of script for the generation of events")
384 logger.info(" Including possible plotting, shower and detector resolution.")
385 logger.info(" Those steps are performed if the related program are installed")
386 logger.info(" and if the related card are present in the Cards directory.")
387 self.run_options_help([('-f', 'Use default for all questions.'),
388 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.'),
389 ('-M', 'in order to add MadSpin'),
390 ('-R', 'in order to add the reweighting module')])
391
393 logger.info("syntax: initMadLoop [options]",'$MG:color:GREEN')
394 logger.info(
395 """-- Command only useful when MadEvent simulates loop-induced processes. This command compiles and run
396 the MadLoop output for the matrix element computation so as to initialize the filter for analytically
397 zero helicity configurations and loop topologies. If you suspect that a change you made in the model
398 parameters can have affected these filters, this command allows you to automatically refresh them. """)
399 logger.info(" The available options are:",'$MG:color:BLUE')
400 logger.info(" -f : Bypass the edition of MadLoopParams.dat.",'$MG:color:BLUE')
401 logger.info(" -r : Refresh of the existing filters (erasing them if already present).",'$MG:color:BLUE')
402 logger.info(" --nPS=<int> : Specify how many phase-space points should be tried to set up the filters.",'$MG:color:BLUE')
403
405 logger.info("syntax: add_time_of_flight [run_name|path_to_file] [--threshold=]")
406 logger.info('-- Add in the lhe files the information')
407 logger.info(' of how long it takes to a particle to decay.')
408 logger.info(' threshold option allows to change the minimal value required to')
409 logger.info(' a non zero value for the particle (default:1e-12s)')
410
412
413 if self.ninitial != 1:
414 logger.warning("This command is only valid for processes of type A > B C.")
415 logger.warning("This command can not be run in current context.")
416 logger.warning("")
417
418 logger.info("syntax: calculate_decay_widths [run_name] [options])")
419 logger.info("-- Calculate decay widths and enter widths and BRs in param_card")
420 logger.info(" for a series of processes of type A > B C ...")
421 self.run_options_help([('-f', 'Use default for all questions.'),
422 ('--accuracy=', 'accuracy (for each partial decay width).'\
423 + ' Default is 0.01.')])
424
426 logger.info("syntax: multi_run NB_RUN [run_name] [--run_options])")
427 logger.info("-- Launch the full chain of script for the generation of events")
428 logger.info(" NB_RUN times. This chains includes possible plotting, shower")
429 logger.info(" and detector resolution.")
430 self.run_options_help([('-f', 'Use default for all questions.'),
431 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
432
438
440 """exec generate_events for 2>N and calculate_width for 1>N"""
441 logger.info("syntax: launch [run_name] [options])")
442 logger.info(" --alias for either generate_events/calculate_decay_widths")
443 logger.info(" depending of the number of particles in the initial state.")
444
445 if self.ninitial == 1:
446 logger.info("For this directory this is equivalent to calculate_decay_widths")
447 self.help_calculate_decay_widths()
448 else:
449 logger.info("For this directory this is equivalent to $generate_events")
450 self.help_generate_events()
451
453 logger.info("syntax: refine require_precision [max_channel] [--run_options]")
454 logger.info("-- refine the LAST run to achieve a given precision.")
455 logger.info(" require_precision: can be either the targeted number of events")
456 logger.info(' or the required relative error')
457 logger.info(' max_channel:[5] maximal number of channel per job')
458 self.run_options_help([])
459
461 """ """
462 logger.info("syntax: combine_events [run_name] [--tag=tag_name] [--run_options]")
463 logger.info("-- Combine the last run in order to write the number of events")
464 logger.info(" asked in the run_card.")
465 self.run_options_help([])
466
473
480
486
488 logger.info("syntax: syscalc [RUN] [%s] [-f | --tag=]" % '|'.join(self._plot_mode))
489 logger.info("-- calculate systematics information for the RUN (current run by default)")
490 logger.info(" at different stages of the event generation for scale/pdf/...")
491
493 logger.info("syntax: remove RUN [all|parton|pythia|pgs|delphes|banner] [-f] [--tag=]")
494 logger.info("-- Remove all the files linked to previous run RUN")
495 logger.info(" if RUN is 'all', then all run will be cleaned.")
496 logger.info(" The optional argument precise which part should be cleaned.")
497 logger.info(" By default we clean all the related files but the banners.")
498 logger.info(" the optional '-f' allows to by-pass all security question")
499 logger.info(" The banner can be remove only if all files are removed first.")
500
507 """ The Series of check routine for the MadEventCmd"""
508
510 """check the validity of line"""
511
512 if len(args) == 0:
513 self.help_banner_run()
514 raise self.InvalidCmd('banner_run requires at least one argument.')
515
516 tag = [a[6:] for a in args if a.startswith('--tag=')]
517
518
519 if os.path.exists(args[0]):
520 type ='banner'
521 format = self.detect_card_type(args[0])
522 if format != 'banner':
523 raise self.InvalidCmd('The file is not a valid banner.')
524 elif tag:
525 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \
526 (args[0], tag))
527 if not os.path.exists(args[0]):
528 raise self.InvalidCmd('No banner associates to this name and tag.')
529 else:
530 name = args[0]
531 type = 'run'
532 banners = misc.glob('*_banner.txt', pjoin(self.me_dir,'Events', args[0]))
533 if not banners:
534 raise self.InvalidCmd('No banner associates to this name.')
535 elif len(banners) == 1:
536 args[0] = banners[0]
537 else:
538
539 tags = [os.path.basename(p)[len(args[0])+1:-11] for p in banners]
540 tag = self.ask('which tag do you want to use?', tags[0], tags)
541 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \
542 (args[0], tag))
543
544 run_name = [arg[7:] for arg in args if arg.startswith('--name=')]
545 if run_name:
546 try:
547 self.exec_cmd('remove %s all banner -f' % run_name)
548 except Exception:
549 pass
550 self.set_run_name(args[0], tag=None, level='parton', reload_card=True)
551 elif type == 'banner':
552 self.set_run_name(self.find_available_run_name(self.me_dir))
553 elif type == 'run':
554 if not self.results[name].is_empty():
555 run_name = self.find_available_run_name(self.me_dir)
556 logger.info('Run %s is not empty so will use run_name: %s' % \
557 (name, run_name))
558 self.set_run_name(run_name)
559 else:
560 try:
561 self.exec_cmd('remove %s all banner -f' % run_name)
562 except Exception:
563 pass
564 self.set_run_name(name)
565
566 - def check_history(self, args):
567 """check the validity of line"""
568
569 if len(args) > 1:
570 self.help_history()
571 raise self.InvalidCmd('\"history\" command takes at most one argument')
572
573 if not len(args):
574 return
575 elif args[0] != 'clean':
576 dirpath = os.path.dirname(args[0])
577 if dirpath and not os.path.exists(dirpath) or \
578 os.path.isdir(args[0]):
579 raise self.InvalidCmd("invalid path %s " % dirpath)
580
582 """ check the validity of the line"""
583
584 if len(args) == 0:
585 args.append('options')
586
587 if args[0] not in self._save_opts:
588 raise self.InvalidCmd('wrong \"save\" format')
589
590 if args[0] != 'options' and len(args) != 2:
591 self.help_save()
592 raise self.InvalidCmd('wrong \"save\" format')
593 elif args[0] != 'options' and len(args) == 2:
594 basename = os.path.dirname(args[1])
595 if not os.path.exists(basename):
596 raise self.InvalidCmd('%s is not a valid path, please retry' % \
597 args[1])
598
599 if args[0] == 'options':
600 has_path = None
601 for arg in args[1:]:
602 if arg in ['--auto', '--all']:
603 continue
604 elif arg.startswith('--'):
605 raise self.InvalidCmd('unknow command for \'save options\'')
606 else:
607 basename = os.path.dirname(arg)
608 if not os.path.exists(basename):
609 raise self.InvalidCmd('%s is not a valid path, please retry' % \
610 arg)
611 elif has_path:
612 raise self.InvalidCmd('only one path is allowed')
613 else:
614 args.remove(arg)
615 args.insert(1, arg)
616 has_path = True
617 if not has_path:
618 if '--auto' in arg and self.options['mg5_path']:
619 args.insert(1, pjoin(self.options['mg5_path'],'input','mg5_configuration.txt'))
620 else:
621 args.insert(1, pjoin(self.me_dir,'Cards','me5_configuration.txt'))
622
624 """ check the validity of the line"""
625
626 if len(args) < 2:
627 self.help_set()
628 raise self.InvalidCmd('set needs an option and an argument')
629
630 if args[0] not in self._set_options + self.options.keys():
631 self.help_set()
632 raise self.InvalidCmd('Possible options for set are %s' % \
633 self._set_options)
634
635 if args[0] in ['stdout_level']:
636 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \
637 and not args[1].isdigit():
638 raise self.InvalidCmd('output_level needs ' + \
639 'a valid level')
640
641 if args[0] in ['timeout']:
642 if not args[1].isdigit():
643 raise self.InvalidCmd('timeout values should be a integer')
644
646 """ check the validity of the line """
647
648 if len(args) != 1:
649 self.help_open()
650 raise self.InvalidCmd('OPEN command requires exactly one argument')
651
652 if args[0].startswith('./'):
653 if not os.path.isfile(args[0]):
654 raise self.InvalidCmd('%s: not such file' % args[0])
655 return True
656
657
658 if not self.me_dir:
659 if not os.path.isfile(args[0]):
660 self.help_open()
661 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file')
662 else:
663 return True
664
665 path = self.me_dir
666 if os.path.isfile(os.path.join(path,args[0])):
667 args[0] = os.path.join(path,args[0])
668 elif os.path.isfile(os.path.join(path,'Cards',args[0])):
669 args[0] = os.path.join(path,'Cards',args[0])
670 elif os.path.isfile(os.path.join(path,'HTML',args[0])):
671 args[0] = os.path.join(path,'HTML',args[0])
672
673 elif '_card.dat' in args[0]:
674 name = args[0].replace('_card.dat','_card_default.dat')
675 if os.path.isfile(os.path.join(path,'Cards', name)):
676 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0]))
677 args[0] = os.path.join(path,'Cards', args[0])
678 else:
679 raise self.InvalidCmd('No default path for this file')
680 elif not os.path.isfile(args[0]):
681 raise self.InvalidCmd('No default path for this file')
682
684 """ check initMadLoop command arguments are valid."""
685
686 opt = {'refresh': False, 'nPS': None, 'force': False}
687
688 for arg in args:
689 if arg in ['-r','--refresh']:
690 opt['refresh'] = True
691 if arg in ['-f','--force']:
692 opt['force'] = True
693 elif arg.startswith('--nPS='):
694 n_attempts = arg.split('=')[1]
695 try:
696 opt['nPS'] = int(n_attempts)
697 except ValueError:
698 raise InvalidCmd("The number of attempts specified "+
699 "'%s' is not a valid integer."%n_attempts)
700
701 return opt
702
704 """check that treatcards arguments are valid
705 [param|run|all] [--output_dir=] [--param_card=] [--run_card=]
706 """
707
708 opt = {'output_dir':pjoin(self.me_dir,'Source'),
709 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'),
710 'run_card':pjoin(self.me_dir,'Cards','run_card.dat'),
711 'forbid_MadLoopInit': False}
712 mode = 'all'
713 for arg in args:
714 if arg.startswith('--') and '=' in arg:
715 key,value =arg[2:].split('=',1)
716 if not key in opt:
717 self.help_treatcards()
718 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \
719 % key)
720 if key in ['param_card', 'run_card']:
721 if os.path.isfile(value):
722 card_name = self.detect_card_type(value)
723 if card_name != key:
724 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
725 % (card_name, key))
726 opt[key] = value
727 elif os.path.isfile(pjoin(self.me_dir,value)):
728 card_name = self.detect_card_type(pjoin(self.me_dir,value))
729 if card_name != key:
730 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
731 % (card_name, key))
732 opt[key] = value
733 else:
734 raise self.InvalidCmd('No such file: %s ' % value)
735 elif key in ['output_dir']:
736 if os.path.isdir(value):
737 opt[key] = value
738 elif os.path.isdir(pjoin(self.me_dir,value)):
739 opt[key] = pjoin(self.me_dir, value)
740 else:
741 raise self.InvalidCmd('No such directory: %s' % value)
742 elif arg in ['loop','param','run','all']:
743 mode = arg
744 elif arg == '--no_MadLoopInit':
745 opt['forbid_MadLoopInit'] = True
746 else:
747 self.help_treatcards()
748 raise self.InvalidCmd('Unvalid argument %s' % arg)
749
750 return mode, opt
751
752
754 """check that the argument for survey are valid"""
755
756
757 self.opts = dict([(key,value[1]) for (key,value) in \
758 self._survey_options.items()])
759
760
761 while args and args[-1].startswith('--'):
762 arg = args.pop(-1)
763 try:
764 for opt,value in self._survey_options.items():
765 if arg.startswith('--%s=' % opt):
766 exec('self.opts[\'%s\'] = %s(arg.split(\'=\')[-1])' % \
767 (opt, value[0]))
768 arg = ""
769 if arg != "": raise Exception
770 except Exception:
771 self.help_survey()
772 raise self.InvalidCmd('invalid %s argument'% arg)
773
774 if len(args) > 1:
775 self.help_survey()
776 raise self.InvalidCmd('Too many argument for %s command' % cmd)
777 elif not args:
778
779 self.set_run_name(self.find_available_run_name(self.me_dir))
780 else:
781 self.set_run_name(args[0], None,'parton', True)
782 args.pop(0)
783
784 return True
785
787 """check that the argument for generate_events are valid"""
788
789 run = None
790 if args and args[-1].startswith('--laststep='):
791 run = args[-1].split('=')[-1]
792 if run not in ['auto','parton', 'pythia', 'pgs', 'delphes']:
793 self.help_generate_events()
794 raise self.InvalidCmd('invalid %s argument'% args[-1])
795 if run != 'parton' and not self.options['pythia-pgs_path']:
796 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first.
797 To do so type: \'install pythia-pgs\' in the mg5 interface''')
798 if run == 'delphes' and not self.options['delphes_path']:
799 raise self.InvalidCmd('''delphes not install. Please install this package first.
800 To do so type: \'install Delphes\' in the mg5 interface''')
801 del args[-1]
802
803
804
805
806
807
808 return run
809
811 """check that the argument are correct"""
812
813
814 if len(args) >2:
815 self.help_time_of_flight()
816 raise self.InvalidCmd('Too many arguments')
817
818
819 if args and args[-1].startswith('--threshold='):
820 try:
821 threshold = float(args[-1].split('=')[1])
822 except ValueError:
823 raise self.InvalidCmd('threshold options require a number.')
824 args.remove(args[-1])
825 else:
826 threshold = 1e-12
827
828 if len(args) == 1 and os.path.exists(args[0]):
829 event_path = args[0]
830 else:
831 if len(args) and self.run_name != args[0]:
832 self.set_run_name(args.pop(0))
833 elif not self.run_name:
834 self.help_add_time_of_flight()
835 raise self.InvalidCmd('Need a run_name to process')
836 event_path = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')
837 if not os.path.exists(event_path):
838 event_path = event_path[:-3]
839 if not os.path.exists(event_path):
840 raise self.InvalidCmd('No unweighted events associate to this run.')
841
842
843
844
845 args[:] = [event_path, threshold]
846
848 """check that the argument for calculate_decay_widths are valid"""
849
850 if self.ninitial != 1:
851 raise self.InvalidCmd('Can only calculate decay widths for decay processes A > B C ...')
852
853 accuracy = 0.01
854 run = None
855 if args and args[-1].startswith('--accuracy='):
856 try:
857 accuracy = float(args[-1].split('=')[-1])
858 except Exception:
859 raise self.InvalidCmd('Argument error in calculate_decay_widths command')
860 del args[-1]
861 if len(args) > 1:
862 self.help_calculate_decay_widths()
863 raise self.InvalidCmd('Too many argument for calculate_decay_widths command: %s' % cmd)
864
865 return accuracy
866
867
868
870 """check that the argument for survey are valid"""
871
872 run = None
873
874 if not len(args):
875 self.help_multi_run()
876 raise self.InvalidCmd("""multi_run command requires at least one argument for
877 the number of times that it call generate_events command""")
878
879 if args[-1].startswith('--laststep='):
880 run = args[-1].split('=')[-1]
881 if run not in ['parton', 'pythia', 'pgs', 'delphes']:
882 self.help_multi_run()
883 raise self.InvalidCmd('invalid %s argument'% args[-1])
884 if run != 'parton' and not self.options['pythia-pgs_path']:
885 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first.
886 To do so type: \'install pythia-pgs\' in the mg5 interface''')
887 if run == 'delphes' and not self.options['delphes_path']:
888 raise self.InvalidCmd('''delphes not install. Please install this package first.
889 To do so type: \'install Delphes\' in the mg5 interface''')
890 del args[-1]
891
892
893 elif not args[0].isdigit():
894 self.help_multi_run()
895 raise self.InvalidCmd("The first argument of multi_run should be a integer.")
896
897 nb_run = args.pop(0)
898 args.insert(0, int(nb_run))
899
900
901 return run
902
904 """check that the argument for survey are valid"""
905
906
907 try:
908 float(args[-1])
909 except ValueError:
910 self.help_refine()
911 raise self.InvalidCmd('Not valid arguments')
912 except IndexError:
913 self.help_refine()
914 raise self.InvalidCmd('require_precision argument is require for refine cmd')
915
916
917 if not self.run_name:
918 if self.results.lastrun:
919 self.set_run_name(self.results.lastrun)
920 else:
921 raise self.InvalidCmd('No run_name currently define. Unable to run refine')
922
923 if len(args) > 2:
924 self.help_refine()
925 raise self.InvalidCmd('Too many argument for refine command')
926 else:
927 try:
928 [float(arg) for arg in args]
929 except ValueError:
930 self.help_refine()
931 raise self.InvalidCmd('refine arguments are suppose to be number')
932
933 return True
934
936 """ Check the argument for the combine events command """
937
938 tag = [a for a in arg if a.startswith('--tag=')]
939 if tag:
940 arg.remove(tag[0])
941 tag = tag[0][6:]
942 elif not self.run_tag:
943 tag = 'tag_1'
944 else:
945 tag = self.run_tag
946 self.run_tag = tag
947
948 if len(arg) > 1:
949 self.help_combine_events()
950 raise self.InvalidCmd('Too many argument for combine_events command')
951
952 if len(arg) == 1:
953 self.set_run_name(arg[0], self.run_tag, 'parton', True)
954
955 if not self.run_name:
956 if not self.results.lastrun:
957 raise self.InvalidCmd('No run_name currently define. Unable to run combine')
958 else:
959 self.set_run_name(self.results.lastrun)
960
961 return True
962
964 """Check the argument for pythia command
965 syntax: pythia [NAME]
966 Note that other option are already removed at this point
967 """
968
969 mode = None
970 laststep = [arg for arg in args if arg.startswith('--laststep=')]
971 if laststep and len(laststep)==1:
972 mode = laststep[0].split('=')[-1]
973 if mode not in ['auto', 'pythia', 'pgs', 'delphes']:
974 self.help_pythia()
975 raise self.InvalidCmd('invalid %s argument'% args[-1])
976 elif laststep:
977 raise self.InvalidCmd('only one laststep argument is allowed')
978
979 if not self.options['pythia-pgs_path']:
980 logger.info('Retry to read configuration file to find pythia-pgs path')
981 self.set_configuration()
982
983 if not self.options['pythia-pgs_path'] or not \
984 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')):
985 error_msg = 'No valid pythia-pgs path set.\n'
986 error_msg += 'Please use the set command to define the path and retry.\n'
987 error_msg += 'You can also define it in the configuration file.\n'
988 raise self.InvalidCmd(error_msg)
989
990
991
992 tag = [a for a in args if a.startswith('--tag=')]
993 if tag:
994 args.remove(tag[0])
995 tag = tag[0][6:]
996
997 if len(args) == 0 and not self.run_name:
998 if self.results.lastrun:
999 args.insert(0, self.results.lastrun)
1000 else:
1001 raise self.InvalidCmd('No run name currently define. Please add this information.')
1002
1003 if len(args) >= 1:
1004 if args[0] != self.run_name and\
1005 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 'unweighted_events.lhe.gz')):
1006 raise self.InvalidCmd('No events file corresponding to %s run. '% args[0])
1007 self.set_run_name(args[0], tag, 'pythia')
1008 else:
1009 if tag:
1010 self.run_card['run_tag'] = tag
1011 self.set_run_name(self.run_name, tag, 'pythia')
1012
1013 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe')
1014 output_file = pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')
1015 if not os.path.exists('%s.gz' % input_file):
1016 if not os.path.exists(input_file):
1017 raise self.InvalidCmd('No events file corresponding to %s run. '% self.run_name)
1018 files.ln(input_file, os.path.dirname(output_file))
1019 else:
1020 misc.gunzip(input_file, keep=True, stdout=output_file)
1021
1022 args.append(mode)
1023
1025 """Check the argument for pythia command
1026 syntax: pythia8 [NAME]
1027 Note that other option are already removed at this point
1028 """
1029 mode = None
1030 laststep = [arg for arg in args if arg.startswith('--laststep=')]
1031 if laststep and len(laststep)==1:
1032 mode = laststep[0].split('=')[-1]
1033 if mode not in ['auto', 'pythia','pythia8','delphes']:
1034 self.help_pythia8()
1035 raise self.InvalidCmd('invalid %s argument'% args[-1])
1036 elif laststep:
1037 raise self.InvalidCmd('only one laststep argument is allowed')
1038
1039
1040 if not self.options['pythia8_path']:
1041 logger.info('Retry reading configuration file to find pythia8 path')
1042 self.set_configuration()
1043
1044 if not self.options['pythia8_path'] or not \
1045 os.path.exists(pjoin(self.options['pythia8_path'],'bin','pythia8-config')):
1046 error_msg = 'No valid pythia8 path set.\n'
1047 error_msg += 'Please use the set command to define the path and retry.\n'
1048 error_msg += 'You can also define it in the configuration file.\n'
1049 error_msg += 'Finally, it can be installed automatically using the'
1050 error_msg += ' install command.\n'
1051 raise self.InvalidCmd(error_msg)
1052
1053 tag = [a for a in args if a.startswith('--tag=')]
1054 if tag:
1055 args.remove(tag[0])
1056 tag = tag[0][6:]
1057
1058 if len(args) == 0 and not self.run_name:
1059 if self.results.lastrun:
1060 args.insert(0, self.results.lastrun)
1061 else:
1062 raise self.InvalidCmd('No run name currently define. '+
1063 'Please add this information.')
1064
1065 if len(args) >= 1:
1066 if args[0] != self.run_name and\
1067 not os.path.exists(pjoin(self.me_dir,'Events',args[0],
1068 'unweighted_events.lhe.gz')):
1069 raise self.InvalidCmd('No events file corresponding to %s run. '
1070 % args[0])
1071 self.set_run_name(args[0], tag, 'pythia8')
1072 else:
1073 if tag:
1074 self.run_card['run_tag'] = tag
1075 self.set_run_name(self.run_name, tag, 'pythia8')
1076
1077 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe')
1078 if not os.path.exists('%s.gz'%input_file):
1079 if os.path.exists(input_file):
1080 misc.gzip(input_file, keep=True, stdout='%s.gz'%input_file)
1081 else:
1082 raise self.InvalidCmd('No event file corresponding to %s run. '
1083 % self.run_name)
1084
1085 args.append(mode)
1086
1088 """Check that the remove command is valid"""
1089
1090 tmp_args = args[:]
1091
1092 tag = [a[6:] for a in tmp_args if a.startswith('--tag=')]
1093 if tag:
1094 tag = tag[0]
1095 tmp_args.remove('--tag=%s' % tag)
1096
1097
1098 if len(tmp_args) == 0:
1099 self.help_remove()
1100 raise self.InvalidCmd('clean command require the name of the run to clean')
1101 elif len(tmp_args) == 1:
1102 return tmp_args[0], tag, ['all']
1103 else:
1104 for arg in tmp_args[1:]:
1105 if arg not in self._clean_mode:
1106 self.help_remove()
1107 raise self.InvalidCmd('%s is not a valid options for clean command'\
1108 % arg)
1109 return tmp_args[0], tag, tmp_args[1:]
1110
1112 """Check the argument for the plot command
1113 plot run_name modes"""
1114
1115 madir = self.options['madanalysis_path']
1116 td = self.options['td_path']
1117
1118 if not madir or not td:
1119 logger.info('Retry to read configuration file to find madanalysis/td')
1120 self.set_configuration()
1121
1122 madir = self.options['madanalysis_path']
1123 td = self.options['td_path']
1124
1125 if not madir:
1126 error_msg = 'No valid MadAnalysis path set.\n'
1127 error_msg += 'Please use the set command to define the path and retry.\n'
1128 error_msg += 'You can also define it in the configuration file.\n'
1129 raise self.InvalidCmd(error_msg)
1130 if not td:
1131 error_msg = 'No valid td path set.\n'
1132 error_msg += 'Please use the set command to define the path and retry.\n'
1133 error_msg += 'You can also define it in the configuration file.\n'
1134 raise self.InvalidCmd(error_msg)
1135
1136 if len(args) == 0:
1137 if not hasattr(self, 'run_name') or not self.run_name:
1138 self.help_plot()
1139 raise self.InvalidCmd('No run name currently define. Please add this information.')
1140 args.append('all')
1141 return
1142
1143
1144 if args[0] not in self._plot_mode:
1145 self.set_run_name(args[0], level='plot')
1146 del args[0]
1147 if len(args) == 0:
1148 args.append('all')
1149 elif not self.run_name:
1150 self.help_plot()
1151 raise self.InvalidCmd('No run name currently define. Please add this information.')
1152
1153 for arg in args:
1154 if arg not in self._plot_mode and arg != self.run_name:
1155 self.help_plot()
1156 raise self.InvalidCmd('unknown options %s' % arg)
1157
1159 """Check the argument for the syscalc command
1160 syscalc run_name modes"""
1161
1162 scdir = self.options['syscalc_path']
1163
1164 if not scdir:
1165 logger.info('Retry to read configuration file to find SysCalc')
1166 self.set_configuration()
1167
1168 scdir = self.options['syscalc_path']
1169
1170 if not scdir:
1171 error_msg = 'No valid SysCalc path set.\n'
1172 error_msg += 'Please use the set command to define the path and retry.\n'
1173 error_msg += 'You can also define it in the configuration file.\n'
1174 error_msg += 'Please note that you need to compile SysCalc first.'
1175 raise self.InvalidCmd(error_msg)
1176
1177 if len(args) == 0:
1178 if not hasattr(self, 'run_name') or not self.run_name:
1179 self.help_syscalc()
1180 raise self.InvalidCmd('No run name currently defined. Please add this information.')
1181 args.append('all')
1182 return
1183
1184
1185 tag = [a for a in args if a.startswith('--tag=')]
1186 if tag:
1187 args.remove(tag[0])
1188 tag = tag[0][6:]
1189
1190 if args[0] not in self._syscalc_mode:
1191 self.set_run_name(args[0], tag=tag, level='syscalc')
1192 del args[0]
1193 if len(args) == 0:
1194 args.append('all')
1195 elif not self.run_name:
1196 self.help_syscalc()
1197 raise self.InvalidCmd('No run name currently defined. Please add this information.')
1198 elif tag and tag != self.run_tag:
1199 self.set_run_name(self.run_name, tag=tag, level='syscalc')
1200
1201 for arg in args:
1202 if arg not in self._syscalc_mode and arg != self.run_name:
1203 self.help_syscalc()
1204 raise self.InvalidCmd('unknown options %s' % arg)
1205
1206 if self.run_card['use_syst'] not in self.true:
1207 raise self.InvalidCmd('Run %s does not include ' % self.run_name + \
1208 'systematics information needed for syscalc.')
1209
1210
1211 - def check_pgs(self, arg, no_default=False):
1212 """Check the argument for pythia command
1213 syntax is "pgs [NAME]"
1214 Note that other option are already remove at this point
1215 """
1216
1217
1218 if not self.options['pythia-pgs_path']:
1219 logger.info('Retry to read configuration file to find pythia-pgs path')
1220 self.set_configuration()
1221
1222 if not self.options['pythia-pgs_path'] or not \
1223 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')):
1224 error_msg = 'No valid pythia-pgs path set.\n'
1225 error_msg += 'Please use the set command to define the path and retry.\n'
1226 error_msg += 'You can also define it in the configuration file.\n'
1227 raise self.InvalidCmd(error_msg)
1228
1229 tag = [a for a in arg if a.startswith('--tag=')]
1230 if tag:
1231 arg.remove(tag[0])
1232 tag = tag[0][6:]
1233
1234
1235 if len(arg) == 0 and not self.run_name:
1236 if self.results.lastrun:
1237 arg.insert(0, self.results.lastrun)
1238 else:
1239 raise self.InvalidCmd('No run name currently define. Please add this information.')
1240
1241 if len(arg) == 1 and self.run_name == arg[0]:
1242 arg.pop(0)
1243
1244 if not len(arg) and \
1245 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')):
1246 if not no_default:
1247 self.help_pgs()
1248 raise self.InvalidCmd('''No file file pythia_events.hep currently available
1249 Please specify a valid run_name''')
1250
1251 lock = None
1252 if len(arg) == 1:
1253 prev_tag = self.set_run_name(arg[0], tag, 'pgs')
1254 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name,'%s_pythia_events.hep.gz' % prev_tag)):
1255 raise self.InvalidCmd('No events file corresponding to %s run with tag %s. '% (self.run_name, prev_tag))
1256 else:
1257 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
1258 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep')
1259 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'),
1260 argument=['-c', input_file])
1261
1262 else:
1263 if tag:
1264 self.run_card['run_tag'] = tag
1265 self.set_run_name(self.run_name, tag, 'pgs')
1266
1267 return lock
1268
1270 """check the validity of line
1271 syntax is "display XXXXX"
1272 """
1273
1274 if len(args) < 1 or args[0] not in self._display_opts:
1275 self.help_display()
1276 raise self.InvalidCmd
1277
1278 if args[0] == 'variable' and len(args) !=2:
1279 raise self.InvalidCmd('variable need a variable name')
1280
1281
1282
1283
1284
1286 """check the validity of line"""
1287
1288 if not args:
1289 self.help_import()
1290 raise self.InvalidCmd('wrong \"import\" format')
1291
1292 if args[0] != 'command':
1293 args.insert(0,'command')
1294
1295
1296 if not len(args) == 2 or not os.path.exists(args[1]):
1297 raise self.InvalidCmd('PATH is mandatory for import command\n')
1298
1304 """ The Series of help routine for the MadGraphCmd"""
1305
1306
1308 "Complete command"
1309
1310 args = self.split_arg(line[0:begidx], error=False)
1311
1312 if len(args) == 1:
1313
1314 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), pjoin(self.me_dir, 'Events'))
1315 data = [n.rsplit('/',2)[1] for n in data]
1316 return self.list_completion(text, data + ['--threshold='], line)
1317 elif args[-1].endswith(os.path.sep):
1318 return self.path_completion(text,
1319 os.path.join('.',*[a for a in args \
1320 if a.endswith(os.path.sep)]))
1321 else:
1322 return self.list_completion(text, ['--threshold='], line)
1323
1325 "Complete the banner run command"
1326 try:
1327
1328
1329 args = self.split_arg(line[0:begidx], error=False)
1330
1331 if args[-1].endswith(os.path.sep):
1332 return self.path_completion(text,
1333 os.path.join('.',*[a for a in args \
1334 if a.endswith(os.path.sep)]))
1335
1336
1337 if len(args) > 1:
1338
1339 tags = misc.glob('%s_*_banner.txt' % args[1], pjoin(self.me_dir, 'Events' , args[1]))
1340 tags = ['%s' % os.path.basename(t)[len(args[1])+1:-11] for t in tags]
1341
1342 if args[-1] != '--tag=':
1343 tags = ['--tag=%s' % t for t in tags]
1344 else:
1345 return self.list_completion(text, tags)
1346 return self.list_completion(text, tags +['--name=','-f'], line)
1347
1348
1349 possibilites = {}
1350
1351 comp = self.path_completion(text, os.path.join('.',*[a for a in args \
1352 if a.endswith(os.path.sep)]))
1353 if os.path.sep in line:
1354 return comp
1355 else:
1356 possibilites['Path from ./'] = comp
1357
1358 run_list = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events'))
1359 run_list = [n.rsplit('/',2)[1] for n in run_list]
1360 possibilites['RUN Name'] = self.list_completion(text, run_list)
1361
1362 return self.deal_multiple_categories(possibilites, formatting)
1363
1364
1365 except Exception, error:
1366 print error
1367
1368
1369 - def complete_history(self, text, line, begidx, endidx):
1370 "Complete the history command"
1371
1372 args = self.split_arg(line[0:begidx], error=False)
1373
1374
1375 if args[-1].endswith(os.path.sep):
1376 return self.path_completion(text,
1377 os.path.join('.',*[a for a in args \
1378 if a.endswith(os.path.sep)]))
1379
1380 if len(args) == 1:
1381 return self.path_completion(text)
1382
1384 """ complete the open command """
1385
1386 args = self.split_arg(line[0:begidx])
1387
1388
1389 if os.path.sep in args[-1] + text:
1390 return self.path_completion(text,
1391 os.path.join('.',*[a for a in args if \
1392 a.endswith(os.path.sep)]))
1393
1394 possibility = []
1395 if self.me_dir:
1396 path = self.me_dir
1397 possibility = ['index.html']
1398 if os.path.isfile(os.path.join(path,'README')):
1399 possibility.append('README')
1400 if os.path.isdir(os.path.join(path,'Cards')):
1401 possibility += [f for f in os.listdir(os.path.join(path,'Cards'))
1402 if f.endswith('.dat')]
1403 if os.path.isdir(os.path.join(path,'HTML')):
1404 possibility += [f for f in os.listdir(os.path.join(path,'HTML'))
1405 if f.endswith('.html') and 'default' not in f]
1406 else:
1407 possibility.extend(['./','../'])
1408 if os.path.exists('ME5_debug'):
1409 possibility.append('ME5_debug')
1410 if os.path.exists('MG5_debug'):
1411 possibility.append('MG5_debug')
1412 return self.list_completion(text, possibility)
1413
1415 "Complete the set command"
1416
1417 args = self.split_arg(line[0:begidx])
1418
1419
1420 if len(args) == 1:
1421 return self.list_completion(text, self._set_options + self.options.keys() )
1422
1423 if len(args) == 2:
1424 if args[1] == 'stdout_level':
1425 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR','CRITICAL'])
1426 else:
1427 first_set = ['None','True','False']
1428
1429 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)]
1430 return self.list_completion(text, first_set + second_set)
1431 elif len(args) >2 and args[-1].endswith(os.path.sep):
1432 return self.path_completion(text,
1433 os.path.join('.',*[a for a in args if a.endswith(os.path.sep)]),
1434 only_dirs = True)
1435
1437 """ Complete the survey command """
1438
1439 if line.endswith('nb_core=') and not text:
1440 import multiprocessing
1441 max = multiprocessing.cpu_count()
1442 return [str(i) for i in range(2,max+1)]
1443
1444 return self.list_completion(text, self._run_options, line)
1445
1446 complete_refine = complete_survey
1447 complete_combine_events = complete_survey
1448 complite_store = complete_survey
1449 complete_generate_events = complete_survey
1450 complete_create_gridpack = complete_survey
1451
1453 """ Complete the generate events"""
1454
1455 if line.endswith('nb_core=') and not text:
1456 import multiprocessing
1457 max = multiprocessing.cpu_count()
1458 return [str(i) for i in range(2,max+1)]
1459 if line.endswith('laststep=') and not text:
1460 return ['parton','pythia','pgs','delphes']
1461 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ':
1462 return self.list_completion(text,['parton','pythia','pgs','delphes'],line)
1463
1464 opts = self._run_options + self._generate_options
1465 return self.list_completion(text, opts, line)
1466
1467
1469 "Complete the initMadLoop command"
1470
1471 numbers = [str(i) for i in range(10)]
1472 opts = ['-f','-r','--nPS=']
1473
1474 args = self.split_arg(line[0:begidx], error=False)
1475 if len(line) >=6 and line[begidx-6:begidx]=='--nPS=':
1476 return self.list_completion(text, numbers, line)
1477 else:
1478 return self.list_completion(text, [opt for opt in opts if not opt in
1479 line], line)
1480
1487
1489 """ Complete the calculate_decay_widths command"""
1490
1491 if line.endswith('nb_core=') and not text:
1492 import multiprocessing
1493 max = multiprocessing.cpu_count()
1494 return [str(i) for i in range(2,max+1)]
1495
1496 opts = self._run_options + self._calculate_decay_options
1497 return self.list_completion(text, opts, line)
1498
1507
1509 """complete multi run command"""
1510
1511 args = self.split_arg(line[0:begidx], error=False)
1512 if len(args) == 1:
1513 data = [str(i) for i in range(0,20)]
1514 return self.list_completion(text, data, line)
1515
1516 if line.endswith('run=') and not text:
1517 return ['parton','pythia','pgs','delphes']
1518 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ':
1519 return self.list_completion(text,['parton','pythia','pgs','delphes'],line)
1520
1521 opts = self._run_options + self._generate_options
1522 return self.list_completion(text, opts, line)
1523
1524
1525
1526 if line.endswith('nb_core=') and not text:
1527 import multiprocessing
1528 max = multiprocessing.cpu_count()
1529 return [str(i) for i in range(2,max+1)]
1530 opts = self._run_options + self._generate_options
1531 return self.list_completion(text, opts, line)
1532
1541
1559
1561 """Complete the remove command """
1562
1563 args = self.split_arg(line[0:begidx], error=False)
1564 if len(args) > 1 and (text.startswith('--t')):
1565 run = args[1]
1566 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]]
1567 return self.list_completion(text, tags)
1568 elif len(args) > 1 and '--' == args[-1]:
1569 run = args[1]
1570 tags = ['tag=%s' % tag['tag'] for tag in self.results[run]]
1571 return self.list_completion(text, tags)
1572 elif len(args) > 1 and '--tag=' == args[-1]:
1573 run = args[1]
1574 tags = [tag['tag'] for tag in self.results[run]]
1575 return self.list_completion(text, tags)
1576 elif len(args) > 1:
1577 return self.list_completion(text, self._clean_mode + ['-f','--tag='])
1578 else:
1579 data = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events'))
1580 data = [n.rsplit('/',2)[1] for n in data]
1581 return self.list_completion(text, ['all'] + data)
1582
1583
1593
1595 "Complete the pythia8 command"
1596 args = self.split_arg(line[0:begidx], error=False)
1597 if len(args) == 1:
1598
1599 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'),pjoin(self.me_dir, 'Events'))
1600 data = [n.rsplit('/',2)[1] for n in data]
1601 tmp1 = self.list_completion(text, data)
1602 if not self.run_name:
1603 return tmp1
1604 else:
1605 tmp2 = self.list_completion(text, self._run_options + ['-f',
1606 '--no_default', '--tag='], line)
1607 return tmp1 + tmp2
1608 elif line[-1] != '=':
1609 return self.list_completion(text, self._run_options + ['-f',
1610 '--no_default','--tag='], line)
1611
1613 "Complete the madanalysis5 command"
1614 args = self.split_arg(line[0:begidx], error=False)
1615 if len(args) == 1:
1616
1617 data = []
1618 for name in ['unweighted_events.lhe']:
1619 data += misc.glob(pjoin('*','%s'%name), pjoin(self.me_dir, 'Events'))
1620 data += misc.glob(pjoin('*','%s.gz'%name), pjoin(self.me_dir, 'Events'))
1621 data = [n.rsplit('/',2)[1] for n in data]
1622 tmp1 = self.list_completion(text, data)
1623 if not self.run_name:
1624 return tmp1
1625 else:
1626 tmp2 = self.list_completion(text, ['-f',
1627 '--MA5_stdout_lvl=','--no_default','--tag='], line)
1628 return tmp1 + tmp2
1629 elif '--MA5_stdout_lvl=' in line and not any(arg.startswith(
1630 '--MA5_stdout_lvl=') for arg in args):
1631 return self.list_completion(text,
1632 ['--MA5_stdout_lvl=%s'%opt for opt in
1633 ['logging.INFO','logging.DEBUG','logging.WARNING',
1634 'logging.CRITICAL','90']], line)
1635 else:
1636 return self.list_completion(text, ['-f',
1637 '--MA5_stdout_lvl=','--no_default','--tag='], line)
1638
1640 "Complete the pythia command"
1641 args = self.split_arg(line[0:begidx], error=False)
1642
1643 if len(args) == 1:
1644
1645 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'), pjoin(self.me_dir, 'Events'))
1646 data = [n.rsplit('/',2)[1] for n in data]
1647 tmp1 = self.list_completion(text, data)
1648 if not self.run_name:
1649 return tmp1
1650 else:
1651 tmp2 = self.list_completion(text, self._run_options + ['-f',
1652 '--no_default', '--tag='], line)
1653 return tmp1 + tmp2
1654 elif line[-1] != '=':
1655 return self.list_completion(text, self._run_options + ['-f',
1656 '--no_default','--tag='], line)
1657
1659 "Complete the pythia command"
1660 args = self.split_arg(line[0:begidx], error=False)
1661 if len(args) == 1:
1662
1663 data = misc.glob(pjoin('*', '*_pythia_events.hep.gz'), pjoin(self.me_dir, 'Events'))
1664 data = [n.rsplit('/',2)[1] for n in data]
1665 tmp1 = self.list_completion(text, data)
1666 if not self.run_name:
1667 return tmp1
1668 else:
1669 tmp2 = self.list_completion(text, self._run_options + ['-f',
1670 '--tag=' ,'--no_default'], line)
1671 return tmp1 + tmp2
1672 else:
1673 return self.list_completion(text, self._run_options + ['-f',
1674 '--tag=','--no_default'], line)
1675
1676 complete_delphes = complete_pgs
1677
1678
1679
1680
1681
1682
1683
1684
1685 -class MadEventCmd(CompleteForCmd, CmdExtended, HelpToCmd, common_run.CommonRunCmd):
1686
1687 """The command line processor of MadGraph"""
1688
1689
1690 true = ['T','.true.',True,'true']
1691
1692 _run_options = ['--cluster','--multicore','--nb_core=','--nb_core=2', '-c', '-m']
1693 _generate_options = ['-f', '--laststep=parton', '--laststep=pythia', '--laststep=pgs', '--laststep=delphes']
1694 _calculate_decay_options = ['-f', '--accuracy=0.']
1695 _interfaced_showers = ['pythia','pythia8']
1696 _set_options = ['stdout_level','fortran_compiler','timeout']
1697 _plot_mode = ['all', 'parton','pythia','pgs','delphes','channel', 'banner']
1698 _syscalc_mode = ['all', 'parton','pythia']
1699 _clean_mode = _plot_mode
1700 _display_opts = ['run_name', 'options', 'variable', 'results']
1701 _save_opts = ['options']
1702 _initMadLoop_opts = ['-f','-r','--nPS=']
1703
1704 _survey_options = {'points':('int', 1000,'Number of points for first iteration'),
1705 'iterations':('int', 5, 'Number of iterations'),
1706 'accuracy':('float', 0.1, 'Required accuracy'),
1707 'gridpack':('str', '.false.', 'Gridpack generation')}
1708
1709 true = ['T','.true.',True,'true', 1, '1']
1710 web = False
1711 cluster_mode = 0
1712 queue = 'madgraph'
1713 nb_core = None
1714
1715 next_possibility = {
1716 'start': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]',
1717 'calculate_decay_widths [OPTIONS]',
1718 'help generate_events'],
1719 'generate_events': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 'pythia', 'pgs','delphes'],
1720 'calculate_decay_widths': ['calculate_decay_widths [OPTIONS]',
1721 'generate_events [OPTIONS]'],
1722 'multi_run': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'],
1723 'survey': ['refine'],
1724 'refine': ['combine_events'],
1725 'combine_events': ['store'],
1726 'store': ['pythia'],
1727 'pythia': ['pgs', 'delphes'],
1728 'pgs': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'],
1729 'delphes' : ['generate_events [OPTIONS]', 'multi_run [OPTIONS]']
1730 }
1731
1732
1733 - def __init__(self, me_dir = None, options={}, *completekey, **stdin):
1734 """ add information to the cmd """
1735
1736 CmdExtended.__init__(self, me_dir, options, *completekey, **stdin)
1737
1738
1739 self.mode = 'madevent'
1740 self.nb_refine=0
1741 if self.web:
1742 os.system('touch %s' % pjoin(self.me_dir,'Online'))
1743
1744 self.load_results_db()
1745 self.results.def_web_mode(self.web)
1746
1747 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir))
1748 self.configured = 0
1749 self._options = {}
1750
1751
1753 """configure web data"""
1754 self.web = True
1755 self.results.def_web_mode(True)
1756 self.force = True
1757 if os.environ['MADGRAPH_BASE']:
1758 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1759
1760
1762 """ Check that the output path is a valid madevent directory """
1763
1764 bin_path = os.path.join(path,'bin')
1765 if os.path.isfile(os.path.join(bin_path,'generate_events')):
1766 return True
1767 else:
1768 return False
1769
1770
1772 """assign all configuration variable from file
1773 loop over the different config file if config_file not define """
1774
1775 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo,
1776 final=final, **opt)
1777
1778 if not final:
1779 return self.options
1780
1781
1782
1783
1784
1785 for key in (k for k in self.options if k.endswith('path')):
1786 path = self.options[key]
1787 if path is None or key.startswith("cluster"):
1788 continue
1789 if not os.path.isdir(path):
1790 path = pjoin(self.me_dir, self.options[key])
1791 if os.path.isdir(path):
1792 self.options[key] = None
1793 if key == "pythia-pgs_path":
1794 if not os.path.exists(pjoin(path, 'src','pythia')):
1795 logger.info("No valid pythia-pgs path found")
1796 continue
1797 elif key == "delphes_path":
1798 if not os.path.exists(pjoin(path, 'Delphes')) and not\
1799 os.path.exists(pjoin(path, 'DelphesSTDHEP')):
1800 logger.info("No valid Delphes path found")
1801 continue
1802 elif key == "madanalysis_path":
1803 if not os.path.exists(pjoin(path, 'plot_events')):
1804 logger.info("No valid MadAnalysis path found")
1805 continue
1806 elif key == "td_path":
1807 if not os.path.exists(pjoin(path, 'td')):
1808 logger.info("No valid td path found")
1809 continue
1810 elif key == "syscalc_path":
1811 if not os.path.exists(pjoin(path, 'sys_calc')):
1812 logger.info("No valid SysCalc path found")
1813 continue
1814
1815
1816 self.options[key] = os.path.realpath(path)
1817 continue
1818 else:
1819 self.options[key] = None
1820
1821
1822 return self.options
1823
1824
1878
1879
1881 """Make a run from the banner file"""
1882
1883 args = self.split_arg(line)
1884
1885 self.check_banner_run(args)
1886
1887
1888 for name in ['delphes_trigger.dat', 'delphes_card.dat',
1889 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat',
1890 'reweight_card.dat']:
1891 try:
1892 os.remove(pjoin(self.me_dir, 'Cards', name))
1893 except Exception:
1894 pass
1895
1896 banner_mod.split_banner(args[0], self.me_dir, proc_card=False)
1897
1898
1899 if not self.force:
1900 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n'])
1901 if ans == 'n':
1902 self.force = True
1903
1904
1905 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1906
1907
1908
1909
1911 """Display current internal status"""
1912
1913 args = self.split_arg(line)
1914
1915 self.check_display(args)
1916
1917 if args[0] == 'run_name':
1918
1919 data = misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events'))
1920 data = [n.rsplit('/',2)[1:] for n in data]
1921
1922 if data:
1923 out = {}
1924 for name, tag in data:
1925 tag = tag[len(name)+1:-11]
1926 if name in out:
1927 out[name].append(tag)
1928 else:
1929 out[name] = [tag]
1930 print 'the runs available are:'
1931 for run_name, tags in out.items():
1932 print ' run: %s' % run_name
1933 print ' tags: ',
1934 print ', '.join(tags)
1935 else:
1936 print 'No run detected.'
1937
1938 elif args[0] == 'options':
1939 outstr = " Run Options \n"
1940 outstr += " ----------- \n"
1941 for key, default in self.options_madgraph.items():
1942 value = self.options[key]
1943 if value == default:
1944 outstr += " %25s \t:\t%s\n" % (key,value)
1945 else:
1946 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1947 outstr += "\n"
1948 outstr += " MadEvent Options \n"
1949 outstr += " ---------------- \n"
1950 for key, default in self.options_madevent.items():
1951 if key in self.options:
1952 value = self.options[key]
1953 else:
1954 default = ''
1955 if value == default:
1956 outstr += " %25s \t:\t%s\n" % (key,value)
1957 else:
1958 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1959 outstr += "\n"
1960 outstr += " Configuration Options \n"
1961 outstr += " --------------------- \n"
1962 for key, default in self.options_configuration.items():
1963 value = self.options[key]
1964 if value == default:
1965 outstr += " %25s \t:\t%s\n" % (key,value)
1966 else:
1967 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1968 output.write(outstr)
1969 elif args[0] == 'results':
1970 self.do_print_results(' '.join(args[1:]))
1971 else:
1972 super(MadEventCmd, self).do_display(line, output)
1973
1974 - def do_save(self, line, check=True, to_keep={}):
1975 """Not in help: Save information to file"""
1976
1977 args = self.split_arg(line)
1978
1979 if check:
1980 self.check_save(args)
1981
1982 if args[0] == 'options':
1983
1984 to_define = {}
1985 for key, default in self.options_configuration.items():
1986 if self.options[key] != self.options_configuration[key]:
1987 to_define[key] = self.options[key]
1988
1989 if not '--auto' in args:
1990 for key, default in self.options_madevent.items():
1991 if self.options[key] != self.options_madevent[key]:
1992 to_define[key] = self.options[key]
1993
1994 if '--all' in args:
1995 for key, default in self.options_madgraph.items():
1996 if self.options[key] != self.options_madgraph[key]:
1997 to_define[key] = self.options[key]
1998 elif not '--auto' in args:
1999 for key, default in self.options_madgraph.items():
2000 if self.options[key] != self.options_madgraph[key]:
2001 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
2002 % (key,self.options_madgraph[key]) )
2003 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
2004 if len(args) >1 and not args[1].startswith('--'):
2005 filepath = args[1]
2006 else:
2007 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
2008 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
2009 basedir = self.me_dir
2010
2011 if to_keep:
2012 to_define = to_keep
2013 self.write_configuration(filepath, basefile, basedir, to_define)
2014
2015
2016
2017
2026
2027
2028
2029
2031 """Main Commands: launch the full chain """
2032
2033 self.banner = None
2034 args = self.split_arg(line)
2035
2036 mode = self.check_generate_events(args)
2037 self.ask_run_configuration(mode, args)
2038 if not args:
2039
2040 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton')
2041 else:
2042 self.set_run_name(args[0], None, 'parton', True)
2043 args.pop(0)
2044
2045 if self.proc_characteristics['loop_induced'] and self.options['run_mode']==0:
2046
2047
2048 logger.warning(
2049 """Single-core mode not supported for loop-induced processes.
2050 Beware that MG5aMC now changes your runtime options to a multi-core mode with only one active core.""")
2051 self.do_set('run_mode 2')
2052 self.do_set('nb_core 1')
2053
2054 if self.run_card['gridpack'] in self.true:
2055
2056 gridpack_opts=[('accuracy', 0.01),
2057 ('points', 2000),
2058 ('iterations',8),
2059 ('gridpack','.true.')]
2060 logger.info('Generating gridpack with run name %s' % self.run_name)
2061 self.exec_cmd('survey %s %s' % \
2062 (self.run_name,
2063 " ".join(['--' + opt + '=' + str(val) for (opt,val) \
2064 in gridpack_opts])),
2065 postcmd=False)
2066 self.exec_cmd('combine_events', postcmd=False)
2067 self.exec_cmd('store_events', postcmd=False)
2068 self.exec_cmd('decay_events -from_cards', postcmd=False)
2069 self.exec_cmd('create_gridpack', postcmd=False)
2070 else:
2071
2072 logger.info('Generating %s events with run name %s' %
2073 (self.run_card['nevents'], self.run_name))
2074
2075 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)),
2076 postcmd=False)
2077 nb_event = self.run_card['nevents']
2078 bypass_run=False
2079 self.exec_cmd('refine %s' % nb_event, postcmd=False)
2080 if not float(self.results.current['cross']):
2081
2082 text = '''Survey return zero cross section.
2083 Typical reasons are the following:
2084 1) A massive s-channel particle has a width set to zero.
2085 2) The pdf are zero for at least one of the initial state particles
2086 or you are using maxjetflavor=4 for initial state b:s.
2087 3) The cuts are too strong.
2088 Please check/correct your param_card and/or your run_card.'''
2089 logger_stderr.critical(text)
2090 if not self.param_card_iterator:
2091 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14')
2092 else:
2093 bypass_run = True
2094
2095
2096 if not bypass_run:
2097 self.exec_cmd('refine %s' % nb_event, postcmd=False)
2098
2099 self.exec_cmd('combine_events', postcmd=False,printcmd=False)
2100 self.print_results_in_shell(self.results.current)
2101
2102 if self.run_card['use_syst']:
2103 if self.run_card['systematics_program'] == 'auto':
2104 scdir = self.options['syscalc_path']
2105 if not scdir or not os.path.exists(scdir):
2106 to_use = 'systematics'
2107 else:
2108 to_use = 'syscalc'
2109 elif self.run_card['systematics_program'].lower() in ['systematics','syscalc', 'none']:
2110 to_use = self.run_card['systematics_program']
2111 else:
2112 logger.critical('Unvalid options for systematics_program: bypass computation of systematics variations.')
2113 to_use = 'none'
2114
2115 if to_use == 'systematics':
2116 if self.run_card['systematics_arguments'] != ['']:
2117 self.exec_cmd('systematics %s %s ' % (self.run_name,
2118 ' '.join(self.run_card['systematics_arguments'])),
2119 postcmd=False, printcmd=False)
2120 else:
2121 self.exec_cmd('systematics %s --from_card' % self.run_name,
2122 postcmd=False,printcmd=False)
2123 elif to_use == 'syscalc':
2124 self.run_syscalc('parton')
2125
2126
2127 self.create_plot('parton')
2128 self.exec_cmd('store_events', postcmd=False)
2129 self.exec_cmd('reweight -from_cards', postcmd=False)
2130 self.exec_cmd('decay_events -from_cards', postcmd=False)
2131 if self.run_card['time_of_flight']>=0:
2132 self.exec_cmd("add_time_of_flight --threshold=%s" % self.run_card['time_of_flight'] ,postcmd=False)
2133
2134 self.exec_cmd('madanalysis5_parton --no_default', postcmd=False, printcmd=False)
2135
2136 self.exec_cmd('shower --no_default', postcmd=False, printcmd=False)
2137 self.exec_cmd('madanalysis5_hadron --no_default', postcmd=False, printcmd=False)
2138 self.store_result()
2139
2140 if self.param_card_iterator:
2141 param_card_iterator = self.param_card_iterator
2142 self.param_card_iterator = []
2143 with misc.TMP_variable(self, 'allow_notification_center', False):
2144 param_card_iterator.store_entry(self.run_name, self.results.current['cross'])
2145
2146 orig_name = self.run_name
2147 for card in param_card_iterator:
2148 path = pjoin(self.me_dir,'Cards','param_card.dat')
2149 card.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2150 self.check_param_card(path, dependent=True)
2151 next_name = param_card_iterator.get_next_name(self.run_name)
2152 try:
2153 self.exec_cmd("generate_events -f %s" % next_name,
2154 precmd=True, postcmd=True,errorhandling=False)
2155 except ZeroResult:
2156 param_card_iterator.store_entry(self.run_name, 0)
2157 else:
2158 param_card_iterator.store_entry(self.run_name, self.results.current['cross'])
2159 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2160 name = misc.get_scan_name(orig_name, self.run_name)
2161 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % name)
2162 logger.info("write all cross-section results in %s" % path ,'$MG:color:BLACK')
2163 param_card_iterator.write_summary(path)
2164
2165
2166 if self.allow_notification_center:
2167 misc.apple_notify('Run %s finished' % os.path.basename(self.me_dir),
2168 '%s: %s +- %s ' % (self.results.current['run_name'],
2169 self.results.current['cross'],
2170 self.results.current['error']))
2171
2173 """Compile and run MadLoop for a certain number of PS point so as to
2174 initialize MadLoop (setup the zero helicity and loop filter.)"""
2175
2176 args = line.split()
2177
2178 options = self.check_initMadLoop(args)
2179
2180 if not options['force']:
2181 self.ask_edit_cards(['MadLoopParams.dat'], mode='fixed', plot=False)
2182 self.exec_cmd('treatcards loop --no_MadLoopInit')
2183
2184 if options['refresh']:
2185 for filter in misc.glob('*Filter*',
2186 pjoin(self.me_dir,'SubProcesses','MadLoop5_resources')):
2187 logger.debug("Resetting filter '%s'."%os.path.basename(filter))
2188 os.remove(filter)
2189
2190 MLCard = banner_mod.MadLoopParam(pjoin(self.me_dir,
2191 'Cards','MadLoopParams.dat'))
2192 if options['nPS'] is None:
2193 options['nPS'] = MLCard['CheckCycle']+2
2194 elif options['nPS'] < MLCard['CheckCycle']+2:
2195 new_n_PS = MLCard['CheckCycle']+2
2196 logger.debug('Hard-setting user-defined n_PS (%d) to %d, because '\
2197 %(options['nPS'],new_n_PS)+"of the 'CheckCycle' value (%d) "%MLCard['CheckCycle']+\
2198 "specified in the ML param card.")
2199 options['nPS'] = new_n_PS
2200
2201 MadLoopInitializer.init_MadLoop(self.me_dir,n_PS=options['nPS'],
2202 subproc_prefix='PV', MG_options=self.options, interface=self)
2203
2205 """Main Commands: exec generate_events for 2>N and calculate_width for 1>N"""
2206
2207 if self.ninitial == 1:
2208 logger.info("Note that since 2.3. The launch for 1>N pass in event generation\n"+
2209 " To have the previous behavior use the calculate_decay_widths function")
2210
2211
2212 self.do_generate_events(line, *args, **opt)
2213
2215 """Have a nice results prints in the shell,
2216 data should be of type: gen_crossxhtml.OneTagResults"""
2217
2218 if not data:
2219 return
2220
2221 if data['run_statistics']:
2222 globalstat = sum_html.RunStatistics()
2223
2224 logger.info(" " )
2225 logger.debug(" === Run statistics summary ===")
2226 for key, value in data['run_statistics'].items():
2227 globalstat.aggregate_statistics(value)
2228 level = 5
2229 if value.has_warning():
2230 level = 10
2231 logger.log(level, value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\
2232 replace(' statistics',''))
2233 logger.info(" " )
2234 logger.debug(globalstat.nice_output('combined', no_warning=True))
2235 if globalstat.has_warning():
2236 logger.warning(globalstat.get_warning_text())
2237 logger.info(" ")
2238
2239
2240 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag']))
2241
2242 total_time = int(sum(_['cumulative_timing'] for _ in data['run_statistics'].values()))
2243 if total_time > 0:
2244 logger.info(" Cumulative sequential time for this run: %s"%misc.format_time(total_time))
2245
2246 if self.ninitial == 1:
2247 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error']))
2248 else:
2249 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error']))
2250 logger.info(" Nb of events : %s" % data['nb_event'] )
2251
2252 if data['run_mode']=='madevent':
2253 if data['cross_pythia'] and data['nb_event_pythia']:
2254 if data['cross_pythia'] == -1:
2255 path = pjoin(self.me_dir, 'Events', self.run_name, '%s_merged_xsecs.txt' % self.run_tag)
2256 cross_sections = {}
2257 if os.path.exists(path):
2258 for line in open(path):
2259 split = line.split()
2260 if len(split)!=3:
2261 continue
2262 scale, cross, error = split
2263 cross_sections[float(scale)] = (float(cross), float(error))
2264 if len(cross_sections)>0:
2265 logger.info(' Pythia8 merged cross-sections are:')
2266 for scale in sorted(cross_sections.keys()):
2267 logger.info(' > Merging scale = %-6.4g : %-11.5g +/- %-7.2g [pb]'%\
2268 (scale,cross_sections[scale][0],cross_sections[scale][1]))
2269
2270 else:
2271 if self.ninitial == 1:
2272 logger.info(" Matched width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia']))
2273 else:
2274 logger.info(" Matched cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia']))
2275 logger.info(" Nb of events after matching/merging : %d" % int(data['nb_event_pythia']))
2276 if self.run_card['use_syst'] in self.true and \
2277 (int(self.run_card['ickkw'])==1 or self.run_card['ktdurham']>0.0
2278 or self.run_card['ptlund']>0.0):
2279 logger.info(" Notice that because Systematics computation is turned on, the merging did not veto events but modified their weights instead.\n"+\
2280 " The resulting hepmc/stdhep file should therefore be use with those weights.")
2281 else:
2282 logger.info(" Nb of events after merging : %s" % data['nb_event_pythia'])
2283
2284 logger.info(" " )
2285
2287 """Have a nice results prints in the shell,
2288 data should be of type: gen_crossxhtml.OneTagResults"""
2289 if not data:
2290 return
2291
2292 fsock = open(path, mode)
2293
2294 if data['run_statistics']:
2295 logger.debug(" === Run statistics summary ===")
2296 for key, value in data['run_statistics'].items():
2297 logger.debug(value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).\
2298 replace(' statistics',''))
2299 logger.info(" " )
2300
2301 if format == "full":
2302 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \
2303 (data['run_name'],data['tag'], os.path.basename(self.me_dir)))
2304
2305 if self.ninitial == 1:
2306 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error']))
2307 else:
2308 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error']))
2309 fsock.write(" Nb of events : %s\n" % data['nb_event'] )
2310 if data['cross_pythia'] and data['nb_event_pythia']:
2311 if self.ninitial == 1:
2312 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia']))
2313 else:
2314 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia']))
2315 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia'])
2316 fsock.write(" \n" )
2317 elif format == "short":
2318 if mode == "w":
2319 fsock.write("# run_name tag cross error Nb_event cross_after_matching nb_event_after matching\n")
2320
2321 if data['cross_pythia'] and data['nb_event_pythia']:
2322 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s %(cross_pythia)s %(nb_event_pythia)s\n"
2323 else:
2324 text = "%(run_name)s %(tag)s %(cross)s %(error)s %(nb_event)s\n"
2325 fsock.write(text % data)
2326
2327
2329 """Main Commands: launch decay width calculation and automatic inclusion of
2330 calculated widths and BRs in the param_card."""
2331
2332 args = self.split_arg(line)
2333
2334 accuracy = self.check_calculate_decay_widths(args)
2335 self.ask_run_configuration('parton')
2336 self.banner = None
2337 if not args:
2338
2339 self.set_run_name(self.find_available_run_name(self.me_dir))
2340 else:
2341 self.set_run_name(args[0], reload_card=True)
2342 args.pop(0)
2343
2344 self.configure_directory()
2345
2346
2347 opts=[('accuracy', accuracy),
2348 ('points', 1000),
2349 ('iterations',9)]
2350
2351 logger.info('Calculating decay widths with run name %s' % self.run_name)
2352
2353 self.exec_cmd('survey %s %s' % \
2354 (self.run_name,
2355 " ".join(['--' + opt + '=' + str(val) for (opt,val) \
2356 in opts])),
2357 postcmd=False)
2358 self.refine_mode = "old"
2359 self.exec_cmd('combine_events', postcmd=False)
2360 self.exec_cmd('store_events', postcmd=False)
2361
2362 self.collect_decay_widths()
2363 self.print_results_in_shell(self.results.current)
2364 self.update_status('calculate_decay_widths done',
2365 level='parton', makehtml=False)
2366
2367
2368
2370 """ Collect the decay widths and calculate BRs for all particles, and put
2371 in param_card form.
2372 """
2373
2374 particle_dict = {}
2375 run_name = self.run_name
2376
2377
2378 for P_path in SubProcesses.get_subP(self.me_dir):
2379 ids = SubProcesses.get_subP_ids(P_path)
2380
2381
2382
2383 nb_output = len(ids) / (len(set([p[0] for p in ids])))
2384 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0]
2385 result = float(results.strip().split(' ')[0])
2386 for particles in ids:
2387 try:
2388 particle_dict[particles[0]].append([particles[1:], result/nb_output])
2389 except KeyError:
2390 particle_dict[particles[0]] = [[particles[1:], result/nb_output]]
2391
2392 self.update_width_in_param_card(particle_dict,
2393 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'),
2394 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2395
2396 @staticmethod
2398
2399
2400 if not output:
2401 output = initial
2402
2403 param_card_file = open(initial)
2404 param_card = param_card_file.read().split('\n')
2405 param_card_file.close()
2406
2407 decay_lines = []
2408 line_number = 0
2409
2410 while line_number < len(param_card):
2411 line = param_card[line_number]
2412 if line.lower().startswith('decay'):
2413
2414
2415 line = param_card.pop(line_number)
2416 line = line.split()
2417 particle = 0
2418 if int(line[1]) not in decay_info:
2419 try:
2420 particle = int(line[1])
2421 width = float(line[2])
2422 except Exception:
2423 particle = 0
2424
2425 line = param_card[line_number]
2426 while line.startswith('#') or line.startswith(' '):
2427 line = param_card.pop(line_number)
2428 if not particle or line.startswith('#'):
2429 line=param_card[line_number]
2430 continue
2431
2432 line = line.split()
2433 try:
2434 partial_width = float(line[0])*width
2435 decay_products = [int(p) for p in line[2:2+int(line[1])]]
2436 except Exception:
2437 line=param_card[line_number]
2438 continue
2439 try:
2440 decay_info[particle].append([decay_products, partial_width])
2441 except KeyError:
2442 decay_info[particle] = [[decay_products, partial_width]]
2443 if line_number == len(param_card):
2444 break
2445 line=param_card[line_number]
2446 if particle and particle not in decay_info:
2447
2448 decay_info[particle] = [[[], width]]
2449 else:
2450 line_number += 1
2451
2452 while not param_card[-1] or param_card[-1].startswith('#'):
2453 param_card.pop(-1)
2454
2455
2456 param_card.append("#\n#*************************")
2457 param_card.append("# Decay widths *")
2458 param_card.append("#*************************")
2459 for key in sorted(decay_info.keys()):
2460 width = sum([r for p,r in decay_info[key]])
2461 param_card.append("#\n# PDG Width")
2462 param_card.append("DECAY %i %e" % (key, width.real))
2463 if not width:
2464 continue
2465 if decay_info[key][0][0]:
2466 param_card.append("# BR NDA ID1 ID2 ...")
2467 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]]
2468 for val in sorted(brs, reverse=True):
2469 param_card.append(" %e %i %s # %s" %
2470 (val[0].real, len(val[1]),
2471 " ".join([str(v) for v in val[1]]),
2472 val[0] * width
2473 ))
2474 decay_table = open(output, 'w')
2475 decay_table.write("\n".join(param_card) + "\n")
2476 decay_table.close()
2477 logger.info("Results written to %s" % output)
2478
2479
2480
2482
2483 args = self.split_arg(line)
2484
2485 mode = self.check_multi_run(args)
2486 nb_run = args.pop(0)
2487 if nb_run == 1:
2488 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead")
2489 self.ask_run_configuration(mode)
2490
2491 self.check_survey(args, cmd='multi_run')
2492 main_name = self.run_name
2493
2494 path=pjoin(self.me_dir, 'Cards', 'param_card.dat')
2495 self.check_param_card(path, run=False)
2496
2497 param_card_iterator, self.param_card_iterator = self.param_card_iterator, []
2498
2499 crossoversig = 0
2500 inv_sq_err = 0
2501 nb_event = 0
2502 for i in range(nb_run):
2503 self.nb_refine = 0
2504 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False)
2505
2506 nb_event += int(self.results[self.run_name][-1]['nb_event'])
2507 self.results.add_detail('nb_event', nb_event , run=main_name)
2508 cross = self.results[self.run_name][-1]['cross']
2509 error = self.results[self.run_name][-1]['error'] + 1e-99
2510 crossoversig+=cross/error**2
2511 inv_sq_err+=1.0/error**2
2512 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err
2513 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err)
2514 self.results.def_current(main_name)
2515 self.run_name = main_name
2516 self.update_status("Merging LHE files", level='parton')
2517 try:
2518 os.mkdir(pjoin(self.me_dir,'Events', self.run_name))
2519 except Exception:
2520 pass
2521 os.system('%(bin)s/merge.pl %(event)s/%(name)s_*/unweighted_events.lhe.gz %(event)s/%(name)s/unweighted_events.lhe.gz %(event)s/%(name)s_banner.txt'
2522 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'),
2523 'name': self.run_name})
2524
2525 eradir = self.options['exrootanalysis_path']
2526 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')):
2527 self.update_status("Create Root file", level='parton')
2528 misc.gunzip('%s/%s/unweighted_events.lhe.gz' %
2529 (pjoin(self.me_dir,'Events'), self.run_name))
2530
2531 self.create_root_file('%s/unweighted_events.lhe' % self.run_name,
2532 '%s/unweighted_events.root' % self.run_name)
2533
2534 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe")
2535 self.create_plot('parton', path,
2536 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
2537 )
2538
2539
2540 if not os.path.exists('%s.gz' % path):
2541 misc.gzip(path)
2542
2543 self.update_status('', level='parton')
2544 self.print_results_in_shell(self.results.current)
2545
2546 if param_card_iterator:
2547
2548 param_card_iterator.store_entry(self.run_name, self.results.current['cross'])
2549
2550 orig_name=self.run_name
2551 for card in param_card_iterator:
2552 card.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2553 self.exec_cmd("multi_run %s -f " % nb_run ,precmd=True, postcmd=True,errorhandling=False)
2554 param_card_iterator.store_entry(self.run_name, self.results.current['cross'])
2555 param_card_iterator.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2556 scan_name = misc.get_scan_name(orig_name, self.run_name)
2557 path = pjoin(self.me_dir, 'Events','scan_%s.txt' % scan_name)
2558 logger.info("write all cross-section results in %s" % path, '$MG:color:BLACK')
2559 param_card_iterator.write_summary(path)
2560
2561
2562
2564 """Advanced commands: create .inc files from param_card.dat/run_card.dat"""
2565
2566 if not mode and not opt:
2567 args = self.split_arg(line)
2568 mode, opt = self.check_treatcards(args)
2569
2570
2571
2572
2573 need_MadLoopFilterUpdate = False
2574
2575
2576 type_of_change = ''
2577 if not opt['forbid_MadLoopInit'] and self.proc_characteristics['loop_induced'] \
2578 and mode in ['loop', 'all']:
2579 paramDat = pjoin(self.me_dir, 'Cards','param_card.dat')
2580 paramInc = pjoin(opt['output_dir'], 'param_card.inc')
2581 if (not os.path.isfile(paramDat)) or (not os.path.isfile(paramInc)) or \
2582 (os.path.getmtime(paramDat)-os.path.getmtime(paramInc)) > 0.0:
2583 need_MadLoopFilterUpdate = True
2584 type_of_change = 'model'
2585
2586 ML_in = pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat')
2587 ML_out = pjoin(self.me_dir,"SubProcesses",
2588 "MadLoop5_resources", "MadLoopParams.dat")
2589 if (not os.path.isfile(ML_in)) or (not os.path.isfile(ML_out)) or \
2590 (os.path.getmtime(ML_in)-os.path.getmtime(ML_out)) > 0.0:
2591 need_MadLoopFilterUpdate = True
2592 type_of_change = 'MadLoop'
2593
2594
2595 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat'))
2596
2597 if mode in ['param', 'all']:
2598 model = self.find_model_name()
2599 tmp_model = os.path.basename(model)
2600 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'):
2601 if not '--param_card=' in line:
2602 param_card = pjoin(self.me_dir, 'Cards','param_card.dat')
2603 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat')
2604 check_param_card.convert_to_mg5card(param_card, mg5_param)
2605 check_param_card.check_valid_param_card(mg5_param)
2606 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat')
2607 else:
2608 check_param_card.check_valid_param_card(opt['param_card'])
2609
2610 logger.debug('write compile file for card: %s' % opt['param_card'])
2611 param_card = check_param_card.ParamCard(opt['param_card'])
2612 outfile = pjoin(opt['output_dir'], 'param_card.inc')
2613 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat')
2614 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')):
2615 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')
2616 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')):
2617 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
2618 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')):
2619 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w')
2620 fsock.write(' ')
2621 fsock.close()
2622 if mode == 'all':
2623 self.do_treatcards('', 'run', opt)
2624 return
2625 else:
2626 devnull = open(os.devnull,'w')
2627 subprocess.call([sys.executable, 'write_param_card.py'],
2628 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'),
2629 stdout=devnull)
2630 devnull.close()
2631 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
2632
2633 need_mp = self.proc_characteristics['loop_induced']
2634 param_card.write_inc_file(outfile, ident_card, default, need_mp=need_mp)
2635
2636
2637 if mode in ['run', 'all']:
2638 if not hasattr(self, 'run_card'):
2639 run_card = banner_mod.RunCard(opt['run_card'])
2640 else:
2641 run_card = self.run_card
2642 if self.ninitial == 1:
2643 run_card['lpp1'] = 0
2644 run_card['lpp2'] = 0
2645 run_card['ebeam1'] = 0
2646 run_card['ebeam2'] = 0
2647
2648
2649
2650 if run_card['bias_module'].lower() not in ['dummy','none']:
2651
2652 bias_module_path = pjoin(self.me_dir,'Source','BIAS',
2653 os.path.basename(run_card['bias_module']))
2654 if not os.path.isdir(bias_module_path):
2655 if not os.path.isdir(run_card['bias_module']):
2656 raise InvalidCmd("The bias module at '%s' cannot be found."%run_card['bias_module'])
2657 else:
2658 for mandatory_file in ['makefile','%s.f'%os.path.basename(run_card['bias_module'])]:
2659 if not os.path.isfile(pjoin(run_card['bias_module'],mandatory_file)):
2660 raise InvalidCmd("Could not find the mandatory file '%s' in bias module '%s'."%(
2661 mandatory_file,run_card['bias_module']))
2662 shutil.copytree(run_card['bias_module'], pjoin(self.me_dir,'Source','BIAS',
2663 os.path.basename(run_card['bias_module'])))
2664
2665
2666 default_bias_parameters = {}
2667 start, last = False,False
2668 for line in open(pjoin(bias_module_path,'%s.f'%os.path.basename(bias_module_path))):
2669 if start and last:
2670 break
2671 if not start and not re.search('c\s*parameters\s*=\s*{',line, re.I):
2672 continue
2673 start = True
2674 if not line.startswith('C'):
2675 continue
2676 line = line[1:]
2677 if '{' in line:
2678 line = line.split('{')[-1]
2679
2680 split_result = re.split('(\}|!|\#)', line,1, re.M)
2681 line = split_result[0]
2682 sep = split_result[1] if len(split_result)>1 else None
2683 if sep == '}':
2684 last = True
2685 if ',' in line:
2686 for pair in line.split(','):
2687 if not pair.strip():
2688 continue
2689 x,y =pair.split(':')
2690 x=x.strip()
2691 if x.startswith(('"',"'")) and x.endswith(x[0]):
2692 x = x[1:-1]
2693 default_bias_parameters[x] = y
2694 elif ':' in line:
2695 x,y = line.split(':')
2696 x = x.strip()
2697 if x.startswith(('"',"'")) and x.endswith(x[0]):
2698 x = x[1:-1]
2699 default_bias_parameters[x] = y
2700 for key,value in run_card['bias_parameters'].items():
2701 if key not in default_bias_parameters:
2702 logger.warning('%s not supported by the bias module. We discard this entry.', key)
2703 else:
2704 default_bias_parameters[key] = value
2705 run_card['bias_parameters'] = default_bias_parameters
2706
2707
2708
2709 run_card.write_include_file(opt['output_dir'])
2710
2711
2712 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']:
2713 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir,
2714 'Cards', 'MadLoopParams.dat'))
2715
2716
2717
2718
2719 if 'WriteOutFilters' in self.MadLoopparam.user_set and \
2720 self.MadLoopparam.get('WriteOutFilters'):
2721 logger.info(
2722 """You chose to have MadLoop writing out filters.
2723 Beware that this can be dangerous for local multicore runs.""")
2724 self.MadLoopparam.set('WriteOutFilters',False, changeifuserset=False)
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745 self.MadLoopparam.set('HelicityFilterLevel',1, changeifuserset=False)
2746
2747
2748
2749 self.MadLoopparam.set('CheckCycle',4, changeifuserset=False)
2750
2751
2752
2753
2754
2755 self.MadLoopparam.set('DoubleCheckHelicityFilter',False,
2756 changeifuserset=False)
2757
2758
2759
2760 if not hasattr(self, 'run_card'):
2761 run_card = banner_mod.RunCard(opt['run_card'])
2762 else:
2763 run_card = self.run_card
2764 if run_card['nhel'] == 0:
2765 if 'MLReductionLib' in self.MadLoopparam.user_set and \
2766 (self.MadLoopparam.get('MLReductionLib').startswith('1') or
2767 self.MadLoopparam.get('MLReductionLib').startswith('6')):
2768 logger.warning(
2769 """You chose to set the preferred reduction technique in MadLoop to be OPP (see parameter MLReductionLib).
2770 Beware that this can bring significant slowdown; the optimal choice --when not MC over helicity-- being to first start with TIR reduction.""")
2771
2772 self.MadLoopparam.set('MLReductionLib','7|6|1', changeifuserset=False)
2773 else:
2774 if 'MLReductionLib' in self.MadLoopparam.user_set and \
2775 not (self.MadLoopparam.get('MLReductionLib').startswith('1') or
2776 self.MadLoopparam.get('MLReductionLib').startswith('6')):
2777 logger.warning(
2778 """You chose to set the preferred reduction technique in MadLoop to be different than OPP (see parameter MLReductionLib).
2779 Beware that this can bring significant slowdown; the optimal choice --when MC over helicity-- being to first start with OPP reduction.""")
2780 self.MadLoopparam.set('MLReductionLib','6|7|1', changeifuserset=False)
2781
2782
2783
2784
2785
2786 if run_card['nhel'] == 0:
2787 if ('NRotations_DP' in self.MadLoopparam.user_set and \
2788 self.MadLoopparam.get('NRotations_DP')!=0) or \
2789 ('NRotations_QP' in self.MadLoopparam.user_set and \
2790 self.MadLoopparam.get('NRotations_QP')!=0):
2791 logger.warning(
2792 """You chose to also use a lorentz rotation for stability tests (see parameter NRotations_[DP|QP]).
2793 Beware that, for optimization purposes, MadEvent uses manual TIR cache clearing which is not compatible
2794 with the lorentz rotation stability test. The number of these rotations to be used will be reset to
2795 zero by MadLoop. You can avoid this by changing the parameter 'FORCE_ML_HELICITY_SUM' int he matrix<i>.f
2796 files to be .TRUE. so that the sum over helicity configurations is performed within MadLoop (in which case
2797 the helicity of final state particles cannot be speicfied in the LHE file.""")
2798 self.MadLoopparam.set('NRotations_DP',0,changeifuserset=False)
2799 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False)
2800 else:
2801
2802
2803
2804
2805
2806
2807 self.MadLoopparam.set('NRotations_DP',1,changeifuserset=False)
2808 self.MadLoopparam.set('NRotations_QP',0,changeifuserset=False)
2809
2810
2811
2812
2813
2814
2815
2816
2817 if self.proc_characteristics['nexternal']<=4:
2818 if ('MLStabThres' in self.MadLoopparam.user_set and \
2819 self.MadLoopparam.get('MLStabThres')>1.0e-7):
2820 logger.warning(
2821 """You chose to increase the default value of the MadLoop parameter 'MLStabThres' above 1.0e-7.
2822 Stability tests can be less reliable on the limited kinematic of processes with less or equal
2823 than four external legs, so this is not recommended (especially not for g g > z z).""")
2824 self.MadLoopparam.set('MLStabThres',1.0e-7,changeifuserset=False)
2825 else:
2826 self.MadLoopparam.set('MLStabThres',1.0e-4,changeifuserset=False)
2827
2828
2829 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses","MadLoop5_resources",
2830 "MadLoopParams.dat"))
2831
2832 if self.proc_characteristics['loop_induced'] and mode in ['loop', 'all']:
2833
2834
2835 if need_MadLoopFilterUpdate:
2836 logger.debug('Changes to the %s parameters'%type_of_change+\
2837 ' have been detected. Madevent will then now reinitialize'+\
2838 ' MadLoop filters.')
2839 self.exec_cmd('initMadLoop -r -f')
2840
2841
2842
2843
2844
2845 elif not opt['forbid_MadLoopInit'] and \
2846 MadLoopInitializer.need_MadLoopInit(self.me_dir):
2847 self.exec_cmd('initMadLoop -f')
2848
2849
2851 """Advanced commands: launch survey for the current process """
2852
2853
2854 args = self.split_arg(line)
2855
2856 self.check_survey(args)
2857
2858
2859 if os.path.exists(pjoin(self.me_dir,'error')):
2860 os.remove(pjoin(self.me_dir,'error'))
2861
2862 self.configure_directory()
2863
2864 self.random_orig = self.random
2865 logger.info("Using random number seed offset = %s" % self.random)
2866
2867 self.update_random()
2868 self.save_random()
2869 self.update_status('Running Survey', level=None)
2870 if self.cluster_mode:
2871 logger.info('Creating Jobs')
2872
2873 self.total_jobs = 0
2874 subproc = [l.strip() for l in open(pjoin(self.me_dir,
2875 'SubProcesses', 'subproc.mg'))]
2876
2877 P_zero_result = []
2878
2879
2880 if os.path.exists(pjoin(self.me_dir,'SubProcesses',
2881 'MadLoop5_resources')) and cluster.need_transfer(self.options):
2882 tf=tarfile.open(pjoin(self.me_dir, 'SubProcesses',
2883 'MadLoop5_resources.tar.gz'), 'w:gz', dereference=True)
2884 tf.add(pjoin(self.me_dir,'SubProcesses','MadLoop5_resources'),
2885 arcname='MadLoop5_resources')
2886 tf.close()
2887
2888 logger.info('Working on SubProcesses')
2889 ajobcreator = gen_ximprove.gensym(self)
2890
2891
2892 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])):
2893 self.pass_in_difficult_integration_mode()
2894
2895 jobs, P_zero_result = ajobcreator.launch()
2896
2897
2898 if P_zero_result:
2899 if len(P_zero_result) == len(subproc):
2900 Pdir = pjoin(self.me_dir, 'SubProcesses',subproc[0].strip())
2901 raise ZeroResult, '%s' % \
2902 open(pjoin(Pdir,'ajob.no_ps.log')).read()
2903 else:
2904 logger.warning(''' %s SubProcesses doesn\'t have available phase-space.
2905 Please check mass spectrum.''' % ','.join(P_zero_result))
2906
2907
2908 self.monitor(run_type='All jobs submitted for survey', html=True)
2909 if not self.history or 'survey' in self.history[-1] or self.ninitial ==1 or \
2910 self.run_card['gridpack']:
2911
2912 cross, error = sum_html.make_all_html_results(self)
2913 self.results.add_detail('cross', cross)
2914 self.results.add_detail('error', error)
2915 self.exec_cmd("print_results %s" % self.run_name,
2916 errorhandling=False, printcmd=False, precmd=False, postcmd=False)
2917
2918 self.results.add_detail('run_statistics', dict(ajobcreator.run_statistics))
2919 self.update_status('End survey', 'parton', makehtml=False)
2920
2921
2923 """be more secure for the integration to not miss it due to strong cut"""
2924
2925
2926 if self.opts['points'] == self._survey_options['points'][1]:
2927 self.opts['points'] = 2 * self._survey_options['points'][1]
2928 if self.opts['iterations'] == self._survey_options['iterations'][1]:
2929 self.opts['iterations'] = 1 + self._survey_options['iterations'][1]
2930 if self.opts['accuracy'] == self._survey_options['accuracy'][1]:
2931 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945 for name in ['../bin/internal/gen_ximprove', 'all',
2946 '../bin/internal/combine_events']:
2947 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2948
2949
2950
2952 """Advanced commands: launch survey for the current process """
2953 devnull = open(os.devnull, 'w')
2954 self.nb_refine += 1
2955 args = self.split_arg(line)
2956
2957 self.check_refine(args)
2958
2959 refine_opt = {'err_goal': args[0], 'split_channels': True}
2960 precision = args[0]
2961 if len(args) == 2:
2962 refine_opt['max_process']= args[1]
2963
2964
2965
2966 self.configure_directory()
2967
2968
2969 self.update_random()
2970 self.save_random()
2971
2972 if self.cluster_mode:
2973 logger.info('Creating Jobs')
2974 self.update_status('Refine results to %s' % precision, level=None)
2975
2976 self.total_jobs = 0
2977 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
2978 'subproc.mg'))]
2979
2980
2981 for nb_proc,subdir in enumerate(subproc):
2982 subdir = subdir.strip()
2983 Pdir = pjoin(self.me_dir, 'SubProcesses', subdir)
2984 for match in misc.glob('*ajob*', Pdir):
2985 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
2986 os.remove(match)
2987
2988 x_improve = gen_ximprove.gen_ximprove(self, refine_opt)
2989
2990 survey_statistics = dict(self.results.get_detail('run_statistics'))
2991
2992 if __debug__ and survey_statistics:
2993 globalstat = sum_html.RunStatistics()
2994 logger.debug(" === Survey statistics summary ===")
2995 for key, value in survey_statistics.items():
2996 globalstat.aggregate_statistics(value)
2997 level = 5
2998 if value.has_warning():
2999 level = 10
3000 logger.log(level,
3001 value.nice_output(str('/'.join([key[0],'G%s'%key[1]]))).
3002 replace(' statistics',''))
3003 logger.debug(globalstat.nice_output('combined', no_warning=True))
3004
3005 if survey_statistics:
3006 x_improve.run_statistics = survey_statistics
3007
3008 x_improve.launch()
3009 if not self.history or 'refine' not in self.history[-1]:
3010 cross, error = x_improve.update_html()
3011 if cross == 0:
3012 return
3013 logger.info("Current estimate of cross-section: %s +- %s" % (cross, error))
3014
3015 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4):
3016
3017
3018 for nb_proc,subdir in enumerate(subproc):
3019 subdir = subdir.strip()
3020 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
3021 bindir = pjoin(os.path.relpath(self.dirbin, Pdir))
3022
3023 logger.info(' %s ' % subdir)
3024
3025 if os.path.exists(pjoin(Pdir, 'ajob1')):
3026 self.compile(['madevent'], cwd=Pdir)
3027
3028 alljobs = misc.glob('ajob*', Pdir)
3029
3030
3031 Gre = re.compile("\s*j=(G[\d\.\w]+)")
3032 for job in alljobs:
3033 Gdirs = Gre.findall(open(job).read())
3034 for Gdir in Gdirs:
3035 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')):
3036 os.remove(pjoin(Pdir, Gdir,'results.dat'))
3037
3038 nb_tot = len(alljobs)
3039 self.total_jobs += nb_tot
3040 for i, job in enumerate(alljobs):
3041 job = os.path.basename(job)
3042 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1),
3043 run_type='Refine number %s on %s (%s/%s)' %
3044 (self.nb_refine, subdir, nb_proc+1, len(subproc)))
3045
3046 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine,
3047 html=True)
3048
3049 self.update_status("Combining runs", level='parton')
3050 try:
3051 os.remove(pjoin(Pdir, 'combine_runs.log'))
3052 except Exception:
3053 pass
3054
3055 if isinstance(x_improve, gen_ximprove.gen_ximprove_v4):
3056
3057
3058 combine_runs.CombineRuns(self.me_dir)
3059 self.refine_mode = "old"
3060 else:
3061 self.refine_mode = "new"
3062
3063 cross, error = sum_html.make_all_html_results(self)
3064 self.results.add_detail('cross', cross)
3065 self.results.add_detail('error', error)
3066
3067 self.results.add_detail('run_statistics',
3068 dict(self.results.get_detail('run_statistics')))
3069
3070 self.update_status('finish refine', 'parton', makehtml=False)
3071 devnull.close()
3072
3073
3075 """Not in help: Combine a given iteration combine_iteration Pdir Gdir S|R step
3076 S is for survey
3077 R is for refine
3078 step is the iteration number (not very critical)"""
3079
3080 self.set_run_name("tmp")
3081 self.configure_directory(html_opening=False)
3082 Pdir, Gdir, mode, step = self.split_arg(line)
3083 if Gdir.startswith("G"):
3084 Gdir = Gdir[1:]
3085 if "SubProcesses" not in Pdir:
3086 Pdir = pjoin(self.me_dir, "SubProcesses", Pdir)
3087 if mode == "S":
3088 self.opts = dict([(key,value[1]) for (key,value) in \
3089 self._survey_options.items()])
3090 gensym = gen_ximprove.gensym(self)
3091 gensym.combine_iteration(Pdir, Gdir, int(step))
3092 elif mode == "R":
3093 refine = gen_ximprove.gen_ximprove_share(self)
3094 refine.combine_iteration(Pdir, Gdir, int(step))
3095
3096
3097
3098
3099
3101 """Advanced commands: Launch combine events"""
3102
3103 args = self.split_arg(line)
3104
3105 self.check_combine_events(args)
3106
3107 self.update_status('Combining Events', level='parton')
3108
3109
3110
3111 if self.run_card['gridpack']:
3112 try:
3113 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log'))
3114 except Exception:
3115 pass
3116
3117 cluster.onecore.launch_and_wait('../bin/internal/run_combine',
3118 args=[self.run_name],
3119 cwd=pjoin(self.me_dir,'SubProcesses'),
3120 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'),
3121 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')])
3122
3123
3124
3125
3126
3127
3128 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read()
3129
3130 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''')
3131 try:
3132 nb_event = pat.search(output).groups()[0]
3133 except AttributeError:
3134 time.sleep(10)
3135 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read()
3136 try:
3137 nb_event = pat.search(output).groups()[0]
3138 except AttributeError:
3139 logger.warning('Fail to read the number of unweighted events in the combine.log file')
3140 nb_event = 0
3141
3142 self.results.add_detail('nb_event', nb_event)
3143
3144
3145
3146 tag = self.run_card['run_tag']
3147
3148
3149 if not self.banner:
3150 self.banner = banner_mod.recover_banner(self.results, 'parton')
3151 self.banner.load_basic(self.me_dir)
3152
3153 self.banner.add_generation_info(self.results.current['cross'], nb_event)
3154 if not hasattr(self, 'random_orig'): self.random_orig = 0
3155 self.banner.change_seed(self.random_orig)
3156 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
3157 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
3158 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name,
3159 '%s_%s_banner.txt' % (self.run_name, tag)))
3160
3161
3162 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'),
3163 out=pjoin(self.me_dir,'Events', self.run_name, 'events.lhe'))
3164 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'),
3165 out=pjoin(self.me_dir,'Events', self.run_name, 'unweighted_events.lhe'))
3166
3167 else:
3168
3169 tag = self.run_card['run_tag']
3170
3171 if not self.banner:
3172 self.banner = banner_mod.recover_banner(self.results, 'parton')
3173 self.banner.load_basic(self.me_dir)
3174
3175 self.banner.add_generation_info(self.results.current['cross'], self.run_card['nevents'])
3176 if not hasattr(self, 'random_orig'): self.random_orig = 0
3177 self.banner.change_seed(self.random_orig)
3178 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
3179 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
3180 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name,
3181 '%s_%s_banner.txt' % (self.run_name, tag)))
3182
3183
3184 get_wgt = lambda event: event.wgt
3185 AllEvent = lhe_parser.MultiEventFile()
3186 AllEvent.banner = self.banner
3187
3188 partials = 0
3189 sum_xsec, sum_xerru, sum_axsec = 0,[],0
3190 for Gdir,mfactor in self.get_Gdir():
3191 if os.path.exists(pjoin(Gdir, 'events.lhe')):
3192 result = sum_html.OneResult('')
3193 result.read_results(pjoin(Gdir, 'results.dat'))
3194 AllEvent.add(pjoin(Gdir, 'events.lhe'),
3195 result.get('xsec'),
3196 result.get('xerru'),
3197 result.get('axsec')
3198 )
3199
3200 sum_xsec += result.get('xsec')
3201 sum_xerru.append(result.get('xerru'))
3202 sum_axsec += result.get('axsec')
3203
3204 if len(AllEvent) >= 80:
3205 AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials),
3206 get_wgt, log_level=5, trunc_error=1e-2, event_target=self.run_card['nevents'])
3207 AllEvent = lhe_parser.MultiEventFile()
3208 AllEvent.banner = self.banner
3209 AllEvent.add(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % partials),
3210 sum_xsec,
3211 math.sqrt(sum(x**2 for x in sum_xerru)),
3212 sum_axsec)
3213 partials +=1
3214
3215 nb_event = AllEvent.unweight(pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe.gz"),
3216 get_wgt, trunc_error=1e-2, event_target=self.run_card['nevents'],
3217 log_level=logging.DEBUG, normalization=self.run_card['event_norm'])
3218
3219 if partials:
3220 misc.sprint("used partials")
3221 for i in range(partials):
3222 try:
3223 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe.gz" % i))
3224 except Exception:
3225 os.remove(pjoin(self.me_dir, "Events", self.run_name, "partials%s.lhe" % i))
3226
3227 self.results.add_detail('nb_event', nb_event)
3228
3229 if self.run_card['bias_module'].lower() not in ['dummy', 'none']:
3230 self.correct_bias()
3231
3232
3233
3234 self.to_store.append('event')
3235 eradir = self.options['exrootanalysis_path']
3236 madir = self.options['madanalysis_path']
3237 td = self.options['td_path']
3238 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\
3239 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')):
3240 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
3241 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
3242 self.create_root_file(output='%s/unweighted_events.root' % \
3243 self.run_name)
3244
3245
3247 """check the first event and correct the weight by the bias
3248 and correct the cross-section.
3249 If the event do not have the bias tag it means that the bias is
3250 one modifying the cross-section/shape so we have nothing to do
3251 """
3252
3253 lhe = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz'))
3254 init = False
3255 cross = collections.defaultdict(float)
3256 nb_event = 0
3257 for event in lhe:
3258 rwgt_info = event.parse_reweight()
3259 if not init:
3260 if 'bias' in rwgt_info:
3261 output = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, '.unweighted_events.lhe.tmp.gz'),'w')
3262
3263 init = True
3264 else:
3265 return
3266
3267 event.wgt /= rwgt_info['bias']
3268
3269 del event.reweight_data['bias']
3270
3271 cross[event.ievent] += event.wgt
3272 nb_event +=1
3273 output.write(str(event))
3274 output.write('</LesHouchesEvents>')
3275 output.close()
3276 lhe.close()
3277
3278
3279
3280 total_cross = sum(cross[key] for key in cross)
3281 if 'event_norm' in self.run_card:
3282 if self.run_card['event_norm'] == 'average':
3283 total_cross = total_cross / nb_event
3284 for key in cross:
3285 cross[key] /= nb_event
3286 elif self.run_card['event_norm'] == 'unity':
3287 total_cross = self.results.current['cross'] * total_cross / nb_event
3288 for key in cross:
3289 cross[key] *= total_cross / nb_event
3290
3291 bannerfile = lhe_parser.EventFile(pjoin(self.me_dir, 'Events', self.run_name, '.banner.tmp.gz'),'w')
3292 banner = banner_mod.Banner(lhe.banner)
3293 banner.modify_init_cross(cross)
3294 banner.write(bannerfile, close_tag=False)
3295 bannerfile.close()
3296
3297 os.system('cat %s %s > %s' %(bannerfile.name, output.name, lhe.name))
3298 os.remove(bannerfile.name)
3299 os.remove(output.name)
3300
3301
3302 self.results.current['cross'] = total_cross
3303 self.results.current['error'] = 0
3304
3305
3307 """Advanced commands: Launch store events"""
3308
3309 args = self.split_arg(line)
3310
3311 self.check_combine_events(args)
3312 self.update_status('Storing parton level results', level='parton')
3313
3314 run = self.run_name
3315 tag = self.run_card['run_tag']
3316 devnull = open(os.devnull, 'w')
3317
3318 if not os.path.exists(pjoin(self.me_dir, 'Events', run)):
3319 os.mkdir(pjoin(self.me_dir, 'Events', run))
3320 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)):
3321 os.mkdir(pjoin(self.me_dir, 'HTML', run))
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331 if self.results.current['nb_event'] == 0:
3332 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" +
3333 " cd Subprocesses; ../bin/internal/combine_events\n"+
3334 " to have your events if those one are missing.")
3335 else:
3336 for P_path in SubProcesses.get_subP(self.me_dir):
3337 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and
3338 os.path.isdir(pjoin(P_path,G))]
3339 for G in G_dir:
3340 G_path = pjoin(P_path,G)
3341 try:
3342
3343 if os.path.exists(pjoin(G_path, 'events.lhe')):
3344 os.remove(pjoin(G_path, 'events.lhe'))
3345 except Exception:
3346 continue
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356 try:
3357 if os.path.exists(pjoin(G_path, 'log.txt')):
3358 input = pjoin(G_path, 'log.txt')
3359 output = pjoin(G_path, '%s_log.txt' % run)
3360 files.mv(input, output)
3361 except Exception:
3362 continue
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376 if os.path.exists(pjoin(G_path, 'ftn25')):
3377 os.remove(pjoin(G_path, 'ftn25'))
3378
3379
3380 misc.call(['%s/gen_cardhtml-pl' % self.dirbin],
3381 cwd=pjoin(self.me_dir))
3382
3383
3384
3385 E_path = pjoin(self.me_dir, 'Events')
3386 O_path = pjoin(self.me_dir, 'Events', run)
3387
3388
3389 for name in ['events.lhe', 'unweighted_events.lhe']:
3390 finput = pjoin(E_path, name)
3391 foutput = pjoin(O_path, name)
3392 if os.path.exists(finput):
3393 logger.debug("File %s exists BAAAAD. Not move anymore!" % pjoin(E_path, name))
3394 if os.path.exists(foutput):
3395 misc.gzip(foutput, stdout="%s.gz" % foutput, error=False)
3396
3397
3398
3399
3400
3401
3402 self.update_status('End Parton', level='parton', makehtml=False)
3403 devnull.close()
3404
3405
3406
3408 """Advanced commands: Create gridpack from present run"""
3409
3410 self.update_status('Creating gridpack', level='parton')
3411
3412 misc.compile(['../bin/internal/gen_ximprove'], cwd=pjoin(self.me_dir, "Source"))
3413 args = self.split_arg(line)
3414 self.check_combine_events(args)
3415 if not self.run_tag: self.run_tag = 'tag_1'
3416 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \
3417 % self.me_dir)
3418 misc.call(['./bin/internal/restore_data', self.run_name],
3419 cwd=self.me_dir)
3420 misc.call(['./bin/internal/store4grid',
3421 self.run_name, self.run_tag],
3422 cwd=self.me_dir)
3423 misc.call(['./bin/internal/clean'], cwd=self.me_dir)
3424 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir)
3425 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'),
3426 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name))
3427 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \
3428 % self.me_dir)
3429 self.update_status('gridpack created', level='gridpack')
3430
3431
3433 """launch the shower"""
3434
3435 args = self.split_arg(line)
3436 if len(args)>1 and args[0] in self._interfaced_showers:
3437 chosen_showers = [args.pop(0)]
3438 elif '--no_default' in line:
3439
3440
3441
3442 chosen_showers = list(self._interfaced_showers)
3443 else:
3444 chosen_showers = list(self._interfaced_showers)
3445
3446
3447 shower_priority = ['pythia8','pythia']
3448 chosen_showers = [sorted(chosen_showers,key=lambda sh:
3449 shower_priority.index(sh) if sh in shower_priority else len(shower_priority)+1)[0]]
3450
3451 for shower in chosen_showers:
3452 self.exec_cmd('%s %s'%(shower,' '.join(args)),
3453 postcmd=False, printcmd=False)
3454
3456 """launch MadAnalysis5 at the parton level."""
3457 return self.run_madanalysis5(line,mode='parton')
3458
3459
3460
3461
3462
3463
3464 @staticmethod
3466 """ Check the consistency of the mg5amc_py8_interface installed with
3467 the current MG5 and Pythia8 versions. """
3468
3469
3470 if not options['pythia8_path']:
3471 return None
3472
3473 if not options['mg5amc_py8_interface_path']:
3474 return \
3475 """
3476 A Pythia8 path is specified via the option 'pythia8_path' but no path for option
3477 'mg5amc_py8_interface_path' is specified. This means that Pythia8 cannot be used
3478 leading order simulations with MadEvent.
3479 Consider installing the MG5_aMC-PY8 interface with the following command:
3480 MG5_aMC>install mg5amc_py8_interface
3481 """
3482
3483 mg5amc_py8_interface_path = options['mg5amc_py8_interface_path']
3484 py8_path = options['pythia8_path']
3485
3486
3487 if not MADEVENT:
3488 mg5amc_py8_interface_path = pjoin(MG5DIR,mg5amc_py8_interface_path)
3489 py8_path = pjoin(MG5DIR,py8_path)
3490
3491
3492 MG5_version_on_install = open(pjoin(mg5amc_py8_interface_path,
3493 'MG5AMC_VERSION_ON_INSTALL')).read().replace('\n','')
3494 if MG5_version_on_install == 'UNSPECIFIED':
3495 MG5_version_on_install = None
3496 PY8_version_on_install = open(pjoin(mg5amc_py8_interface_path,
3497 'PYTHIA8_VERSION_ON_INSTALL')).read().replace('\n','')
3498 MG5_curr_version =misc.get_pkg_info()['version']
3499 try:
3500 p = subprocess.Popen(['./get_pythia8_version.py',py8_path],
3501 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
3502 cwd=mg5amc_py8_interface_path)
3503 (out, err) = p.communicate()
3504 out = out.replace('\n','')
3505 PY8_curr_version = out
3506
3507
3508 float(out)
3509 except:
3510 PY8_curr_version = None
3511
3512 if not MG5_version_on_install is None and not MG5_curr_version is None:
3513 if MG5_version_on_install != MG5_curr_version:
3514 return \
3515 """
3516 The current version of MG5_aMC (v%s) is different than the one active when
3517 installing the 'mg5amc_py8_interface_path' (which was MG5aMC v%s).
3518 Please consider refreshing the installation of this interface with the command:
3519 MG5_aMC>install mg5amc_py8_interface
3520 """%(MG5_curr_version, MG5_version_on_install)
3521
3522 if not PY8_version_on_install is None and not PY8_curr_version is None:
3523 if PY8_version_on_install != PY8_curr_version:
3524 return \
3525 """
3526 The current version of Pythia8 (v%s) is different than the one active when
3527 installing the 'mg5amc_py8_interface' tool (which was Pythia8 v%s).
3528 Please consider refreshing the installation of this interface with the command:
3529 MG5_aMC>install mg5amc_py8_interface
3530 """%(PY8_curr_version,PY8_version_on_install)
3531
3532 return None
3533
3535 """ Setup the Pythia8 Run environment and card. In particular all the process and run specific parameters
3536 of the card are automatically set here. This function returns the path where HEPMC events will be output,
3537 if any."""
3538
3539 HepMC_event_output = None
3540 tag = self.run_tag
3541
3542 PY8_Card.subruns[0].systemSet('Beams:LHEF',"unweighted_events.lhe.gz")
3543
3544 if PY8_Card['HEPMCoutput:file']=='auto':
3545 HepMC_event_output = pjoin(self.me_dir,'Events', self.run_name,
3546 '%s_pythia8_events.hepmc'%tag)
3547 PY8_Card.MadGraphSet('HEPMCoutput:file','%s_pythia8_events.hepmc'%tag)
3548 elif PY8_Card['HEPMCoutput:file'].startswith('fifo'):
3549 fifo_specs = PY8_Card['HEPMCoutput:file'].split('@')
3550 fifo_path = None
3551 if len(fifo_specs)<=1:
3552 fifo_path = pjoin(self.me_dir,'Events', self.run_name,'PY8.hepmc.fifo')
3553 if os.path.exists(fifo_path):
3554 os.remove(fifo_path)
3555 misc.mkfifo(fifo_path)
3556
3557 PY8_Card.defaultSet('HEPMCoutput:file','PY8.hepmc.fifo')
3558 else:
3559 fifo_path = fifo_specs[1]
3560 if os.path.exists(fifo_path):
3561 if stat.S_ISFIFO(os.stat(fifo_path).st_mode):
3562 logger.warning('PY8 will be reusing already existing '+
3563 'custom fifo file at:\n %s'%fifo_path)
3564 else:
3565 raise InvalidCmd(
3566 """The fifo path speficied for the PY8 parameter 'HEPMCoutput:file':
3567 %s
3568 already exists and is not a fifo file."""%fifo_path)
3569 else:
3570 misc.mkfifo(fifo_path)
3571
3572 PY8_Card.defaultSet('HEPMCoutput:file',fifo_path)
3573 HepMC_event_output=fifo_path
3574 elif PY8_Card['HEPMCoutput:file'] in ['','/dev/null','None']:
3575 logger.warning('User disabled the HepMC output of Pythia8.')
3576 HepMC_event_output = None
3577 else:
3578
3579 HepMC_event_output = pjoin(self.me_dir,'Events', self.run_name,
3580 PY8_Card['HEPMCoutput:file'])
3581
3582
3583
3584 PY8_Card.MadGraphSet('JetMatching:setMad', False)
3585 if run_type=='MLM':
3586
3587
3588 if PY8_Card['JetMatching:qCut']==-1.0:
3589 PY8_Card.MadGraphSet('JetMatching:qCut',1.5*self.run_card['xqcut'])
3590
3591 if PY8_Card['JetMatching:qCut']<(1.5*self.run_card['xqcut']):
3592 logger.error(
3593 'The MLM merging qCut parameter you chose (%f) is less than'%PY8_Card['JetMatching:qCut']+
3594 '1.5*xqcut, with xqcut your run_card parameter (=%f).\n'%self.run_card['xqcut']+
3595 'It would be better/safer to use a larger qCut or a smaller xqcut.')
3596
3597
3598
3599 PY8_Card.systemSet('Beams:setProductionScalesFromLHEF',True)
3600
3601
3602 if PY8_Card['SysCalc:qWeed']==-1.0:
3603 PY8_Card.MadGraphSet('SysCalc:qWeed',self.run_card['xqcut'])
3604
3605 if PY8_Card['SysCalc:qCutList']=='auto':
3606 if self.run_card['use_syst']:
3607 if self.run_card['sys_matchscale']=='auto':
3608 qcut = PY8_Card['JetMatching:qCut']
3609 value = [factor*qcut for factor in [0.5,0.75,1.0,1.5,2.0] if\
3610 factor*qcut> 1.5*self.run_card['xqcut'] ]
3611 PY8_Card.MadGraphSet('SysCalc:qCutList', value)
3612 else:
3613 qCutList = [float(qc) for qc in self.run_card['sys_matchscale'].split()]
3614 if PY8_Card['JetMatching:qCut'] not in qCutList:
3615 qCutList.append(PY8_Card['JetMatching:qCut'])
3616 PY8_Card.MadGraphSet('SysCalc:qCutList', qCutList)
3617
3618 for scale in PY8_Card['SysCalc:qCutList']:
3619 if scale<(1.5*self.run_card['xqcut']):
3620 logger.error(
3621 'One of the MLM merging qCut parameter you chose (%f) in the variation list'%scale+\
3622 " (either via 'SysCalc:qCutList' in the PY8 shower card or "+\
3623 "'sys_matchscale' in the run_card) is less than 1.5*xqcut, where xqcut is"+
3624 ' the run_card parameter (=%f)\n'%self.run_card['xqcut']+
3625 'It would be better/safer to use a larger qCut or a smaller xqcut.')
3626
3627
3628
3629
3630 if self.run_card['use_syst']:
3631 PY8_Card.MadGraphSet('JetMatching:doVeto',False)
3632
3633 PY8_Card.MadGraphSet('JetMatching:merge',True)
3634 PY8_Card.MadGraphSet('JetMatching:scheme',1)
3635
3636
3637 PY8_Card.MadGraphSet('JetMatching:nQmatch',self.run_card['maxjetflavor'])
3638
3639 PY8_Card.MadGraphSet('JetMatching:coneRadius',1.0)
3640
3641
3642 if not hasattr(self,'proc_characteristic'):
3643 self.proc_characteristic = self.get_characteristics()
3644 nJetMax = self.proc_characteristic['max_n_matched_jets']
3645 if PY8_Card['JetMatching:nJetMax'.lower()] == -1:
3646 logger.info("No user-defined value for Pythia8 parameter "+
3647 "'JetMatching:nJetMax'. Setting it automatically to %d."%nJetMax)
3648 PY8_Card.MadGraphSet('JetMatching:nJetMax',nJetMax)
3649
3650 elif run_type=='CKKW':
3651 CKKW_cut = None
3652
3653 if self.run_card['ptlund']<=0.0 and self.run_card['ktdurham']>0.0:
3654 PY8_Card.subruns[0].MadGraphSet('Merging:doKTMerging',True)
3655 PY8_Card.subruns[0].MadGraphSet('Merging:Dparameter',
3656 self.run_card['dparameter'])
3657 CKKW_cut = 'ktdurham'
3658 elif self.run_card['ptlund']>0.0 and self.run_card['ktdurham']<=0.0:
3659 PY8_Card.subruns[0].MadGraphSet('Merging:doPTLundMerging',True)
3660 CKKW_cut = 'ptlund'
3661 else:
3662 raise InvalidCmd("*Either* the 'ptlund' or 'ktdurham' cut in "+\
3663 " the run_card must be turned on to activate CKKW(L) merging"+
3664 " with Pythia8, but *both* cuts cannot be turned on at the same time."+
3665 "\n ptlund=%f, ktdurham=%f."%(self.run_card['ptlund'],self.run_card['ktdurham']))
3666
3667
3668
3669 if PY8_Card['SysCalc:qWeed']==-1.0:
3670 PY8_Card.MadGraphSet('SysCalc:qWeed',self.run_card[CKKW_cut])
3671
3672
3673
3674 if PY8_Card['Merging:TMS']==-1.0:
3675 if self.run_card[CKKW_cut]>0.0:
3676 PY8_Card.MadGraphSet('Merging:TMS',self.run_card[CKKW_cut])
3677 else:
3678 raise self.InvalidCmd('When running CKKWl merging, the user'+\
3679 " select a '%s' cut larger than 0.0 in the run_card."%CKKW_cut)
3680 if PY8_Card['Merging:TMS']<self.run_card[CKKW_cut]:
3681 logger.error(
3682 'The CKKWl merging scale you chose (%f) is less than'%PY8_Card['Merging:TMS']+
3683 'the %s cut specified in the run_card parameter (=%f).\n'%(CKKW_cut,self.run_card[CKKW_cut])+
3684 'It is incorrect to use a smaller CKKWl scale than the generation-level %s cut!'%CKKW_cut)
3685
3686 if PY8_Card['Merging:Process']=='<set_by_user>':
3687 raise self.InvalidCmd('When running CKKWl merging, the user must'+
3688 " specifiy the option 'Merging:Process' in pythia8_card.dat.\n"+
3689 "Read section 'Defining the hard process' of "+\
3690 "http://home.thep.lu.se/~torbjorn/pythia81html/CKKWLMerging.html for more information.")
3691 PY8_Card.MadGraphSet('TimeShower:pTmaxMatch',1)
3692 PY8_Card.MadGraphSet('SpaceShower:pTmaxMatch',1)
3693 PY8_Card.MadGraphSet('SpaceShower:rapidityOrder',False)
3694
3695 if self.run_card['use_syst']:
3696 PY8_Card.MadGraphSet('Merging:applyVeto',False)
3697 PY8_Card.MadGraphSet('Merging:includeWeightInXsection',False)
3698
3699
3700 PY8_Card.MadGraphSet('Merging:nQuarksMerge',self.run_card['maxjetflavor'])
3701 if not hasattr(self,'proc_characteristic'):
3702 self.proc_characteristic = self.get_characteristics()
3703 nJetMax = self.proc_characteristic['max_n_matched_jets']
3704 if PY8_Card['Merging:nJetMax'.lower()] == -1:
3705 logger.info("No user-defined value for Pythia8 parameter "+
3706 "'Merging:nJetMax'. Setting it automatically to %d."%nJetMax)
3707 PY8_Card.MadGraphSet('Merging:nJetMax',nJetMax)
3708 if PY8_Card['SysCalc:tmsList']=='auto':
3709 if self.run_card['use_syst']:
3710 if self.run_card['sys_matchscale']=='auto':
3711 tms = PY8_Card["Merging:TMS"]
3712 value = [factor*tms for factor in [0.5,0.75,1.0,1.5,2.0]
3713 if factor*tms > self.run_card[CKKW_cut]]
3714 PY8_Card.MadGraphSet('SysCalc:tmsList', value)
3715 else:
3716 tmsList = [float(tms) for tms in self.run_card['sys_matchscale'].split()]
3717 if PY8_Card['Merging:TMS'] not in tmsList:
3718 tmsList.append(PY8_Card['Merging:TMS'])
3719 PY8_Card.MadGraphSet('SysCalc:tmsList', tmsList)
3720
3721 for scale in PY8_Card['SysCalc:tmsList']:
3722 if scale<self.run_card[CKKW_cut]:
3723 logger.error(
3724 'One of the CKKWl merging scale you chose (%f) in the variation list'%scale+\
3725 " (either via 'SysCalc:tmsList' in the PY8 shower card or "+\
3726 "'sys_matchscale' in the run_card) is less than %f, "%self.run_card[CKKW_cut]+
3727 'the %s cut specified in the run_card parameter.\n'%CKKW_cut+
3728 'It is incorrect to use a smaller CKKWl scale than the generation-level %s cut!'%CKKW_cut)
3729 else:
3730
3731
3732
3733 PY8_Card.vetoParamWriteOut('Merging:Process')
3734
3735 return HepMC_event_output
3736
3738 """launch pythia8"""
3739
3740
3741 args = self.split_arg(line)
3742 if '--no_default' in args:
3743 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia8_card.dat')):
3744 return
3745 no_default = True
3746 args.remove('--no_default')
3747 else:
3748 no_default = False
3749
3750 if not self.run_name:
3751 self.check_pythia8(args)
3752 self.configure_directory(html_opening =False)
3753 else:
3754
3755 self.configure_directory(html_opening =False)
3756 self.check_pythia8(args)
3757
3758
3759 if not no_default:
3760 self.ask_pythia_run_configuration(args[-1], pythia_version=8)
3761
3762 if self.options['automatic_html_opening']:
3763 misc.open_file(os.path.join(self.me_dir, 'crossx.html'))
3764 self.options['automatic_html_opening'] = False
3765
3766 if self.run_card['event_norm'] not in ['unit','average']:
3767 logger.critical("Pythia8 does not support normalization to the sum. Not running Pythia8")
3768 return
3769
3770
3771
3772
3773
3774 if not self.banner or len(self.banner) <=1:
3775
3776 self.banner = banner_mod.recover_banner(self.results, 'pythia')
3777
3778 if not self.options['mg5amc_py8_interface_path'] or not \
3779 os.path.exists(pjoin(self.options['mg5amc_py8_interface_path'],
3780 'MG5aMC_PY8_interface')):
3781 raise self.InvalidCmd(
3782 """The MG5aMC_PY8_interface tool cannot be found, so that MadEvent cannot steer Pythia8 shower.
3783 Please install this tool with the following MG5_aMC command:
3784 MG5_aMC> install mg5amc_py8_interface_path""")
3785 else:
3786 pythia_main = pjoin(self.options['mg5amc_py8_interface_path'],
3787 'MG5aMC_PY8_interface')
3788 warnings = MadEventCmd.mg5amc_py8_interface_consistency_warning(self.options)
3789 if warnings:
3790 logger.warning(warnings)
3791
3792 self.results.add_detail('run_mode', 'madevent')
3793
3794
3795 self.update_status('\033[92mRunning Pythia8 [arXiv:1410.3012]\033[0m', 'pythia8')
3796
3797 tag = self.run_tag
3798
3799
3800
3801 PY8_Card = banner_mod.PY8Card(pjoin(self.me_dir, 'Cards',
3802 'pythia8_card_default.dat'))
3803 PY8_Card.read(pjoin(self.me_dir, 'Cards', 'pythia8_card.dat'),
3804 setter='user')
3805
3806 run_type = 'default'
3807 merged_run_types = ['MLM','CKKW']
3808 if int(self.run_card['ickkw'])==1:
3809 run_type = 'MLM'
3810 elif int(self.run_card['ickkw'])==2 or \
3811 self.run_card['ktdurham']>0.0 or self.run_card['ptlund']>0.0:
3812 run_type = 'CKKW'
3813
3814
3815 HepMC_event_output = self.setup_Pythia8RunAndCard(PY8_Card, run_type)
3816
3817
3818 pythia_cmd_card = pjoin(self.me_dir, 'Events', self.run_name ,
3819 '%s_pythia8.cmd' % tag)
3820 cmd_card = StringIO.StringIO()
3821 PY8_Card.write(cmd_card,pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
3822 direct_pythia_input=True)
3823
3824
3825
3826
3827 if 'heptools_install_dir' in self.options:
3828 preamble = misc.get_HEPTools_location_setter(
3829 self.options['heptools_install_dir'],'lib')
3830 else:
3831 if MADEVENT:
3832 preamble = misc.get_HEPTools_location_setter(
3833 pjoin(self.options['mg5amc_py8_interface_path'],os.pardir),'lib')
3834 else:
3835 preamble = misc.get_HEPTools_location_setter(
3836 pjoin(MG5DIR,'HEPTools'),'lib')
3837
3838 open(pythia_cmd_card,'w').write("""!
3839 ! It is possible to run this card manually with:
3840 ! %s %s
3841 !
3842 """%(preamble+pythia_main,os.path.basename(pythia_cmd_card))+cmd_card.getvalue())
3843
3844
3845 pythia_log = pjoin(self.me_dir, 'Events', self.run_name ,
3846 '%s_pythia8.log' % tag)
3847
3848
3849 wrapper_path = pjoin(self.me_dir,'Events',self.run_name,'run_shower.sh')
3850 wrapper = open(wrapper_path,'w')
3851 shell = 'bash' if misc.get_shell_type() in ['bash',None] else 'tcsh'
3852 shell_exe = None
3853 if os.path.exists('/usr/bin/env'):
3854 shell_exe = '/usr/bin/env %s'%shell
3855 else:
3856 shell_exe = misc.which(shell)
3857 if not shell_exe:
3858 self.InvalidCmd('No shell could be found in your environment.\n'+
3859 "Make sure that either '%s' is in your path or that the"%shell+\
3860 " command '/usr/bin/env %s' exists and returns a valid path."%shell)
3861
3862 exe_cmd = "#!%s\n%s"%(shell_exe,' '.join(
3863 [preamble+pythia_main,
3864 os.path.basename(pythia_cmd_card)]))
3865
3866 wrapper.write(exe_cmd)
3867 wrapper.close()
3868
3869
3870 st = os.stat(wrapper_path)
3871 os.chmod(wrapper_path, st.st_mode | stat.S_IEXEC)
3872
3873
3874
3875 is_HepMC_output_fifo = False if not HepMC_event_output else \
3876 ( os.path.exists(HepMC_event_output) and \
3877 stat.S_ISFIFO(os.stat(HepMC_event_output).st_mode))
3878 startPY8timer = time.time()
3879
3880
3881 PY8_extracted_information={ 'sigma_m':None, 'Nacc':None, 'Ntry':None,
3882 'cross_sections':{} }
3883
3884 if is_HepMC_output_fifo:
3885 logger.info(
3886 """Pythia8 is set to output HEPMC events to to a fifo file.
3887 You can follow PY8 run with the following command (in a separate terminal):
3888 tail -f %s"""%pythia_log)
3889 py8_log = open(pythia_log,'w')
3890 py8_bkgrd_proc = misc.Popen([wrapper_path],
3891 stdout=py8_log,stderr=py8_log,
3892 cwd=pjoin(self.me_dir,'Events',self.run_name))
3893
3894 if not no_default:
3895 logger.info('You can now run a tool that reads the following fifo file:'+\
3896 '\n %s\nwhere PY8 outputs HEPMC events (e.g. MadAnalysis5).'
3897 %HepMC_event_output,'$MG:color:GREEN')
3898 return
3899 else:
3900 if self.options['run_mode']!=0:
3901
3902 self.configure_run_mode(self.options['run_mode'])
3903 if self.options['run_mode']==1:
3904 n_cores = max(self.options['cluster_size'],1)
3905 elif self.options['run_mode']==2:
3906 n_cores = max(self.cluster.nb_core,1)
3907
3908 lhe_file_name = os.path.basename(PY8_Card.subruns[0]['Beams:LHEF'])
3909 lhe_file = lhe_parser.EventFile(pjoin(self.me_dir,'Events',
3910 self.run_name,PY8_Card.subruns[0]['Beams:LHEF']))
3911 n_available_events = len(lhe_file)
3912 if PY8_Card['Main:numberOfEvents']==-1:
3913 n_events = n_available_events
3914 else:
3915 n_events = PY8_Card['Main:numberOfEvents']
3916 if n_events > n_available_events:
3917 raise self.InvalidCmd, 'You specified more events (%d) in the PY8 parameter'%n_events+\
3918 "'Main:numberOfEvents' than the total number of events available (%d)"%n_available_events+\
3919 ' in the event file:\n %s'%pjoin(self.me_dir,'Events',self.run_name,PY8_Card.subruns[0]['Beams:LHEF'])
3920
3921
3922 if self.options['run_mode']==2:
3923 min_n_events_per_job = 100
3924 elif self.options['run_mode']==1:
3925 min_n_events_per_job = 1000
3926 min_n_core = n_events//min_n_events_per_job
3927 n_cores = max(min(min_n_core,n_cores),1)
3928
3929 if self.options['run_mode']==0 or (self.options['run_mode']==2 and self.options['nb_core']==1):
3930
3931 self.cluster = None
3932 logger.info('Follow Pythia8 shower by running the '+
3933 'following command (in a separate terminal):\n tail -f %s'%pythia_log)
3934
3935 if self.options['run_mode']==2 and self.options['nb_core']>1:
3936 ret_code = self.cluster.launch_and_wait(wrapper_path,
3937 argument= [], stdout= pythia_log, stderr=subprocess.STDOUT,
3938 cwd=pjoin(self.me_dir,'Events',self.run_name))
3939 else:
3940 ret_code = misc.call(wrapper_path, stdout=open(pythia_log,'w'), stderr=subprocess.STDOUT,
3941 cwd=pjoin(self.me_dir,'Events',self.run_name))
3942 if ret_code != 0:
3943 raise self.InvalidCmd, 'Pythia8 shower interrupted with return'+\
3944 ' code %d.\n'%ret_code+\
3945 'You can find more information in this log file:\n%s'%pythia_log
3946 else:
3947 if self.run_card['event_norm']=='sum':
3948 logger.error("")
3949 logger.error("Either run in single core or change event_norm to 'average'.")
3950 raise InvalidCmd("Pythia8 parallelization with event_norm set to 'sum' is not supported."
3951 "Either run in single core or change event_norm to 'average'.")
3952
3953
3954 parallelization_dir = pjoin(self.me_dir,'Events',self.run_name,'PY8_parallelization')
3955 if os.path.isdir(parallelization_dir):
3956 shutil.rmtree(parallelization_dir)
3957 os.mkdir(parallelization_dir)
3958
3959 shutil.copy(pythia_main,parallelization_dir)
3960
3961 ParallelPY8Card = copy.copy(PY8_Card)
3962
3963 if HepMC_event_output:
3964 ParallelPY8Card['HEPMCoutput:file']='events.hepmc'
3965 else:
3966 ParallelPY8Card['HEPMCoutput:file']='/dev/null'
3967
3968 ParallelPY8Card.subruns[0].systemSet('Beams:LHEF','events.lhe.gz')
3969 ParallelPY8Card.write(pjoin(parallelization_dir,'PY8Card.dat'),
3970 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
3971 direct_pythia_input=True)
3972
3973 wrapper_path = pjoin(parallelization_dir,'run_PY8.sh')
3974 wrapper = open(wrapper_path,'w')
3975 if self.options['cluster_temp_path'] is None:
3976 exe_cmd = \
3977 """#!%s
3978 ./%s PY8Card.dat >& PY8_log.txt
3979 """
3980 else:
3981 exe_cmd = \
3982 """#!%s
3983 ln -s ./events_$1.lhe.gz ./events.lhe.gz
3984 ./%s PY8Card_$1.dat >& PY8_log.txt
3985 mkdir split_$1
3986 if [ -f ./events.hepmc ];
3987 then
3988 mv ./events.hepmc ./split_$1/
3989 fi
3990 if [ -f ./pts.dat ];
3991 then
3992 mv ./pts.dat ./split_$1/
3993 fi
3994 if [ -f ./djrs.dat ];
3995 then
3996 mv ./djrs.dat ./split_$1/
3997 fi
3998 if [ -f ./PY8_log.txt ];
3999 then
4000 mv ./PY8_log.txt ./split_$1/
4001 fi
4002 tar -czf split_$1.tar.gz split_$1
4003 """
4004 exe_cmd = exe_cmd%(shell_exe,os.path.basename(pythia_main))
4005 wrapper.write(exe_cmd)
4006 wrapper.close()
4007
4008 st = os.stat(wrapper_path)
4009 os.chmod(wrapper_path, st.st_mode | stat.S_IEXEC)
4010
4011
4012 partition=[n_available_events//n_cores]*n_cores
4013 for i in range(n_available_events%n_cores):
4014 partition[i] += 1
4015
4016
4017
4018 partition_for_PY8=[n_events//n_cores]*n_cores
4019 for i in range(n_events%n_cores):
4020 partition_for_PY8[i] += 1
4021
4022 logger.info('Splitting .lhe event file for PY8 parallelization...')
4023 n_splits = lhe_file.split(partition=partition, cwd=parallelization_dir, zip=True)
4024
4025 if n_splits!=len(partition):
4026 raise MadGraph5Error('Error during lhe file splitting. Expected %d files but obtained %d.'
4027 %(len(partition),n_splits))
4028
4029 split_files = []
4030 split_dirs = []
4031 for split_id in range(n_splits):
4032 split_files.append('events_%s.lhe.gz'%split_id)
4033 split_dirs.append(pjoin(parallelization_dir,'split_%d'%split_id))
4034
4035 shutil.move(pjoin(parallelization_dir,lhe_file.name+'_%d.lhe.gz'%split_id),
4036 pjoin(parallelization_dir,split_files[-1]))
4037
4038 logger.info('Submitting Pythia8 jobs...')
4039 for i, split_file in enumerate(split_files):
4040
4041
4042
4043 split_PY8_Card = banner_mod.PY8Card(pjoin(parallelization_dir,'PY8Card.dat'))
4044
4045 split_PY8_Card.systemSet('Main:numberOfEvents',partition_for_PY8[i])
4046 split_PY8_Card.systemSet('HEPMCoutput:scaling',split_PY8_Card['HEPMCoutput:scaling']*
4047 (float(partition_for_PY8[i])/float(n_events)))
4048
4049
4050 split_PY8_Card.write(pjoin(parallelization_dir,'PY8Card_%d.dat'%i),
4051 pjoin(parallelization_dir,'PY8Card.dat'), add_missing=False)
4052 in_files = [pjoin(parallelization_dir,os.path.basename(pythia_main)),
4053 pjoin(parallelization_dir,'PY8Card_%d.dat'%i),
4054 pjoin(parallelization_dir,split_file)]
4055 if self.options['cluster_temp_path'] is None:
4056 out_files = []
4057 os.mkdir(pjoin(parallelization_dir,'split_%d'%i))
4058 selected_cwd = pjoin(parallelization_dir,'split_%d'%i)
4059 for in_file in in_files+[pjoin(parallelization_dir,'run_PY8.sh')]:
4060
4061
4062 if os.path.basename(in_file)==split_file:
4063 ln(in_file,selected_cwd,name='events.lhe.gz')
4064 elif os.path.basename(in_file).startswith('PY8Card'):
4065 ln(in_file,selected_cwd,name='PY8Card.dat')
4066 else:
4067 ln(in_file,selected_cwd)
4068 in_files = []
4069 else:
4070 out_files = ['split_%d.tar.gz'%i]
4071 selected_cwd = parallelization_dir
4072 self.cluster.submit2(wrapper_path,
4073 argument=[str(i)], cwd=selected_cwd,
4074 input_files=in_files,
4075 output_files=out_files,
4076 required_output=out_files)
4077
4078 def wait_monitoring(Idle, Running, Done):
4079 if Idle+Running+Done == 0:
4080 return
4081 logger.info('Pythia8 shower jobs: %d Idle, %d Running, %d Done [%s]'\
4082 %(Idle, Running, Done, misc.format_time(time.time() - startPY8timer)))
4083 self.cluster.wait(parallelization_dir,wait_monitoring)
4084
4085 logger.info('Merging results from the split PY8 runs...')
4086 if self.options['cluster_temp_path']:
4087
4088 for i, split_file in enumerate(split_files):
4089 misc.call(['tar','-xzf','split_%d.tar.gz'%i],cwd=parallelization_dir)
4090 os.remove(pjoin(parallelization_dir,'split_%d.tar.gz'%i))
4091
4092
4093 pythia_log_file = open(pythia_log,'w')
4094 n_added = 0
4095 for split_dir in split_dirs:
4096 log_file = pjoin(split_dir,'PY8_log.txt')
4097 pythia_log_file.write('='*35+'\n')
4098 pythia_log_file.write(' -> Pythia8 log file for run %d <-'%i+'\n')
4099 pythia_log_file.write('='*35+'\n')
4100 pythia_log_file.write(open(log_file,'r').read()+'\n')
4101 if run_type in merged_run_types:
4102 sigma_m, Nacc, Ntry = self.parse_PY8_log_file(log_file)
4103 if any(elem is None for elem in [sigma_m, Nacc, Ntry]):
4104 continue
4105 n_added += 1
4106 if PY8_extracted_information['sigma_m'] is None:
4107 PY8_extracted_information['sigma_m'] = sigma_m
4108 else:
4109 PY8_extracted_information['sigma_m'] += sigma_m
4110 if PY8_extracted_information['Nacc'] is None:
4111 PY8_extracted_information['Nacc'] = Nacc
4112 else:
4113 PY8_extracted_information['Nacc'] += Nacc
4114 if PY8_extracted_information['Ntry'] is None:
4115 PY8_extracted_information['Ntry'] = Ntry
4116 else:
4117 PY8_extracted_information['Ntry'] += Ntry
4118
4119 if n_added>0:
4120 PY8_extracted_information['sigma_m'] /= float(n_added)
4121 pythia_log_file.close()
4122
4123
4124 djr_HwU = None
4125 n_added = 0
4126 for split_dir in split_dirs:
4127 djr_file = pjoin(split_dir,'djrs.dat')
4128 if not os.path.isfile(djr_file):
4129 continue
4130 xsecs = self.extract_cross_sections_from_DJR(djr_file)
4131 if len(xsecs)>0:
4132 n_added += 1
4133 if len(PY8_extracted_information['cross_sections'])==0:
4134 PY8_extracted_information['cross_sections'] = xsecs
4135
4136 for key in PY8_extracted_information['cross_sections']:
4137 PY8_extracted_information['cross_sections'][key][1] = \
4138 PY8_extracted_information['cross_sections'][key][1]**2
4139 else:
4140 for key, value in xsecs.items():
4141 PY8_extracted_information['cross_sections'][key][0] += value[0]
4142
4143 PY8_extracted_information['cross_sections'][key][1] += value[1]**2
4144 new_djr_HwU = histograms.HwUList(djr_file,run_id=0)
4145 if djr_HwU is None:
4146 djr_HwU = new_djr_HwU
4147 else:
4148 for i, hist in enumerate(djr_HwU):
4149 djr_HwU[i] = hist + new_djr_HwU[i]
4150 if not djr_HwU is None:
4151 djr_HwU.output(pjoin(self.me_dir,'Events',self.run_name,'djrs'),format='HwU')
4152 shutil.move(pjoin(self.me_dir,'Events',self.run_name,'djrs.HwU'),
4153 pjoin(self.me_dir,'Events',self.run_name,'%s_djrs.dat'%tag))
4154 if n_added>0:
4155 for key in PY8_extracted_information['cross_sections']:
4156 PY8_extracted_information['cross_sections'][key][0] /= float(n_added)
4157 PY8_extracted_information['cross_sections'][key][1] = \
4158 math.sqrt(PY8_extracted_information['cross_sections'][key][1])/float(n_added)
4159
4160
4161 pts_HwU = None
4162 for split_dir in split_dirs:
4163 pts_file = pjoin(split_dir,'pts.dat')
4164 if not os.path.isfile(pts_file):
4165 continue
4166 new_pts_HwU = histograms.HwUList(pts_file,run_id=0)
4167 if pts_HwU is None:
4168 pts_HwU = new_pts_HwU
4169 else:
4170 for i, hist in enumerate(pts_HwU):
4171 pts_HwU[i] = hist + new_pts_HwU[i]
4172 if not pts_HwU is None:
4173 pts_HwU.output(pjoin(self.me_dir,'Events',self.run_name,'pts'),format='HwU')
4174 shutil.move(pjoin(self.me_dir,'Events',self.run_name,'pts.HwU'),
4175 pjoin(self.me_dir,'Events',self.run_name,'%s_pts.dat'%tag))
4176
4177
4178 all_hepmc_files = []
4179 for split_dir in split_dirs:
4180 hepmc_file = pjoin(split_dir,'events.hepmc')
4181 if not os.path.isfile(hepmc_file):
4182 continue
4183 all_hepmc_files.append(hepmc_file)
4184
4185 if len(all_hepmc_files)>0:
4186 hepmc_output = pjoin(self.me_dir,'Events',self.run_name,HepMC_event_output)
4187 with misc.TMP_directory() as tmp_dir:
4188
4189 header = open(pjoin(tmp_dir,'header.hepmc'),'w')
4190 n_head = 0
4191 for line in open(all_hepmc_files[0],'r'):
4192 if not line.startswith('E'):
4193 n_head += 1
4194 header.write(line)
4195 else:
4196 break
4197 header.close()
4198 tail = open(pjoin(tmp_dir,'tail.hepmc'),'w')
4199 n_tail = 0
4200 for line in misc.BackRead(all_hepmc_files[-1]):
4201 if line.startswith('HepMC::'):
4202 n_tail += 1
4203 tail.write(line)
4204 else:
4205 break
4206 tail.close()
4207 if n_tail>1:
4208 raise MadGraph5Error,'HEPMC files should only have one trailing command.'
4209
4210
4211
4212
4213 for hepmc_file in all_hepmc_files:
4214
4215 os.system(' '.join(['sed','-i',"''","'%s;$d'"%
4216 (';'.join('%id'%(i+1) for i in range(n_head))),hepmc_file]))
4217 os.system(' '.join(['cat',pjoin(tmp_dir,'header.hepmc')]+all_hepmc_files+
4218 [pjoin(tmp_dir,'tail.hepmc'),'>',hepmc_output]))
4219
4220
4221 if os.path.isdir(parallelization_dir):
4222 shutil.rmtree(parallelization_dir)
4223
4224
4225 djr_output = pjoin(self.me_dir,'Events', self.run_name, 'djrs.dat')
4226 if os.path.isfile(djr_output):
4227 shutil.move(djr_output, pjoin(self.me_dir,'Events',
4228 self.run_name, '%s_djrs.dat' % tag))
4229 pt_output = pjoin(self.me_dir,'Events', self.run_name, 'pts.dat')
4230 if os.path.isfile(pt_output):
4231 shutil.move(pt_output, pjoin(self.me_dir,'Events',
4232 self.run_name, '%s_pts.dat' % tag))
4233
4234 if not os.path.isfile(pythia_log) or \
4235 'Inclusive cross section:' not in '\n'.join(open(pythia_log,'r').readlines()[-20:]):
4236 logger.warning('Fail to produce a pythia8 output. More info in \n %s'%pythia_log)
4237 return
4238
4239
4240 successful = self.create_plot('Pythia8')
4241 if not successful:
4242 logger.warning('Failed to produce Pythia8 merging plots.')
4243
4244 self.to_store.append('pythia8')
4245
4246
4247 if run_type in merged_run_types:
4248
4249 if all(PY8_extracted_information[_] is None for _ in ['sigma_m','Nacc','Ntry']):
4250 PY8_extracted_information['sigma_m'],PY8_extracted_information['Nacc'],\
4251 PY8_extracted_information['Ntry'] = self.parse_PY8_log_file(
4252 pjoin(self.me_dir,'Events', self.run_name,'%s_pythia8.log' % tag))
4253
4254 if not any(PY8_extracted_information[_] is None for _ in ['sigma_m','Nacc','Ntry']):
4255 self.results.add_detail('cross_pythia', PY8_extracted_information['sigma_m'])
4256 self.results.add_detail('nb_event_pythia', PY8_extracted_information['Nacc'])
4257
4258 error = self.results[self.run_name].return_tag(self.run_tag)['error']
4259 try:
4260 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc)
4261 except ZeroDivisionError:
4262
4263 error_m = -1.0
4264
4265 self.results.add_detail('error_pythia', error_m)
4266
4267 if self.run_card['use_syst']:
4268 self.results.add_detail('cross_pythia', -1)
4269 self.results.add_detail('error_pythia', 0)
4270
4271
4272 djr_output = pjoin(self.me_dir,'Events',self.run_name,'%s_djrs.dat'%tag)
4273 if os.path.isfile(djr_output) and len(PY8_extracted_information['cross_sections'])==0:
4274 PY8_extracted_information['cross_sections'] = self.extract_cross_sections_from_DJR(djr_output)
4275 cross_sections = PY8_extracted_information['cross_sections']
4276 if cross_sections:
4277
4278
4279 a_float_re = '[\+|-]?\d+(\.\d*)?([EeDd][\+|-]?\d+)?'
4280 central_merging_re = re.compile(
4281 '^\s*Weight_MERGING\s*=\s*(?P<merging>%s)\s*$'%a_float_re,
4282 re.IGNORECASE)
4283 cross_sections = dict(
4284 (float(central_merging_re.match(xsec).group('merging')),value)
4285 for xsec, value in cross_sections.items() if not
4286 central_merging_re.match(xsec) is None)
4287 central_scale = PY8_Card['JetMatching:qCut'] if \
4288 int(self.run_card['ickkw'])==1 else PY8_Card['Merging:TMS']
4289 if central_scale in cross_sections:
4290 self.results.add_detail('cross_pythia8', cross_sections[central_scale][0])
4291 self.results.add_detail('error_pythia8', cross_sections[central_scale][1])
4292
4293
4294
4295
4296
4297
4298 xsecs_file = open(pjoin(self.me_dir,'Events',self.run_name,
4299 '%s_merged_xsecs.txt'%tag),'w')
4300 if cross_sections:
4301 xsecs_file.write('%-20s%-20s%-20s\n'%('Merging scale',
4302 'Cross-section [pb]','MC uncertainty [pb]'))
4303 for scale in sorted(cross_sections.keys()):
4304 xsecs_file.write('%-20.4g%-20.6e%-20.2e\n'%
4305 (scale,cross_sections[scale][0],cross_sections[scale][1]))
4306 else:
4307 xsecs_file.write('Cross-sections could not be read from the'+\
4308 "XML node 'xsection' of the .dat file produced by Pythia8.")
4309 xsecs_file.close()
4310
4311
4312
4313
4314 self.banner.add(pythia_cmd_card)
4315
4316 if int(self.run_card['ickkw']):
4317
4318 if 'MGGenerationInfo' in self.banner:
4319 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
4320 else:
4321 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
4322 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))
4323 self.banner.write(banner_path)
4324
4325 self.update_status('Pythia8 shower finished after %s.'%misc.format_time(time.time() - startPY8timer), level='pythia8')
4326 if self.options['delphes_path']:
4327 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False)
4328 self.print_results_in_shell(self.results.current)
4329
4331 """ Parse a log file to extract number of event and cross-section. """
4332 pythiare = re.compile("Les Houches User Process\(es\)\s*\d+\s*\|\s*(?P<tried>\d+)\s*(?P<selected>\d+)\s*(?P<generated>\d+)\s*\|\s*(?P<xsec>[\d\.e\-\+]+)\s*(?P<xsec_error>[\d\.e\-\+]+)")
4333 for line in misc.BackRead(log_file_path):
4334 info = pythiare.search(line)
4335 if not info:
4336 continue
4337 try:
4338
4339 sigma_m = float(info.group('xsec')) *1e9
4340 Nacc = int(info.group('generated'))
4341 Ntry = int(info.group('tried'))
4342 if Nacc==0:
4343 raise self.InvalidCmd, 'Pythia8 shower failed since it'+\
4344 ' did not accept any event from the MG5aMC event file.'
4345 return sigma_m, Nacc, Ntry
4346 except ValueError:
4347 return None,None,None
4348 raise self.InvalidCmd, "Could not find cross-section and event number information "+\
4349 "in Pythia8 log\n '%s'."%log_file_path
4350
4352 """Extract cross-sections from a djr XML output."""
4353 run_nodes = minidom.parse(djr_output).getElementsByTagName("run")
4354 all_nodes = dict((int(node.getAttribute('id')),node) for
4355 node in run_nodes)
4356 try:
4357 selected_run_node = all_nodes[0]
4358 except:
4359 return {}
4360 xsections = selected_run_node.getElementsByTagName("xsection")
4361
4362 return dict((xsec.getAttribute('name'),
4363 [float(xsec.childNodes[0].data.split()[0])*1e9,
4364 float(xsec.childNodes[0].data.split()[1])*1e9])
4365 for xsec in xsections)
4366
4368 """launch pythia"""
4369
4370
4371
4372 args = self.split_arg(line)
4373 if '--no_default' in args:
4374 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')):
4375 return
4376 no_default = True
4377 args.remove('--no_default')
4378 else:
4379 no_default = False
4380
4381 if not self.run_name:
4382 self.check_pythia(args)
4383 self.configure_directory(html_opening =False)
4384 else:
4385
4386 self.configure_directory(html_opening =False)
4387 self.check_pythia(args)
4388
4389 if self.run_card['event_norm'] != 'sum':
4390 logger.error('pythia-pgs require event_norm to be on sum. Do not run pythia6')
4391 return
4392
4393
4394 if not no_default:
4395 self.ask_pythia_run_configuration(args[-1])
4396 if self.options['automatic_html_opening']:
4397 misc.open_file(os.path.join(self.me_dir, 'crossx.html'))
4398 self.options['automatic_html_opening'] = False
4399
4400
4401 if not self.banner or len(self.banner) <=1:
4402 self.banner = banner_mod.recover_banner(self.results, 'pythia')
4403
4404 pythia_src = pjoin(self.options['pythia-pgs_path'],'src')
4405
4406 self.results.add_detail('run_mode', 'madevent')
4407
4408 self.update_status('Running Pythia', 'pythia')
4409 try:
4410 os.remove(pjoin(self.me_dir,'Events','pythia.done'))
4411 except Exception:
4412 pass
4413
4414
4415
4416 if not re.search(r'^\s*LHAPATH=%s/PDFsets' % pythia_src,
4417 open(pjoin(self.me_dir,'Cards','pythia_card.dat')).read(),
4418 re.M):
4419 f = open(pjoin(self.me_dir,'Cards','pythia_card.dat'),'a')
4420 f.write('\n LHAPATH=%s/PDFsets' % pythia_src)
4421 f.close()
4422 tag = self.run_tag
4423 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag)
4424
4425
4426
4427
4428 output_files = ['pythia_events.hep']
4429 if self.run_card['use_syst']:
4430 output_files.append('syst.dat')
4431 if self.run_card['ickkw'] == 1:
4432 output_files.append(['beforeveto.tree', 'xsecs.tree', 'events.tree'])
4433
4434 os.environ['PDG_MASS_TBL'] = pjoin(pythia_src,'mass_width_2004.mc')
4435 self.cluster.launch_and_wait(pjoin(pythia_src, 'pythia'),
4436 input_files=[pjoin(self.me_dir, "Events", "unweighted_events.lhe"),
4437 pjoin(self.me_dir,'Cards','pythia_card.dat'),
4438 pjoin(pythia_src,'mass_width_2004.mc')],
4439 output_files=output_files,
4440 stdout= pythia_log,
4441 stderr=subprocess.STDOUT,
4442 cwd=pjoin(self.me_dir,'Events'))
4443
4444
4445 os.remove(pjoin(self.me_dir, "Events", "unweighted_events.lhe"))
4446
4447 if not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')):
4448 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log)
4449 return
4450
4451 self.to_store.append('pythia')
4452
4453
4454 if int(self.run_card['ickkw']):
4455
4456 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name,
4457 '%s_pythia.log' % tag))
4458 pythiare = re.compile("\s*I\s+0 All included subprocesses\s+I\s+(?P<generated>\d+)\s+(?P<tried>\d+)\s+I\s+(?P<xsec>[\d\.D\-+]+)\s+I")
4459 for line in pythia_log:
4460 info = pythiare.search(line)
4461 if not info:
4462 continue
4463 try:
4464
4465 sigma_m = float(info.group('xsec').replace('D','E')) *1e9
4466 Nacc = int(info.group('generated'))
4467 Ntry = int(info.group('tried'))
4468 except ValueError:
4469
4470 self.results.add_detail('cross_pythia', 0)
4471 self.results.add_detail('nb_event_pythia', 0)
4472 self.results.add_detail('error_pythia', 0)
4473 else:
4474 self.results.add_detail('cross_pythia', sigma_m)
4475 self.results.add_detail('nb_event_pythia', Nacc)
4476
4477 error = self.results[self.run_name].return_tag(self.run_tag)['error']
4478 if Nacc:
4479 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc)
4480 else:
4481 error_m = 10000 * sigma_m
4482
4483 self.results.add_detail('error_pythia', error_m)
4484 break
4485
4486 pythia_log.close()
4487
4488 pydir = pjoin(self.options['pythia-pgs_path'], 'src')
4489 eradir = self.options['exrootanalysis_path']
4490 madir = self.options['madanalysis_path']
4491 td = self.options['td_path']
4492
4493
4494 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat'))
4495 if int(self.run_card['ickkw']):
4496
4497 if 'MGGenerationInfo' in self.banner:
4498 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
4499 else:
4500 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
4501 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))
4502 self.banner.write(banner_path)
4503
4504
4505 self.run_hep2lhe(banner_path)
4506
4507 if int(self.run_card['ickkw']):
4508 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'),
4509 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz'))
4510
4511
4512 if self.run_card['use_syst'] in self.true:
4513
4514 try:
4515 self.run_syscalc('Pythia')
4516 except SysCalcError, error:
4517 logger.error(str(error))
4518 else:
4519 if os.path.exists(pjoin(self.me_dir,'Events', 'syst.dat')):
4520
4521 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'),
4522 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz'))
4523
4524
4525 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')):
4526 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
4527 '%s_syscalc.dat' % self.run_tag)
4528 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'),
4529 stdout = "%s.gz" % filename)
4530
4531
4532 self.create_plot('Pythia')
4533
4534 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')):
4535 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'),
4536 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag))
4537
4538 self.update_status('finish', level='pythia', makehtml=False)
4539 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False)
4540 if self.options['delphes_path']:
4541 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False)
4542 self.print_results_in_shell(self.results.current)
4543
4544
4545
4547 """Remove one/all run or only part of it"""
4548
4549 args = self.split_arg(line)
4550 run, tag, mode = self.check_remove(args)
4551 if 'banner' in mode:
4552 mode.append('all')
4553
4554
4555 if run == 'all':
4556
4557 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')):
4558 logger.warning('A run with name all exists. So we will not supress all processes.')
4559 else:
4560 for match in misc.glob(pjoin('*','*_banner.txt'), pjoin(self.me_dir, 'Events')):
4561 run = match.rsplit(os.path.sep,2)[1]
4562 if self.force:
4563 args.append('-f')
4564 try:
4565 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) )
4566 except self.InvalidCmd, error:
4567 logger.info(error)
4568 pass
4569 return
4570
4571
4572 if not os.path.exists(pjoin(self.me_dir, 'Events', run)):
4573 raise self.InvalidCmd('No run \'%s\' detected' % run)
4574
4575 try:
4576 self.resuls.def_current(run)
4577 self.update_status(' Cleaning %s' % run, level=None)
4578 except Exception:
4579 misc.sprint('fail to update results or html status')
4580 pass
4581
4582
4583
4584
4585 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run))
4586 to_delete += misc.glob('*', pjoin(self.me_dir, 'HTML', run))
4587
4588 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f]
4589 if tag:
4590 to_delete = [f for f in to_delete if tag in f]
4591 if 'parton' in mode or 'all' in mode:
4592 try:
4593 if self.results[run][0]['tag'] != tag:
4594 raise Exception, 'dummy'
4595 except Exception:
4596 pass
4597 else:
4598 nb_rm = len(to_delete)
4599 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')):
4600 to_delete.append('events.lhe.gz')
4601 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')):
4602 to_delete.append('unweighted_events.lhe.gz')
4603 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')):
4604 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html'))
4605 if nb_rm != len(to_delete):
4606 logger.warning('Be carefull that partonic information are on the point to be removed.')
4607 if 'all' in mode:
4608 pass
4609 else:
4610 if 'pythia' not in mode:
4611 to_delete = [f for f in to_delete if 'pythia' not in f]
4612 if 'pgs' not in mode:
4613 to_delete = [f for f in to_delete if 'pgs' not in f]
4614 if 'delphes' not in mode:
4615 to_delete = [f for f in to_delete if 'delphes' not in f]
4616 if 'parton' not in mode:
4617 to_delete = [f for f in to_delete if 'delphes' in f
4618 or 'pgs' in f
4619 or 'pythia' in f]
4620 if not self.force and len(to_delete):
4621 question = 'Do you want to delete the following files?\n %s' % \
4622 '\n '.join(to_delete)
4623 ans = self.ask(question, 'y', choices=['y','n'])
4624 else:
4625 ans = 'y'
4626
4627 if ans == 'y':
4628 for file2rm in to_delete:
4629 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)):
4630 try:
4631 os.remove(pjoin(self.me_dir, 'Events', run, file2rm))
4632 except Exception:
4633 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm))
4634 else:
4635 try:
4636 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm))
4637 except Exception:
4638 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm))
4639
4640
4641
4642
4643 if 'all' in mode or 'channel' in mode:
4644 try:
4645 if tag and self.results[run][0]['tag'] != tag:
4646 raise Exception, 'dummy'
4647 except Exception:
4648 pass
4649 else:
4650 to_delete = misc.glob('%s*' % run, pjoin(self.me_dir, 'SubProcesses'))
4651 to_delete += misc.glob(pjoin('*','%s*' % run), pjoin(self.me_dir, 'SubProcesses'))
4652 to_delete += misc.glob(pjoin('*','*','%s*' % run), pjoin(self.me_dir, 'SubProcesses'))
4653
4654 if self.force or len(to_delete) == 0:
4655 ans = 'y'
4656 else:
4657 question = 'Do you want to delete the following files?\n %s' % \
4658 '\n '.join(to_delete)
4659 ans = self.ask(question, 'y', choices=['y','n'])
4660
4661 if ans == 'y':
4662 for file2rm in to_delete:
4663 os.remove(file2rm)
4664
4665 if 'banner' in mode:
4666 to_delete = misc.glob('*', pjoin(self.me_dir, 'Events', run))
4667 if tag:
4668
4669 try:
4670 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag)))
4671 except Exception:
4672 logger.warning('fail to remove the banner')
4673
4674 if run in self.results:
4675 self.results.delete_run(run, tag)
4676 return
4677 elif any(['banner' not in os.path.basename(p) for p in to_delete]):
4678 if to_delete:
4679 raise MadGraph5Error, '''Some output still exists for this run.
4680 Please remove those output first. Do for example:
4681 remove %s all banner
4682 ''' % run
4683 else:
4684 shutil.rmtree(pjoin(self.me_dir, 'Events',run))
4685 if run in self.results:
4686 self.results.delete_run(run)
4687 return
4688 else:
4689 logger.info('''The banner is not removed. In order to remove it run:
4690 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or ''))
4691
4692
4693 self.results.clean(mode, run, tag)
4694 self.update_status('', level='all')
4695
4696
4697
4698
4700 """Create the plot for a given run"""
4701
4702
4703 self.store_result()
4704 args = self.split_arg(line)
4705
4706 self.check_plot(args)
4707 logger.info('plot for run %s' % self.run_name)
4708 if not self.force:
4709 self.ask_edit_cards([], args, plot=True)
4710
4711 if any([arg in ['all','parton'] for arg in args]):
4712 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe')
4713 if os.path.exists(filename+'.gz'):
4714 misc.gunzip('%s.gz' % filename, keep=True)
4715 if os.path.exists(filename):
4716 files.ln(filename, pjoin(self.me_dir, 'Events'))
4717 self.create_plot('parton')
4718 if not os.path.exists(filename+'.gz'):
4719 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
4720 stdout= "%s.gz" % filename)
4721 else:
4722 try:
4723 os.remove(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
4724 os.remove(filename)
4725 except Exception:
4726 pass
4727 else:
4728 logger.info('No valid files for partonic plot')
4729
4730 if any([arg in ['all','pythia'] for arg in args]):
4731 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
4732 '%s_pythia_events.lhe' % self.run_tag)
4733 if os.path.exists(filename+'.gz'):
4734 misc.gunzip("%s.gz" % filename)
4735 if os.path.exists(filename):
4736 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe'))
4737 self.create_plot('Pythia')
4738 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'),
4739 stdout= "%s.gz" % filename)
4740 else:
4741 logger.info('No valid files for pythia plot')
4742
4743
4744 if any([arg in ['all','pgs'] for arg in args]):
4745 filename = pjoin(self.me_dir, 'Events', self.run_name,
4746 '%s_pgs_events.lhco' % self.run_tag)
4747 if os.path.exists(filename+'.gz'):
4748 misc.gunzip("%s.gz" % filename)
4749 if os.path.exists(filename):
4750 self.create_plot('PGS')
4751 misc.gzip(filename)
4752 else:
4753 logger.info('No valid files for pgs plot')
4754
4755 if any([arg in ['all','delphes'] for arg in args]):
4756 filename = pjoin(self.me_dir, 'Events', self.run_name,
4757 '%s_delphes_events.lhco' % self.run_tag)
4758 if os.path.exists(filename+'.gz'):
4759 misc.gunzip("%s.gz" % filename)
4760 if os.path.exists(filename):
4761 self.create_plot('Delphes')
4762 misc.gzip(filename)
4763 else:
4764 logger.info('No valid files for delphes plot')
4765
4766
4768 """Evaluate systematics variation weights for a given run"""
4769
4770
4771 self.store_result()
4772 args = self.split_arg(line)
4773
4774 self.check_syscalc(args)
4775 if self.ninitial == 1:
4776 logger.error('SysCalc can\'t be run for decay processes')
4777 return
4778
4779 logger.info('Calculating systematics for run %s' % self.run_name)
4780
4781 self.ask_edit_cards(['run_card'], args)
4782 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat'))
4783 if any([arg in ['all','parton'] for arg in args]):
4784 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe')
4785 if os.path.exists(filename+'.gz'):
4786 misc.gunzip("%s.gz" % filename)
4787 if os.path.exists(filename):
4788 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
4789 self.run_syscalc('parton')
4790 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
4791 stdout="%s.gz" % filename)
4792 else:
4793 logger.info('No valid files for parton level systematics run.')
4794
4795 if any([arg in ['all','pythia'] for arg in args]):
4796 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
4797 '%s_pythia_syst.dat' % self.run_tag)
4798 if os.path.exists(filename+'.gz'):
4799 misc.gunzip("%s.gz" % filename)
4800 if os.path.exists(filename):
4801 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat'))
4802 try:
4803 self.run_syscalc('Pythia')
4804 except SysCalcError, error:
4805 logger.warning(str(error))
4806 return
4807 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename)
4808 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
4809 '%s_syscalc.dat' % self.run_tag)
4810 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'),
4811 stdout=filename)
4812 else:
4813 logger.info('No valid files for pythia level')
4814
4815
4817 """ tar the pythia results. This is done when we are quite sure that
4818 the pythia output will not be use anymore """
4819
4820 if not self.run_name:
4821 return
4822
4823 self.results.save()
4824
4825
4826 if not self.to_store:
4827 return
4828
4829 tag = self.run_card['run_tag']
4830 self.update_status('storing files of previous run', level=None,\
4831 error=True)
4832 if 'event' in self.to_store:
4833 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')) and\
4834 os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe')):
4835 logger.info("gzipping output file: unweighted_events.lhe")
4836 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe"))
4837 if os.path.exists(pjoin(self.me_dir,'Events','reweight.lhe')):
4838 os.remove(pjoin(self.me_dir,'Events', 'reweight.lhe'))
4839
4840 if 'pythia' in self.to_store:
4841 self.update_status('Storing Pythia files of previous run', level='pythia', error=True)
4842
4843 p = pjoin(self.me_dir,'Events')
4844 n = self.run_name
4845 t = tag
4846 self.to_store.remove('pythia')
4847 misc.gzip(pjoin(p,'pythia_events.hep'),
4848 stdout=pjoin(p, str(n),'%s_pythia_events.hep' % t))
4849
4850 if 'pythia8' in self.to_store:
4851 p = pjoin(self.me_dir,'Events')
4852 n = self.run_name
4853 t = tag
4854 file_path = pjoin(p, n ,'%s_pythia8_events.hepmc'%t)
4855 self.to_store.remove('pythia8')
4856 if os.path.isfile(file_path):
4857 self.update_status('Storing Pythia8 files of previous run',
4858 level='pythia', error=True)
4859 misc.gzip(file_path,stdout=file_path)
4860
4861 self.update_status('Done', level='pythia',makehtml=False,error=True)
4862
4863 self.to_store = []
4864
4865 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0,
4866 run_type='', mode=None, **opt):
4867 """ """
4868 argument = [str(arg) for arg in argument]
4869 if mode is None:
4870 mode = self.cluster_mode
4871
4872
4873 if os.path.exists(exe) and not os.access(exe, os.X_OK):
4874 os.system('chmod +x %s ' % exe)
4875 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \
4876 os.access(pjoin(cwd, exe), os.X_OK):
4877 os.system('chmod +x %s ' % pjoin(cwd, exe))
4878
4879 if mode == 0:
4880 self.update_status((remaining, 1,
4881 self.total_jobs - remaining -1, run_type), level=None, force=False)
4882 start = time.time()
4883
4884 status = misc.call([exe] + argument, cwd=cwd, stdout=stdout, **opt)
4885 logger.info('%s run in %f s' % (exe, time.time() -start))
4886 if status:
4887 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe
4888
4889
4890 elif mode in [1,2]:
4891 exename = os.path.basename(exe)
4892
4893 if 'ajob' in exename:
4894 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat',
4895 pjoin(self.me_dir, 'SubProcesses','randinit')]
4896 if os.path.exists(pjoin(self.me_dir,'SubProcesses',
4897 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options):
4898 input_files.append(pjoin(self.me_dir,'SubProcesses', 'MadLoop5_resources.tar.gz'))
4899
4900 output_files = []
4901 required_output = []
4902
4903
4904
4905 input_files.append(self.get_pdf_input_filename())
4906
4907
4908 Gre = re.compile("\s*j=(G[\d\.\w]+)")
4909 origre = re.compile("grid_directory=(G[\d\.\w]+)")
4910 try :
4911 fsock = open(exe)
4912 except Exception:
4913 fsock = open(pjoin(cwd,exe))
4914 text = fsock.read()
4915 output_files = Gre.findall(text)
4916 if not output_files:
4917 Ire = re.compile("for i in ([\d\.\s]*) ; do")
4918 data = Ire.findall(text)
4919 data = ' '.join(data).split()
4920 for nb in data:
4921 output_files.append('G%s' % nb)
4922 required_output.append('G%s/results.dat' % nb)
4923 else:
4924 for G in output_files:
4925 if os.path.isdir(pjoin(cwd,G)):
4926 input_files.append(G)
4927 required_output.append('%s/results.dat' % G)
4928
4929 if origre.search(text):
4930 G_grid = origre.search(text).groups()[0]
4931 input_files.append(pjoin(G_grid, 'ftn26'))
4932
4933
4934 self.cluster.submit2(exe, stdout=stdout, cwd=cwd,
4935 input_files=input_files, output_files=output_files,
4936 required_output=required_output)
4937 elif 'survey' in exename:
4938 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat',
4939 pjoin(self.me_dir, 'SubProcesses','randinit')]
4940 if os.path.exists(pjoin(self.me_dir,'SubProcesses',
4941 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options):
4942 input_files.append(pjoin(self.me_dir,'SubProcesses',
4943 'MadLoop5_resources.tar.gz'))
4944
4945
4946 input_files.append(self.get_pdf_input_filename())
4947
4948
4949 output_files = []
4950 required_output = []
4951
4952
4953 suffix = "_%s" % int(float(argument[0]))
4954 if suffix == '_0':
4955 suffix = ''
4956 output_files = ['G%s%s' % (i, suffix) for i in argument[1:]]
4957 for G in output_files:
4958 required_output.append('%s/results.dat' % G)
4959
4960
4961 for G in output_files:
4962 if '.' in argument[0]:
4963 offset = int(str(argument[0]).split('.')[1])
4964 else:
4965 offset = 0
4966
4967 if offset ==0 or offset == int(float(argument[0])):
4968 if os.path.exists(pjoin(cwd, G, 'input_app.txt')):
4969 os.remove(pjoin(cwd, G, 'input_app.txt'))
4970
4971 if os.path.exists(os.path.realpath(pjoin(cwd, G, 'ftn25'))):
4972 if offset == 0 or offset == int(float(argument[0])):
4973 os.remove(pjoin(cwd, G, 'ftn25'))
4974 continue
4975 else:
4976 input_files.append(pjoin(cwd, G, 'ftn25'))
4977 input_files.remove('input_app.txt')
4978 input_files.append(pjoin(cwd, G, 'input_app.txt'))
4979 elif os.path.lexists(pjoin(cwd, G, 'ftn25')):
4980 try:
4981 os.remove(pjoin(cwd,G,'ftn25'))
4982 except:
4983 pass
4984
4985
4986 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument,
4987 input_files=input_files, output_files=output_files,
4988 required_output=required_output, **opt)
4989 elif "refine_splitted.sh" in exename:
4990 input_files = ['madevent','symfact.dat','iproc.dat',
4991 pjoin(self.me_dir, 'SubProcesses','randinit')]
4992
4993 if os.path.exists(pjoin(self.me_dir,'SubProcesses',
4994 'MadLoop5_resources.tar.gz')) and cluster.need_transfer(self.options):
4995 input_files.append(pjoin(self.me_dir,'SubProcesses',
4996 'MadLoop5_resources.tar.gz'))
4997
4998
4999 input_files.append(self.get_pdf_input_filename())
5000
5001
5002 output_files = [argument[0]]
5003 required_output = []
5004 for G in output_files:
5005 required_output.append('%s/results.dat' % G)
5006 input_files.append(pjoin(argument[1], "input_app.txt"))
5007 input_files.append(pjoin(argument[1], "ftn26"))
5008
5009
5010 self.cluster.cluster_submit(exe, stdout=stdout, cwd=cwd, argument=argument,
5011 input_files=input_files, output_files=output_files,
5012 required_output=required_output, **opt)
5013
5014
5015
5016 else:
5017 self.cluster.submit(exe, argument=argument, stdout=stdout, cwd=cwd, **opt)
5018
5019
5020
5022 """Find if Madevent is in Group mode or not"""
5023
5024
5025
5026 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc')
5027 text = open(file_path).read()
5028 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M):
5029 return 'group'
5030 else:
5031 return 'v4'
5032
5033
5034 - def monitor(self, run_type='monitor', mode=None, html=False):
5035 """ monitor the progress of running job """
5036
5037
5038 starttime = time.time()
5039 if mode is None:
5040 mode = self.cluster_mode
5041 if mode > 0:
5042 if html:
5043 update_status = lambda idle, run, finish: \
5044 self.update_status((idle, run, finish, run_type), level=None,
5045 force=False, starttime=starttime)
5046 update_first = lambda idle, run, finish: \
5047 self.update_status((idle, run, finish, run_type), level=None,
5048 force=True, starttime=starttime)
5049 else:
5050 update_status = lambda idle, run, finish: None
5051 update_first = None
5052 try:
5053 self.cluster.wait(self.me_dir, update_status, update_first=update_first)
5054 except Exception, error:
5055 logger.info(error)
5056 if not self.force:
5057 ans = self.ask('Cluster Error detected. Do you want to clean the queue? ("c"=continue the run anyway)',
5058 default = 'y', choices=['y','n', 'c'])
5059 else:
5060 ans = 'y'
5061 if ans == 'y':
5062 self.cluster.remove()
5063 elif ans == 'c':
5064 return self.monitor(run_type=run_type, mode=mode, html=html)
5065 raise
5066 except KeyboardInterrupt, error:
5067 self.cluster.remove()
5068 raise
5069
5070
5071
5072
5193
5194
5195
5196
5197 @staticmethod
5199 """check if the directory exists. if so return the path otherwise the
5200 default"""
5201
5202 if os.path.isdir(path):
5203 return path
5204 else:
5205 return default
5206
5207
5209 """get the list of Pdirectory if not yet saved."""
5210
5211 if hasattr(self, "Pdirs"):
5212 if self.me_dir in self.Pdirs[0]:
5213 return self.Pdirs
5214 self.Pdirs = [pjoin(self.me_dir, 'SubProcesses', l.strip())
5215 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))]
5216 return self.Pdirs
5217
5218
5220 """get the list of Gdirectory if not yet saved."""
5221
5222 if hasattr(self, "Gdirs"):
5223 if self.me_dir in self.Gdirs[0]:
5224 return self.Gdirs
5225
5226 Pdirs = self.get_Pdir()
5227 Gdirs = []
5228 for P in Pdirs:
5229 for line in open(pjoin(P, "symfact.dat")):
5230 tag, mfactor = line.split()
5231 Gdirs.append( (pjoin(P, "G%s" % tag), int(mfactor)) )
5232
5233
5234 self.Gdirs = Gdirs
5235 return self.Gdirs
5236
5237
5238 - def set_run_name(self, name, tag=None, level='parton', reload_card=False,
5239 allow_new_tag=True):
5240 """define the run name, the run_tag, the banner and the results."""
5241
5242 def get_last_tag(self, level):
5243
5244
5245 if level == 'parton':
5246 return
5247 elif level in ['pythia','pythia8','madanalysis5_parton','madanalysis5_hadron']:
5248 return self.results[self.run_name][0]['tag']
5249 else:
5250 for i in range(-1,-len(self.results[self.run_name])-1,-1):
5251 tagRun = self.results[self.run_name][i]
5252 if tagRun.pythia or tagRun.shower or tagRun.pythia8 :
5253 return tagRun['tag']
5254
5255
5256
5257 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes','madanalysis5_hadron','madanalysis5_parton'],
5258 'pythia': ['pythia','pgs','delphes','madanalysis5_hadron'],
5259 'pythia8': ['pythia8','pgs','delphes','madanalysis5_hadron'],
5260 'pgs': ['pgs'],
5261 'delphes':['delphes'],
5262 'madanalysis5_hadron':['madanalysis5_hadron'],
5263 'madanalysis5_parton':['madanalysis5_parton'],
5264 'plot':[],
5265 'syscalc':[]}
5266
5267 if name == self.run_name:
5268 if reload_card:
5269 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
5270 self.run_card = banner_mod.RunCard(run_card)
5271
5272
5273 if tag:
5274 self.run_card['run_tag'] = tag
5275 self.run_tag = tag
5276 self.results.add_run(self.run_name, self.run_card)
5277 else:
5278 for tag in upgrade_tag[level]:
5279 if getattr(self.results[self.run_name][-1], tag):
5280 tag = self.get_available_tag()
5281 self.run_card['run_tag'] = tag
5282 self.run_tag = tag
5283 self.results.add_run(self.run_name, self.run_card)
5284 break
5285 return get_last_tag(self, level)
5286
5287
5288
5289 if self.run_name:
5290 self.store_result()
5291
5292 self.run_name = name
5293
5294 new_tag = False
5295
5296 self.banner = banner_mod.recover_banner(self.results, level, name)
5297 if 'mgruncard' in self.banner:
5298 self.run_card = self.banner.charge_card('run_card')
5299 else:
5300
5301 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
5302 self.run_card = banner_mod.RunCard(run_card)
5303
5304 if tag:
5305 self.run_card['run_tag'] = tag
5306 new_tag = True
5307 elif not self.run_name in self.results and level =='parton':
5308 pass
5309 elif not self.run_name in self.results:
5310
5311 logger.warning('Trying to run data on unknown run.')
5312 self.results.add_run(name, self.run_card)
5313 self.results.update('add run %s' % name, 'all', makehtml=False)
5314 else:
5315 for tag in upgrade_tag[level]:
5316
5317 if getattr(self.results[self.run_name][-1], tag):
5318
5319 tag = self.get_available_tag()
5320 self.run_card['run_tag'] = tag
5321 new_tag = True
5322 break
5323 if not new_tag:
5324
5325 tag = self.results[self.run_name][-1]['tag']
5326 self.run_card['run_tag'] = tag
5327
5328 if allow_new_tag and (name in self.results and not new_tag):
5329 self.results.def_current(self.run_name)
5330 else:
5331 self.results.add_run(self.run_name, self.run_card)
5332
5333 self.run_tag = self.run_card['run_tag']
5334
5335 return get_last_tag(self, level)
5336
5337
5338
5340 """ return the model name """
5341 if hasattr(self, 'model_name'):
5342 return self.model_name
5343
5344 model = 'sm'
5345 proc = []
5346 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')):
5347 line = line.split('#')[0]
5348
5349 if line.startswith('import') and 'model' in line:
5350 model = line.split()[2]
5351 proc = []
5352 elif line.startswith('generate'):
5353 proc.append(line.split(None,1)[1])
5354 elif line.startswith('add process'):
5355 proc.append(line.split(None,2)[2])
5356
5357 self.model = model
5358 self.process = proc
5359 return model
5360
5361
5362
5364 """Find the number of event in the run_card, and check that this is not
5365 too large"""
5366
5367
5368 nb_event = int(self.run_card['nevents'])
5369 if nb_event > 1000000:
5370 logger.warning("Attempting to generate more than 1M events")
5371 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.")
5372 path = pjoin(self.me_dir, 'Cards', 'run_card.dat')
5373 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \
5374 % path)
5375 self.run_card['nevents'] = 1000000
5376
5377 return
5378
5379
5380
5382 """ change random number"""
5383
5384 self.random += 3
5385 if self.random > 30081*30081:
5386 raise MadGraph5Error,\
5387 'Random seed too large ' + str(self.random) + ' > 30081*30081'
5388
5389
5391 """save random number in appropirate file"""
5392
5393 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w')
5394 fsock.writelines('r=%s\n' % self.random)
5395
5396 - def do_quit(self, *args, **opts):
5400
5401
5403 """check for ckkw"""
5404
5405 lpp1 = self.run_card['lpp1']
5406 lpp2 = self.run_card['lpp2']
5407 e1 = self.run_card['ebeam1']
5408 e2 = self.run_card['ebeam2']
5409 pd = self.run_card['pdlabel']
5410 lha = self.run_card['lhaid']
5411 xq = self.run_card['xqcut']
5412 translation = {'e1': e1, 'e2':e2, 'pd':pd,
5413 'lha':lha, 'xq':xq}
5414
5415 if lpp1 or lpp2:
5416
5417 if pd.startswith("'"):
5418 pd = pd[1:]
5419 if pd.endswith("'"):
5420 pd = pd[:-1]
5421
5422 if xq >2 or xq ==2:
5423 xq = 2
5424
5425
5426 if pd == "lhapdf":
5427 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz'
5428 else:
5429 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz'
5430 if self.web:
5431 issudfile = pjoin(self.webbin, issudfile % translation)
5432 else:
5433 issudfile = pjoin(self.me_dir, issudfile % translation)
5434
5435 logger.info('Sudakov grid file: %s' % issudfile)
5436
5437
5438 if os.path.exists(issudfile):
5439 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat')
5440 misc.gunzip(issudfile, keep=True, stdout=path)
5441 else:
5442 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while'
5443 logger.info(msg)
5444 self.update_status('GENERATE SUDAKOV GRID', level='parton')
5445
5446 for i in range(-2,6):
5447 self.cluster.submit('%s/gensudgrid ' % self.dirbin,
5448 argument = ['%d'%i],
5449 cwd=self.me_dir,
5450 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i),'w'))
5451 self.monitor()
5452 for i in range(-2,6):
5453 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat')
5454 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path))
5455 misc.gzip(path, stdout=issudfile)
5456
5457
5458 - def create_root_file(self, input='unweighted_events.lhe',
5459 output='unweighted_events.root' ):
5460 """create the LHE root file """
5461 self.update_status('Creating root files', level='parton')
5462
5463 eradir = self.options['exrootanalysis_path']
5464 try:
5465 misc.call(['%s/ExRootLHEFConverter' % eradir,
5466 input, output],
5467 cwd=pjoin(self.me_dir, 'Events'))
5468 except Exception:
5469 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
5470
5471 - def run_syscalc(self, mode='parton', event_path=None, output=None):
5472 """create the syscalc output"""
5473
5474 if self.run_card['use_syst'] not in self.true:
5475 return
5476
5477 scdir = self.options['syscalc_path']
5478 if not scdir or not os.path.exists(scdir):
5479 return
5480
5481 if self.run_card['event_norm'] != 'sum':
5482 logger.critical('SysCalc works only when event_norm is on \'sum\'.')
5483 return
5484 logger.info('running SysCalc on mode %s' % mode)
5485
5486
5487 if self.run_card['sys_matchscale']=='auto':
5488 self.run_card['sys_matchscale'] = "30 50"
5489
5490
5491 lhaid = [self.run_card.get_lhapdf_id()]
5492 if '&&' in self.run_card['sys_pdf']:
5493 line = ' '.join(self.run_card['sys_pdf'])
5494 sys_pdf = line.split('&&')
5495 lhaid += [l.split()[0] for l in sys_pdf]
5496 else:
5497 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500]
5498 try:
5499 pdfsets_dir = self.get_lhapdf_pdfsetsdir()
5500 except Exception, error:
5501 logger.debug(str(error))
5502 logger.warning('Systematic computation requires lhapdf to run. Bypass SysCalc')
5503 return
5504
5505
5506 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid]
5507
5508 to_syscalc={'sys_scalefact': self.run_card['sys_scalefact'],
5509 'sys_alpsfact': self.run_card['sys_alpsfact'],
5510 'sys_matchscale': self.run_card['sys_matchscale'],
5511 'sys_scalecorrelation': self.run_card['sys_scalecorrelation'],
5512 'sys_pdf': self.run_card['sys_pdf']}
5513
5514 tag = self.run_card['run_tag']
5515 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat')
5516 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read()
5517
5518 if '&&' in to_syscalc['sys_pdf']:
5519 to_syscalc['sys_pdf'] = to_syscalc['sys_pdf'].split('#',1)[0].replace('&&',' \n ')
5520 else:
5521 data = to_syscalc['sys_pdf'].split()
5522 new = []
5523 for d in data:
5524 if not d.isdigit():
5525 new.append(d)
5526 elif int(d) > 500:
5527 new.append(d)
5528 else:
5529 new[-1] += ' %s' % d
5530 to_syscalc['sys_pdf'] = '\n'.join(new)
5531
5532 if to_syscalc['sys_pdf'].lower() in ['', 'f', 'false', 'none', '.false.']:
5533 to_syscalc['sys_pdf'] = ''
5534 if to_syscalc['sys_alpsfact'].lower() in ['', 'f', 'false', 'none','.false.']:
5535 to_syscalc['sys_alpsfact'] = ''
5536
5537
5538
5539
5540
5541 if not 'sys_scalecorrelation' in self.run_card:
5542 self.run_card['sys_scalecorrelation'] = -1
5543 open(card,'w').write(template % self.run_card)
5544
5545 if not os.path.exists(card):
5546 return False
5547
5548
5549
5550 event_dir = pjoin(self.me_dir, 'Events')
5551
5552 if not event_path:
5553 if mode == 'parton':
5554 event_path = pjoin(event_dir,self.run_name, 'unweighted_events.lhe')
5555 if not (os.path.exists(event_path) or os.path.exists(event_path+".gz")):
5556 event_path = pjoin(event_dir, 'unweighted_events.lhe')
5557 output = pjoin(event_dir, 'syscalc.lhe')
5558 stdout = open(pjoin(event_dir, self.run_name, '%s_systematics.log' % (mode)),'w')
5559 elif mode == 'Pythia':
5560 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w')
5561 if 'mgpythiacard' in self.banner:
5562 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I)
5563 data = pat.search(self.banner['mgpythiacard'])
5564 if data:
5565 qcut = float(data.group(1))
5566 xqcut = abs(self.run_card['xqcut'])
5567 for value in self.run_card['sys_matchscale'].split():
5568 if float(value) < qcut:
5569 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc'
5570 if float(value) < xqcut:
5571 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc'
5572
5573
5574 event_path = pjoin(event_dir,'syst.dat')
5575 output = pjoin(event_dir, 'syscalc.dat')
5576 else:
5577 raise self.InvalidCmd, 'Invalid mode %s' % mode
5578
5579 if not os.path.exists(event_path):
5580 if os.path.exists(event_path+'.gz'):
5581 misc.gunzip(event_path+'.gz')
5582 else:
5583 raise SysCalcError, 'Events file %s does not exits' % event_path
5584
5585 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower())
5586 try:
5587 proc = misc.call([os.path.join(scdir, 'sys_calc'),
5588 event_path, card, output],
5589 stdout = stdout,
5590 stderr = subprocess.STDOUT,
5591 cwd=event_dir)
5592
5593 time.sleep(5)
5594 except OSError, error:
5595 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error)
5596 else:
5597 if not os.path.exists(output):
5598 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?')
5599 elif mode == 'parton':
5600 files.mv(output, event_path)
5601
5602 self.update_status('End syscalc for %s level' % mode, level = mode.lower(),
5603 makehtml=False)
5604
5605 return True
5606
5607
5608
5609
5611 """Ask the question when launching generate_events/multi_run"""
5612
5613 available_mode = ['0']
5614 void = 'Not installed'
5615 switch_order = ['shower', 'detector', 'analysis', 'madspin', 'reweight']
5616
5617 switch = dict((k, void) for k in switch_order)
5618
5619 description = {'shower': 'Choose the shower/hadronization program:',
5620 'detector': 'Choose the detector simulation program:',
5621 'madspin': 'Decay particles with the MadSpin module:',
5622 'reweight':'Add weights to events for different model hypothesis:',
5623 'analysis':'Run an analysis package on the events generated:'
5624 }
5625
5626 force_switch = {('shower', 'OFF'): {'detector': 'OFF'},
5627 ('detector', 'PGS'): {'shower':'PYTHIA6'},
5628 ('detector', 'DELPHES'): {'shower': ['PYTHIA8', 'PYTHIA6']}}
5629
5630 switch_assign = lambda key, value: switch.__setitem__(key, value if value \
5631 in valid_options[key] else switch[key])
5632
5633 valid_options = dict((k, ['OFF']) for k in switch_order)
5634 options = ['auto', 'done']
5635 options_legacy = []
5636
5637
5638 if self.options['pythia-pgs_path']:
5639 available_mode.append('1')
5640 available_mode.append('2')
5641 valid_options['shower'].append('PYTHIA6')
5642 valid_options['detector'].append('PGS')
5643 options_legacy += ['pythia', 'pgs', 'pythia=ON', 'pythia=OFF', 'pgs=ON', 'pgs=OFF']
5644 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')):
5645 switch['shower'] = 'PYTHIA6'
5646 else:
5647 switch['shower'] = 'OFF'
5648 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')):
5649 switch['detector'] = 'PGS'
5650 else:
5651 switch['detector'] = 'OFF'
5652
5653 if self.options['pythia8_path']:
5654 available_mode.append('1')
5655 valid_options['shower'].append('PYTHIA8')
5656 if os.path.exists(pjoin(self.me_dir,'Cards','pythia8_card.dat')):
5657 switch['shower'] = 'PYTHIA8'
5658 elif switch['shower'] == void:
5659 switch['shower'] = 'OFF'
5660
5661
5662 if self.options['madanalysis_path']:
5663 if os.path.exists(pjoin(self.me_dir,'Cards','plot_card_default.dat')):
5664 valid_options['analysis'].insert(0,'MADANALYSIS_4')
5665
5666 if os.path.exists(pjoin(self.me_dir,'Cards','plot_card.dat')):
5667 switch['analysis'] = 'MADANALYSIS_4'
5668
5669
5670 if self.options['madanalysis5_path']:
5671 if os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat')) or \
5672 os.path.exists(pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')):
5673 valid_options['analysis'].append('MADANALYSIS_5')
5674
5675 parton_card_present = os.path.exists(pjoin(self.me_dir,'Cards',
5676 'madanalysis5_parton_card.dat'))
5677 hadron_card_present = os.path.exists(pjoin(self.me_dir,'Cards',
5678 'madanalysis5_hadron_card.dat'))
5679 if hadron_card_present or parton_card_present:
5680 switch['analysis'] = 'MADANALYSIS_5'
5681
5682 if len(valid_options['analysis'])>1:
5683 available_mode.append('5')
5684 if switch['analysis'] == void:
5685 switch['analysis'] = 'OFF'
5686 else:
5687 switch['analysis'] = 'No analysis tool interfaced to MG5aMC.'
5688
5689
5690 if self.options['delphes_path']:
5691 if valid_options['shower'] != ['OFF']:
5692 available_mode.append('2')
5693 valid_options['detector'].append('DELPHES')
5694 options += ['delphes', 'delphes=ON', 'delphes=OFF']
5695 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')):
5696 switch['detector'] = 'DELPHES'
5697 else:
5698 switch['detector'] = 'OFF'
5699 elif valid_options['detector'] == ['OFF']:
5700 switch['detector'] = "Requires a shower"
5701
5702
5703 if not MADEVENT or ('mg5_path' in self.options and self.options['mg5_path']):
5704 available_mode.append('3')
5705 valid_options['madspin'] = ['ON', 'OFF']
5706 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')):
5707 switch['madspin'] = 'ON'
5708 else:
5709 switch['madspin'] = 'OFF'
5710 if misc.has_f2py() or self.options['f2py_compiler']:
5711 available_mode.append('4')
5712 valid_options['reweight'] = ['ON', 'OFF']
5713 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')):
5714 switch['reweight'] = 'ON'
5715 else:
5716 switch['reweight'] = 'OFF'
5717 else:
5718 switch['reweight'] = 'Not available (requires NumPy)'
5719
5720 if '-R' in args or '--reweight' in args:
5721 if switch['reweight'] == 'OFF':
5722 switch['reweight'] = 'ON'
5723 elif switch['reweight'] != 'ON':
5724 logger.critical("Cannot run reweight: %s", switch['reweight'])
5725 if '-M' in args or '--madspin' in args:
5726 if switch['madspin'] == 'OFF':
5727 switch['madspin'] = 'ON'
5728 elif switch['madspin'] != 'ON':
5729 logger.critical("Cannot run madspin: %s", switch['reweight'])
5730
5731 for id, key in enumerate(switch_order):
5732 if len(valid_options[key]) >1:
5733 options += ['%s=%s' % (key, s) for s in valid_options[key]]
5734 options.append(key)
5735
5736 options += ['parton'] + sorted(list(set(available_mode)))
5737 options += options_legacy
5738
5739
5740
5741 def color(switch_value):
5742 green = '\x1b[32m%s\x1b[0m'
5743 bold = '\x1b[33m%s\x1b[0m'
5744 red = '\x1b[31m%s\x1b[0m'
5745 if switch_value in ['OFF',void,'Requires a shower',
5746 'Not available (requires NumPy)',
5747 'Not available yet for this output/process']:
5748 return red%switch_value
5749 elif switch_value in ['ON','MADANALYSIS_4','MADANALYSIS_5',
5750 'PYTHIA8','PYTHIA6','PGS','DELPHES-ATLAS',
5751 'DELPHES-CMS','DELPHES']:
5752 return green%switch_value
5753 else:
5754 return bold%switch_value
5755
5756 if mode or not self.force:
5757 answer = ''
5758 while answer not in ['0', 'done', 'auto']:
5759 if mode:
5760 answer = mode
5761 else:
5762 switch_format = " \x1b[31m%i\x1b[0m. %-60s %12s = %s"
5763 question = "The following switches determine which programs are run:\n"
5764 question += '/'+'-'*98+'\\\n'
5765 for id, key in enumerate(switch_order):
5766 question += '| %-115s|\n'%(switch_format%(id+1, description[key], key, color(switch[key])))
5767 question += '\\'+'-'*98+'/\n'
5768 question += ' Either type the switch number (1 to %s) to change its setting,\n' % (id+1)
5769 question += ' Set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n'
5770 question += ' Type \'help\' for the list of all valid option\n'
5771 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n'
5772 answer = self.ask(question, '0', options, casesensitive=False)
5773 if (answer.isdigit() and answer != '0') or answer in ['shower', 'detector']:
5774 if answer.isdigit():
5775 key = switch_order[int(answer) - 1]
5776 else:
5777 key = answer
5778 for i, opt in enumerate(valid_options[key]):
5779 if opt == switch[key]:
5780 break
5781 i +=1
5782 if i == len(valid_options[key]):
5783 i=0
5784 answer = '%s=%s' % (key, valid_options[key][i])
5785
5786 if '=' in answer:
5787 key, status = answer.split('=')
5788 key, status = key.lower().strip(), status.upper().strip()
5789
5790 if key not in switch:
5791
5792 logger.warning("Using old syntax. Please check that we run what you expect.")
5793 if key == "pythia" and status == "ON":
5794 key, status = "shower", "PYTHIA6"
5795 elif key == "pythia" and status == "OFF":
5796 key, status = "shower", "OFF"
5797 elif key == "pgs" and status == "ON":
5798 if switch["detector"] in ["OFF", "PGS"] :
5799 key, status = "detector", "PGS"
5800 else:
5801 key, status = "detector", "DELPHES+PGS"
5802 elif key == "delphes" and status == "ON":
5803 if switch["detector"] in ["OFF", "DELPHES"] :
5804 key, status = "detector", "DELPHES"
5805 else:
5806 key, status = "detector", "DELPHES+PGS"
5807 elif key == "pgs" and status == "OFF":
5808 if switch["detector"] in ["OFF", "PGS"] :
5809 key, status = "detector", "OFF"
5810 elif switch["detector"] == "DELPHES+PGS":
5811 key, status = "detector", "DELPHES"
5812 else:
5813 key, status = "detector", switch['detector']
5814 elif key == "delphes" and status == "OFF":
5815 if switch["detector"] in ["OFF", "DELPHES"] :
5816 key, status = "detector", "OFF"
5817 elif switch["detector"] == "DELPHES+PGS":
5818 key, status = "detector", "PGS"
5819 else:
5820 key, status = "detector", switch['detector']
5821
5822
5823 switch[key] = status
5824 if (key, status) in force_switch:
5825 for key2, status2 in force_switch[(key, status)].items():
5826 if isinstance(status2, str):
5827 if switch[key2] not in [status2, void]:
5828 logger.info('For coherence \'%s\' is set to \'%s\''
5829 % (key2, status2), '$MG:color:BLACK')
5830 switch[key2] = status2
5831 else:
5832 if switch[key2] not in status2 + [void]:
5833 logger.info('For coherence \'%s\' is set to \'%s\''
5834 % (key2, status2[0]), '$MG:color:BLACK')
5835 switch[key2] = status2[0]
5836 elif answer in ['0', 'auto', 'done']:
5837 continue
5838 elif answer in ['parton', 'pythia','pgs','madspin','reweight', 'delphes']:
5839 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK')
5840 switch_assign('madspin', 'OFF')
5841 switch_assign('reweight', 'OFF')
5842 if answer == 'parton':
5843 switch_assign('shower', 'OFF')
5844 switch_assign('detector', 'OFF')
5845 elif answer == 'pythia':
5846 switch_assign('shower', 'PYTHIA6')
5847 switch_assign('detector', 'OFF')
5848 elif answer == 'pgs':
5849 switch_assign('shower', 'PYTHIA6')
5850 switch_assign('detector', 'PGS')
5851 elif answer == 'delphes':
5852 switch_assign('shower', 'PYTHIA6')
5853 if switch['shower'] == 'OFF':
5854 switch_assign('shower', 'PYTHIA8')
5855 switch_assign('detector', 'DELPHES')
5856 elif answer == 'madspin':
5857 switch_assign('madspin', 'ON')
5858 switch_assign('shower', 'OFF')
5859 switch_assign('detector', 'OFF')
5860 elif answer == 'reweight':
5861 switch_assign('reweight', 'ON')
5862 switch_assign('shower', 'OFF')
5863 switch_assign('detector', 'OFF')
5864
5865 if mode:
5866 answer = '0'
5867 else:
5868 answer = 'auto'
5869
5870
5871
5872
5873 cards = ['param_card.dat', 'run_card.dat']
5874 if switch['shower'] in ['PY6', 'PYTHIA6']:
5875 cards.append('pythia_card.dat')
5876 if switch['shower'] in ['PY8', 'PYTHIA8']:
5877 cards.append('pythia8_card.dat')
5878 if switch['detector'] in ['PGS','DELPHES+PGS']:
5879 cards.append('pgs_card.dat')
5880 if switch['detector'] in ['DELPHES', 'DELPHES+PGS']:
5881 cards.append('delphes_card.dat')
5882 delphes3 = True
5883 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
5884 delphes3 = False
5885 cards.append('delphes_trigger.dat')
5886 if switch['madspin'] == 'ON':
5887 cards.append('madspin_card.dat')
5888 if switch['reweight'] == 'ON':
5889 cards.append('reweight_card.dat')
5890 if switch['analysis'] in ['MADANALYSIS_5']:
5891 cards.append('madanalysis5_parton_card.dat')
5892 if switch['analysis'] in ['MADANALYSIS_5'] and not switch['shower']=='OFF':
5893 cards.append('madanalysis5_hadron_card.dat')
5894 if switch['analysis'] in ['MADANALYSIS_4']:
5895 cards.append('plot_card.dat')
5896
5897 self.keep_cards(cards)
5898
5899 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')):
5900 cards.append('MadLoopParams.dat')
5901
5902 if self.force:
5903 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' ))
5904 return
5905
5906 if answer == 'auto':
5907 self.ask_edit_cards(cards, plot=False, mode='auto')
5908 else:
5909 self.ask_edit_cards(cards, plot=False)
5910 return
5911
5912
5914 """Ask the question when launching pythia"""
5915
5916 pythia_suffix = '' if pythia_version==6 else '%d'%pythia_version
5917
5918 available_mode = ['0', '1']
5919 if pythia_version==6:
5920 available_mode.append('2')
5921 if self.options['delphes_path']:
5922 available_mode.append('3')
5923 name = {'0': 'auto', '2':'pgs', '3':'delphes'}
5924 name['1'] = 'pythia%s'%pythia_suffix
5925 options = available_mode + [name[val] for val in available_mode]
5926 question = """Which programs do you want to run?
5927 0 / auto : running existing cards\n"""
5928 if pythia_version==6:
5929 question += """ 1. pythia : Pythia\n"""
5930 question += """ 2. pgs : Pythia + PGS\n"""
5931 else:
5932 question += """ 1. pythia8 : Pythia8\n"""
5933
5934 if '3' in available_mode:
5935 question += """ 3. delphes : Pythia%s + Delphes.\n"""%pythia_suffix
5936
5937 if not self.force:
5938 if not mode:
5939 mode = self.ask(question, '0', options)
5940 elif not mode:
5941 mode = 'auto'
5942
5943 if mode.isdigit():
5944 mode = name[mode]
5945
5946 auto = False
5947 if mode == 'auto':
5948 auto = True
5949 if pythia_version==6 and os.path.exists(pjoin(self.me_dir,
5950 'Cards', 'pgs_card.dat')):
5951 mode = 'pgs'
5952 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
5953 mode = 'delphes'
5954 else:
5955 mode = 'pythia%s'%pythia_suffix
5956 logger.info('Will run in mode %s' % mode)
5957
5958
5959 cards = ['pythia%s_card.dat'%pythia_suffix]
5960 if mode == 'pgs' and pythia_version==6:
5961 cards.append('pgs_card.dat')
5962 if mode == 'delphes':
5963 cards.append('delphes_card.dat')
5964 delphes3 = True
5965 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
5966 delphes3 = False
5967 cards.append('delphes_trigger.dat')
5968 self.keep_cards(cards, ignore=['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat',
5969 'plot_card.dat'])
5970
5971 if self.force:
5972 return mode
5973
5974 if auto:
5975 self.ask_edit_cards(cards, mode='auto', plot=(pythia_version==6))
5976 else:
5977 self.ask_edit_cards(cards, plot=(pythia_version==6))
5978
5979 return mode
5980
5985 """The command line processor of MadGraph"""
5986
5993
5994 name_to_pdg = {}
5995
5996 @classmethod
5999
6000 @staticmethod
6002 """return the list of Subprocesses"""
6003
6004 out = []
6005 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')):
6006 if not line:
6007 continue
6008 name = line.strip()
6009 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)):
6010 out.append(pjoin(me_dir, 'SubProcesses', name))
6011
6012 return out
6013
6014
6015
6016 @staticmethod
6018 """ return the list of processes with their name"""
6019
6020 nb_sub = 0
6021 names = {}
6022 old_main = ''
6023
6024 if not os.path.exists(os.path.join(path,'processes.dat')):
6025 return SubProcesses.get_subP_info_v4(path)
6026
6027 for line in open(os.path.join(path,'processes.dat')):
6028 main = line[:8].strip()
6029 if main == 'mirror':
6030 main = old_main
6031 if line[8:].strip() == 'none':
6032 continue
6033 else:
6034 main = int(main)
6035 old_main = main
6036
6037 sub_proccess = line[8:]
6038 nb_sub += sub_proccess.count(',') + 1
6039 if main in names:
6040 names[main] += [sub_proccess.split(',')]
6041 else:
6042 names[main]= [sub_proccess.split(',')]
6043
6044 return names
6045
6046 @staticmethod
6048 """ return the list of processes with their name in case without grouping """
6049
6050 nb_sub = 0
6051 names = {'':[[]]}
6052 path = os.path.join(path, 'auto_dsig.f')
6053 found = 0
6054 for line in open(path):
6055 if line.startswith('C Process:'):
6056 found += 1
6057 names[''][0].append(line[15:])
6058 elif found >1:
6059 break
6060 return names
6061
6062
6063 @staticmethod
6065 """return the pdg codes of the particles present in the Subprocesses"""
6066
6067 all_ids = []
6068 for line in open(pjoin(path, 'leshouche.inc')):
6069 if not 'IDUP' in line:
6070 continue
6071 particles = re.search("/([\d,-]+)/", line)
6072 all_ids.append([int(p) for p in particles.group(1).split(',')])
6073 return all_ids
6074
6078 """The command for the gridpack --Those are not suppose to be use interactively--"""
6079
6080 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
6081 """Initialize the command and directly run"""
6082
6083
6084
6085 MadEventCmd.__init__(self, me_dir, *completekey, **stdin)
6086 self.run_mode = 0
6087 self.random = seed
6088 self.random_orig = self.random
6089 self.options['automatic_html_opening'] = False
6090
6091 if me_dir and nb_event and seed:
6092 self.launch(nb_event, seed)
6093 else:
6094 raise MadGraph5Error,\
6095 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \
6096 str(seed)
6097
6098 - def launch(self, nb_event, seed):
6121
6123 """Special refine for gridpack run."""
6124 self.nb_refine += 1
6125
6126 precision = nb_event
6127
6128
6129
6130 self.cluster_mode = 0
6131
6132
6133 self.save_random()
6134
6135 self.update_status('Refine results to %s' % precision, level=None)
6136 logger.info("Using random number seed offset = %s" % self.random)
6137
6138 self.total_jobs = 0
6139 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if
6140 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))]
6141 devnull = open(os.devnull, 'w')
6142 for nb_proc,subdir in enumerate(subproc):
6143 subdir = subdir.strip()
6144 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
6145 bindir = pjoin(os.path.relpath(self.dirbin, Pdir))
6146
6147 logger.info(' %s ' % subdir)
6148
6149 for match in misc.glob('*ajob*', Pdir):
6150 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
6151 os.remove(pjoin(Pdir, match))
6152
6153
6154 logfile = pjoin(Pdir, 'gen_ximprove.log')
6155 misc.call([pjoin(bindir, 'gen_ximprove')],
6156 stdin=subprocess.PIPE,
6157 stdout=open(logfile,'w'),
6158 cwd=Pdir)
6159
6160 if os.path.exists(pjoin(Pdir, 'ajob1')):
6161 alljobs = misc.glob('ajob*', Pdir)
6162 nb_tot = len(alljobs)
6163 self.total_jobs += nb_tot
6164 for i, job in enumerate(alljobs):
6165 job = os.path.basename(job)
6166 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1),
6167 run_type='Refine number %s on %s (%s/%s)' %
6168 (self.nb_refine, subdir, nb_proc+1, len(subproc)))
6169 if os.path.exists(pjoin(self.me_dir,'error')):
6170 self.monitor(html=True)
6171 raise MadEventError, \
6172 'Error detected in dir %s: %s' % \
6173 (Pdir, open(pjoin(self.me_dir,'error')).read())
6174 self.monitor(run_type='All job submitted for refine number %s' %
6175 self.nb_refine)
6176
6177 self.update_status("Combining runs", level='parton')
6178 try:
6179 os.remove(pjoin(Pdir, 'combine_runs.log'))
6180 except Exception:
6181 pass
6182
6183 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses')))
6184 combine_runs.CombineRuns(self.me_dir)
6185
6186
6187 cross, error = sum_html.make_all_html_results(self)
6188 self.results.add_detail('cross', cross)
6189 self.results.add_detail('error', error)
6190
6191
6192 self.update_status('finish refine', 'parton', makehtml=False)
6193 devnull.close()
6194
6197 """ A container class for the various methods for initializing MadLoop. It is
6198 placed in MadEventInterface because it is used by Madevent for loop-induced
6199 simulations. """
6200
6201 @staticmethod
6203 """ Compile the check program in the directory dir_name.
6204 Return the compilation and running time. """
6205
6206
6207
6208 if os.path.isfile(pjoin(dir_name,'check')):
6209 os.remove(pjoin(dir_name,'check'))
6210 os.remove(pjoin(dir_name,'check_sa.o'))
6211 os.remove(pjoin(dir_name,'loop_matrix.o'))
6212
6213 devnull = open(os.devnull, 'w')
6214 start=time.time()
6215 retcode = subprocess.call(['make','check'],
6216 cwd=dir_name, stdout=devnull, stderr=devnull)
6217 compilation_time = time.time()-start
6218 if retcode != 0:
6219 logging.info("Error while executing make in %s" % dir_name)
6220 return None, None, None
6221
6222 if not checkRam:
6223 start=time.time()
6224 retcode = subprocess.call('./check',
6225 cwd=dir_name, stdout=devnull, stderr=devnull)
6226
6227 run_time = time.time()-start
6228 ram_usage = None
6229 else:
6230 ptimer = misc.ProcessTimer(['./check'], cwd=dir_name, shell=False, \
6231 stdout=devnull, stderr=devnull, close_fds=True)
6232 try:
6233 ptimer.execute()
6234
6235
6236
6237 while ptimer.poll():
6238 time.sleep(.2)
6239 finally:
6240
6241 ptimer.close()
6242
6243 ram_usage = ptimer.max_rss_memory
6244
6245
6246 run_time = (ptimer.t1 - ptimer.t0)
6247 retcode = ptimer.p.returncode
6248
6249 devnull.close()
6250
6251 if retcode != 0:
6252 logging.warning("Error while executing ./check in %s" % dir_name)
6253 return None, None, None
6254
6255 return compilation_time, run_time, ram_usage
6256
6257 @staticmethod
6258 - def fix_PSPoint_in_check(dir_path, read_ps = True, npoints = 1,
6259 hel_config = -1, mu_r=0.0, split_orders=-1):
6260 """Set check_sa.f to be reading PS.input assuming a working dir dir_name.
6261 if hel_config is different than -1 then check_sa.f is configured so to
6262 evaluate only the specified helicity.
6263 If mu_r > 0.0, then the renormalization constant value will be hardcoded
6264 directly in check_sa.f, if is is 0 it will be set to Sqrt(s) and if it
6265 is < 0.0 the value in the param_card.dat is used.
6266 If the split_orders target (i.e. the target squared coupling orders for
6267 the computation) is != -1, it will be changed in check_sa.f via the
6268 subroutine CALL SET_COUPLINGORDERS_TARGET(split_orders)."""
6269
6270 file_path = dir_path
6271 if not os.path.isfile(dir_path) or \
6272 not os.path.basename(dir_path)=='check_sa.f':
6273 file_path = pjoin(dir_path,'check_sa.f')
6274 if not os.path.isfile(file_path):
6275 directories = [d for d in misc.glob('P*_*', dir_path) \
6276 if (re.search(r'.*P\d+_\w*$', d) and os.path.isdir(d))]
6277 if len(directories)>0:
6278 file_path = pjoin(directories[0],'check_sa.f')
6279 if not os.path.isfile(file_path):
6280 raise MadGraph5Error('Could not find the location of check_sa.f'+\
6281 ' from the specified path %s.'%str(file_path))
6282
6283 file = open(file_path, 'r')
6284 check_sa = file.read()
6285 file.close()
6286
6287 file = open(file_path, 'w')
6288 check_sa = re.sub(r"READPS = \S+\)","READPS = %s)"%('.TRUE.' if read_ps \
6289 else '.FALSE.'), check_sa)
6290 check_sa = re.sub(r"NPSPOINTS = \d+","NPSPOINTS = %d"%npoints, check_sa)
6291 if hel_config != -1:
6292 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,",
6293 "SLOOPMATRIXHEL_THRES(P,%d,MATELEM,"%hel_config, check_sa)
6294 else:
6295 check_sa = re.sub(r"SLOOPMATRIX\S+\(\S+,MATELEM,",
6296 "SLOOPMATRIX_THRES(P,MATELEM,",check_sa)
6297 if mu_r > 0.0:
6298 check_sa = re.sub(r"MU_R=SQRTS","MU_R=%s"%\
6299 (("%.17e"%mu_r).replace('e','d')),check_sa)
6300 elif mu_r < 0.0:
6301 check_sa = re.sub(r"MU_R=SQRTS","",check_sa)
6302
6303 if split_orders > 0:
6304 check_sa = re.sub(r"SET_COUPLINGORDERS_TARGET\(-?\d+\)",
6305 "SET_COUPLINGORDERS_TARGET(%d)"%split_orders,check_sa)
6306
6307 file.write(check_sa)
6308 file.close()
6309
6310 @staticmethod
6311 - def run_initialization(run_dir=None, SubProc_dir=None, infos=None,\
6312 req_files = ['HelFilter.dat','LoopFilter.dat'],
6313 attempts = [4,15]):
6314 """ Run the initialization of the process in 'run_dir' with success
6315 characterized by the creation of the files req_files in this directory.
6316 The directory containing the driving source code 'check_sa.f'.
6317 The list attempt gives the successive number of PS points the
6318 initialization should be tried with before calling it failed.
6319 Returns the number of PS points which were necessary for the init.
6320 Notice at least run_dir or SubProc_dir must be provided.
6321 A negative attempt number given in input means that quadprec will be
6322 forced for initialization."""
6323
6324
6325
6326 if infos is None:
6327 infos={}
6328
6329 if SubProc_dir is None and run_dir is None:
6330 raise MadGraph5Error, 'At least one of [SubProc_dir,run_dir] must'+\
6331 ' be provided in run_initialization.'
6332
6333
6334
6335 if SubProc_dir is None:
6336 SubProc_dir = os.path.abspath(pjoin(run_dir,os.pardir))
6337
6338 if run_dir is None:
6339 directories =[ dir for dir in misc.glob('P[0-9]*', SubProc_dir)
6340 if os.path.isdir(dir) ]
6341 if directories:
6342 run_dir = directories[0]
6343 else:
6344 raise MadGraph5Error, 'Could not find a valid running directory'+\
6345 ' in %s.'%str(SubProc_dir)
6346
6347
6348
6349
6350
6351 if not os.path.isfile(pjoin(run_dir,'born_matrix.f')):
6352 if len(attempts)>=1 and attempts[0]<8:
6353 attempts[0]=8
6354 if len(attempts)>=2 and attempts[1]<25:
6355 attempts[1]=25
6356
6357 to_attempt = list(attempts)
6358 to_attempt.reverse()
6359 my_req_files = list(req_files)
6360
6361 MLCardPath = pjoin(SubProc_dir,'MadLoopParams.dat')
6362 if not os.path.isfile(MLCardPath):
6363 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\
6364 %MLCardPath
6365 else:
6366 MLCard = banner_mod.MadLoopParam(MLCardPath)
6367 MLCard_orig = banner_mod.MadLoopParam(MLCard)
6368
6369
6370 if not MLCard['UseLoopFilter']:
6371 try:
6372 my_req_files.remove('LoopFilter.dat')
6373 except ValueError:
6374 pass
6375
6376 if MLCard['HelicityFilterLevel']==0:
6377 try:
6378 my_req_files.remove('HelFilter.dat')
6379 except ValueError:
6380 pass
6381
6382 def need_init():
6383 """ True if init not done yet."""
6384 proc_prefix_file = open(pjoin(run_dir,'proc_prefix.txt'),'r')
6385 proc_prefix = proc_prefix_file.read()
6386 proc_prefix_file.close()
6387 return any([not os.path.exists(pjoin(run_dir,'MadLoop5_resources',
6388 proc_prefix+fname)) for fname in my_req_files]) or \
6389 not os.path.isfile(pjoin(run_dir,'check')) or \
6390 not os.access(pjoin(run_dir,'check'), os.X_OK)
6391
6392
6393
6394 is_loop_induced = os.path.exists(pjoin(run_dir,'born_matrix.f'))
6395
6396
6397
6398
6399 if not any(attempt<0 for attempt in to_attempt):
6400 to_attempt = [-attempt for attempt in to_attempt] + to_attempt
6401 use_quad_prec = 1
6402 curr_attempt = 1
6403
6404 MLCard.set('WriteOutFilters',True)
6405
6406 while to_attempt!=[] and need_init():
6407 curr_attempt = to_attempt.pop()
6408
6409
6410 if curr_attempt < 0:
6411 use_quad_prec = -1
6412
6413 MLCard.set('CTModeInit',4)
6414 MLCard.set('ZeroThres',1e-11)
6415 else:
6416
6417 MLCard.set('CTModeInit',1)
6418 MLCard.set('ZeroThres',1e-9)
6419
6420 curr_attempt = abs(curr_attempt+1)
6421 MLCard.set('MaxAttempts',curr_attempt)
6422 MLCard.write(pjoin(SubProc_dir,'MadLoopParams.dat'))
6423
6424
6425 MadLoopInitializer.fix_PSPoint_in_check(run_dir, read_ps = False,
6426 npoints = curr_attempt)
6427 compile_time, run_time, ram_usage = \
6428 MadLoopInitializer.make_and_run(run_dir)
6429 if compile_time==None:
6430 logging.error("Failed at running the process in %s."%run_dir)
6431 attempts = None
6432 return None
6433
6434 if 'Process_compilation' not in infos.keys() or \
6435 infos['Process_compilation']==None:
6436 infos['Process_compilation'] = compile_time
6437 infos['Initialization'] = run_time
6438
6439 MLCard_orig.write(pjoin(SubProc_dir,'MadLoopParams.dat'))
6440 if need_init():
6441 return None
6442 else:
6443 return use_quad_prec*(curr_attempt-1)
6444
6445 @staticmethod
6447 """Checks whether the necessary filters are present or not."""
6448
6449 def need_init(ML_resources_path, proc_prefix, r_files):
6450 """ Returns true if not all required files are present. """
6451 return any([not os.path.exists(pjoin(ML_resources_path,
6452 proc_prefix+fname)) for fname in r_files])
6453
6454 MLCardPath = pjoin(proc_dir,'SubProcesses','MadLoopParams.dat')
6455 if not os.path.isfile(MLCardPath):
6456 raise MadGraph5Error, 'Could not find MadLoopParams.dat at %s.'\
6457 %MLCardPath
6458 MLCard = banner_mod.MadLoopParam(MLCardPath)
6459
6460 req_files = ['HelFilter.dat','LoopFilter.dat']
6461
6462 if not MLCard['UseLoopFilter']:
6463 try:
6464 req_files.remove('LoopFilter.dat')
6465 except ValueError:
6466 pass
6467 if MLCard['HelicityFilterLevel']==0:
6468 try:
6469 req_files.remove('HelFilter.dat')
6470 except ValueError:
6471 pass
6472
6473 for v_folder in glob.iglob(pjoin(proc_dir,'SubProcesses',
6474 '%s*'%subproc_prefix)):
6475
6476 if not os.path.isdir(v_folder) or not os.path.isfile(\
6477 pjoin(v_folder,'loop_matrix.f')):
6478 continue
6479 proc_prefix_file = open(pjoin(v_folder,'proc_prefix.txt'),'r')
6480 proc_prefix = proc_prefix_file.read()
6481 proc_prefix_file.close()
6482 if need_init(pjoin(proc_dir,'SubProcesses','MadLoop5_resources'),
6483 proc_prefix, req_files):
6484 return True
6485
6486 return False
6487
6488 @staticmethod
6489 - def init_MadLoop(proc_dir, n_PS=None, subproc_prefix='PV', MG_options=None,
6490 interface = None):
6491 """Advanced commands: Compiles and run MadLoop on RAMBO random PS points to initilize the
6492 filters."""
6493
6494 logger.debug('Compiling Source materials necessary for MadLoop '+
6495 'initialization.')
6496
6497
6498
6499 if interface is None:
6500 misc.compile(arg=['treatCardsLoopNoInit'], cwd=pjoin(proc_dir,'Source'))
6501 else:
6502 interface.do_treatcards('all --no_MadLoopInit')
6503
6504
6505 if os.path.exists(pjoin(proc_dir,'Source','CutTools')):
6506 misc.compile(arg=['libcuttools'],cwd=pjoin(proc_dir,'Source'))
6507 if os.path.exists(pjoin(proc_dir,'Source','IREGI')):
6508 misc.compile(arg=['libiregi'],cwd=pjoin(proc_dir,'Source'))
6509
6510 misc.compile(arg=['libmodel'],cwd=pjoin(proc_dir,'Source'))
6511 misc.compile(arg=['libdhelas'],cwd=pjoin(proc_dir,'Source'))
6512
6513
6514 logger.info('Initializing MadLoop loop-induced matrix elements '+\
6515 '(this can take some time)...')
6516
6517
6518 if MG_options:
6519 mcore = cluster.MultiCore(**MG_options)
6520 else:
6521 mcore = cluster.onecore
6522 def run_initialization_wrapper(run_dir, infos, attempts):
6523 if attempts is None:
6524 n_PS = MadLoopInitializer.run_initialization(
6525 run_dir=run_dir, infos=infos)
6526 else:
6527 n_PS = MadLoopInitializer.run_initialization(
6528 run_dir=run_dir, infos=infos, attempts=attempts)
6529 infos['nPS'] = n_PS
6530 return 0
6531
6532 def wait_monitoring(Idle, Running, Done):
6533 if Idle+Running+Done == 0:
6534 return
6535 logger.debug('MadLoop initialization jobs: %d Idle, %d Running, %d Done'\
6536 %(Idle, Running, Done))
6537
6538 init_info = {}
6539
6540 VirtualFolders = [f for f in glob.iglob(pjoin(proc_dir,'SubProcesses',
6541 '%s*'%subproc_prefix)) if (os.path.isdir(f) or
6542 os.path.isfile(pjoin(f,'loop_matrix.f')))]
6543 logger.debug("Now Initializing MadLoop matrix element in %d folder%s:"%\
6544 (len(VirtualFolders),'s' if len(VirtualFolders)>1 else ''))
6545 logger.debug(', '.join("'%s'"%os.path.basename(v_folder) for v_folder in
6546 VirtualFolders))
6547 for v_folder in VirtualFolders:
6548 init_info[v_folder] = {}
6549
6550
6551
6552 max_mult = 3
6553 if n_PS is None:
6554
6555 mcore.submit(run_initialization_wrapper,
6556 [pjoin(v_folder), init_info[v_folder], None])
6557 else:
6558
6559 mcore.submit(run_initialization_wrapper, [pjoin(v_folder),
6560 init_info[v_folder],
6561 [n_PS*multiplier for multiplier in range(1,max_mult+1)]])
6562
6563
6564 mcore.wait('',wait_monitoring,update_first=wait_monitoring)
6565 for v_folder in VirtualFolders:
6566 init = init_info[v_folder]
6567 if init['nPS'] is None:
6568 raise MadGraph5Error, 'Failed the initialization of'+\
6569 " loop-induced matrix element '%s'%s."%\
6570 (os.path.basename(v_folder),' (using default n_PS points)' if\
6571 n_PS is None else ' (trying with a maximum of %d PS points)'\
6572 %(max_mult*n_PS))
6573 if init['nPS']==0:
6574 logger.debug("Nothing to be done in '%s', all filters already "%\
6575 os.path.basename(v_folder)+\
6576 "present (use the '-r' option to force their recomputation)")
6577 else:
6578 logger.debug("'%s' finished using "%os.path.basename(v_folder)+
6579 '%d PS points (%s), in %.3g(compil.) + %.3g(init.) secs.'%(
6580 abs(init['nPS']),'DP' if init['nPS']>0 else 'QP',
6581 init['Process_compilation'],init['Initialization']))
6582
6583 logger.info('MadLoop initialization finished.')
6584
6585 AskforEditCard = common_run.AskforEditCard
6586
6587
6588 if '__main__' == __name__:
6589
6590
6591 import sys
6592 if not sys.version_info[0] == 2 or sys.version_info[1] < 6:
6593 sys.exit('MadGraph/MadEvent 5 works only with python 2.6 or later (but not python 3.X).\n'+\
6594 'Please upgrate your version of python.')
6595
6596 import os
6597 import optparse
6598
6599
6600 root_path = os.path.dirname(os.path.dirname(os.path.realpath( __file__ )))
6601 sys.path.insert(0, root_path)
6605 - def error(self, msg=''):
6607
6608 usage = "usage: %prog [options] [FILE] "
6609 parser = MyOptParser(usage=usage)
6610 parser.add_option("-l", "--logging", default='INFO',
6611 help="logging level (DEBUG|INFO|WARNING|ERROR|CRITICAL) [%default]")
6612 parser.add_option("","--web", action="store_true", default=False, dest='web', \
6613 help='force toce to be in secure mode')
6614 parser.add_option("","--debug", action="store_true", default=False, dest='debug', \
6615 help='force to launch debug mode')
6616 parser_error = ''
6617 done = False
6618
6619 for i in range(len(sys.argv)-1):
6620 try:
6621 (options, args) = parser.parse_args(sys.argv[1:len(sys.argv)-i])
6622 done = True
6623 except MyOptParser.InvalidOption, error:
6624 pass
6625 else:
6626 args += sys.argv[len(sys.argv)-i:]
6627 if not done:
6628
6629 try:
6630 (options, args) = parser.parse_args()
6631 except MyOptParser.InvalidOption, error:
6632 print error
6633 sys.exit(2)
6634
6635 if len(args) == 0:
6636 args = ''
6637
6638 import subprocess
6639 import logging
6640 import logging.config
6641
6642
6643 import internal.coloring_logging
6644 try:
6645 if __debug__ and options.logging == 'INFO':
6646 options.logging = 'DEBUG'
6647 if options.logging.isdigit():
6648 level = int(options.logging)
6649 else:
6650 level = eval('logging.' + options.logging)
6651 print os.path.join(root_path, 'internal', 'me5_logging.conf')
6652 logging.config.fileConfig(os.path.join(root_path, 'internal', 'me5_logging.conf'))
6653 logging.root.setLevel(level)
6654 logging.getLogger('madgraph').setLevel(level)
6655 except:
6656 raise
6657 pass
6658
6659
6660 try:
6661 if args:
6662
6663 if '--web' in args:
6664 i = args.index('--web')
6665 args.pop(i)
6666 cmd_line = MadEventCmd(force_run=True)
6667 else:
6668 cmd_line = MadEventCmdShell(force_run=True)
6669 if not hasattr(cmd_line, 'do_%s' % args[0]):
6670 if parser_error:
6671 print parser_error
6672 print 'and %s can not be interpreted as a valid command.' % args[0]
6673 else:
6674 print 'ERROR: %s not a valid command. Please retry' % args[0]
6675 else:
6676 cmd_line.use_rawinput = False
6677 cmd_line.run_cmd(' '.join(args))
6678 cmd_line.run_cmd('quit')
6679
6680 except KeyboardInterrupt:
6681 print 'quit on KeyboardInterrupt'
6682 pass
6683