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 cmath
22 import glob
23 import logging
24 import math
25 import optparse
26 import os
27 import pydoc
28 import random
29 import re
30 import signal
31 import shutil
32 import stat
33 import subprocess
34 import sys
35 import traceback
36 import time
37
38 try:
39 import readline
40 GNU_SPLITTING = ('GNU' in readline.__doc__)
41 except:
42 GNU_SPLITTING = True
43
44 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
45 root_path = os.path.split(root_path)[0]
46 sys.path.insert(0, os.path.join(root_path,'bin'))
47
48
49 pjoin = os.path.join
50
51 logger = logging.getLogger('madevent.stdout')
52 logger_stderr = logging.getLogger('madevent.stderr')
53
54 try:
55
56 import madgraph.interface.extended_cmd as cmd
57 import madgraph.interface.common_run_interface as common_run
58 import madgraph.iolibs.files as files
59 import madgraph.iolibs.save_load_object as save_load_object
60 import madgraph.various.banner as banner_mod
61 import madgraph.various.cluster as cluster
62 import madgraph.various.gen_crossxhtml as gen_crossxhtml
63 import madgraph.various.sum_html as sum_html
64 import madgraph.various.misc as misc
65 import madgraph.various.combine_runs as combine_runs
66
67 import models.check_param_card as check_param_card
68 from madgraph import InvalidCmd, MadGraph5Error, MG5DIR, ReadWrite
69 MADEVENT = False
70 except ImportError, error:
71 if __debug__:
72 print error
73
74 import internal.extended_cmd as cmd
75 import internal.common_run_interface as common_run
76 import internal.banner as banner_mod
77 import internal.misc as misc
78 from internal import InvalidCmd, MadGraph5Error, ReadWrite
79 import internal.files as files
80 import internal.gen_crossxhtml as gen_crossxhtml
81 import internal.save_load_object as save_load_object
82 import internal.cluster as cluster
83 import internal.check_param_card as check_param_card
84 import internal.sum_html as sum_html
85 import internal.combine_runs as combine_runs
86 MADEVENT = True
90
93
95
96 MadEventAlreadyRunning = common_run.MadEventAlreadyRunning
97
98
99
100
101 -class CmdExtended(common_run.CommonRunCmd):
102 """Particularisation of the cmd command for MadEvent"""
103
104
105 next_possibility = {
106 'start': [],
107 }
108
109 debug_output = 'ME5_debug'
110 error_debug = 'Please report this bug on https://bugs.launchpad.net/madgraph5\n'
111 error_debug += 'More information is found in \'%(debug)s\'.\n'
112 error_debug += 'Please attach this file to your report.'
113
114 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/madgraph5\n'
115
116
117 keyboard_stop_msg = """stopping all operation
118 in order to quit MadGraph5_aMC@NLO please enter exit"""
119
120
121 InvalidCmd = InvalidCmd
122 ConfigurationError = MadGraph5Error
123
124 - def __init__(self, me_dir, options, *arg, **opt):
125 """Init history and line continuation"""
126
127
128 self.force = False
129
130
131
132 info = misc.get_pkg_info()
133 info_line = ""
134 if info and info.has_key('version') and info.has_key('date'):
135 len_version = len(info['version'])
136 len_date = len(info['date'])
137 if len_version + len_date < 30:
138 info_line = "#* VERSION %s %s %s *\n" % \
139 (info['version'],
140 (30 - len_version - len_date) * ' ',
141 info['date'])
142 else:
143 version = open(pjoin(root_path,'MGMEVersion.txt')).readline().strip()
144 info_line = "#* VERSION %s %s *\n" % \
145 (version, (24 - len(version)) * ' ')
146
147
148
149 self.history_header = \
150 '#************************************************************\n' + \
151 '#* MadGraph5_aMC@NLO/MadEvent *\n' + \
152 '#* *\n' + \
153 "#* * * *\n" + \
154 "#* * * * * *\n" + \
155 "#* * * * * 5 * * * * *\n" + \
156 "#* * * * * *\n" + \
157 "#* * * *\n" + \
158 "#* *\n" + \
159 "#* *\n" + \
160 info_line + \
161 "#* *\n" + \
162 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
163 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
164 '#* *\n' + \
165 '#************************************************************\n' + \
166 '#* *\n' + \
167 '#* Command File for MadEvent *\n' + \
168 '#* *\n' + \
169 '#* run as ./bin/madevent.py filename *\n' + \
170 '#* *\n' + \
171 '#************************************************************\n'
172
173 if info_line:
174 info_line = info_line[1:]
175
176 logger.info(\
177 "************************************************************\n" + \
178 "* *\n" + \
179 "* W E L C O M E to *\n" + \
180 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
181 "* M A D E V E N T *\n" + \
182 "* *\n" + \
183 "* * * *\n" + \
184 "* * * * * *\n" + \
185 "* * * * * 5 * * * * *\n" + \
186 "* * * * * *\n" + \
187 "* * * *\n" + \
188 "* *\n" + \
189 info_line + \
190 "* *\n" + \
191 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
192 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
193 "* *\n" + \
194 "* Type 'help' for in-line help. *\n" + \
195 "* *\n" + \
196 "************************************************************")
197 super(CmdExtended, self).__init__(me_dir, options, *arg, **opt)
198
200 """return the history header"""
201 return self.history_header % misc.get_time_info()
202
204 """action to perform to close nicely on a keyboard interupt"""
205 try:
206 if hasattr(self, 'cluster'):
207 logger.info('rm jobs on queue')
208 self.cluster.remove()
209 if hasattr(self, 'results'):
210 self.update_status('Stop by the user', level=None, makehtml=False, error=True)
211 self.add_error_log_in_html(KeyboardInterrupt)
212 except:
213 pass
214
215 - def postcmd(self, stop, line):
216 """ Update the status of the run for finishing interactive command """
217
218 stop = super(CmdExtended, self).postcmd(stop, line)
219
220 self.force = False
221
222 if not self.use_rawinput:
223 return stop
224
225 if self.results and not self.results.current:
226 return stop
227
228 arg = line.split()
229 if len(arg) == 0:
230 return stop
231 if isinstance(self.results.status, str) and self.results.status.startswith('Error'):
232 return stop
233 if isinstance(self.results.status, str) and self.results.status == 'Stop by the user':
234 self.update_status('%s Stop by the user' % arg[0], level=None, error=True)
235 return stop
236 elif not self.results.status:
237 return stop
238 elif str(arg[0]) in ['exit','quit','EOF']:
239 return stop
240
241 try:
242 self.update_status('Command \'%s\' done.<br> Waiting for instruction.' % arg[0],
243 level=None, error=True)
244 except Exception:
245 misc.sprint('update_status fails')
246 pass
247
248
254
268
269
271 """If a ME run is currently running add a link in the html output"""
272
273 if isinstance(error, ZeroResult):
274 self.add_error_log_in_html(error)
275 logger.warning('Zero result detected: %s' % error)
276
277 try:
278 if not self.banner:
279 self.banner = banner_mod.Banner()
280 if 'slha' not in self.banner:
281 self.banner.add(pjoin(self.me_dir,'Cards','param_card.dat'))
282 if 'mgruncard' not in self.banner:
283 self.banner.add(pjoin(self.me_dir,'Cards','run_card.dat'))
284 if 'mg5proccard' not in self.banner:
285 proc_card = pjoin(self.me_dir,'Cards','proc_card_mg5.dat')
286 if os.path.exists(proc_card):
287 self.banner.add(proc_card)
288
289 out_dir = pjoin(self.me_dir, 'Events', self.run_name)
290 if not os.path.isdir(out_dir):
291 os.mkdir(out_dir)
292 output_path = pjoin(out_dir, '%s_%s_banner.txt' % \
293 (self.run_name, self.run_tag))
294 self.banner.write(output_path)
295 except Exception:
296 if __debug__:
297 raise
298 else:
299 pass
300 else:
301 self.add_error_log_in_html()
302 cmd.Cmd.nice_error_handling(self, error, line)
303 try:
304 debug_file = open(self.debug_output, 'a')
305 debug_file.write(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')))
306 debug_file.close()
307 except:
308 pass
309
315 """ The Series of help routine for the MadEventCmd"""
316
318 logger.info("syntax: banner_run Path|RUN [--run_options]")
319 logger.info("-- Reproduce a run following a given banner")
320 logger.info(" One of the following argument is require:")
321 logger.info(" Path should be the path of a valid banner.")
322 logger.info(" RUN should be the name of a run of the current directory")
323 self.run_options_help([('-f','answer all question by default'),
324 ('--name=X', 'Define the name associated with the new run')])
325
327 logger.info("syntax: open FILE ")
328 logger.info("-- open a file with the appropriate editor.")
329 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
330 logger.info(' the path to the last created/used directory is used')
331 logger.info(' The program used to open those files can be chosen in the')
332 logger.info(' configuration file ./input/mg5_configuration.txt')
333
334
336 if data:
337 logger.info('-- local options:')
338 for name, info in data:
339 logger.info(' %s : %s' % (name, info))
340
341 logger.info("-- session options:")
342 logger.info(" Note that those options will be kept for the current session")
343 logger.info(" --cluster : Submit to the cluster. Current cluster: %s" % self.options['cluster_type'])
344 logger.info(" --multicore : Run in multi-core configuration")
345 logger.info(" --nb_core=X : limit the number of core to use to X.")
346
347
349 logger.info("syntax: generate_events [run_name] [options])")
350 logger.info("-- Launch the full chain of script for the generation of events")
351 logger.info(" Including possible plotting, shower and detector resolution.")
352 logger.info(" Those steps are performed if the related program are installed")
353 logger.info(" and if the related card are present in the Cards directory.")
354 self.run_options_help([('-f', 'Use default for all questions.'),
355 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
356
357
359 logger.info("syntax: add_time_of_flight [run_name|path_to_file] [--treshold=]")
360 logger.info('-- Add in the lhe files the information')
361 logger.info(' of how long it takes to a particle to decay.')
362 logger.info(' threshold option allows to change the minimal value required to')
363 logger.info(' a non zero value for the particle (default:1e-12s)')
364
366
367 if self.ninitial != 1:
368 logger.warning("This command is only valid for processes of type A > B C.")
369 logger.warning("This command can not be run in current context.")
370 logger.warning("")
371
372 logger.info("syntax: calculate_decay_widths [run_name] [options])")
373 logger.info("-- Calculate decay widths and enter widths and BRs in param_card")
374 logger.info(" for a series of processes of type A > B C ...")
375 self.run_options_help([('-f', 'Use default for all questions.'),
376 ('--accuracy=', 'accuracy (for each partial decay width).'\
377 + ' Default is 0.01.')])
378
380 logger.info("syntax: multi_run NB_RUN [run_name] [--run_options])")
381 logger.info("-- Launch the full chain of script for the generation of events")
382 logger.info(" NB_RUN times. This chains includes possible plotting, shower")
383 logger.info(" and detector resolution.")
384 self.run_options_help([('-f', 'Use default for all questions.'),
385 ('--laststep=', 'argument might be parton/pythia/pgs/delphes and indicate the last level to be run.')])
386
392
394 """exec generate_events for 2>N and calculate_width for 1>N"""
395 logger.info("syntax: launch [run_name] [options])")
396 logger.info(" --alias for either generate_events/calculate_decay_widths")
397 logger.info(" depending of the number of particles in the initial state.")
398
399 if self.ninitial == 1:
400 logger.info("For this directory this is equivalent to calculate_decay_widths")
401 self.help_calculate_decay_widths()
402 else:
403 logger.info("For this directory this is equivalent to $generate_events")
404 self.help_generate_events()
405
407 logger.info("syntax: refine require_precision [max_channel] [--run_options]")
408 logger.info("-- refine the LAST run to achieve a given precision.")
409 logger.info(" require_precision: can be either the targeted number of events")
410 logger.info(' or the required relative error')
411 logger.info(' max_channel:[5] maximal number of channel per job')
412 self.run_options_help([])
413
415 """ """
416 logger.info("syntax: combine_events [run_name] [--tag=tag_name] [--run_options]")
417 logger.info("-- Combine the last run in order to write the number of events")
418 logger.info(" asked in the run_card.")
419 self.run_options_help([])
420
427
434
440
442 logger.info("syntax: syscalc [RUN] [%s] [-f | --tag=]" % '|'.join(self._plot_mode))
443 logger.info("-- calculate systematics information for the RUN (current run by default)")
444 logger.info(" at different stages of the event generation for scale/pdf/...")
445
447 logger.info("syntax: remove RUN [all|parton|pythia|pgs|delphes|banner] [-f] [--tag=]")
448 logger.info("-- Remove all the files linked to previous run RUN")
449 logger.info(" if RUN is 'all', then all run will be cleaned.")
450 logger.info(" The optional argument precise which part should be cleaned.")
451 logger.info(" By default we clean all the related files but the banners.")
452 logger.info(" the optional '-f' allows to by-pass all security question")
453 logger.info(" The banner can be remove only if all files are removed first.")
454
461 """ The Series of check routine for the MadEventCmd"""
462
464 """check the validity of line"""
465
466 if len(args) == 0:
467 self.help_banner_run()
468 raise self.InvalidCmd('banner_run requires at least one argument.')
469
470 tag = [a[6:] for a in args if a.startswith('--tag=')]
471
472
473 if os.path.exists(args[0]):
474 type ='banner'
475 format = self.detect_card_type(args[0])
476 if format != 'banner':
477 raise self.InvalidCmd('The file is not a valid banner.')
478 elif tag:
479 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \
480 (args[0], tag))
481 if not os.path.exists(args[0]):
482 raise self.InvalidCmd('No banner associates to this name and tag.')
483 else:
484 name = args[0]
485 type = 'run'
486 banners = glob.glob(pjoin(self.me_dir,'Events', args[0], '*_banner.txt'))
487 if not banners:
488 raise self.InvalidCmd('No banner associates to this name.')
489 elif len(banners) == 1:
490 args[0] = banners[0]
491 else:
492
493 tags = [os.path.basename(p)[len(args[0])+1:-11] for p in banners]
494 tag = self.ask('which tag do you want to use?', tags[0], tags)
495 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \
496 (args[0], tag))
497
498 run_name = [arg[7:] for arg in args if arg.startswith('--name=')]
499 if run_name:
500 try:
501 self.exec_cmd('remove %s all banner -f' % run_name)
502 except Exception:
503 pass
504 self.set_run_name(args[0], tag=None, level='parton', reload_card=True)
505 elif type == 'banner':
506 self.set_run_name(self.find_available_run_name(self.me_dir))
507 elif type == 'run':
508 if not self.results[name].is_empty():
509 run_name = self.find_available_run_name(self.me_dir)
510 logger.info('Run %s is not empty so will use run_name: %s' % \
511 (name, run_name))
512 self.set_run_name(run_name)
513 else:
514 try:
515 self.exec_cmd('remove %s all banner -f' % run_name)
516 except Exception:
517 pass
518 self.set_run_name(name)
519
520 - def check_history(self, args):
521 """check the validity of line"""
522
523 if len(args) > 1:
524 self.help_history()
525 raise self.InvalidCmd('\"history\" command takes at most one argument')
526
527 if not len(args):
528 return
529 elif args[0] != 'clean':
530 dirpath = os.path.dirname(args[0])
531 if dirpath and not os.path.exists(dirpath) or \
532 os.path.isdir(args[0]):
533 raise self.InvalidCmd("invalid path %s " % dirpath)
534
536 """ check the validity of the line"""
537
538 if len(args) == 0:
539 args.append('options')
540
541 if args[0] not in self._save_opts:
542 raise self.InvalidCmd('wrong \"save\" format')
543
544 if args[0] != 'options' and len(args) != 2:
545 self.help_save()
546 raise self.InvalidCmd('wrong \"save\" format')
547 elif args[0] != 'options' and len(args) == 2:
548 basename = os.path.dirname(args[1])
549 if not os.path.exists(basename):
550 raise self.InvalidCmd('%s is not a valid path, please retry' % \
551 args[1])
552
553 if args[0] == 'options':
554 has_path = None
555 for arg in args[1:]:
556 if arg in ['--auto', '--all']:
557 continue
558 elif arg.startswith('--'):
559 raise self.InvalidCmd('unknow command for \'save options\'')
560 else:
561 basename = os.path.dirname(arg)
562 if not os.path.exists(basename):
563 raise self.InvalidCmd('%s is not a valid path, please retry' % \
564 arg)
565 elif has_path:
566 raise self.InvalidCmd('only one path is allowed')
567 else:
568 args.remove(arg)
569 args.insert(1, arg)
570 has_path = True
571 if not has_path:
572 if '--auto' in arg and self.options['mg5_path']:
573 args.insert(1, pjoin(self.options['mg5_path'],'input','mg5_configuration.txt'))
574 else:
575 args.insert(1, pjoin(self.me_dir,'Cards','me5_configuration.txt'))
576
578 """ check the validity of the line"""
579
580 if len(args) < 2:
581 self.help_set()
582 raise self.InvalidCmd('set needs an option and an argument')
583
584 if args[0] not in self._set_options + self.options.keys():
585 self.help_set()
586 raise self.InvalidCmd('Possible options for set are %s' % \
587 self._set_options)
588
589 if args[0] in ['stdout_level']:
590 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \
591 and not args[1].isdigit():
592 raise self.InvalidCmd('output_level needs ' + \
593 'a valid level')
594
595 if args[0] in ['timeout']:
596 if not args[1].isdigit():
597 raise self.InvalidCmd('timeout values should be a integer')
598
600 """ check the validity of the line """
601
602 if len(args) != 1:
603 self.help_open()
604 raise self.InvalidCmd('OPEN command requires exactly one argument')
605
606 if args[0].startswith('./'):
607 if not os.path.isfile(args[0]):
608 raise self.InvalidCmd('%s: not such file' % args[0])
609 return True
610
611
612 if not self.me_dir:
613 if not os.path.isfile(args[0]):
614 self.help_open()
615 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file')
616 else:
617 return True
618
619 path = self.me_dir
620 if os.path.isfile(os.path.join(path,args[0])):
621 args[0] = os.path.join(path,args[0])
622 elif os.path.isfile(os.path.join(path,'Cards',args[0])):
623 args[0] = os.path.join(path,'Cards',args[0])
624 elif os.path.isfile(os.path.join(path,'HTML',args[0])):
625 args[0] = os.path.join(path,'HTML',args[0])
626
627 elif '_card.dat' in args[0]:
628 name = args[0].replace('_card.dat','_card_default.dat')
629 if os.path.isfile(os.path.join(path,'Cards', name)):
630 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0]))
631 args[0] = os.path.join(path,'Cards', args[0])
632 else:
633 raise self.InvalidCmd('No default path for this file')
634 elif not os.path.isfile(args[0]):
635 raise self.InvalidCmd('No default path for this file')
636
638 """check that treatcards arguments are valid
639 [param|run|all] [--output_dir=] [--param_card=] [--run_card=]
640 """
641
642 opt = {'output_dir':pjoin(self.me_dir,'Source'),
643 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'),
644 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')}
645 mode = 'all'
646 for arg in args:
647 if arg.startswith('--') and '=' in arg:
648 key,value =arg[2:].split('=',1)
649 if not key in opt:
650 self.help_treatcards()
651 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \
652 % key)
653 if key in ['param_card', 'run_card']:
654 if os.path.isfile(value):
655 card_name = self.detect_card_type(value)
656 if card_name != key:
657 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
658 % (card_name, key))
659 opt[key] = value
660 elif os.path.isfile(pjoin(self.me_dir,value)):
661 card_name = self.detect_card_type(pjoin(self.me_dir,value))
662 if card_name != key:
663 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
664 % (card_name, key))
665 opt[key] = value
666 else:
667 raise self.InvalidCmd('No such file: %s ' % value)
668 elif key in ['output_dir']:
669 if os.path.isdir(value):
670 opt[key] = value
671 elif os.path.isdir(pjoin(self.me_dir,value)):
672 opt[key] = pjoin(self.me_dir, value)
673 else:
674 raise self.InvalidCmd('No such directory: %s' % value)
675 elif arg in ['param','run','all']:
676 mode = arg
677 else:
678 self.help_treatcards()
679 raise self.InvalidCmd('Unvalid argument %s' % arg)
680
681 return mode, opt
682
683
685 """check that the argument for survey are valid"""
686
687
688 self.opts = dict([(key,value[1]) for (key,value) in \
689 self._survey_options.items()])
690
691
692 while args and args[-1].startswith('--'):
693 arg = args.pop(-1)
694 try:
695 for opt,value in self._survey_options.items():
696 if arg.startswith('--%s=' % opt):
697 exec('self.opts[\'%s\'] = %s(arg.split(\'=\')[-1])' % \
698 (opt, value[0]))
699 arg = ""
700 if arg != "": raise Exception
701 except Exception:
702 self.help_survey()
703 raise self.InvalidCmd('invalid %s argument'% arg)
704
705 if len(args) > 1:
706 self.help_survey()
707 raise self.InvalidCmd('Too many argument for %s command' % cmd)
708 elif not args:
709
710 self.set_run_name(self.find_available_run_name(self.me_dir))
711 else:
712 self.set_run_name(args[0], None,'parton', True)
713 args.pop(0)
714
715 return True
716
718 """check that the argument for generate_events are valid"""
719
720 run = None
721 if args and args[-1].startswith('--laststep='):
722 run = args[-1].split('=')[-1]
723 if run not in ['auto','parton', 'pythia', 'pgs', 'delphes']:
724 self.help_generate_events()
725 raise self.InvalidCmd('invalid %s argument'% args[-1])
726 if run != 'parton' and not self.options['pythia-pgs_path']:
727 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first.
728 To do so type: \'install pythia-pgs\' in the mg5 interface''')
729 if run == 'delphes' and not self.options['delphes_path']:
730 raise self.InvalidCmd('''delphes not install. Please install this package first.
731 To do so type: \'install Delphes\' in the mg5 interface''')
732 del args[-1]
733
734 if len(args) > 1:
735 self.help_generate_events()
736 raise self.InvalidCmd('Too many argument for generate_events command: %s' % cmd)
737
738 return run
739
741 """check that the argument are correct"""
742
743
744 if len(args) >2:
745 self.help_time_of_flight()
746 raise self.InvalidCmd('Too many arguments')
747
748
749 if args and args[-1].startswith('--threshold='):
750 try:
751 threshold = float(args[-1].split('=')[1])
752 except ValueError:
753 raise self.InvalidCmd('threshold options require a number.')
754 args.remove(args[-1])
755 else:
756 threshold = 1e-12
757
758 if len(args) == 1 and os.path.exists(args[0]):
759 event_path = args[0]
760 else:
761 if len(args) and self.run_name != args[0]:
762 self.set_run_name(args.pop(0))
763 elif not self.run_name:
764 self.help_add_time_of_flight()
765 raise self.InvalidCmd('Need a run_name to process')
766 event_path = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')
767 if not os.path.exists(event_path):
768 event_path = event_path[:-3]
769 if not os.path.exists(event_path):
770 raise self.InvalidCmd('No unweighted events associate to this run.')
771
772
773
774
775 args[:] = [event_path, threshold]
776
778 """check that the argument for calculate_decay_widths are valid"""
779
780 if self.ninitial != 1:
781 raise self.InvalidCmd('Can only calculate decay widths for decay processes A > B C ...')
782
783 accuracy = 0.01
784 run = None
785 if args and args[-1].startswith('--accuracy='):
786 try:
787 accuracy = float(args[-1].split('=')[-1])
788 except Exception:
789 raise self.InvalidCmd('Argument error in calculate_decay_widths command')
790 del args[-1]
791 if len(args) > 1:
792 self.help_calculate_decay_widths()
793 raise self.InvalidCmd('Too many argument for calculate_decay_widths command: %s' % cmd)
794
795 return accuracy
796
797
798
800 """check that the argument for survey are valid"""
801
802 run = None
803
804 if not len(args):
805 self.help_multi_run()
806 raise self.InvalidCmd("""multi_run command requires at least one argument for
807 the number of times that it call generate_events command""")
808
809 if args[-1].startswith('--laststep='):
810 run = args[-1].split('=')[-1]
811 if run not in ['parton', 'pythia', 'pgs', 'delphes']:
812 self.help_multi_run()
813 raise self.InvalidCmd('invalid %s argument'% args[-1])
814 if run != 'parton' and not self.options['pythia-pgs_path']:
815 raise self.InvalidCmd('''pythia-pgs not install. Please install this package first.
816 To do so type: \'install pythia-pgs\' in the mg5 interface''')
817 if run == 'delphes' and not self.options['delphes_path']:
818 raise self.InvalidCmd('''delphes not install. Please install this package first.
819 To do so type: \'install Delphes\' in the mg5 interface''')
820 del args[-1]
821
822
823 elif not args[0].isdigit():
824 self.help_multi_run()
825 raise self.InvalidCmd("The first argument of multi_run should be a integer.")
826 nb_run = args.pop(0)
827 self.check_survey(args, cmd='multi_run')
828 args.insert(0, int(nb_run))
829
830 return run
831
833 """check that the argument for survey are valid"""
834
835
836 try:
837 float(args[-1])
838 except ValueError:
839 self.help_refine()
840 raise self.InvalidCmd('Not valid arguments')
841 except IndexError:
842 self.help_refine()
843 raise self.InvalidCmd('require_precision argument is require for refine cmd')
844
845
846 if not self.run_name:
847 if self.results.lastrun:
848 self.set_run_name(self.results.lastrun)
849 else:
850 raise self.InvalidCmd('No run_name currently define. Unable to run refine')
851
852 if len(args) > 2:
853 self.help_refine()
854 raise self.InvalidCmd('Too many argument for refine command')
855 else:
856 try:
857 [float(arg) for arg in args]
858 except ValueError:
859 self.help_refine()
860 raise self.InvalidCmd('refine arguments are suppose to be number')
861
862 return True
863
865 """ Check the argument for the combine events command """
866
867 tag = [a for a in arg if a.startswith('--tag=')]
868 if tag:
869 arg.remove(tag[0])
870 tag = tag[0][6:]
871 elif not self.run_tag:
872 tag = 'tag_1'
873 else:
874 tag = self.run_tag
875 self.run_tag = tag
876
877 if len(arg) > 1:
878 self.help_combine_events()
879 raise self.InvalidCmd('Too many argument for combine_events command')
880
881 if len(arg) == 1:
882 self.set_run_name(arg[0], self.run_tag, 'parton', True)
883
884 if not self.run_name:
885 if not self.results.lastrun:
886 raise self.InvalidCmd('No run_name currently define. Unable to run combine')
887 else:
888 self.set_run_name(self.results.lastrun)
889
890 return True
891
893 """Check the argument for pythia command
894 syntax: pythia [NAME]
895 Note that other option are already remove at this point
896 """
897
898 mode = None
899 laststep = [arg for arg in args if arg.startswith('--laststep=')]
900 if laststep and len(laststep)==1:
901 mode = laststep[0].split('=')[-1]
902 if mode not in ['auto', 'pythia', 'pgs', 'delphes']:
903 self.help_pythia()
904 raise self.InvalidCmd('invalid %s argument'% args[-1])
905 elif laststep:
906 raise self.InvalidCmd('only one laststep argument is allowed')
907
908
909 if not self.options['pythia-pgs_path']:
910 logger.info('Retry to read configuration file to find pythia-pgs path')
911 self.set_configuration()
912
913 if not self.options['pythia-pgs_path'] or not \
914 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')):
915 error_msg = 'No valid pythia-pgs path set.\n'
916 error_msg += 'Please use the set command to define the path and retry.\n'
917 error_msg += 'You can also define it in the configuration file.\n'
918 raise self.InvalidCmd(error_msg)
919
920
921
922 tag = [a for a in args if a.startswith('--tag=')]
923 if tag:
924 args.remove(tag[0])
925 tag = tag[0][6:]
926
927 if len(args) == 0 and not self.run_name:
928 if self.results.lastrun:
929 args.insert(0, self.results.lastrun)
930 else:
931 raise self.InvalidCmd('No run name currently define. Please add this information.')
932
933 if len(args) >= 1:
934 if args[0] != self.run_name and\
935 not os.path.exists(pjoin(self.me_dir,'Events',args[0], 'unweighted_events.lhe.gz')):
936 raise self.InvalidCmd('No events file corresponding to %s run. '% args[0])
937 self.set_run_name(args[0], tag, 'pythia')
938 else:
939 if tag:
940 self.run_card['run_tag'] = tag
941 self.set_run_name(self.run_name, tag, 'pythia')
942
943 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe')
944 output_file = pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')
945 if not os.path.exists('%s.gz' % input_file):
946 if not os.path.exists(input_file):
947 raise self.InvalidCmd('No events file corresponding to %s run. '% self.run_name)
948 files.cp(input_file, output_file)
949 else:
950 misc.gunzip(input_file, keep=True, stdout=output_file)
951
952 args.append(mode)
953
955 """Check that the remove command is valid"""
956
957 tmp_args = args[:]
958
959 tag = [a[6:] for a in tmp_args if a.startswith('--tag=')]
960 if tag:
961 tag = tag[0]
962 tmp_args.remove('--tag=%s' % tag)
963
964
965 if len(tmp_args) == 0:
966 self.help_remove()
967 raise self.InvalidCmd('clean command require the name of the run to clean')
968 elif len(tmp_args) == 1:
969 return tmp_args[0], tag, ['all']
970 else:
971 for arg in tmp_args[1:]:
972 if arg not in self._clean_mode:
973 self.help_remove()
974 raise self.InvalidCmd('%s is not a valid options for clean command'\
975 % arg)
976 return tmp_args[0], tag, tmp_args[1:]
977
979 """Check the argument for the plot command
980 plot run_name modes"""
981
982 madir = self.options['madanalysis_path']
983 td = self.options['td_path']
984
985 if not madir or not td:
986 logger.info('Retry to read configuration file to find madanalysis/td')
987 self.set_configuration()
988
989 madir = self.options['madanalysis_path']
990 td = self.options['td_path']
991
992 if not madir:
993 error_msg = 'No valid MadAnalysis path set.\n'
994 error_msg += 'Please use the set command to define the path and retry.\n'
995 error_msg += 'You can also define it in the configuration file.\n'
996 raise self.InvalidCmd(error_msg)
997 if not td:
998 error_msg = 'No valid td path set.\n'
999 error_msg += 'Please use the set command to define the path and retry.\n'
1000 error_msg += 'You can also define it in the configuration file.\n'
1001 raise self.InvalidCmd(error_msg)
1002
1003 if len(args) == 0:
1004 if not hasattr(self, 'run_name') or not self.run_name:
1005 self.help_plot()
1006 raise self.InvalidCmd('No run name currently define. Please add this information.')
1007 args.append('all')
1008 return
1009
1010
1011 if args[0] not in self._plot_mode:
1012 self.set_run_name(args[0], level='plot')
1013 del args[0]
1014 if len(args) == 0:
1015 args.append('all')
1016 elif not self.run_name:
1017 self.help_plot()
1018 raise self.InvalidCmd('No run name currently define. Please add this information.')
1019
1020 for arg in args:
1021 if arg not in self._plot_mode and arg != self.run_name:
1022 self.help_plot()
1023 raise self.InvalidCmd('unknown options %s' % arg)
1024
1026 """Check the argument for the syscalc command
1027 syscalc run_name modes"""
1028
1029 scdir = self.options['syscalc_path']
1030
1031 if not scdir:
1032 logger.info('Retry to read configuration file to find SysCalc')
1033 self.set_configuration()
1034
1035 scdir = self.options['syscalc_path']
1036
1037 if not scdir:
1038 error_msg = 'No valid SysCalc path set.\n'
1039 error_msg += 'Please use the set command to define the path and retry.\n'
1040 error_msg += 'You can also define it in the configuration file.\n'
1041 error_msg += 'Please note that you need to compile SysCalc first.'
1042 raise self.InvalidCmd(error_msg)
1043
1044 if len(args) == 0:
1045 if not hasattr(self, 'run_name') or not self.run_name:
1046 self.help_syscalc()
1047 raise self.InvalidCmd('No run name currently defined. Please add this information.')
1048 args.append('all')
1049 return
1050
1051
1052 tag = [a for a in args if a.startswith('--tag=')]
1053 if tag:
1054 args.remove(tag[0])
1055 tag = tag[0][6:]
1056
1057 if args[0] not in self._syscalc_mode:
1058 self.set_run_name(args[0], tag=tag, level='syscalc')
1059 del args[0]
1060 if len(args) == 0:
1061 args.append('all')
1062 elif not self.run_name:
1063 self.help_syscalc()
1064 raise self.InvalidCmd('No run name currently defined. Please add this information.')
1065 elif tag and tag != self.run_tag:
1066 self.set_run_name(self.run_name, tag=tag, level='syscalc')
1067
1068 for arg in args:
1069 if arg not in self._syscalc_mode and arg != self.run_name:
1070 self.help_syscalc()
1071 raise self.InvalidCmd('unknown options %s' % arg)
1072
1073 if self.run_card['use_syst'] not in self.true:
1074 raise self.InvalidCmd('Run %s does not include ' % self.run_name + \
1075 'systematics information needed for syscalc.')
1076
1077
1079 """Check the argument for pythia command
1080 syntax: pgs [NAME]
1081 Note that other option are already remove at this point
1082 """
1083
1084
1085 if not self.options['pythia-pgs_path']:
1086 logger.info('Retry to read configuration file to find pythia-pgs path')
1087 self.set_configuration()
1088
1089 if not self.options['pythia-pgs_path'] or not \
1090 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')):
1091 error_msg = 'No valid pythia-pgs path set.\n'
1092 error_msg += 'Please use the set command to define the path and retry.\n'
1093 error_msg += 'You can also define it in the configuration file.\n'
1094 raise self.InvalidCmd(error_msg)
1095
1096 tag = [a for a in arg if a.startswith('--tag=')]
1097 if tag:
1098 arg.remove(tag[0])
1099 tag = tag[0][6:]
1100
1101
1102 if len(arg) == 0 and not self.run_name:
1103 if self.results.lastrun:
1104 arg.insert(0, self.results.lastrun)
1105 else:
1106 raise self.InvalidCmd('No run name currently define. Please add this information.')
1107
1108 if len(arg) == 1 and self.run_name == arg[0]:
1109 arg.pop(0)
1110
1111 if not len(arg) and \
1112 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')):
1113 self.help_pgs()
1114 raise self.InvalidCmd('''No file file pythia_events.hep currently available
1115 Please specify a valid run_name''')
1116
1117 lock = None
1118 if len(arg) == 1:
1119 prev_tag = self.set_run_name(arg[0], tag, 'pgs')
1120 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name,'%s_pythia_events.hep.gz' % prev_tag)):
1121 raise self.InvalidCmd('No events file corresponding to %s run with tag %s. '% (self.run_name, prev_tag))
1122 else:
1123 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
1124 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep')
1125 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'),
1126 argument=['-c', input_file])
1127
1128 else:
1129 if tag:
1130 self.run_card['run_tag'] = tag
1131 self.set_run_name(self.run_name, tag, 'pgs')
1132
1133 return lock
1134
1136 """Check the argument for pythia command
1137 syntax: delphes [NAME]
1138 Note that other option are already remove at this point
1139 """
1140
1141
1142 if not self.options['delphes_path']:
1143 logger.info('Retry to read configuration file to find delphes path')
1144 self.set_configuration()
1145
1146 if not self.options['delphes_path']:
1147 error_msg = 'No valid Delphes path set.\n'
1148 error_msg += 'Please use the set command to define the path and retry.\n'
1149 error_msg += 'You can also define it in the configuration file.\n'
1150 raise self.InvalidCmd(error_msg)
1151
1152 tag = [a for a in arg if a.startswith('--tag=')]
1153 if tag:
1154 arg.remove(tag[0])
1155 tag = tag[0][6:]
1156
1157
1158 if len(arg) == 0 and not self.run_name:
1159 if self.results.lastrun:
1160 arg.insert(0, self.results.lastrun)
1161 else:
1162 raise self.InvalidCmd('No run name currently define. Please add this information.')
1163
1164 if len(arg) == 1 and self.run_name == arg[0]:
1165 arg.pop(0)
1166
1167 if not len(arg) and \
1168 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')):
1169 self.help_pgs()
1170 raise self.InvalidCmd('''No file file pythia_events.hep currently available
1171 Please specify a valid run_name''')
1172
1173 lock = None
1174 if len(arg) == 1:
1175 prev_tag = self.set_run_name(arg[0], tag, 'delphes')
1176 if not os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)):
1177 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\
1178 % (self.run_name, prev_tag,
1179 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)))
1180 else:
1181 input_file = pjoin(self.me_dir,'Events', self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
1182 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep')
1183 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'),
1184 argument=['-c', input_file])
1185 else:
1186 if tag:
1187 self.run_card['run_tag'] = tag
1188 self.set_run_name(self.run_name, tag, 'delphes')
1189
1190 return lock
1191
1203
1204
1205
1206
1207
1209 """check the validity of line"""
1210
1211 if not args:
1212 self.help_import()
1213 raise self.InvalidCmd('wrong \"import\" format')
1214
1215 if args[0] != 'command':
1216 args.insert(0,'command')
1217
1218
1219 if not len(args) == 2 or not os.path.exists(args[1]):
1220 raise self.InvalidCmd('PATH is mandatory for import command\n')
1221
1227 """ The Series of help routine for the MadGraphCmd"""
1228
1229
1231 "Complete command"
1232
1233 args = self.split_arg(line[0:begidx], error=False)
1234
1235 if len(args) == 1:
1236
1237 data = glob.glob(pjoin(self.me_dir, 'Events', '*','unweighted_events.lhe.gz'))
1238 data = [n.rsplit('/',2)[1] for n in data]
1239 return self.list_completion(text, data + ['--threshold='], line)
1240 elif args[-1].endswith(os.path.sep):
1241 return self.path_completion(text,
1242 os.path.join('.',*[a for a in args \
1243 if a.endswith(os.path.sep)]))
1244 else:
1245 return self.list_completion(text, ['--threshold='], line)
1246
1248 "Complete the banner run command"
1249 try:
1250
1251
1252 args = self.split_arg(line[0:begidx], error=False)
1253
1254 if args[-1].endswith(os.path.sep):
1255 return self.path_completion(text,
1256 os.path.join('.',*[a for a in args \
1257 if a.endswith(os.path.sep)]))
1258
1259
1260 if len(args) > 1:
1261
1262 tags = glob.glob(pjoin(self.me_dir, 'Events' , args[1],'%s_*_banner.txt' % args[1]))
1263 tags = ['%s' % os.path.basename(t)[len(args[1])+1:-11] for t in tags]
1264
1265 if args[-1] != '--tag=':
1266 tags = ['--tag=%s' % t for t in tags]
1267 else:
1268 return self.list_completion(text, tags)
1269 return self.list_completion(text, tags +['--name=','-f'], line)
1270
1271
1272 possibilites = {}
1273
1274 comp = self.path_completion(text, os.path.join('.',*[a for a in args \
1275 if a.endswith(os.path.sep)]))
1276 if os.path.sep in line:
1277 return comp
1278 else:
1279 possibilites['Path from ./'] = comp
1280
1281 run_list = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt'))
1282 run_list = [n.rsplit('/',2)[1] for n in run_list]
1283 possibilites['RUN Name'] = self.list_completion(text, run_list)
1284
1285 return self.deal_multiple_categories(possibilites)
1286
1287
1288 except Exception, error:
1289 print error
1290
1291
1292 - def complete_history(self, text, line, begidx, endidx):
1293 "Complete the history command"
1294
1295 args = self.split_arg(line[0:begidx], error=False)
1296
1297
1298 if args[-1].endswith(os.path.sep):
1299 return self.path_completion(text,
1300 os.path.join('.',*[a for a in args \
1301 if a.endswith(os.path.sep)]))
1302
1303 if len(args) == 1:
1304 return self.path_completion(text)
1305
1307 """ complete the open command """
1308
1309 args = self.split_arg(line[0:begidx])
1310
1311
1312 if os.path.sep in args[-1] + text:
1313 return self.path_completion(text,
1314 os.path.join('.',*[a for a in args if \
1315 a.endswith(os.path.sep)]))
1316
1317 possibility = []
1318 if self.me_dir:
1319 path = self.me_dir
1320 possibility = ['index.html']
1321 if os.path.isfile(os.path.join(path,'README')):
1322 possibility.append('README')
1323 if os.path.isdir(os.path.join(path,'Cards')):
1324 possibility += [f for f in os.listdir(os.path.join(path,'Cards'))
1325 if f.endswith('.dat')]
1326 if os.path.isdir(os.path.join(path,'HTML')):
1327 possibility += [f for f in os.listdir(os.path.join(path,'HTML'))
1328 if f.endswith('.html') and 'default' not in f]
1329 else:
1330 possibility.extend(['./','../'])
1331 if os.path.exists('ME5_debug'):
1332 possibility.append('ME5_debug')
1333 if os.path.exists('MG5_debug'):
1334 possibility.append('MG5_debug')
1335 return self.list_completion(text, possibility)
1336
1338 "Complete the set command"
1339
1340 args = self.split_arg(line[0:begidx])
1341
1342
1343 if len(args) == 1:
1344 return self.list_completion(text, self._set_options + self.options.keys() )
1345
1346 if len(args) == 2:
1347 if args[1] == 'stdout_level':
1348 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR','CRITICAL'])
1349 else:
1350 first_set = ['None','True','False']
1351
1352 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)]
1353 return self.list_completion(text, first_set + second_set)
1354 elif len(args) >2 and args[-1].endswith(os.path.sep):
1355 return self.path_completion(text,
1356 os.path.join('.',*[a for a in args if a.endswith(os.path.sep)]),
1357 only_dirs = True)
1358
1360 """ Complete the survey command """
1361
1362 if line.endswith('nb_core=') and not text:
1363 import multiprocessing
1364 max = multiprocessing.cpu_count()
1365 return [str(i) for i in range(2,max+1)]
1366
1367 return self.list_completion(text, self._run_options, line)
1368
1369 complete_refine = complete_survey
1370 complete_combine_events = complete_survey
1371 complite_store = complete_survey
1372 complete_generate_events = complete_survey
1373 complete_create_gridpack = complete_survey
1374
1376 """ Complete the generate events"""
1377
1378 if line.endswith('nb_core=') and not text:
1379 import multiprocessing
1380 max = multiprocessing.cpu_count()
1381 return [str(i) for i in range(2,max+1)]
1382 if line.endswith('laststep=') and not text:
1383 return ['parton','pythia','pgs','delphes']
1384 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ':
1385 return self.list_completion(text,['parton','pythia','pgs','delphes'],line)
1386
1387 opts = self._run_options + self._generate_options
1388 return self.list_completion(text, opts, line)
1389
1396
1398 """ Complete the calculate_decay_widths command"""
1399
1400 if line.endswith('nb_core=') and not text:
1401 import multiprocessing
1402 max = multiprocessing.cpu_count()
1403 return [str(i) for i in range(2,max+1)]
1404
1405 opts = self._run_options + self._calculate_decay_options
1406 return self.list_completion(text, opts, line)
1407
1416
1418 """complete multi run command"""
1419
1420 args = self.split_arg(line[0:begidx], error=False)
1421 if len(args) == 1:
1422 data = [str(i) for i in range(0,20)]
1423 return self.list_completion(text, data, line)
1424
1425 if line.endswith('run=') and not text:
1426 return ['parton','pythia','pgs','delphes']
1427 elif '--laststep=' in line.split()[-1] and line and line[-1] != ' ':
1428 return self.list_completion(text,['parton','pythia','pgs','delphes'],line)
1429
1430 opts = self._run_options + self._generate_options
1431 return self.list_completion(text, opts, line)
1432
1433
1434
1435 if line.endswith('nb_core=') and not text:
1436 import multiprocessing
1437 max = multiprocessing.cpu_count()
1438 return [str(i) for i in range(2,max+1)]
1439 opts = self._run_options + self._generate_options
1440 return self.list_completion(text, opts, line)
1441
1450
1468
1470 """Complete the remove command """
1471
1472 args = self.split_arg(line[0:begidx], error=False)
1473 if len(args) > 1 and (text.startswith('--t')):
1474 run = args[1]
1475 tags = ['--tag=%s' % tag['tag'] for tag in self.results[run]]
1476 return self.list_completion(text, tags)
1477 elif len(args) > 1 and '--' == args[-1]:
1478 run = args[1]
1479 tags = ['tag=%s' % tag['tag'] for tag in self.results[run]]
1480 return self.list_completion(text, tags)
1481 elif len(args) > 1 and '--tag=' == args[-1]:
1482 run = args[1]
1483 tags = [tag['tag'] for tag in self.results[run]]
1484 return self.list_completion(text, tags)
1485 elif len(args) > 1:
1486 return self.list_completion(text, self._clean_mode + ['-f','--tag='])
1487 else:
1488 data = glob.glob(pjoin(self.me_dir, 'Events','*','*_banner.txt'))
1489 data = [n.rsplit('/',2)[1] for n in data]
1490 return self.list_completion(text, ['all'] + data)
1491
1492
1494 "Complete the pythia command"
1495 args = self.split_arg(line[0:begidx], error=False)
1496
1497 if len(args) == 1:
1498
1499 data = glob.glob(pjoin(self.me_dir, 'Events', '*','unweighted_events.lhe.gz'))
1500 data = [n.rsplit('/',2)[1] for n in data]
1501 tmp1 = self.list_completion(text, data)
1502 if not self.run_name:
1503 return tmp1
1504 else:
1505 tmp2 = self.list_completion(text, self._run_options + ['-f',
1506 '--no_default', '--tag='], line)
1507 return tmp1 + tmp2
1508 elif line[-1] != '=':
1509 return self.list_completion(text, self._run_options + ['-f',
1510 '--no_default','--tag='], line)
1511
1513 "Complete the pythia command"
1514 args = self.split_arg(line[0:begidx], error=False)
1515 if len(args) == 1:
1516
1517 data = glob.glob(pjoin(self.me_dir, 'Events', '*', '*_pythia_events.hep.gz'))
1518 data = [n.rsplit('/',2)[1] for n in data]
1519 tmp1 = self.list_completion(text, data)
1520 if not self.run_name:
1521 return tmp1
1522 else:
1523 tmp2 = self.list_completion(text, self._run_options + ['-f',
1524 '--tag=' ,'--no_default'], line)
1525 return tmp1 + tmp2
1526 else:
1527 return self.list_completion(text, self._run_options + ['-f',
1528 '--tag=','--no_default'], line)
1529
1530 complete_delphes = complete_pgs
1531
1532
1533
1534
1535
1536
1537
1538
1539 -class MadEventCmd(CompleteForCmd, CmdExtended, HelpToCmd, common_run.CommonRunCmd):
1540
1541 """The command line processor of MadGraph"""
1542
1543
1544 true = ['T','.true.',True,'true']
1545
1546 _run_options = ['--cluster','--multicore','--nb_core=','--nb_core=2', '-c', '-m']
1547 _generate_options = ['-f', '--laststep=parton', '--laststep=pythia', '--laststep=pgs', '--laststep=delphes']
1548 _calculate_decay_options = ['-f', '--accuracy=0.']
1549 _set_options = ['stdout_level','fortran_compiler','timeout']
1550 _plot_mode = ['all', 'parton','pythia','pgs','delphes','channel', 'banner']
1551 _syscalc_mode = ['all', 'parton','pythia']
1552 _clean_mode = _plot_mode
1553 _display_opts = ['run_name', 'options', 'variable', 'results']
1554 _save_opts = ['options']
1555
1556 _survey_options = {'points':('int', 1000,'Number of points for first iteration'),
1557 'iterations':('int', 5, 'Number of iterations'),
1558 'accuracy':('float', 0.1, 'Required accuracy'),
1559 'gridpack':('str', '.false.', 'Gridpack generation')}
1560
1561 true = ['T','.true.',True,'true', 1, '1']
1562 web = False
1563 cluster_mode = 0
1564 queue = 'madgraph'
1565 nb_core = None
1566
1567 next_possibility = {
1568 'start': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]',
1569 'calculate_decay_widths [OPTIONS]',
1570 'help generate_events'],
1571 'generate_events': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]', 'pythia', 'pgs','delphes'],
1572 'calculate_decay_widths': ['calculate_decay_widths [OPTIONS]',
1573 'generate_events [OPTIONS]'],
1574 'multi_run': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'],
1575 'survey': ['refine'],
1576 'refine': ['combine_events'],
1577 'combine_events': ['store'],
1578 'store': ['pythia'],
1579 'pythia': ['pgs', 'delphes'],
1580 'pgs': ['generate_events [OPTIONS]', 'multi_run [OPTIONS]'],
1581 'delphes' : ['generate_events [OPTIONS]', 'multi_run [OPTIONS]']
1582 }
1583
1584
1585 - def __init__(self, me_dir = None, options={}, *completekey, **stdin):
1586 """ add information to the cmd """
1587
1588 CmdExtended.__init__(self, me_dir, options, *completekey, **stdin)
1589
1590
1591 self.mode = 'madevent'
1592 self.nb_refine=0
1593 if self.web:
1594 os.system('touch %s' % pjoin(self.me_dir,'Online'))
1595
1596
1597
1598 if os.path.exists(pjoin(self.me_dir,'HTML','results.pkl')):
1599 try:
1600 self.results = save_load_object.load_from_file(pjoin(self.me_dir,'HTML','results.pkl'))
1601 except Exception:
1602
1603 model = self.find_model_name()
1604 process = self.process
1605 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
1606 self.results.resetall(self.me_dir)
1607 else:
1608 self.results.resetall(self.me_dir)
1609 else:
1610 model = self.find_model_name()
1611 process = self.process
1612 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
1613 self.results.def_web_mode(self.web)
1614
1615 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir))
1616 self.configured = 0
1617 self._options = {}
1618
1620 """configure web data"""
1621 self.web = True
1622 self.results.def_web_mode(True)
1623 self.force = True
1624 if os.environ['MADGRAPH_BASE']:
1625 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1626
1627
1629 """ Check that the output path is a valid madevent directory """
1630
1631 bin_path = os.path.join(path,'bin')
1632 if os.path.isfile(os.path.join(bin_path,'generate_events')):
1633 return True
1634 else:
1635 return False
1636
1637
1639 """assign all configuration variable from file
1640 loop over the different config file if config_file not define """
1641
1642 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo,
1643 final=final, **opt)
1644 if not final:
1645 return self.options
1646
1647
1648
1649
1650 for key in (k for k in self.options if k.endswith('path')):
1651 path = self.options[key]
1652 if path is None:
1653 continue
1654 if not os.path.isdir(path):
1655 path = pjoin(self.me_dir, self.options[key])
1656 if os.path.isdir(path):
1657 self.options[key] = None
1658 if key == "pythia-pgs_path":
1659 if not os.path.exists(pjoin(path, 'src','pythia')):
1660 logger.info("No valid pythia-pgs path found")
1661 continue
1662 elif key == "delphes_path":
1663 if not os.path.exists(pjoin(path, 'Delphes')) and not\
1664 os.path.exists(pjoin(path, 'DelphesSTDHEP')):
1665 logger.info("No valid Delphes path found")
1666 continue
1667 elif key == "madanalysis_path":
1668 if not os.path.exists(pjoin(path, 'plot_events')):
1669 logger.info("No valid MadAnalysis path found")
1670 continue
1671 elif key == "td_path":
1672 if not os.path.exists(pjoin(path, 'td')):
1673 logger.info("No valid td path found")
1674 continue
1675 elif key == "syscalc_path":
1676 if not os.path.exists(pjoin(path, 'sys_calc')):
1677 logger.info("No valid SysCalc path found")
1678 continue
1679
1680
1681 self.options[key] = os.path.realpath(path)
1682 continue
1683 else:
1684 self.options[key] = None
1685
1686
1687 return self.options
1688
1689
1742
1743
1745 """Make a run from the banner file"""
1746
1747 args = self.split_arg(line)
1748
1749 self.check_banner_run(args)
1750
1751
1752 for name in ['delphes_trigger.dat', 'delphes_card.dat',
1753 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat',
1754 'reweight_card.dat']:
1755 try:
1756 os.remove(pjoin(self.me_dir, 'Cards', name))
1757 except Exception:
1758 pass
1759
1760 banner_mod.split_banner(args[0], self.me_dir, proc_card=False)
1761
1762
1763 if not self.force:
1764 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n'])
1765 if ans == 'n':
1766 self.force = True
1767
1768
1769 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1770
1771
1772
1773
1775 """Display current internal status"""
1776
1777 args = self.split_arg(line)
1778
1779 self.check_display(args)
1780
1781 if args[0] == 'run_name':
1782
1783 data = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt'))
1784 data = [n.rsplit('/',2)[1:] for n in data]
1785
1786 if data:
1787 out = {}
1788 for name, tag in data:
1789 tag = tag[len(name)+1:-11]
1790 if name in out:
1791 out[name].append(tag)
1792 else:
1793 out[name] = [tag]
1794 print 'the runs available are:'
1795 for run_name, tags in out.items():
1796 print ' run: %s' % run_name
1797 print ' tags: ',
1798 print ', '.join(tags)
1799 else:
1800 print 'No run detected.'
1801
1802 elif args[0] == 'options':
1803 outstr = " Run Options \n"
1804 outstr += " ----------- \n"
1805 for key, default in self.options_madgraph.items():
1806 value = self.options[key]
1807 if value == default:
1808 outstr += " %25s \t:\t%s\n" % (key,value)
1809 else:
1810 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1811 outstr += "\n"
1812 outstr += " MadEvent Options \n"
1813 outstr += " ---------------- \n"
1814 for key, default in self.options_madevent.items():
1815 if key in self.options:
1816 value = self.options[key]
1817 else:
1818 default = ''
1819 if value == default:
1820 outstr += " %25s \t:\t%s\n" % (key,value)
1821 else:
1822 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1823 outstr += "\n"
1824 outstr += " Configuration Options \n"
1825 outstr += " --------------------- \n"
1826 for key, default in self.options_configuration.items():
1827 value = self.options[key]
1828 if value == default:
1829 outstr += " %25s \t:\t%s\n" % (key,value)
1830 else:
1831 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1832 output.write(outstr)
1833 elif args[0] == 'results':
1834 self.do_print_results(' '.join(args[1:]))
1835 else:
1836 super(MadEventCmd, self).do_display(line, output)
1837
1838 - def do_save(self, line, check=True, to_keep={}):
1839 """Not in help: Save information to file"""
1840
1841 args = self.split_arg(line)
1842
1843 if check:
1844 self.check_save(args)
1845
1846 if args[0] == 'options':
1847
1848 to_define = {}
1849 for key, default in self.options_configuration.items():
1850 if self.options[key] != self.options_configuration[key]:
1851 to_define[key] = self.options[key]
1852
1853 if not '--auto' in args:
1854 for key, default in self.options_madevent.items():
1855 if self.options[key] != self.options_madevent[key]:
1856 to_define[key] = self.options[key]
1857
1858 if '--all' in args:
1859 for key, default in self.options_madgraph.items():
1860 if self.options[key] != self.options_madgraph[key]:
1861 to_define[key] = self.options[key]
1862 elif not '--auto' in args:
1863 for key, default in self.options_madgraph.items():
1864 if self.options[key] != self.options_madgraph[key]:
1865 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
1866 % (key,self.options_madgraph[key]) )
1867 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
1868 if len(args) >1 and not args[1].startswith('--'):
1869 filepath = args[1]
1870 else:
1871 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1872 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1873 basedir = self.me_dir
1874
1875 if to_keep:
1876 to_define = to_keep
1877 self.write_configuration(filepath, basefile, basedir, to_define)
1878
1879
1880
1881
1882
1883
1884
1885
1886
1888 """Main Commands: launch the full chain """
1889
1890 args = self.split_arg(line)
1891
1892 mode = self.check_generate_events(args)
1893 self.ask_run_configuration(mode)
1894 if not args:
1895
1896 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton')
1897 else:
1898 self.set_run_name(args[0], None, 'parton', True)
1899 args.pop(0)
1900
1901 if self.run_card['gridpack'] in self.true:
1902
1903 gridpack_opts=[('accuracy', 0.01),
1904 ('points', 2000),
1905 ('iterations',8),
1906 ('gridpack','.true.')]
1907 logger.info('Generating gridpack with run name %s' % self.run_name)
1908 self.exec_cmd('survey %s %s' % \
1909 (self.run_name,
1910 " ".join(['--' + opt + '=' + str(val) for (opt,val) \
1911 in gridpack_opts])),
1912 postcmd=False)
1913 self.exec_cmd('combine_events', postcmd=False)
1914 self.exec_cmd('store_events', postcmd=False)
1915 self.exec_cmd('decay_events -from_cards', postcmd=False)
1916 self.exec_cmd('create_gridpack', postcmd=False)
1917 else:
1918
1919 logger.info('Generating %s events with run name %s' %
1920 (self.run_card['nevents'], self.run_name))
1921
1922 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)),
1923 postcmd=False)
1924 if not float(self.results.current['cross']):
1925
1926 text = '''Survey return zero cross section.
1927 Typical reasons are the following:
1928 1) A massive s-channel particle has a width set to zero.
1929 2) The pdf are zero for at least one of the initial state particles
1930 or you are using maxjetflavor=4 for initial state b:s.
1931 3) The cuts are too strong.
1932 Please check/correct your param_card and/or your run_card.'''
1933 logger_stderr.critical(text)
1934 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14')
1935 nb_event = self.run_card['nevents']
1936 self.exec_cmd('refine %s' % nb_event, postcmd=False)
1937 self.exec_cmd('refine %s' % nb_event, postcmd=False)
1938 self.exec_cmd('combine_events', postcmd=False)
1939 self.print_results_in_shell(self.results.current)
1940 self.run_syscalc('parton')
1941 self.create_plot('parton')
1942 self.exec_cmd('store_events', postcmd=False)
1943 self.exec_cmd('reweight -from_cards', postcmd=False)
1944 self.exec_cmd('decay_events -from_cards', postcmd=False)
1945 self.exec_cmd('pythia --no_default', postcmd=False, printcmd=False)
1946
1947 self.store_result()
1948
1949
1956
1958 """Have a nice results prints in the shell,
1959 data should be of type: gen_crossxhtml.OneTagResults"""
1960 if not data:
1961 return
1962 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag']))
1963 if self.ninitial == 1:
1964 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error']))
1965 else:
1966 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error']))
1967 logger.info(" Nb of events : %s" % data['nb_event'] )
1968 if data['cross_pythia'] and data['nb_event_pythia']:
1969 if self.ninitial == 1:
1970 logger.info(" Matched Width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia']))
1971 else:
1972 logger.info(" Matched Cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia']))
1973 logger.info(" Nb of events after Matching : %s" % data['nb_event_pythia'])
1974 if self.run_card['use_syst'] in self.true:
1975 logger.info(" Be carefull that matched information are here NOT for the central value. Refer to SysCalc output for it")
1976
1977 logger.info(" " )
1978
1980 """Have a nice results prints in the shell,
1981 data should be of type: gen_crossxhtml.OneTagResults"""
1982 if not data:
1983 return
1984
1985 fsock = open(path, mode)
1986
1987 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \
1988 (data['run_name'],data['tag'], os.path.basename(self.me_dir)))
1989
1990 if self.ninitial == 1:
1991 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error']))
1992 else:
1993 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error']))
1994 fsock.write(" Nb of events : %s\n" % data['nb_event'] )
1995 if data['cross_pythia'] and data['nb_event_pythia']:
1996 if self.ninitial == 1:
1997 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia']))
1998 else:
1999 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia']))
2000 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia'])
2001 fsock.write(" \n" )
2002
2003
2005 """Main Commands: launch decay width calculation and automatic inclusion of
2006 calculated widths and BRs in the param_card."""
2007
2008 args = self.split_arg(line)
2009
2010 accuracy = self.check_calculate_decay_widths(args)
2011 self.ask_run_configuration('parton')
2012 if not args:
2013
2014 self.set_run_name(self.find_available_run_name(self.me_dir))
2015 else:
2016 self.set_run_name(args[0], reload_card=True)
2017 args.pop(0)
2018
2019 self.configure_directory()
2020
2021
2022 opts=[('accuracy', accuracy),
2023 ('points', 1000),
2024 ('iterations',9)]
2025
2026 logger.info('Calculating decay widths with run name %s' % self.run_name)
2027
2028 self.exec_cmd('survey %s %s' % \
2029 (self.run_name,
2030 " ".join(['--' + opt + '=' + str(val) for (opt,val) \
2031 in opts])),
2032 postcmd=False)
2033 self.exec_cmd('combine_events', postcmd=False)
2034 self.exec_cmd('store_events', postcmd=False)
2035
2036 self.collect_decay_widths()
2037 self.update_status('calculate_decay_widths done',
2038 level='parton', makehtml=False)
2039
2040
2041
2043 """ Collect the decay widths and calculate BRs for all particles, and put
2044 in param_card form.
2045 """
2046
2047 particle_dict = {}
2048 run_name = self.run_name
2049
2050
2051 for P_path in SubProcesses.get_subP(self.me_dir):
2052 ids = SubProcesses.get_subP_ids(P_path)
2053
2054
2055
2056 nb_output = len(ids) / (len(set([p[0] for p in ids])))
2057 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0]
2058 result = float(results.strip().split(' ')[0])
2059 for particles in ids:
2060 try:
2061 particle_dict[particles[0]].append([particles[1:], result/nb_output])
2062 except KeyError:
2063 particle_dict[particles[0]] = [[particles[1:], result/nb_output]]
2064
2065 self.update_width_in_param_card(particle_dict,
2066 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'),
2067 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2068
2069 @staticmethod
2071
2072
2073 if not output:
2074 output = initial
2075
2076 param_card_file = open(initial)
2077 param_card = param_card_file.read().split('\n')
2078 param_card_file.close()
2079
2080 decay_lines = []
2081 line_number = 0
2082
2083 while line_number < len(param_card):
2084 line = param_card[line_number]
2085 if line.lower().startswith('decay'):
2086
2087
2088 line = param_card.pop(line_number)
2089 line = line.split()
2090 particle = 0
2091 if int(line[1]) not in decay_info:
2092 try:
2093 particle = int(line[1])
2094 width = float(line[2])
2095 except Exception:
2096 particle = 0
2097
2098 line = param_card[line_number]
2099 while line.startswith('#') or line.startswith(' '):
2100 line = param_card.pop(line_number)
2101 if not particle or line.startswith('#'):
2102 line=param_card[line_number]
2103 continue
2104
2105 line = line.split()
2106 try:
2107 partial_width = float(line[0])*width
2108 decay_products = [int(p) for p in line[2:2+int(line[1])]]
2109 except Exception:
2110 line=param_card[line_number]
2111 continue
2112 try:
2113 decay_info[particle].append([decay_products, partial_width])
2114 except KeyError:
2115 decay_info[particle] = [[decay_products, partial_width]]
2116 if line_number == len(param_card):
2117 break
2118 line=param_card[line_number]
2119 if particle and particle not in decay_info:
2120
2121 decay_info[particle] = [[[], width]]
2122 else:
2123 line_number += 1
2124
2125 while not param_card[-1] or param_card[-1].startswith('#'):
2126 param_card.pop(-1)
2127
2128
2129 param_card.append("#\n#*************************")
2130 param_card.append("# Decay widths *")
2131 param_card.append("#*************************")
2132 for key in sorted(decay_info.keys()):
2133 width = sum([r for p,r in decay_info[key]])
2134 param_card.append("#\n# PDG Width")
2135 param_card.append("DECAY %i %e" % (key, width.real))
2136 if not width:
2137 continue
2138 if decay_info[key][0][0]:
2139 param_card.append("# BR NDA ID1 ID2 ...")
2140 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]]
2141 for val in sorted(brs, reverse=True):
2142 param_card.append(" %e %i %s # %s" %
2143 (val[0].real, len(val[1]),
2144 " ".join([str(v) for v in val[1]]),
2145 val[0] * width
2146 ))
2147 decay_table = open(output, 'w')
2148 decay_table.write("\n".join(param_card) + "\n")
2149 decay_table.close()
2150 logger.info("Results written to %s" % output)
2151
2152
2153
2155
2156 args = self.split_arg(line)
2157
2158 mode = self.check_multi_run(args)
2159 nb_run = args.pop(0)
2160 if nb_run == 1:
2161 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead")
2162 self.ask_run_configuration(mode)
2163 main_name = self.run_name
2164
2165
2166
2167
2168
2169 crossoversig = 0
2170 inv_sq_err = 0
2171 nb_event = 0
2172 for i in range(nb_run):
2173 self.nb_refine = 0
2174 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False)
2175
2176 nb_event += int(self.results[self.run_name][-1]['nb_event'])
2177 self.results.add_detail('nb_event', nb_event , run=main_name)
2178 cross = self.results[self.run_name][-1]['cross']
2179 error = self.results[self.run_name][-1]['error'] + 1e-99
2180 crossoversig+=cross/error**2
2181 inv_sq_err+=1.0/error**2
2182 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err
2183 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err)
2184 self.results.def_current(main_name)
2185 self.run_name = main_name
2186 self.update_status("Merging LHE files", level='parton')
2187 try:
2188 os.mkdir(pjoin(self.me_dir,'Events', self.run_name))
2189 except Exception:
2190 pass
2191 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'
2192 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'),
2193 'name': self.run_name})
2194
2195 eradir = self.options['exrootanalysis_path']
2196 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')):
2197 self.update_status("Create Root file", level='parton')
2198 misc.gunzip('%s/%s/unweighted_events.lhe.gz' %
2199 (pjoin(self.me_dir,'Events'), self.run_name))
2200
2201 self.create_root_file('%s/unweighted_events.lhe' % self.run_name,
2202 '%s/unweighted_events.root' % self.run_name)
2203
2204 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe")
2205 self.create_plot('parton', path,
2206 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
2207 )
2208
2209
2210 if not os.path.exists('%s.gz' % path):
2211 misc.gzip(path)
2212
2213 self.update_status('', level='parton')
2214 self.print_results_in_shell(self.results.current)
2215
2216
2217
2219 """Advanced commands: create .inc files from param_card.dat/run_card.dat"""
2220
2221
2222 if not mode and not opt:
2223 args = self.split_arg(line)
2224 mode, opt = self.check_treatcards(args)
2225
2226 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat'))
2227
2228
2229 if mode in ['param', 'all']:
2230 model = self.find_model_name()
2231 tmp_model = os.path.basename(model)
2232 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'):
2233 if not '--param_card=' in line:
2234 param_card = pjoin(self.me_dir, 'Cards','param_card.dat')
2235 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat')
2236 check_param_card.convert_to_mg5card(param_card, mg5_param)
2237 check_param_card.check_valid_param_card(mg5_param)
2238 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat')
2239 else:
2240 check_param_card.check_valid_param_card(opt['param_card'])
2241
2242 logger.debug('write compile file for card: %s' % opt['param_card'])
2243 param_card = check_param_card.ParamCard(opt['param_card'])
2244 outfile = pjoin(opt['output_dir'], 'param_card.inc')
2245 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat')
2246 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')):
2247 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')
2248 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')):
2249 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
2250 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')):
2251 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w')
2252 fsock.write(' ')
2253 fsock.close()
2254 if mode == 'all':
2255 self.do_treatcards('', 'run', opt)
2256 return
2257 else:
2258 devnull = open(os.devnull,'w')
2259 subprocess.call([sys.executable, 'write_param_card.py'],
2260 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'),
2261 stdout=devnull)
2262 devnull.close()
2263 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
2264 param_card.write_inc_file(outfile, ident_card, default)
2265
2266
2267 if mode in ['run', 'all']:
2268 if not hasattr(self, 'run_card'):
2269 run_card = banner_mod.RunCard(opt['run_card'])
2270 else:
2271 run_card = self.run_card
2272 if self.ninitial == 1:
2273 run_card['lpp1'] = 0
2274 run_card['lpp2'] = 0
2275 run_card['ebeam1'] = 0
2276 run_card['ebeam2'] = 0
2277
2278 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc'))
2279
2280
2282 """Advanced commands: launch survey for the current process """
2283
2284
2285 args = self.split_arg(line)
2286
2287 self.check_survey(args)
2288
2289
2290 if os.path.exists(pjoin(self.me_dir,'error')):
2291 os.remove(pjoin(self.me_dir,'error'))
2292
2293 self.configure_directory()
2294
2295 self.random_orig = self.random
2296 logger.info("Using random number seed offset = %s" % self.random)
2297
2298 self.update_random()
2299 self.save_random()
2300 self.update_status('Running Survey', level=None)
2301 if self.cluster_mode:
2302 logger.info('Creating Jobs')
2303
2304 logger.info('Working on SubProcesses')
2305 self.total_jobs = 0
2306 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
2307 'subproc.mg'))]
2308
2309 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])):
2310 self.pass_in_difficult_integration_mode()
2311
2312 P_zero_result = []
2313
2314 nb_tot_proc = len(subproc)
2315 for nb_proc,subdir in enumerate(subproc):
2316 self.update_status('Compiling for process %s/%s. <br> (previous processes already running)' % \
2317 (nb_proc+1,nb_tot_proc), level=None)
2318 subdir = subdir.strip()
2319 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
2320 logger.info(' %s ' % subdir)
2321
2322 for match in glob.glob(pjoin(Pdir, '*ajob*')):
2323 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
2324 os.remove(match)
2325 for match in glob.glob(pjoin(Pdir, 'G*')):
2326 if os.path.exists(pjoin(match,'results.dat')):
2327 os.remove(pjoin(match, 'results.dat'))
2328
2329
2330 self.compile(['gensym'], cwd=Pdir)
2331 if not os.path.exists(pjoin(Pdir, 'gensym')):
2332 raise MadEventError, 'Error make gensym not successful'
2333
2334
2335 p = misc.Popen(['./gensym'], stdin=subprocess.PIPE,
2336 stdout=subprocess.PIPE,
2337 stderr=subprocess.STDOUT, cwd=Pdir)
2338 sym_input = "%(points)d %(iterations)d %(accuracy)f \n" % self.opts
2339 (stdout, stderr) = p.communicate(sym_input)
2340 if os.path.exists(pjoin(self.me_dir,'error')):
2341 files.mv(pjoin(self.me_dir,'error'), pjoin(Pdir,'ajob.no_ps.log'))
2342 P_zero_result.append(subdir)
2343 continue
2344
2345 if not os.path.exists(pjoin(Pdir, 'ajob1')) or p.returncode:
2346 logger.critical(stdout)
2347 raise MadEventError, 'Error gensym run not successful'
2348
2349
2350 self.compile(['madevent'], cwd=Pdir)
2351
2352 alljobs = glob.glob(pjoin(Pdir,'ajob*'))
2353 self.total_jobs += len(alljobs)
2354 for i, job in enumerate(alljobs):
2355 job = os.path.basename(job)
2356 self.launch_job('%s' % job, cwd=Pdir, remaining=(len(alljobs)-i-1),
2357 run_type='survey on %s (%s/%s)' % (subdir,nb_proc+1,len(subproc)))
2358 if os.path.exists(pjoin(self.me_dir,'error')):
2359 self.monitor(html=False)
2360 raise MadEventError, 'Error detected Stop running: %s' % \
2361 open(pjoin(self.me_dir,'error')).read()
2362
2363
2364 if P_zero_result:
2365 if len(P_zero_result) == len(subproc):
2366 raise ZeroResult, '%s' % \
2367 open(pjoin(Pdir,'ajob.no_ps.log')).read()
2368 else:
2369 logger.warning(''' %s SubProcesses doesn\'t have available phase-space.
2370 Please check mass spectrum.''' % ','.join(P_zero_result))
2371
2372
2373 self.monitor(run_type='All jobs submitted for survey', html=True)
2374 cross, error = sum_html.make_all_html_results(self)
2375 self.results.add_detail('cross', cross)
2376 self.results.add_detail('error', error)
2377 self.update_status('End survey', 'parton', makehtml=False)
2378
2379
2381 """be more secure for the integration to not miss it due to strong cut"""
2382
2383
2384 if self.opts['points'] == self._survey_options['points'][1]:
2385 self.opts['points'] = 2 * self._survey_options['points'][1]
2386 if self.opts['iterations'] == self._survey_options['iterations'][1]:
2387 self.opts['iterations'] = 1 + self._survey_options['iterations'][1]
2388 if self.opts['accuracy'] == self._survey_options['accuracy'][1]:
2389 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2
2390
2391
2392 conf_path = pjoin(self.me_dir, 'Source','run_config.inc')
2393 files.cp(conf_path, conf_path + '.bk')
2394
2395 text = open(conf_path).read()
2396 text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text)
2397 text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text)
2398 fsock = open(conf_path, 'w')
2399 fsock.write(text)
2400 fsock.close()
2401
2402
2403 for name in ['../bin/internal/gen_ximprove', 'all',
2404 '../bin/internal/combine_events']:
2405 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2406
2407
2408
2409
2410
2411
2412
2413
2415 """Advanced commands: launch survey for the current process """
2416 devnull = open(os.devnull, 'w')
2417 self.nb_refine += 1
2418 args = self.split_arg(line)
2419
2420 self.check_refine(args)
2421
2422 precision = args[0]
2423 if len(args) == 2:
2424 max_process = args[1]
2425 else:
2426 max_process = 5
2427
2428
2429 self.configure_directory()
2430
2431
2432 self.update_random()
2433 self.save_random()
2434
2435 if self.cluster_mode:
2436 logger.info('Creating Jobs')
2437 self.update_status('Refine results to %s' % precision, level=None)
2438
2439 self.total_jobs = 0
2440 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
2441 'subproc.mg'))]
2442 for nb_proc,subdir in enumerate(subproc):
2443 subdir = subdir.strip()
2444 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
2445 bindir = pjoin(os.path.relpath(self.dirbin, Pdir))
2446
2447 logger.info(' %s ' % subdir)
2448
2449 for match in glob.glob(pjoin(Pdir, '*ajob*')):
2450 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
2451 os.remove(match)
2452
2453 proc = misc.Popen([pjoin(bindir, 'gen_ximprove')],
2454 stdout=devnull,
2455 stdin=subprocess.PIPE,
2456 cwd=Pdir)
2457 proc.communicate('%s %s T\n' % (precision, max_process))
2458
2459 if os.path.exists(pjoin(Pdir, 'ajob1')):
2460 self.compile(['madevent'], cwd=Pdir)
2461 alljobs = glob.glob(pjoin(Pdir,'ajob*'))
2462
2463
2464 Gre = re.compile("\s*j=(G[\d\.\w]+)")
2465 for job in alljobs:
2466 Gdirs = Gre.findall(open(job).read())
2467 for Gdir in Gdirs:
2468 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')):
2469 os.remove(pjoin(Pdir, Gdir,'results.dat'))
2470
2471 nb_tot = len(alljobs)
2472 self.total_jobs += nb_tot
2473 for i, job in enumerate(alljobs):
2474 job = os.path.basename(job)
2475 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1),
2476 run_type='Refine number %s on %s (%s/%s)' %
2477 (self.nb_refine, subdir, nb_proc+1, len(subproc)))
2478 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine,
2479 html=True)
2480
2481 self.update_status("Combining runs", level='parton')
2482 try:
2483 os.remove(pjoin(Pdir, 'combine_runs.log'))
2484 except Exception:
2485 pass
2486
2487 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses')))
2488
2489 combine_runs.CombineRuns(self.me_dir)
2490
2491 cross, error = sum_html.make_all_html_results(self)
2492 self.results.add_detail('cross', cross)
2493 self.results.add_detail('error', error)
2494
2495 self.update_status('finish refine', 'parton', makehtml=False)
2496 devnull.close()
2497
2498
2500 """Advanced commands: Launch combine events"""
2501
2502 args = self.split_arg(line)
2503
2504 self.check_combine_events(args)
2505
2506 self.update_status('Combining Events', level='parton')
2507 try:
2508 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log'))
2509 except Exception:
2510 pass
2511 self.cluster.launch_and_wait('../bin/internal/run_combine',
2512 cwd=pjoin(self.me_dir,'SubProcesses'),
2513 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'),
2514 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')])
2515
2516 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read()
2517
2518 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''')
2519 try:
2520 nb_event = pat.search(output).groups()[0]
2521 except AttributeError:
2522 time.sleep(10)
2523 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read()
2524 try:
2525 nb_event = pat.search(output).groups()[0]
2526 except AttributeError:
2527 logger.warning('Fail to read the number of unweighted events in the combine.log file')
2528 nb_event = 0
2529
2530 self.results.add_detail('nb_event', nb_event)
2531
2532
2533
2534 tag = self.run_card['run_tag']
2535
2536 if not self.banner:
2537 self.banner = banner_mod.recover_banner(self.results, 'parton')
2538 self.banner.load_basic(self.me_dir)
2539
2540 self.banner.add_generation_info(self.results.current['cross'], nb_event)
2541 if not hasattr(self, 'random_orig'): self.random_orig = 0
2542 self.banner.change_seed(self.random_orig)
2543 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
2544 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
2545 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name,
2546 '%s_%s_banner.txt' % (self.run_name, tag)))
2547
2548
2549 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'))
2550 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'))
2551
2552
2553 eradir = self.options['exrootanalysis_path']
2554 madir = self.options['madanalysis_path']
2555 td = self.options['td_path']
2556 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\
2557 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')):
2558 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
2559 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
2560 self.create_root_file(output='%s/unweighted_events.root' % \
2561 self.run_name)
2562
2563
2564
2565
2566
2567
2569 """Advanced commands: Launch store events"""
2570
2571 args = self.split_arg(line)
2572
2573 self.check_combine_events(args)
2574 self.update_status('Storing parton level results', level='parton')
2575
2576 run = self.run_name
2577 tag = self.run_card['run_tag']
2578 devnull = open(os.devnull, 'w')
2579
2580 if not os.path.exists(pjoin(self.me_dir, 'Events', run)):
2581 os.mkdir(pjoin(self.me_dir, 'Events', run))
2582 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)):
2583 os.mkdir(pjoin(self.me_dir, 'HTML', run))
2584
2585
2586 input = pjoin(self.me_dir, 'SubProcesses', 'results.dat')
2587 output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run)
2588 files.cp(input, output)
2589
2590
2591 for P_path in SubProcesses.get_subP(self.me_dir):
2592 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and
2593 os.path.isdir(pjoin(P_path,G))]
2594 for G in G_dir:
2595 G_path = pjoin(P_path,G)
2596
2597 if os.path.exists(pjoin(G_path, 'events.lhe')):
2598 os.remove(pjoin(G_path, 'events.lhe'))
2599
2600 if os.path.exists(pjoin(G_path, 'results.dat')):
2601 input = pjoin(G_path, 'results.dat')
2602 output = pjoin(G_path, '%s_results.dat' % run)
2603 files.cp(input, output)
2604
2605 if os.path.exists(pjoin(G_path, 'log.txt')):
2606 input = pjoin(G_path, 'log.txt')
2607 output = pjoin(G_path, '%s_log.txt' % run)
2608 files.mv(input, output)
2609
2610 for name in ['ftn26']:
2611 if os.path.exists(pjoin(G_path, name)):
2612 if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))):
2613 os.remove(pjoin(G_path, '%s_%s.gz'%(run,name)))
2614 input = pjoin(G_path, name)
2615 output = pjoin(G_path, '%s_%s' % (run,name))
2616 files.mv(input, output)
2617 misc.gzip(pjoin(G_path, output), error=None)
2618
2619 if os.path.exists(pjoin(G_path, 'ftn25')):
2620 os.remove(pjoin(G_path, 'ftn25'))
2621
2622
2623 misc.call(['%s/gen_cardhtml-pl' % self.dirbin],
2624 cwd=pjoin(self.me_dir))
2625
2626
2627 E_path = pjoin(self.me_dir, 'Events')
2628 O_path = pjoin(self.me_dir, 'Events', run)
2629
2630 for name in ['events.lhe', 'unweighted_events.lhe']:
2631 if os.path.exists(pjoin(E_path, name)):
2632 if os.path.exists(pjoin(O_path, '%s.gz' % name)):
2633 os.remove(pjoin(O_path, '%s.gz' % name))
2634 input = pjoin(E_path, name)
2635 output = pjoin(O_path, name)
2636 misc.gzip(input, stdout="%s.gz" % output, error=False)
2637
2638 self.update_status('End Parton', level='parton', makehtml=False)
2639 devnull.close()
2640
2641
2643 """ Allow to reweight the events generated with a new choices of model
2644 parameter.
2645 """
2646
2647 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')):
2648 return
2649
2650
2651 if MADEVENT and not self.options['mg5_path']:
2652 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system.
2653 You can install it and set its path in ./Cards/me5_configuration.txt'''
2654 elif MADEVENT:
2655 sys.path.append(self.options['mg5_path'])
2656 try:
2657 import madgraph.interface.reweight_interface as reweight_interface
2658 except ImportError:
2659 raise self.ConfigurationError, '''Can\'t load Reweight module.
2660 The variable mg5_path might not be correctly configured.'''
2661
2662 self.to_store.append('event')
2663 if not '-from_cards' in line:
2664 self.keep_cards(['reweight_card.dat'])
2665 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False)
2666
2667
2668 if self.results.current['cross'] == 0 and self.run_name:
2669 self.results.delete_run(self.run_name, self.run_tag)
2670
2671
2672 args = self.split_arg(line)
2673 self.check_decay_events(args)
2674
2675 reweight_cmd = reweight_interface.ReweightInterface(args[0])
2676 reweight_cmd. mother = self
2677 self.update_status('Running Reweight', level='madspin')
2678
2679
2680 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat')
2681 reweight_cmd.me_dir = self.me_dir
2682 reweight_cmd.import_command_file(path)
2683
2684
2685 try:
2686 self.results.def_current(self.run_name, self.run_tag)
2687 except Exception:
2688 pass
2689
2690
2692 """Advanced commands: Create gridpack from present run"""
2693
2694 self.update_status('Creating gridpack', level='parton')
2695 args = self.split_arg(line)
2696 self.check_combine_events(args)
2697 if not self.run_tag: self.run_tag = 'tag_1'
2698 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \
2699 % self.me_dir)
2700 misc.call(['./bin/internal/restore_data', self.run_name],
2701 cwd=self.me_dir)
2702 misc.call(['./bin/internal/store4grid',
2703 self.run_name, self.run_tag],
2704 cwd=self.me_dir)
2705 misc.call(['./bin/internal/clean'], cwd=self.me_dir)
2706 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir)
2707 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'),
2708 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name))
2709 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \
2710 % self.me_dir)
2711 self.update_status('gridpack created', level='gridpack')
2712
2713
2715 """launch pythia"""
2716
2717
2718 args = self.split_arg(line)
2719 if '--no_default' in args:
2720 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')):
2721 return
2722 no_default = True
2723 args.remove('--no_default')
2724 else:
2725 no_default = False
2726
2727 if not self.run_name:
2728 self.check_pythia(args)
2729 self.configure_directory(html_opening =False)
2730 else:
2731
2732 self.configure_directory(html_opening =False)
2733 self.check_pythia(args)
2734
2735
2736 if not no_default:
2737 self.ask_pythia_run_configuration(args[-1])
2738
2739 if self.options['automatic_html_opening']:
2740 misc.open_file(os.path.join(self.me_dir, 'crossx.html'))
2741 self.options['automatic_html_opening'] = False
2742
2743
2744 if not self.banner:
2745 self.banner = banner_mod.recover_banner(self.results, 'pythia')
2746
2747
2748
2749 pythia_src = pjoin(self.options['pythia-pgs_path'],'src')
2750
2751 self.update_status('Running Pythia', 'pythia')
2752 try:
2753 os.remove(pjoin(self.me_dir,'Events','pythia.done'))
2754 except Exception:
2755 pass
2756
2757
2758 tag = self.run_tag
2759 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag)
2760 self.cluster.launch_and_wait('../bin/internal/run_pythia',
2761 argument= [pythia_src], stdout= pythia_log,
2762 stderr=subprocess.STDOUT,
2763 cwd=pjoin(self.me_dir,'Events'))
2764
2765 if not os.path.exists(pjoin(self.me_dir,'Events','pythia.done')):
2766 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log)
2767 return
2768 else:
2769 os.remove(pjoin(self.me_dir,'Events','pythia.done'))
2770
2771 self.to_store.append('pythia')
2772
2773
2774 if int(self.run_card['ickkw']):
2775
2776 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name,
2777 '%s_pythia.log' % tag))
2778 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")
2779 for line in pythia_log:
2780 info = pythiare.search(line)
2781 if not info:
2782 continue
2783 try:
2784
2785 sigma_m = float(info.group('xsec').replace('D','E')) *1e9
2786 Nacc = int(info.group('generated'))
2787 Ntry = int(info.group('tried'))
2788 except ValueError:
2789
2790 self.results.add_detail('cross_pythia', 0)
2791 self.results.add_detail('nb_event_pythia', 0)
2792 self.results.add_detail('error_pythia', 0)
2793 else:
2794 self.results.add_detail('cross_pythia', sigma_m)
2795 self.results.add_detail('nb_event_pythia', Nacc)
2796
2797 error = self.results[self.run_name].return_tag(self.run_tag)['error']
2798 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc)
2799
2800 self.results.add_detail('error_pythia', error_m)
2801 break
2802
2803 pythia_log.close()
2804
2805 pydir = pjoin(self.options['pythia-pgs_path'], 'src')
2806 eradir = self.options['exrootanalysis_path']
2807 madir = self.options['madanalysis_path']
2808 td = self.options['td_path']
2809
2810
2811
2812 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat'))
2813 if int(self.run_card['ickkw']):
2814
2815 if 'MGGenerationInfo' in self.banner:
2816 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
2817 else:
2818 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
2819 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))
2820 self.banner.write(banner_path)
2821
2822
2823 self.run_hep2lhe(banner_path)
2824 if int(self.run_card['ickkw']):
2825 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'),
2826 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz'))
2827
2828 if self.run_card['use_syst'] in self.true:
2829
2830 try:
2831 self.run_syscalc('Pythia')
2832 except SysCalcError, error:
2833 logger.error(str(error))
2834 else:
2835
2836 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'),
2837 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz'))
2838
2839
2840 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')):
2841 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
2842 '%s_syscalc.dat' % self.run_tag)
2843 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'),
2844 stdout = "%s.gz" % filename)
2845
2846
2847 self.create_plot('Pythia')
2848
2849 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')):
2850 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'),
2851 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag))
2852
2853 self.update_status('finish', level='pythia', makehtml=False)
2854 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False)
2855 if self.options['delphes_path']:
2856 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False)
2857 self.print_results_in_shell(self.results.current)
2858
2859
2860
2862 """Remove one/all run or only part of it"""
2863
2864 args = self.split_arg(line)
2865 run, tag, mode = self.check_remove(args)
2866 if 'banner' in mode:
2867 mode.append('all')
2868
2869
2870 if run == 'all':
2871
2872 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')):
2873 logger.warning('A run with name all exists. So we will not supress all processes.')
2874 else:
2875 for match in glob.glob(pjoin(self.me_dir, 'Events','*','*_banner.txt')):
2876 run = match.rsplit(os.path.sep,2)[1]
2877 try:
2878 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) )
2879 except self.InvalidCmd, error:
2880 logger.info(error)
2881 pass
2882 return
2883
2884
2885 if not os.path.exists(pjoin(self.me_dir, 'Events', run)):
2886 raise self.InvalidCmd('No run \'%s\' detected' % run)
2887
2888 try:
2889 self.resuls.def_current(run)
2890 self.update_status(' Cleaning %s' % run, level=None)
2891 except Exception:
2892 misc.sprint('fail to update results or html status')
2893 pass
2894
2895
2896
2897
2898 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*'))
2899 to_delete += glob.glob(pjoin(self.me_dir, 'HTML', run, '*'))
2900
2901 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f]
2902 if tag:
2903 to_delete = [f for f in to_delete if tag in f]
2904 if 'parton' in mode or 'all' in mode:
2905 try:
2906 if self.results[run][0]['tag'] != tag:
2907 raise Exception, 'dummy'
2908 except Exception:
2909 pass
2910 else:
2911 nb_rm = len(to_delete)
2912 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')):
2913 to_delete.append('events.lhe.gz')
2914 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')):
2915 to_delete.append('unweighted_events.lhe.gz')
2916 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')):
2917 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html'))
2918 if nb_rm != len(to_delete):
2919 logger.warning('Be carefull that partonic information are on the point to be removed.')
2920 if 'all' in mode:
2921 pass
2922 else:
2923 if 'pythia' not in mode:
2924 to_delete = [f for f in to_delete if 'pythia' not in f]
2925 if 'pgs' not in mode:
2926 to_delete = [f for f in to_delete if 'pgs' not in f]
2927 if 'delphes' not in mode:
2928 to_delete = [f for f in to_delete if 'delphes' not in f]
2929 if 'parton' not in mode:
2930 to_delete = [f for f in to_delete if 'delphes' in f
2931 or 'pgs' in f
2932 or 'pythia' in f]
2933 if not self.force and len(to_delete):
2934 question = 'Do you want to delete the following files?\n %s' % \
2935 '\n '.join(to_delete)
2936 ans = self.ask(question, 'y', choices=['y','n'])
2937 else:
2938 ans = 'y'
2939
2940 if ans == 'y':
2941 for file2rm in to_delete:
2942 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)):
2943 try:
2944 os.remove(pjoin(self.me_dir, 'Events', run, file2rm))
2945 except Exception:
2946 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm))
2947 else:
2948 try:
2949 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm))
2950 except Exception:
2951 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm))
2952
2953
2954
2955
2956 if 'all' in mode or 'channel' in mode:
2957 try:
2958 if tag and self.results[run][0]['tag'] != tag:
2959 raise Exception, 'dummy'
2960 except Exception:
2961 pass
2962 else:
2963 to_delete = glob.glob(pjoin(self.me_dir, 'SubProcesses', '%s*' % run))
2964 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','%s*' % run))
2965 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','*','%s*' % run))
2966
2967 if self.force or len(to_delete) == 0:
2968 ans = 'y'
2969 else:
2970 question = 'Do you want to delete the following files?\n %s' % \
2971 '\n '.join(to_delete)
2972 ans = self.ask(question, 'y', choices=['y','n'])
2973
2974 if ans == 'y':
2975 for file2rm in to_delete:
2976 os.remove(file2rm)
2977
2978 if 'banner' in mode:
2979 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*'))
2980 if tag:
2981
2982 try:
2983 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag)))
2984 except Exception:
2985 logger.warning('fail to remove the banner')
2986
2987 if run in self.results:
2988 self.results.delete_run(run, tag)
2989 return
2990 elif any(['banner' not in os.path.basename(p) for p in to_delete]):
2991 if to_delete:
2992 raise MadGraph5Error, '''Some output still exists for this run.
2993 Please remove those output first. Do for example:
2994 remove %s all banner
2995 ''' % run
2996 else:
2997 shutil.rmtree(pjoin(self.me_dir, 'Events',run))
2998 if run in self.results:
2999 self.results.delete_run(run)
3000 return
3001 else:
3002 logger.info('''The banner is not removed. In order to remove it run:
3003 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or ''))
3004
3005
3006 self.results.clean(mode, run, tag)
3007 self.update_status('', level='all')
3008
3009
3010
3011
3013 """Create the plot for a given run"""
3014
3015
3016 self.store_result()
3017 args = self.split_arg(line)
3018
3019 self.check_plot(args)
3020 logger.info('plot for run %s' % self.run_name)
3021 if not self.force:
3022 self.ask_edit_cards([], args, plot=True)
3023
3024 if any([arg in ['all','parton'] for arg in args]):
3025 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe')
3026 if os.path.exists(filename+'.gz'):
3027 misc.gunzip('%s.gz' % filename)
3028 if os.path.exists(filename):
3029 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
3030 self.create_plot('parton')
3031 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
3032 stdout= "%s.gz" % filename)
3033 else:
3034 logger.info('No valid files for partonic plot')
3035
3036 if any([arg in ['all','pythia'] for arg in args]):
3037 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
3038 '%s_pythia_events.lhe' % self.run_tag)
3039 if os.path.exists(filename+'.gz'):
3040 misc.gunzip("%s.gz" % filename)
3041 if os.path.exists(filename):
3042 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe'))
3043 self.create_plot('Pythia')
3044 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'),
3045 stdout= "%s.gz" % filename)
3046 else:
3047 logger.info('No valid files for pythia plot')
3048
3049
3050 if any([arg in ['all','pgs'] for arg in args]):
3051 filename = pjoin(self.me_dir, 'Events', self.run_name,
3052 '%s_pgs_events.lhco' % self.run_tag)
3053 if os.path.exists(filename+'.gz'):
3054 misc.gunzip("%s.gz" % filename)
3055 if os.path.exists(filename):
3056 self.create_plot('PGS')
3057 misc.gzip(filename)
3058 else:
3059 logger.info('No valid files for pgs plot')
3060
3061 if any([arg in ['all','delphes'] for arg in args]):
3062 filename = pjoin(self.me_dir, 'Events', self.run_name,
3063 '%s_delphes_events.lhco' % self.run_tag)
3064 if os.path.exists(filename+'.gz'):
3065 misc.gunzip("%s.gz" % filename)
3066 if os.path.exists(filename):
3067 self.create_plot('Delphes')
3068 misc.gzip(filename)
3069 else:
3070 logger.info('No valid files for delphes plot')
3071
3072
3074 """Evaluate systematics variation weights for a given run"""
3075
3076
3077 self.store_result()
3078 args = self.split_arg(line)
3079
3080 self.check_syscalc(args)
3081 if self.ninitial == 1:
3082 logger.error('SysCalc can\'t be run for decay processes')
3083 return
3084
3085 logger.info('Calculating systematics for run %s' % self.run_name)
3086
3087 self.ask_edit_cards(['run_card'], args)
3088
3089 if any([arg in ['all','parton'] for arg in args]):
3090 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe')
3091 if os.path.exists(filename+'.gz'):
3092 misc.gunzip("%s.gz" % filename)
3093 if os.path.exists(filename):
3094 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
3095 self.run_syscalc('parton')
3096 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
3097 stdout="%s.gz" % filename)
3098 else:
3099 logger.info('No valid files for parton level systematics run.')
3100
3101 if any([arg in ['all','pythia'] for arg in args]):
3102 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
3103 '%s_pythia_syst.dat' % self.run_tag)
3104 if os.path.exists(filename+'.gz'):
3105 misc.gunzip("%s.gz" % filename)
3106 if os.path.exists(filename):
3107 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat'))
3108 try:
3109 self.run_syscalc('Pythia')
3110 except SysCalcError, error:
3111 logger.warning(str(error))
3112 return
3113 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename)
3114 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
3115 '%s_syscalc.dat' % self.run_tag)
3116 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'),
3117 stdout=filename)
3118 else:
3119 logger.info('No valid files for pythia level')
3120
3121
3123 """ tar the pythia results. This is done when we are quite sure that
3124 the pythia output will not be use anymore """
3125
3126 if not self.run_name:
3127 return
3128
3129 self.results.save()
3130
3131
3132 if not self.to_store:
3133 return
3134
3135 tag = self.run_card['run_tag']
3136 self.update_status('storring files of Previous run', level=None,\
3137 error=True)
3138 if 'event' in self.to_store:
3139 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')):
3140 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe"))
3141
3142 if 'pythia' in self.to_store:
3143 self.update_status('Storing Pythia files of Previous run', level='pythia', error=True)
3144
3145 p = pjoin(self.me_dir,'Events')
3146 n = self.run_name
3147 t = tag
3148 misc.gzip(pjoin(p,'pythia_events.hep'),
3149 stdout=pjoin(p,'%s/%s_pythia_events.hep' % (n,t)))
3150
3151 self.to_store.remove('pythia')
3152 self.update_status('Done', level='pythia',makehtml=False,error=True)
3153
3154 self.to_store = []
3155
3156 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0,
3157 run_type='', mode=None, **opt):
3158 """ """
3159 argument = [str(arg) for arg in argument]
3160 if mode is None:
3161 mode = self.cluster_mode
3162
3163
3164 if os.path.exists(exe) and not os.access(exe, os.X_OK):
3165 os.system('chmod +x %s ' % exe)
3166 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \
3167 os.access(pjoin(cwd, exe), os.X_OK):
3168 os.system('chmod +x %s ' % pjoin(cwd, exe))
3169
3170 if mode == 0:
3171 self.update_status((remaining, 1,
3172 self.total_jobs - remaining -1, run_type), level=None, force=False)
3173 start = time.time()
3174
3175 status = misc.call(['./'+exe] + argument, cwd=cwd,
3176 stdout=stdout, **opt)
3177 logger.info('%s run in %f s' % (exe, time.time() -start))
3178 if status:
3179 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe
3180
3181
3182 elif mode in [1,2]:
3183
3184 if 'ajob' in exe:
3185 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat',
3186 pjoin(self.me_dir, 'SubProcesses','randinit')]
3187 output_files = []
3188 required_output = []
3189
3190
3191
3192 input_files.append(self.get_pdf_input_filename())
3193
3194
3195 Gre = re.compile("\s*j=(G[\d\.\w]+)")
3196 Ire = re
3197 try :
3198 fsock = open(exe)
3199 except Exception:
3200 fsock = open(pjoin(cwd,exe))
3201 text = fsock.read()
3202 output_files = Gre.findall(text)
3203 if not output_files:
3204 Ire = re.compile("for i in ([\d\.\s]*) ; do")
3205 data = Ire.findall(text)
3206 data = ' '.join(data).split()
3207 for nb in data:
3208 output_files.append('G%s' % nb)
3209 required_output.append('G%s/results.dat' % nb)
3210 else:
3211 for G in output_files:
3212 if os.path.isdir(pjoin(cwd,G)):
3213 input_files.append(G)
3214 required_output.append('%s/results.dat' % G)
3215
3216
3217 self.cluster.submit2(exe, stdout=stdout, cwd=cwd,
3218 input_files=input_files, output_files=output_files,
3219 required_output=required_output)
3220
3221 else:
3222 self.cluster.submit(exe, stdout=stdout, cwd=cwd)
3223
3224
3225
3227 """Find if Madevent is in Group mode or not"""
3228
3229
3230
3231 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc')
3232 text = open(file_path).read()
3233 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M):
3234 return 'group'
3235 else:
3236 return 'v4'
3237
3238
3239 - def monitor(self, run_type='monitor', mode=None, html=False):
3240 """ monitor the progress of running job """
3241
3242 starttime = time.time()
3243 if mode is None:
3244 mode = self.cluster_mode
3245 if mode > 0:
3246 if html:
3247 update_status = lambda idle, run, finish: \
3248 self.update_status((idle, run, finish, run_type), level=None,
3249 force=False, starttime=starttime)
3250 else:
3251 update_status = lambda idle, run, finish: None
3252 try:
3253 self.cluster.wait(self.me_dir, update_status)
3254 except Exception, error:
3255 logger.info(error)
3256 if not self.force:
3257 ans = self.ask('Cluster Error detected. Do you want to clean the queue?',
3258 default = 'y', choices=['y','n'])
3259 else:
3260 ans = 'y'
3261 if ans == 'y':
3262 self.cluster.remove()
3263 raise
3264 except KeyboardInterrupt, error:
3265 self.cluster.remove()
3266 raise
3267
3268
3269
3270
3349
3350
3351
3352
3353
3354 @staticmethod
3356 """check if the directory exists. if so return the path otherwise the
3357 default"""
3358
3359 if os.path.isdir(path):
3360 return path
3361 else:
3362 return default
3363
3364
3365 - def set_run_name(self, name, tag=None, level='parton', reload_card=False,
3366 allow_new_tag=True):
3367 """define the run name, the run_tag, the banner and the results."""
3368
3369
3370 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes'],
3371 'pythia': ['pythia','pgs','delphes'],
3372 'pgs': ['pgs'],
3373 'delphes':['delphes'],
3374 'plot':[],
3375 'syscalc':[]}
3376
3377
3378
3379 if name == self.run_name:
3380 if reload_card:
3381 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
3382 self.run_card = banner_mod.RunCard(run_card)
3383
3384
3385 if tag:
3386 self.run_card['run_tag'] = tag
3387 self.run_tag = tag
3388 self.results.add_run(self.run_name, self.run_card)
3389 else:
3390 for tag in upgrade_tag[level]:
3391 if getattr(self.results[self.run_name][-1], tag):
3392 tag = self.get_available_tag()
3393 self.run_card['run_tag'] = tag
3394 self.run_tag = tag
3395 self.results.add_run(self.run_name, self.run_card)
3396 break
3397 return
3398
3399
3400 if self.run_name:
3401 self.store_result()
3402
3403 self.run_name = name
3404
3405 new_tag = False
3406
3407 self.banner = banner_mod.recover_banner(self.results, level, name)
3408 if 'mgruncard' in self.banner:
3409 self.run_card = self.banner.charge_card('run_card')
3410 else:
3411
3412 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
3413 self.run_card = banner_mod.RunCard(run_card)
3414
3415 if tag:
3416 self.run_card['run_tag'] = tag
3417 new_tag = True
3418 elif not self.run_name in self.results and level =='parton':
3419 pass
3420 elif not self.run_name in self.results:
3421
3422 logger.warning('Trying to run data on unknown run.')
3423 self.results.add_run(name, self.run_card)
3424 self.results.update('add run %s' % name, 'all', makehtml=False)
3425 else:
3426 for tag in upgrade_tag[level]:
3427
3428 if getattr(self.results[self.run_name][-1], tag):
3429
3430 tag = self.get_available_tag()
3431 self.run_card['run_tag'] = tag
3432 new_tag = True
3433 break
3434 if not new_tag:
3435
3436 tag = self.results[self.run_name][-1]['tag']
3437 self.run_card['run_tag'] = tag
3438
3439 if allow_new_tag and (name in self.results and not new_tag):
3440 self.results.def_current(self.run_name)
3441 else:
3442 self.results.add_run(self.run_name, self.run_card)
3443
3444 self.run_tag = self.run_card['run_tag']
3445
3446
3447
3448 if level == 'parton':
3449 return
3450 elif level == 'pythia':
3451 return self.results[self.run_name][0]['tag']
3452 else:
3453 for i in range(-1,-len(self.results[self.run_name])-1,-1):
3454 tagRun = self.results[self.run_name][i]
3455 if tagRun.pythia:
3456 return tagRun['tag']
3457
3458
3459
3460
3461
3462
3463
3464
3465
3467 """ return the model name """
3468 if hasattr(self, 'model_name'):
3469 return self.model_name
3470
3471 model = 'sm'
3472 proc = []
3473 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')):
3474 line = line.split('#')[0]
3475
3476 if line.startswith('import') and 'model' in line:
3477 model = line.split()[2]
3478 proc = []
3479 elif line.startswith('generate'):
3480 proc.append(line.split(None,1)[1])
3481 elif line.startswith('add process'):
3482 proc.append(line.split(None,2)[2])
3483
3484 self.model = model
3485 self.process = proc
3486 return model
3487
3488
3489
3491 """Find the number of event in the run_card, and check that this is not
3492 too large"""
3493
3494
3495 nb_event = int(self.run_card['nevents'])
3496 if nb_event > 1000000:
3497 logger.warning("Attempting to generate more than 1M events")
3498 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.")
3499 path = pjoin(self.me_dir, 'Cards', 'run_card.dat')
3500 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \
3501 % path)
3502 self.run_card['nevents'] = 1000000
3503
3504 return
3505
3506
3507
3509 """ change random number"""
3510
3511 self.random += 3
3512 if self.random > 30081*30081:
3513 raise MadGraph5Error,\
3514 'Random seed too large ' + str(self.random) + ' > 30081*30081'
3515
3516
3518 """save random number in appropirate file"""
3519
3520 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w')
3521 fsock.writelines('r=%s\n' % self.random)
3522
3523 - def do_quit(self, *args, **opts):
3527
3528
3530 """check for ckkw"""
3531
3532 lpp1 = self.run_card['lpp1']
3533 lpp2 = self.run_card['lpp2']
3534 e1 = self.run_card['ebeam1']
3535 e2 = self.run_card['ebeam2']
3536 pd = self.run_card['pdlabel']
3537 lha = self.run_card['lhaid']
3538 xq = self.run_card['xqcut']
3539 translation = {'e1': e1, 'e2':e2, 'pd':pd,
3540 'lha':lha, 'xq':xq}
3541
3542 if lpp1 or lpp2:
3543
3544 if pd.startswith("'"):
3545 pd = pd[1:]
3546 if pd.endswith("'"):
3547 pd = pd[:-1]
3548
3549 if xq >2 or xq ==2:
3550 xq = 2
3551
3552
3553 if pd == "lhapdf":
3554 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz'
3555 else:
3556 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz'
3557 if self.web:
3558 issudfile = pjoin(self.webbin, issudfile % translation)
3559 else:
3560 issudfile = pjoin(self.me_dir, issudfile % translation)
3561
3562 logger.info('Sudakov grid file: %s' % issudfile)
3563
3564
3565 if os.path.exists(issudfile):
3566 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat')
3567 misc.gunzip(issudfile, keep=True, stdout=path)
3568 else:
3569 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while'
3570 logger.info(msg)
3571 self.update_status('GENERATE SUDAKOF GRID', level='parton')
3572
3573 for i in range(-2,6):
3574 self.cluster.submit('%s/gensudgrid ' % self.dirbin,
3575 arguments = [i],
3576 cwd=self.me_dir,
3577 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i,'w')))
3578 self.monitor()
3579 for i in range(-2,6):
3580 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat')
3581 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path))
3582 misc.gzip(path, stdout=issudfile)
3583
3584
3585 - def create_root_file(self, input='unweighted_events.lhe',
3586 output='unweighted_events.root' ):
3587 """create the LHE root file """
3588 self.update_status('Creating root files', level='parton')
3589
3590 eradir = self.options['exrootanalysis_path']
3591 try:
3592 misc.call(['%s/ExRootLHEFConverter' % eradir,
3593 input, output],
3594 cwd=pjoin(self.me_dir, 'Events'))
3595 except Exception:
3596 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
3597
3598 - def run_syscalc(self, mode='parton', event_path=None, output=None):
3599 """create the syscalc output"""
3600
3601 logger.info('running syscalc on mode %s' % mode)
3602 if self.run_card['use_syst'] not in self.true:
3603 return
3604
3605 scdir = self.options['syscalc_path']
3606 tag = self.run_card['run_tag']
3607 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat')
3608 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read()
3609 self.run_card['sys_pdf'] = self.run_card['sys_pdf'].split('#',1)[0].replace('&&',' \n ')
3610
3611 if not 'sys_scalecorrelation' in self.run_card:
3612 self.run_card['sys_scalecorrelation'] = -1
3613 open(card,'w').write(template % self.run_card)
3614
3615 if not scdir or \
3616 not os.path.exists(card):
3617 return False
3618 event_dir = pjoin(self.me_dir, 'Events')
3619
3620 if not event_path:
3621 if mode == 'parton':
3622 event_path = pjoin(event_dir,'unweighted_events.lhe')
3623 output = pjoin(event_dir, 'syscalc.lhe')
3624 elif mode == 'Pythia':
3625 if 'mgpythiacard' in self.banner:
3626 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I)
3627 data = pat.search(self.banner['mgpythiacard'])
3628 if data:
3629 qcut = float(data.group(1))
3630 xqcut = abs(self.run_card['xqcut'])
3631 for value in self.run_card['sys_matchscale'].split():
3632 if float(value) < qcut:
3633 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc'
3634 if float(value) < xqcut:
3635 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc'
3636
3637
3638 event_path = pjoin(event_dir,'syst.dat')
3639 output = pjoin(event_dir, 'syscalc.dat')
3640 else:
3641 raise self.InvalidCmd, 'Invalid mode %s' % mode
3642
3643 if not os.path.exists(event_path):
3644 if os.path.exists(event_path+'.gz'):
3645 misc.gzip(event_path)
3646 else:
3647 raise SysCalcError, 'Events file %s does not exits' % event_path
3648
3649 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower())
3650 try:
3651 proc = misc.call([os.path.join(scdir, 'sys_calc'),
3652 event_path, card, output],
3653 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w'),
3654 stderr = subprocess.STDOUT,
3655 cwd=event_dir)
3656
3657 time.sleep(5)
3658 except OSError, error:
3659 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error)
3660 else:
3661 if mode == 'parton' and os.path.exists(output):
3662 files.mv(output, event_path)
3663 else:
3664 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?')
3665 self.update_status('End syscalc for %s level' % mode, level = mode.lower(),
3666 makehtml=False)
3667
3668 return True
3669
3670
3671
3672
3674 """Ask the question when launching generate_events/multi_run"""
3675
3676 available_mode = ['0']
3677 void = 'NOT INSTALLED'
3678 switch_order = ['pythia', 'pgs', 'delphes', 'madspin', 'reweight']
3679 switch = {'pythia': void, 'pgs': void, 'delphes': void,
3680 'madspin': void, 'reweight': void}
3681 description = {'pythia': 'Run the pythia shower/hadronization:',
3682 'pgs': 'Run PGS as detector simulator:',
3683 'delphes':'Run Delphes as detector simulator:',
3684 'madspin':'Decay particles with the MadSpin module:',
3685 'reweight':'Add weight to events based on coupling parameters:',
3686 }
3687 force_switch = {('pythia', 'OFF'): {'pgs': 'OFF', 'delphes': 'OFF'},
3688 ('pgs', 'ON'): {'pythia':'ON'},
3689 ('delphes', 'ON'): {'pythia': 'ON'}}
3690 switch_assign = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void )
3691
3692
3693
3694 if self.options['pythia-pgs_path']:
3695 available_mode.append('1')
3696 available_mode.append('2')
3697 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')):
3698 switch['pythia'] = 'ON'
3699 else:
3700 switch['pythia'] = 'OFF'
3701 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')):
3702 switch['pgs'] = 'ON'
3703 else:
3704 switch['pgs'] = 'OFF'
3705 if self.options['delphes_path']:
3706 available_mode.append('3')
3707 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')):
3708 switch['delphes'] = 'ON'
3709 else:
3710 switch['delphes'] = 'OFF'
3711
3712
3713 if not MADEVENT or self.options['mg5_path']:
3714 available_mode.append('4')
3715 available_mode.append('5')
3716 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')):
3717 switch['madspin'] = 'ON'
3718 else:
3719 switch['madspin'] = 'OFF'
3720 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')):
3721 switch['reweight'] = 'ON'
3722 else:
3723 switch['reweight'] = 'OFF'
3724
3725
3726
3727 options = list(available_mode) + ['auto', 'done']
3728 for id, key in enumerate(switch_order):
3729 if switch[key] != void:
3730 options += ['%s=%s' % (key, s) for s in ['ON','OFF']]
3731 options.append(key)
3732 options.append('parton')
3733
3734
3735 if mode or not self.force:
3736 answer = ''
3737 while answer not in ['0', 'done', 'auto']:
3738 if mode:
3739 answer = mode
3740 else:
3741 switch_format = " %i %-50s %10s=%s\n"
3742 question = "The following switches determine which programs are run:\n"
3743 for id, key in enumerate(switch_order):
3744 question += switch_format % (id+1, description[key], key, switch[key])
3745 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1)
3746 question += ' or set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n'
3747 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n'
3748 answer = self.ask(question, '0', options)
3749 if answer.isdigit() and answer != '0':
3750 key = switch_order[int(answer) - 1]
3751 answer = '%s=%s' % (key, 'ON' if switch[key] == 'OFF' else 'OFF')
3752
3753 if '=' in answer:
3754 key, status = answer.split('=')
3755 switch[key] = status
3756 if (key, status) in force_switch:
3757 for key2, status2 in force_switch[(key, status)].items():
3758 if switch[key2] not in [status2, void]:
3759 logger.info('For coherence \'%s\' is set to \'%s\''
3760 % (key2, status2), '$MG:color:BLACK')
3761 switch[key2] = status2
3762 elif answer in ['0', 'auto', 'done']:
3763 continue
3764 else:
3765 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK')
3766 switch_assign('madspin', 'OFF')
3767 switch_assign('reweight', 'OFF')
3768 if answer == 'parton':
3769 switch_assign('pythia', 'OFF')
3770 switch_assign('pgs', 'OFF')
3771 switch_assign('delphes', 'OFF')
3772 elif answer == 'pythia':
3773 switch_assign('pythia', 'ON')
3774 switch_assign('pgs', 'OFF')
3775 switch_assign('delphes', 'OFF')
3776 elif answer == 'pgs':
3777 switch_assign('pythia', 'ON')
3778 switch_assign('pgs', 'ON')
3779 switch_assign('delphes', 'OFF')
3780 elif answer == 'delphes':
3781 switch_assign('pythia', 'ON')
3782 switch_assign('pgs', 'OFF')
3783 switch_assign('delphes', 'ON')
3784 elif answer == 'madspin':
3785 switch_assign('madspin', 'ON')
3786 switch_assign('pythia', 'OFF')
3787 switch_assign('pgs', 'OFF')
3788 switch_assign('delphes', 'OF')
3789 elif answer == 'reweight':
3790 switch_assign('reweight', 'ON')
3791 switch_assign('pythia', 'OFF')
3792 switch_assign('pgs', 'OFF')
3793 switch_assign('delphes', 'OFF')
3794
3795
3796 if mode:
3797 answer = '0'
3798 else:
3799 answer = 'auto'
3800
3801
3802
3803
3804 cards = ['param_card.dat', 'run_card.dat']
3805 if switch['pythia'] == 'ON':
3806 cards.append('pythia_card.dat')
3807 if switch['pgs'] == 'ON':
3808 cards.append('pgs_card.dat')
3809 if switch['delphes'] == 'ON':
3810 cards.append('delphes_card.dat')
3811 delphes3 = True
3812 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
3813 delphes3 = False
3814 cards.append('delphes_trigger.dat')
3815 if switch['madspin'] == 'ON':
3816 cards.append('madspin_card.dat')
3817 if switch['reweight'] == 'ON':
3818 cards.append('reweight_card.dat')
3819 self.keep_cards(cards)
3820 if self.force:
3821 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' ))
3822 return
3823
3824 if answer == 'auto':
3825 self.ask_edit_cards(cards, mode='auto')
3826 else:
3827 self.ask_edit_cards(cards)
3828 return
3829
3830
3832 """Ask the question when launching pythia"""
3833
3834 available_mode = ['0', '1', '2']
3835 if self.options['delphes_path']:
3836 available_mode.append('3')
3837 name = {'0': 'auto', '1': 'pythia', '2':'pgs', '3':'delphes'}
3838 options = available_mode + [name[val] for val in available_mode]
3839 question = """Which programs do you want to run?
3840 0 / auto : running existing card
3841 1 / pythia : Pythia
3842 2 / pgs : Pythia + PGS\n"""
3843 if '3' in available_mode:
3844 question += """ 3 / delphes : Pythia + Delphes.\n"""
3845
3846 if not self.force:
3847 if not mode:
3848 mode = self.ask(question, '0', options)
3849 elif not mode:
3850 mode = 'auto'
3851
3852 if mode.isdigit():
3853 mode = name[mode]
3854
3855 auto = False
3856 if mode == 'auto':
3857 auto = True
3858 if os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
3859 mode = 'pgs'
3860 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
3861 mode = 'delphes'
3862 else:
3863 mode = 'pythia'
3864 logger.info('Will run in mode %s' % mode)
3865
3866
3867
3868 cards = ['pythia_card.dat']
3869 if mode == 'pgs':
3870 cards.append('pgs_card.dat')
3871 if mode == 'delphes':
3872 cards.append('delphes_card.dat')
3873 delphes3 = True
3874 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
3875 delphes3 = False
3876 cards.append('delphes_trigger.dat')
3877 self.keep_cards(cards)
3878
3879 if self.force:
3880 return mode
3881
3882 if auto:
3883 self.ask_edit_cards(cards, mode='auto')
3884 else:
3885 self.ask_edit_cards(cards)
3886
3887 return mode
3888
3889
3890
3891
3892
3893
3894
3895
3896 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
3897 """The command line processor of MadGraph"""
3898
3905
3906 name_to_pdg = {}
3907
3908 @classmethod
3911
3912 @staticmethod
3914 """return the list of Subprocesses"""
3915
3916 out = []
3917 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')):
3918 if not line:
3919 continue
3920 name = line.strip()
3921 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)):
3922 out.append(pjoin(me_dir, 'SubProcesses', name))
3923
3924 return out
3925
3926
3927
3928 @staticmethod
3930 """ return the list of processes with their name"""
3931
3932 nb_sub = 0
3933 names = {}
3934 old_main = ''
3935
3936 if not os.path.exists(os.path.join(path,'processes.dat')):
3937 return SubProcesses.get_subP_info_v4(path)
3938
3939 for line in open(os.path.join(path,'processes.dat')):
3940 main = line[:8].strip()
3941 if main == 'mirror':
3942 main = old_main
3943 if line[8:].strip() == 'none':
3944 continue
3945 else:
3946 main = int(main)
3947 old_main = main
3948
3949 sub_proccess = line[8:]
3950 nb_sub += sub_proccess.count(',') + 1
3951 if main in names:
3952 names[main] += [sub_proccess.split(',')]
3953 else:
3954 names[main]= [sub_proccess.split(',')]
3955
3956 return names
3957
3958 @staticmethod
3960 """ return the list of processes with their name in case without grouping """
3961
3962 nb_sub = 0
3963 names = {'':[[]]}
3964 path = os.path.join(path, 'auto_dsig.f')
3965 found = 0
3966 for line in open(path):
3967 if line.startswith('C Process:'):
3968 found += 1
3969 names[''][0].append(line[15:])
3970 elif found >1:
3971 break
3972 return names
3973
3974
3975 @staticmethod
3977 """return the pdg codes of the particles present in the Subprocesses"""
3978
3979 all_ids = []
3980 for line in open(pjoin(path, 'leshouche.inc')):
3981 if not 'IDUP' in line:
3982 continue
3983 particles = re.search("/([\d,-]+)/", line)
3984 all_ids.append([int(p) for p in particles.group(1).split(',')])
3985 return all_ids
3986
3990 """The command for the gridpack --Those are not suppose to be use interactively--"""
3991
3992 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
3993 """Initialize the command and directly run"""
3994
3995
3996
3997 MadEventCmd.__init__(self, me_dir, *completekey, **stdin)
3998 self.run_mode = 0
3999 self.random = seed
4000 self.random_orig = self.random
4001 self.options['automatic_html_opening'] = False
4002
4003 if me_dir and nb_event and seed:
4004 self.launch(nb_event, seed)
4005 else:
4006 raise MadGraph5Error,\
4007 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \
4008 str(seed)
4009
4010 - def launch(self, nb_event, seed):
4011 """ launch the generation for the grid """
4012
4013
4014 logger.info('generate %s events' % nb_event)
4015 self.set_run_name('GridRun_%s' % seed)
4016 self.update_status('restoring default data', level=None)
4017 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'),
4018 'default'],
4019 cwd=self.me_dir)
4020
4021
4022 self.update_status('Generating Events', level=None)
4023
4024
4025
4026 self.refine4grid(nb_event)
4027
4028
4029 self.exec_cmd('combine_events')
4030 self.exec_cmd('store_events')
4031 self.print_results_in_shell(self.results.current)
4032 self.exec_cmd('decay_events -from_cards', postcmd=False)
4033
4035 """Special refine for gridpack run."""
4036 self.nb_refine += 1
4037
4038 precision = nb_event
4039
4040
4041
4042 self.cluster_mode = 0
4043
4044
4045 self.save_random()
4046
4047 self.update_status('Refine results to %s' % precision, level=None)
4048 logger.info("Using random number seed offset = %s" % self.random)
4049
4050 self.total_jobs = 0
4051 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if
4052 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))]
4053 devnull = open(os.devnull, 'w')
4054 for nb_proc,subdir in enumerate(subproc):
4055 subdir = subdir.strip()
4056 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
4057 bindir = pjoin(os.path.relpath(self.dirbin, Pdir))
4058
4059 logger.info(' %s ' % subdir)
4060
4061 for match in glob.glob(pjoin(Pdir, '*ajob*')):
4062 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
4063 os.remove(pjoin(Pdir, match))
4064
4065
4066 logfile = pjoin(Pdir, 'gen_ximprove.log')
4067 proc = misc.Popen([pjoin(bindir, 'gen_ximprove')],
4068 stdin=subprocess.PIPE,
4069 stdout=open(logfile,'w'),
4070 cwd=Pdir)
4071 proc.communicate('%s 1 F\n' % (precision))
4072
4073 if os.path.exists(pjoin(Pdir, 'ajob1')):
4074 alljobs = glob.glob(pjoin(Pdir,'ajob*'))
4075 nb_tot = len(alljobs)
4076 self.total_jobs += nb_tot
4077 for i, job in enumerate(alljobs):
4078 job = os.path.basename(job)
4079 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1),
4080 run_type='Refine number %s on %s (%s/%s)' %
4081 (self.nb_refine, subdir, nb_proc+1, len(subproc)))
4082 if os.path.exists(pjoin(self.me_dir,'error')):
4083 self.monitor(html=True)
4084 raise MadEventError, \
4085 'Error detected in dir %s: %s' % \
4086 (Pdir, open(pjoin(self.me_dir,'error')).read())
4087 self.monitor(run_type='All job submitted for refine number %s' %
4088 self.nb_refine)
4089
4090 self.update_status("Combining runs", level='parton')
4091 try:
4092 os.remove(pjoin(Pdir, 'combine_runs.log'))
4093 except Exception:
4094 pass
4095
4096 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses')))
4097 combine_runs.CombineRuns(self.me_dir)
4098
4099
4100 cross, error = sum_html.make_all_html_results(self)
4101 self.results.add_detail('cross', cross)
4102 self.results.add_detail('error', error)
4103
4104
4105 self.update_status('finish refine', 'parton', makehtml=False)
4106 devnull.close()
4107
4108
4109
4110 AskforEditCard = common_run.AskforEditCard
4111