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.resetall(self.me_dir)
1614 self.results.def_web_mode(self.web)
1615
1616 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir))
1617 self.configured = 0
1618 self._options = {}
1619
1621 """configure web data"""
1622 self.web = True
1623 self.results.def_web_mode(True)
1624 self.force = True
1625 if os.environ['MADGRAPH_BASE']:
1626 self.options['mg5_path'] = pjoin(os.environ['MADGRAPH_BASE'],'MG5')
1627
1628
1630 """ Check that the output path is a valid madevent directory """
1631
1632 bin_path = os.path.join(path,'bin')
1633 if os.path.isfile(os.path.join(bin_path,'generate_events')):
1634 return True
1635 else:
1636 return False
1637
1638
1640 """assign all configuration variable from file
1641 loop over the different config file if config_file not define """
1642
1643 super(MadEventCmd,self).set_configuration(amcatnlo=amcatnlo,
1644 final=final, **opt)
1645 if not final:
1646 return self.options
1647
1648
1649
1650
1651 for key in (k for k in self.options if k.endswith('path')):
1652 path = self.options[key]
1653 if path is None:
1654 continue
1655 if not os.path.isdir(path):
1656 path = pjoin(self.me_dir, self.options[key])
1657 if os.path.isdir(path):
1658 self.options[key] = None
1659 if key == "pythia-pgs_path":
1660 if not os.path.exists(pjoin(path, 'src','pythia')):
1661 logger.info("No valid pythia-pgs path found")
1662 continue
1663 elif key == "delphes_path":
1664 if not os.path.exists(pjoin(path, 'Delphes')) and not\
1665 os.path.exists(pjoin(path, 'DelphesSTDHEP')):
1666 logger.info("No valid Delphes path found")
1667 continue
1668 elif key == "madanalysis_path":
1669 if not os.path.exists(pjoin(path, 'plot_events')):
1670 logger.info("No valid MadAnalysis path found")
1671 continue
1672 elif key == "td_path":
1673 if not os.path.exists(pjoin(path, 'td')):
1674 logger.info("No valid td path found")
1675 continue
1676 elif key == "syscalc_path":
1677 if not os.path.exists(pjoin(path, 'sys_calc')):
1678 logger.info("No valid SysCalc path found")
1679 continue
1680
1681
1682 self.options[key] = os.path.realpath(path)
1683 continue
1684 else:
1685 self.options[key] = None
1686
1687
1688 return self.options
1689
1690
1743
1744
1746 """Make a run from the banner file"""
1747
1748 args = self.split_arg(line)
1749
1750 self.check_banner_run(args)
1751
1752
1753 for name in ['delphes_trigger.dat', 'delphes_card.dat',
1754 'pgs_card.dat', 'pythia_card.dat', 'madspin_card.dat',
1755 'reweight_card.dat']:
1756 try:
1757 os.remove(pjoin(self.me_dir, 'Cards', name))
1758 except Exception:
1759 pass
1760
1761 banner_mod.split_banner(args[0], self.me_dir, proc_card=False)
1762
1763
1764 if not self.force:
1765 ans = self.ask('Do you want to modify the Cards?', 'n', ['y','n'])
1766 if ans == 'n':
1767 self.force = True
1768
1769
1770 self.exec_cmd('generate_events %s %s' % (self.run_name, self.force and '-f' or ''))
1771
1772
1773
1774
1776 """Display current internal status"""
1777
1778 args = self.split_arg(line)
1779
1780 self.check_display(args)
1781
1782 if args[0] == 'run_name':
1783
1784 data = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt'))
1785 data = [n.rsplit('/',2)[1:] for n in data]
1786
1787 if data:
1788 out = {}
1789 for name, tag in data:
1790 tag = tag[len(name)+1:-11]
1791 if name in out:
1792 out[name].append(tag)
1793 else:
1794 out[name] = [tag]
1795 print 'the runs available are:'
1796 for run_name, tags in out.items():
1797 print ' run: %s' % run_name
1798 print ' tags: ',
1799 print ', '.join(tags)
1800 else:
1801 print 'No run detected.'
1802
1803 elif args[0] == 'options':
1804 outstr = " Run Options \n"
1805 outstr += " ----------- \n"
1806 for key, default in self.options_madgraph.items():
1807 value = self.options[key]
1808 if value == default:
1809 outstr += " %25s \t:\t%s\n" % (key,value)
1810 else:
1811 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1812 outstr += "\n"
1813 outstr += " MadEvent Options \n"
1814 outstr += " ---------------- \n"
1815 for key, default in self.options_madevent.items():
1816 if key in self.options:
1817 value = self.options[key]
1818 else:
1819 default = ''
1820 if value == default:
1821 outstr += " %25s \t:\t%s\n" % (key,value)
1822 else:
1823 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1824 outstr += "\n"
1825 outstr += " Configuration Options \n"
1826 outstr += " --------------------- \n"
1827 for key, default in self.options_configuration.items():
1828 value = self.options[key]
1829 if value == default:
1830 outstr += " %25s \t:\t%s\n" % (key,value)
1831 else:
1832 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
1833 output.write(outstr)
1834 elif args[0] == 'results':
1835 self.do_print_results(' '.join(args[1:]))
1836 else:
1837 super(MadEventCmd, self).do_display(line, output)
1838
1839 - def do_save(self, line, check=True, to_keep={}):
1840 """Not in help: Save information to file"""
1841
1842 args = self.split_arg(line)
1843
1844 if check:
1845 self.check_save(args)
1846
1847 if args[0] == 'options':
1848
1849 to_define = {}
1850 for key, default in self.options_configuration.items():
1851 if self.options[key] != self.options_configuration[key]:
1852 to_define[key] = self.options[key]
1853
1854 if not '--auto' in args:
1855 for key, default in self.options_madevent.items():
1856 if self.options[key] != self.options_madevent[key]:
1857 to_define[key] = self.options[key]
1858
1859 if '--all' in args:
1860 for key, default in self.options_madgraph.items():
1861 if self.options[key] != self.options_madgraph[key]:
1862 to_define[key] = self.options[key]
1863 elif not '--auto' in args:
1864 for key, default in self.options_madgraph.items():
1865 if self.options[key] != self.options_madgraph[key]:
1866 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
1867 % (key,self.options_madgraph[key]) )
1868 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
1869 if len(args) >1 and not args[1].startswith('--'):
1870 filepath = args[1]
1871 else:
1872 filepath = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1873 basefile = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1874 basedir = self.me_dir
1875
1876 if to_keep:
1877 to_define = to_keep
1878 self.write_configuration(filepath, basefile, basedir, to_define)
1879
1880
1881
1882
1883
1884
1885
1886
1887
1889 """Main Commands: launch the full chain """
1890
1891 args = self.split_arg(line)
1892
1893 mode = self.check_generate_events(args)
1894 self.ask_run_configuration(mode)
1895 if not args:
1896
1897 self.set_run_name(self.find_available_run_name(self.me_dir), None, 'parton')
1898 else:
1899 self.set_run_name(args[0], None, 'parton', True)
1900 args.pop(0)
1901
1902 if self.run_card['gridpack'] in self.true:
1903
1904 gridpack_opts=[('accuracy', 0.01),
1905 ('points', 2000),
1906 ('iterations',8),
1907 ('gridpack','.true.')]
1908 logger.info('Generating gridpack with run name %s' % self.run_name)
1909 self.exec_cmd('survey %s %s' % \
1910 (self.run_name,
1911 " ".join(['--' + opt + '=' + str(val) for (opt,val) \
1912 in gridpack_opts])),
1913 postcmd=False)
1914 self.exec_cmd('combine_events', postcmd=False)
1915 self.exec_cmd('store_events', postcmd=False)
1916 self.exec_cmd('decay_events -from_cards', postcmd=False)
1917 self.exec_cmd('create_gridpack', postcmd=False)
1918 else:
1919
1920 logger.info('Generating %s events with run name %s' %
1921 (self.run_card['nevents'], self.run_name))
1922
1923 self.exec_cmd('survey %s %s' % (self.run_name,' '.join(args)),
1924 postcmd=False)
1925 if not float(self.results.current['cross']):
1926
1927 text = '''Survey return zero cross section.
1928 Typical reasons are the following:
1929 1) A massive s-channel particle has a width set to zero.
1930 2) The pdf are zero for at least one of the initial state particles
1931 or you are using maxjetflavor=4 for initial state b:s.
1932 3) The cuts are too strong.
1933 Please check/correct your param_card and/or your run_card.'''
1934 logger_stderr.critical(text)
1935 raise ZeroResult('See https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FAQ-General-14')
1936 nb_event = self.run_card['nevents']
1937 self.exec_cmd('refine %s' % nb_event, postcmd=False)
1938 self.exec_cmd('refine %s' % nb_event, postcmd=False)
1939 self.exec_cmd('combine_events', postcmd=False)
1940 self.print_results_in_shell(self.results.current)
1941 self.run_syscalc('parton')
1942 self.create_plot('parton')
1943 self.exec_cmd('store_events', postcmd=False)
1944 self.exec_cmd('reweight -from_cards', postcmd=False)
1945 self.exec_cmd('decay_events -from_cards', postcmd=False)
1946 self.exec_cmd('pythia --no_default', postcmd=False, printcmd=False)
1947
1948 self.store_result()
1949
1950
1957
1959 """Have a nice results prints in the shell,
1960 data should be of type: gen_crossxhtml.OneTagResults"""
1961 if not data:
1962 return
1963 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag']))
1964 if self.ninitial == 1:
1965 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error']))
1966 else:
1967 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error']))
1968 logger.info(" Nb of events : %s" % data['nb_event'] )
1969 if data['cross_pythia'] and data['nb_event_pythia']:
1970 if self.ninitial == 1:
1971 logger.info(" Matched Width : %.4g +- %.4g GeV" % (data['cross_pythia'], data['error_pythia']))
1972 else:
1973 logger.info(" Matched Cross-section : %.4g +- %.4g pb" % (data['cross_pythia'], data['error_pythia']))
1974 logger.info(" Nb of events after Matching : %s" % data['nb_event_pythia'])
1975 if self.run_card['use_syst'] in self.true:
1976 logger.info(" Be carefull that matched information are here NOT for the central value. Refer to SysCalc output for it")
1977
1978 logger.info(" " )
1979
1981 """Have a nice results prints in the shell,
1982 data should be of type: gen_crossxhtml.OneTagResults"""
1983 if not data:
1984 return
1985
1986 fsock = open(path, mode)
1987
1988 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \
1989 (data['run_name'],data['tag'], os.path.basename(self.me_dir)))
1990
1991 if self.ninitial == 1:
1992 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error']))
1993 else:
1994 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error']))
1995 fsock.write(" Nb of events : %s\n" % data['nb_event'] )
1996 if data['cross_pythia'] and data['nb_event_pythia']:
1997 if self.ninitial == 1:
1998 fsock.write(" Matched Width : %.4g +- %.4g GeV\n" % (data['cross_pythia'], data['error_pythia']))
1999 else:
2000 fsock.write(" Matched Cross-section : %.4g +- %.4g pb\n" % (data['cross_pythia'], data['error_pythia']))
2001 fsock.write(" Nb of events after Matching : %s\n" % data['nb_event_pythia'])
2002 fsock.write(" \n" )
2003
2004
2006 """Main Commands: launch decay width calculation and automatic inclusion of
2007 calculated widths and BRs in the param_card."""
2008
2009 args = self.split_arg(line)
2010
2011 accuracy = self.check_calculate_decay_widths(args)
2012 self.ask_run_configuration('parton')
2013 if not args:
2014
2015 self.set_run_name(self.find_available_run_name(self.me_dir))
2016 else:
2017 self.set_run_name(args[0], reload_card=True)
2018 args.pop(0)
2019
2020 self.configure_directory()
2021
2022
2023 opts=[('accuracy', accuracy),
2024 ('points', 1000),
2025 ('iterations',9)]
2026
2027 logger.info('Calculating decay widths with run name %s' % self.run_name)
2028
2029 self.exec_cmd('survey %s %s' % \
2030 (self.run_name,
2031 " ".join(['--' + opt + '=' + str(val) for (opt,val) \
2032 in opts])),
2033 postcmd=False)
2034 self.exec_cmd('combine_events', postcmd=False)
2035 self.exec_cmd('store_events', postcmd=False)
2036
2037 self.collect_decay_widths()
2038 self.update_status('calculate_decay_widths done',
2039 level='parton', makehtml=False)
2040
2041
2042
2044 """ Collect the decay widths and calculate BRs for all particles, and put
2045 in param_card form.
2046 """
2047
2048 particle_dict = {}
2049 run_name = self.run_name
2050
2051
2052 for P_path in SubProcesses.get_subP(self.me_dir):
2053 ids = SubProcesses.get_subP_ids(P_path)
2054
2055
2056
2057 nb_output = len(ids) / (len(set([p[0] for p in ids])))
2058 results = open(pjoin(P_path, run_name + '_results.dat')).read().split('\n')[0]
2059 result = float(results.strip().split(' ')[0])
2060 for particles in ids:
2061 try:
2062 particle_dict[particles[0]].append([particles[1:], result/nb_output])
2063 except KeyError:
2064 particle_dict[particles[0]] = [[particles[1:], result/nb_output]]
2065
2066 self.update_width_in_param_card(particle_dict,
2067 initial = pjoin(self.me_dir, 'Cards', 'param_card.dat'),
2068 output=pjoin(self.me_dir, 'Events', run_name, "param_card.dat"))
2069
2070 @staticmethod
2072
2073
2074 if not output:
2075 output = initial
2076
2077 param_card_file = open(initial)
2078 param_card = param_card_file.read().split('\n')
2079 param_card_file.close()
2080
2081 decay_lines = []
2082 line_number = 0
2083
2084 while line_number < len(param_card):
2085 line = param_card[line_number]
2086 if line.lower().startswith('decay'):
2087
2088
2089 line = param_card.pop(line_number)
2090 line = line.split()
2091 particle = 0
2092 if int(line[1]) not in decay_info:
2093 try:
2094 particle = int(line[1])
2095 width = float(line[2])
2096 except Exception:
2097 particle = 0
2098
2099 line = param_card[line_number]
2100 while line.startswith('#') or line.startswith(' '):
2101 line = param_card.pop(line_number)
2102 if not particle or line.startswith('#'):
2103 line=param_card[line_number]
2104 continue
2105
2106 line = line.split()
2107 try:
2108 partial_width = float(line[0])*width
2109 decay_products = [int(p) for p in line[2:2+int(line[1])]]
2110 except Exception:
2111 line=param_card[line_number]
2112 continue
2113 try:
2114 decay_info[particle].append([decay_products, partial_width])
2115 except KeyError:
2116 decay_info[particle] = [[decay_products, partial_width]]
2117 if line_number == len(param_card):
2118 break
2119 line=param_card[line_number]
2120 if particle and particle not in decay_info:
2121
2122 decay_info[particle] = [[[], width]]
2123 else:
2124 line_number += 1
2125
2126 while not param_card[-1] or param_card[-1].startswith('#'):
2127 param_card.pop(-1)
2128
2129
2130 param_card.append("#\n#*************************")
2131 param_card.append("# Decay widths *")
2132 param_card.append("#*************************")
2133 for key in sorted(decay_info.keys()):
2134 width = sum([r for p,r in decay_info[key]])
2135 param_card.append("#\n# PDG Width")
2136 param_card.append("DECAY %i %e" % (key, width.real))
2137 if not width:
2138 continue
2139 if decay_info[key][0][0]:
2140 param_card.append("# BR NDA ID1 ID2 ...")
2141 brs = [[(val[1]/width).real, val[0]] for val in decay_info[key] if val[1]]
2142 for val in sorted(brs, reverse=True):
2143 param_card.append(" %e %i %s # %s" %
2144 (val[0].real, len(val[1]),
2145 " ".join([str(v) for v in val[1]]),
2146 val[0] * width
2147 ))
2148 decay_table = open(output, 'w')
2149 decay_table.write("\n".join(param_card) + "\n")
2150 decay_table.close()
2151 logger.info("Results written to %s" % output)
2152
2153
2154
2156
2157 args = self.split_arg(line)
2158
2159 mode = self.check_multi_run(args)
2160 nb_run = args.pop(0)
2161 if nb_run == 1:
2162 logger.warn("'multi_run 1' command is not optimal. Think of using generate_events instead")
2163 self.ask_run_configuration(mode)
2164 main_name = self.run_name
2165
2166
2167
2168
2169
2170 crossoversig = 0
2171 inv_sq_err = 0
2172 nb_event = 0
2173 for i in range(nb_run):
2174 self.nb_refine = 0
2175 self.exec_cmd('generate_events %s_%s -f' % (main_name, i), postcmd=False)
2176
2177 nb_event += int(self.results[self.run_name][-1]['nb_event'])
2178 self.results.add_detail('nb_event', nb_event , run=main_name)
2179 cross = self.results[self.run_name][-1]['cross']
2180 error = self.results[self.run_name][-1]['error'] + 1e-99
2181 crossoversig+=cross/error**2
2182 inv_sq_err+=1.0/error**2
2183 self.results[main_name][-1]['cross'] = crossoversig/inv_sq_err
2184 self.results[main_name][-1]['error'] = math.sqrt(1.0/inv_sq_err)
2185 self.results.def_current(main_name)
2186 self.run_name = main_name
2187 self.update_status("Merging LHE files", level='parton')
2188 try:
2189 os.mkdir(pjoin(self.me_dir,'Events', self.run_name))
2190 except Exception:
2191 pass
2192 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'
2193 % {'bin': self.dirbin, 'event': pjoin(self.me_dir,'Events'),
2194 'name': self.run_name})
2195
2196 eradir = self.options['exrootanalysis_path']
2197 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')):
2198 self.update_status("Create Root file", level='parton')
2199 misc.gunzip('%s/%s/unweighted_events.lhe.gz' %
2200 (pjoin(self.me_dir,'Events'), self.run_name))
2201
2202 self.create_root_file('%s/unweighted_events.lhe' % self.run_name,
2203 '%s/unweighted_events.root' % self.run_name)
2204
2205 path = pjoin(self.me_dir, "Events", self.run_name, "unweighted_events.lhe")
2206 self.create_plot('parton', path,
2207 pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
2208 )
2209
2210
2211 if not os.path.exists('%s.gz' % path):
2212 misc.gzip(path)
2213
2214 self.update_status('', level='parton')
2215 self.print_results_in_shell(self.results.current)
2216
2217
2218
2220 """Advanced commands: create .inc files from param_card.dat/run_card.dat"""
2221
2222
2223 if not mode and not opt:
2224 args = self.split_arg(line)
2225 mode, opt = self.check_treatcards(args)
2226
2227 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat'))
2228
2229
2230 if mode in ['param', 'all']:
2231 model = self.find_model_name()
2232 tmp_model = os.path.basename(model)
2233 if tmp_model == 'mssm' or tmp_model.startswith('mssm-'):
2234 if not '--param_card=' in line:
2235 param_card = pjoin(self.me_dir, 'Cards','param_card.dat')
2236 mg5_param = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat')
2237 check_param_card.convert_to_mg5card(param_card, mg5_param)
2238 check_param_card.check_valid_param_card(mg5_param)
2239 opt['param_card'] = pjoin(self.me_dir, 'Source', 'MODEL', 'MG5_param.dat')
2240 else:
2241 check_param_card.check_valid_param_card(opt['param_card'])
2242
2243 logger.debug('write compile file for card: %s' % opt['param_card'])
2244 param_card = check_param_card.ParamCard(opt['param_card'])
2245 outfile = pjoin(opt['output_dir'], 'param_card.inc')
2246 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat')
2247 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')):
2248 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')
2249 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')):
2250 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
2251 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')):
2252 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w')
2253 fsock.write(' ')
2254 fsock.close()
2255 if mode == 'all':
2256 self.do_treatcards('', 'run', opt)
2257 return
2258 else:
2259 devnull = open(os.devnull,'w')
2260 subprocess.call([sys.executable, 'write_param_card.py'],
2261 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'),
2262 stdout=devnull)
2263 devnull.close()
2264 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
2265 param_card.write_inc_file(outfile, ident_card, default)
2266
2267
2268 if mode in ['run', 'all']:
2269 if not hasattr(self, 'run_card'):
2270 run_card = banner_mod.RunCard(opt['run_card'])
2271 else:
2272 run_card = self.run_card
2273 if self.ninitial == 1:
2274 run_card['lpp1'] = 0
2275 run_card['lpp2'] = 0
2276 run_card['ebeam1'] = 0
2277 run_card['ebeam2'] = 0
2278
2279 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc'))
2280
2281
2283 """Advanced commands: launch survey for the current process """
2284
2285
2286 args = self.split_arg(line)
2287
2288 self.check_survey(args)
2289
2290
2291 if os.path.exists(pjoin(self.me_dir,'error')):
2292 os.remove(pjoin(self.me_dir,'error'))
2293
2294 self.configure_directory()
2295
2296 self.random_orig = self.random
2297 logger.info("Using random number seed offset = %s" % self.random)
2298
2299 self.update_random()
2300 self.save_random()
2301 self.update_status('Running Survey', level=None)
2302 if self.cluster_mode:
2303 logger.info('Creating Jobs')
2304
2305 logger.info('Working on SubProcesses')
2306 self.total_jobs = 0
2307 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
2308 'subproc.mg'))]
2309
2310 if float(self.run_card['mmjj']) > 0.01 * (float(self.run_card['ebeam1'])+float(self.run_card['ebeam2'])):
2311 self.pass_in_difficult_integration_mode()
2312
2313 P_zero_result = []
2314
2315 nb_tot_proc = len(subproc)
2316 for nb_proc,subdir in enumerate(subproc):
2317 self.update_status('Compiling for process %s/%s. <br> (previous processes already running)' % \
2318 (nb_proc+1,nb_tot_proc), level=None)
2319 subdir = subdir.strip()
2320 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
2321 logger.info(' %s ' % subdir)
2322
2323 for match in glob.glob(pjoin(Pdir, '*ajob*')):
2324 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
2325 os.remove(match)
2326 for match in glob.glob(pjoin(Pdir, 'G*')):
2327 if os.path.exists(pjoin(match,'results.dat')):
2328 os.remove(pjoin(match, 'results.dat'))
2329
2330
2331 self.compile(['gensym'], cwd=Pdir)
2332 if not os.path.exists(pjoin(Pdir, 'gensym')):
2333 raise MadEventError, 'Error make gensym not successful'
2334
2335
2336 p = misc.Popen(['./gensym'], stdin=subprocess.PIPE,
2337 stdout=subprocess.PIPE,
2338 stderr=subprocess.STDOUT, cwd=Pdir)
2339 sym_input = "%(points)d %(iterations)d %(accuracy)f \n" % self.opts
2340 (stdout, stderr) = p.communicate(sym_input)
2341 if os.path.exists(pjoin(self.me_dir,'error')):
2342 files.mv(pjoin(self.me_dir,'error'), pjoin(Pdir,'ajob.no_ps.log'))
2343 P_zero_result.append(subdir)
2344 continue
2345
2346 if not os.path.exists(pjoin(Pdir, 'ajob1')) or p.returncode:
2347 logger.critical(stdout)
2348 raise MadEventError, 'Error gensym run not successful'
2349
2350
2351 self.compile(['madevent'], cwd=Pdir)
2352
2353 alljobs = glob.glob(pjoin(Pdir,'ajob*'))
2354 self.total_jobs += len(alljobs)
2355 for i, job in enumerate(alljobs):
2356 job = os.path.basename(job)
2357 self.launch_job('%s' % job, cwd=Pdir, remaining=(len(alljobs)-i-1),
2358 run_type='survey on %s (%s/%s)' % (subdir,nb_proc+1,len(subproc)))
2359 if os.path.exists(pjoin(self.me_dir,'error')):
2360 self.monitor(html=False)
2361 raise MadEventError, 'Error detected Stop running: %s' % \
2362 open(pjoin(self.me_dir,'error')).read()
2363
2364
2365 if P_zero_result:
2366 if len(P_zero_result) == len(subproc):
2367 raise ZeroResult, '%s' % \
2368 open(pjoin(Pdir,'ajob.no_ps.log')).read()
2369 else:
2370 logger.warning(''' %s SubProcesses doesn\'t have available phase-space.
2371 Please check mass spectrum.''' % ','.join(P_zero_result))
2372
2373
2374 self.monitor(run_type='All jobs submitted for survey', html=True)
2375 cross, error = sum_html.make_all_html_results(self)
2376 self.results.add_detail('cross', cross)
2377 self.results.add_detail('error', error)
2378 self.update_status('End survey', 'parton', makehtml=False)
2379
2380
2382 """be more secure for the integration to not miss it due to strong cut"""
2383
2384
2385 if self.opts['points'] == self._survey_options['points'][1]:
2386 self.opts['points'] = 2 * self._survey_options['points'][1]
2387 if self.opts['iterations'] == self._survey_options['iterations'][1]:
2388 self.opts['iterations'] = 1 + self._survey_options['iterations'][1]
2389 if self.opts['accuracy'] == self._survey_options['accuracy'][1]:
2390 self.opts['accuracy'] = self._survey_options['accuracy'][1]/2
2391
2392
2393 conf_path = pjoin(self.me_dir, 'Source','run_config.inc')
2394 files.cp(conf_path, conf_path + '.bk')
2395
2396 text = open(conf_path).read()
2397 text = re.sub('''\(min_events = \d+\)''', '''(min_events = 7500 )''', text)
2398 text = re.sub('''\(max_events = \d+\)''', '''(max_events = 20000 )''', text)
2399 fsock = open(conf_path, 'w')
2400 fsock.write(text)
2401 fsock.close()
2402
2403
2404 for name in ['../bin/internal/gen_ximprove', 'all',
2405 '../bin/internal/combine_events']:
2406 self.compile(arg=[name], cwd=os.path.join(self.me_dir, 'Source'))
2407
2408
2409
2410
2411
2412
2413
2414
2416 """Advanced commands: launch survey for the current process """
2417 devnull = open(os.devnull, 'w')
2418 self.nb_refine += 1
2419 args = self.split_arg(line)
2420
2421 self.check_refine(args)
2422
2423 precision = args[0]
2424 if len(args) == 2:
2425 max_process = args[1]
2426 else:
2427 max_process = 5
2428
2429
2430 self.configure_directory()
2431
2432
2433 self.update_random()
2434 self.save_random()
2435
2436 if self.cluster_mode:
2437 logger.info('Creating Jobs')
2438 self.update_status('Refine results to %s' % precision, level=None)
2439
2440 self.total_jobs = 0
2441 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
2442 'subproc.mg'))]
2443 for nb_proc,subdir in enumerate(subproc):
2444 subdir = subdir.strip()
2445 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
2446 bindir = pjoin(os.path.relpath(self.dirbin, Pdir))
2447
2448 logger.info(' %s ' % subdir)
2449
2450 for match in glob.glob(pjoin(Pdir, '*ajob*')):
2451 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
2452 os.remove(match)
2453
2454 proc = misc.Popen([pjoin(bindir, 'gen_ximprove')],
2455 stdout=devnull,
2456 stdin=subprocess.PIPE,
2457 cwd=Pdir)
2458 proc.communicate('%s %s T\n' % (precision, max_process))
2459
2460 if os.path.exists(pjoin(Pdir, 'ajob1')):
2461 self.compile(['madevent'], cwd=Pdir)
2462 alljobs = glob.glob(pjoin(Pdir,'ajob*'))
2463
2464
2465 Gre = re.compile("\s*j=(G[\d\.\w]+)")
2466 for job in alljobs:
2467 Gdirs = Gre.findall(open(job).read())
2468 for Gdir in Gdirs:
2469 if os.path.exists(pjoin(Pdir, Gdir, 'results.dat')):
2470 os.remove(pjoin(Pdir, Gdir,'results.dat'))
2471
2472 nb_tot = len(alljobs)
2473 self.total_jobs += nb_tot
2474 for i, job in enumerate(alljobs):
2475 job = os.path.basename(job)
2476 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1),
2477 run_type='Refine number %s on %s (%s/%s)' %
2478 (self.nb_refine, subdir, nb_proc+1, len(subproc)))
2479 self.monitor(run_type='All job submitted for refine number %s' % self.nb_refine,
2480 html=True)
2481
2482 self.update_status("Combining runs", level='parton')
2483 try:
2484 os.remove(pjoin(Pdir, 'combine_runs.log'))
2485 except Exception:
2486 pass
2487
2488 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses')))
2489
2490 combine_runs.CombineRuns(self.me_dir)
2491
2492 cross, error = sum_html.make_all_html_results(self)
2493 self.results.add_detail('cross', cross)
2494 self.results.add_detail('error', error)
2495
2496 self.update_status('finish refine', 'parton', makehtml=False)
2497 devnull.close()
2498
2499
2501 """Advanced commands: Launch combine events"""
2502
2503 args = self.split_arg(line)
2504
2505 self.check_combine_events(args)
2506
2507 self.update_status('Combining Events', level='parton')
2508 try:
2509 os.remove(pjoin(self.me_dir,'SubProcesses', 'combine.log'))
2510 except Exception:
2511 pass
2512
2513 if self.options['run_mode'] ==1 and self.options['cluster_tmp_path']:
2514 tmpcluster = cluster.MultiCore(nb_core=1)
2515 tmpcluster.launch_and_wait('../bin/internal/run_combine',
2516 cwd=pjoin(self.me_dir,'SubProcesses'),
2517 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'),
2518 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')])
2519 else:
2520 self.cluster.launch_and_wait('../bin/internal/run_combine',
2521 cwd=pjoin(self.me_dir,'SubProcesses'),
2522 stdout=pjoin(self.me_dir,'SubProcesses', 'combine.log'),
2523 required_output=[pjoin(self.me_dir,'SubProcesses', 'combine.log')])
2524
2525 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read()
2526
2527 pat = re.compile(r'''\s*Unweighting\s*selected\s*(\d+)\s*events''')
2528 try:
2529 nb_event = pat.search(output).groups()[0]
2530 except AttributeError:
2531 time.sleep(10)
2532 output = misc.mult_try_open(pjoin(self.me_dir,'SubProcesses','combine.log')).read()
2533 try:
2534 nb_event = pat.search(output).groups()[0]
2535 except AttributeError:
2536 logger.warning('Fail to read the number of unweighted events in the combine.log file')
2537 nb_event = 0
2538
2539 self.results.add_detail('nb_event', nb_event)
2540
2541
2542
2543 tag = self.run_card['run_tag']
2544
2545 if not self.banner:
2546 self.banner = banner_mod.recover_banner(self.results, 'parton')
2547 self.banner.load_basic(self.me_dir)
2548
2549 self.banner.add_generation_info(self.results.current['cross'], nb_event)
2550 if not hasattr(self, 'random_orig'): self.random_orig = 0
2551 self.banner.change_seed(self.random_orig)
2552 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
2553 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
2554 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name,
2555 '%s_%s_banner.txt' % (self.run_name, tag)))
2556
2557
2558 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'events.lhe'))
2559 self.banner.add_to_file(pjoin(self.me_dir,'Events', 'unweighted_events.lhe'))
2560
2561
2562 eradir = self.options['exrootanalysis_path']
2563 madir = self.options['madanalysis_path']
2564 td = self.options['td_path']
2565 if eradir and misc.is_executable(pjoin(eradir,'ExRootLHEFConverter')) and\
2566 os.path.exists(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe')):
2567 if not os.path.exists(pjoin(self.me_dir, 'Events', self.run_name)):
2568 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
2569 self.create_root_file(output='%s/unweighted_events.root' % \
2570 self.run_name)
2571
2572
2573
2574
2575
2576
2578 """Advanced commands: Launch store events"""
2579
2580 args = self.split_arg(line)
2581
2582 self.check_combine_events(args)
2583 self.update_status('Storing parton level results', level='parton')
2584
2585
2586
2587 run = self.run_name
2588 tag = self.run_card['run_tag']
2589 devnull = open(os.devnull, 'w')
2590
2591 if not os.path.exists(pjoin(self.me_dir, 'Events', run)):
2592 os.mkdir(pjoin(self.me_dir, 'Events', run))
2593 if not os.path.exists(pjoin(self.me_dir, 'HTML', run)):
2594 os.mkdir(pjoin(self.me_dir, 'HTML', run))
2595
2596
2597 input = pjoin(self.me_dir, 'SubProcesses', 'results.dat')
2598 output = pjoin(self.me_dir, 'SubProcesses', '%s_results.dat' % run)
2599 files.cp(input, output)
2600
2601
2602
2603 if self.results.current['nb_event'] == 0:
2604 logger.warning("No event detected. No cleaning performed! This should allow to run:\n" +
2605 " cd Subprocesses; ../bin/internal/combine_events\n"+
2606 " to have your events if those one are missing.")
2607 else:
2608 for P_path in SubProcesses.get_subP(self.me_dir):
2609 G_dir = [G for G in os.listdir(P_path) if G.startswith('G') and
2610 os.path.isdir(pjoin(P_path,G))]
2611 for G in G_dir:
2612 G_path = pjoin(P_path,G)
2613 try:
2614
2615 if os.path.exists(pjoin(G_path, 'events.lhe')):
2616 os.remove(pjoin(G_path, 'events.lhe'))
2617 except Exception:
2618 continue
2619 try:
2620
2621 if os.path.exists(pjoin(G_path, 'results.dat')):
2622 input = pjoin(G_path, 'results.dat')
2623 output = pjoin(G_path, '%s_results.dat' % run)
2624 files.cp(input, output)
2625 except Exception:
2626 continue
2627
2628 try:
2629 if os.path.exists(pjoin(G_path, 'log.txt')):
2630 input = pjoin(G_path, 'log.txt')
2631 output = pjoin(G_path, '%s_log.txt' % run)
2632 files.mv(input, output)
2633 except Exception:
2634 continue
2635 try:
2636
2637 for name in ['ftn26']:
2638 if os.path.exists(pjoin(G_path, name)):
2639 if os.path.exists(pjoin(G_path, '%s_%s.gz'%(run,name))):
2640 os.remove(pjoin(G_path, '%s_%s.gz'%(run,name)))
2641 input = pjoin(G_path, name)
2642 output = pjoin(G_path, '%s_%s' % (run,name))
2643 files.mv(input, output)
2644 misc.gzip(pjoin(G_path, output), error=None)
2645 except Exception:
2646 continue
2647
2648 if os.path.exists(pjoin(G_path, 'ftn25')):
2649 os.remove(pjoin(G_path, 'ftn25'))
2650
2651
2652 misc.call(['%s/gen_cardhtml-pl' % self.dirbin],
2653 cwd=pjoin(self.me_dir))
2654
2655
2656 E_path = pjoin(self.me_dir, 'Events')
2657 O_path = pjoin(self.me_dir, 'Events', run)
2658
2659 for name in ['events.lhe', 'unweighted_events.lhe']:
2660 if os.path.exists(pjoin(E_path, name)):
2661 if os.path.exists(pjoin(O_path, '%s.gz' % name)):
2662 os.remove(pjoin(O_path, '%s.gz' % name))
2663 input = pjoin(E_path, name)
2664 output = pjoin(O_path, name)
2665 misc.gzip(input, stdout="%s.gz" % output, error=False)
2666
2667 self.update_status('End Parton', level='parton', makehtml=False)
2668 devnull.close()
2669
2670
2672 """ Allow to reweight the events generated with a new choices of model
2673 parameter.
2674 """
2675
2676 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')):
2677 return
2678
2679
2680 if MADEVENT and not self.options['mg5_path']:
2681 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system.
2682 You can install it and set its path in ./Cards/me5_configuration.txt'''
2683 elif MADEVENT:
2684 sys.path.append(self.options['mg5_path'])
2685 try:
2686 import madgraph.interface.reweight_interface as reweight_interface
2687 except ImportError:
2688 raise self.ConfigurationError, '''Can\'t load Reweight module.
2689 The variable mg5_path might not be correctly configured.'''
2690
2691 self.to_store.append('event')
2692 if not '-from_cards' in line:
2693 self.keep_cards(['reweight_card.dat'])
2694 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False)
2695
2696
2697 if self.results.current['cross'] == 0 and self.run_name:
2698 self.results.delete_run(self.run_name, self.run_tag)
2699
2700
2701 args = self.split_arg(line)
2702 self.check_decay_events(args)
2703
2704 reweight_cmd = reweight_interface.ReweightInterface(args[0])
2705 reweight_cmd. mother = self
2706 self.update_status('Running Reweight', level='madspin')
2707
2708
2709 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat')
2710 reweight_cmd.me_dir = self.me_dir
2711 reweight_cmd.import_command_file(path)
2712
2713
2714 try:
2715 self.results.def_current(self.run_name, self.run_tag)
2716 except Exception:
2717 pass
2718
2719
2721 """Advanced commands: Create gridpack from present run"""
2722
2723 self.update_status('Creating gridpack', level='parton')
2724 args = self.split_arg(line)
2725 self.check_combine_events(args)
2726 if not self.run_tag: self.run_tag = 'tag_1'
2727 os.system("sed -i.bak \"s/ *.false.*=.*GridRun/ .true. = GridRun/g\" %s/Cards/grid_card.dat" \
2728 % self.me_dir)
2729 misc.call(['./bin/internal/restore_data', self.run_name],
2730 cwd=self.me_dir)
2731 misc.call(['./bin/internal/store4grid',
2732 self.run_name, self.run_tag],
2733 cwd=self.me_dir)
2734 misc.call(['./bin/internal/clean'], cwd=self.me_dir)
2735 misc.call(['./bin/internal/make_gridpack'], cwd=self.me_dir)
2736 files.mv(pjoin(self.me_dir, 'gridpack.tar.gz'),
2737 pjoin(self.me_dir, '%s_gridpack.tar.gz' % self.run_name))
2738 os.system("sed -i.bak \"s/\s*.true.*=.*GridRun/ .false. = GridRun/g\" %s/Cards/grid_card.dat" \
2739 % self.me_dir)
2740 self.update_status('gridpack created', level='gridpack')
2741
2742
2744 """launch pythia"""
2745
2746
2747 args = self.split_arg(line)
2748 if '--no_default' in args:
2749 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')):
2750 return
2751 no_default = True
2752 args.remove('--no_default')
2753 else:
2754 no_default = False
2755
2756 if not self.run_name:
2757 self.check_pythia(args)
2758 self.configure_directory(html_opening =False)
2759 else:
2760
2761 self.configure_directory(html_opening =False)
2762 self.check_pythia(args)
2763
2764
2765 if not no_default:
2766 self.ask_pythia_run_configuration(args[-1])
2767
2768 if self.options['automatic_html_opening']:
2769 misc.open_file(os.path.join(self.me_dir, 'crossx.html'))
2770 self.options['automatic_html_opening'] = False
2771
2772
2773 if not self.banner:
2774 self.banner = banner_mod.recover_banner(self.results, 'pythia')
2775
2776
2777
2778 pythia_src = pjoin(self.options['pythia-pgs_path'],'src')
2779
2780 self.update_status('Running Pythia', 'pythia')
2781 try:
2782 os.remove(pjoin(self.me_dir,'Events','pythia.done'))
2783 except Exception:
2784 pass
2785
2786
2787 tag = self.run_tag
2788 pythia_log = pjoin(self.me_dir, 'Events', self.run_name , '%s_pythia.log' % tag)
2789 self.cluster.launch_and_wait('../bin/internal/run_pythia',
2790 argument= [pythia_src], stdout= pythia_log,
2791 stderr=subprocess.STDOUT,
2792 cwd=pjoin(self.me_dir,'Events'))
2793
2794 if not os.path.exists(pjoin(self.me_dir,'Events','pythia.done')):
2795 logger.warning('Fail to produce pythia output. More info in \n %s' % pythia_log)
2796 return
2797 else:
2798 os.remove(pjoin(self.me_dir,'Events','pythia.done'))
2799
2800 self.to_store.append('pythia')
2801
2802
2803 if int(self.run_card['ickkw']):
2804
2805 pythia_log = misc.BackRead(pjoin(self.me_dir,'Events', self.run_name,
2806 '%s_pythia.log' % tag))
2807 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")
2808 for line in pythia_log:
2809 info = pythiare.search(line)
2810 if not info:
2811 continue
2812 try:
2813
2814 sigma_m = float(info.group('xsec').replace('D','E')) *1e9
2815 Nacc = int(info.group('generated'))
2816 Ntry = int(info.group('tried'))
2817 except ValueError:
2818
2819 self.results.add_detail('cross_pythia', 0)
2820 self.results.add_detail('nb_event_pythia', 0)
2821 self.results.add_detail('error_pythia', 0)
2822 else:
2823 self.results.add_detail('cross_pythia', sigma_m)
2824 self.results.add_detail('nb_event_pythia', Nacc)
2825
2826 error = self.results[self.run_name].return_tag(self.run_tag)['error']
2827 error_m = math.sqrt((error * Nacc/Ntry)**2 + sigma_m**2 *(1-Nacc/Ntry)/Nacc)
2828
2829 self.results.add_detail('error_pythia', error_m)
2830 break
2831
2832 pythia_log.close()
2833
2834 pydir = pjoin(self.options['pythia-pgs_path'], 'src')
2835 eradir = self.options['exrootanalysis_path']
2836 madir = self.options['madanalysis_path']
2837 td = self.options['td_path']
2838
2839
2840
2841 self.banner.add(pjoin(self.me_dir, 'Cards','pythia_card.dat'))
2842 if int(self.run_card['ickkw']):
2843
2844 if 'MGGenerationInfo' in self.banner:
2845 self.banner['MGGenerationInfo'] += '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
2846 else:
2847 self.banner['MGGenerationInfo'] = '# Matched Integrated weight (pb) : %s\n' % self.results.current['cross_pythia']
2848 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag))
2849 self.banner.write(banner_path)
2850
2851
2852 self.run_hep2lhe(banner_path)
2853 if int(self.run_card['ickkw']):
2854 misc.gzip(pjoin(self.me_dir,'Events','beforeveto.tree'),
2855 stdout=pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_beforeveto.tree.gz'))
2856
2857 if self.run_card['use_syst'] in self.true:
2858
2859 try:
2860 self.run_syscalc('Pythia')
2861 except SysCalcError, error:
2862 logger.error(str(error))
2863 else:
2864
2865 misc.gzip(pjoin(self.me_dir,'Events', 'syst.dat'),
2866 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_syst.dat.gz'))
2867
2868
2869 if os.path.exists(pjoin(self.me_dir, 'Events', 'syscalc.dat')):
2870 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
2871 '%s_syscalc.dat' % self.run_tag)
2872 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'),
2873 stdout = "%s.gz" % filename)
2874
2875
2876 self.create_plot('Pythia')
2877
2878 if os.path.exists(pjoin(self.me_dir,'Events','pythia_events.lhe')):
2879 misc.gzip(pjoin(self.me_dir,'Events','pythia_events.lhe'),
2880 stdout=pjoin(self.me_dir,'Events', self.run_name,'%s_pythia_events.lhe.gz' % tag))
2881
2882 self.update_status('finish', level='pythia', makehtml=False)
2883 self.exec_cmd('pgs --no_default', postcmd=False, printcmd=False)
2884 if self.options['delphes_path']:
2885 self.exec_cmd('delphes --no_default', postcmd=False, printcmd=False)
2886 self.print_results_in_shell(self.results.current)
2887
2888
2889
2891 """Remove one/all run or only part of it"""
2892
2893 args = self.split_arg(line)
2894 run, tag, mode = self.check_remove(args)
2895 if 'banner' in mode:
2896 mode.append('all')
2897
2898
2899 if run == 'all':
2900
2901 if os.path.exists(pjoin(self.me_dir, 'Events', 'all')):
2902 logger.warning('A run with name all exists. So we will not supress all processes.')
2903 else:
2904 for match in glob.glob(pjoin(self.me_dir, 'Events','*','*_banner.txt')):
2905 run = match.rsplit(os.path.sep,2)[1]
2906 try:
2907 self.exec_cmd('remove %s %s' % (run, ' '.join(args[1:]) ) )
2908 except self.InvalidCmd, error:
2909 logger.info(error)
2910 pass
2911 return
2912
2913
2914 if not os.path.exists(pjoin(self.me_dir, 'Events', run)):
2915 raise self.InvalidCmd('No run \'%s\' detected' % run)
2916
2917 try:
2918 self.resuls.def_current(run)
2919 self.update_status(' Cleaning %s' % run, level=None)
2920 except Exception:
2921 misc.sprint('fail to update results or html status')
2922 pass
2923
2924
2925
2926
2927 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*'))
2928 to_delete += glob.glob(pjoin(self.me_dir, 'HTML', run, '*'))
2929
2930 to_delete = [os.path.basename(f) for f in to_delete if 'banner' not in f]
2931 if tag:
2932 to_delete = [f for f in to_delete if tag in f]
2933 if 'parton' in mode or 'all' in mode:
2934 try:
2935 if self.results[run][0]['tag'] != tag:
2936 raise Exception, 'dummy'
2937 except Exception:
2938 pass
2939 else:
2940 nb_rm = len(to_delete)
2941 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'events.lhe.gz')):
2942 to_delete.append('events.lhe.gz')
2943 if os.path.exists(pjoin(self.me_dir, 'Events', run, 'unweighted_events.lhe.gz')):
2944 to_delete.append('unweighted_events.lhe.gz')
2945 if os.path.exists(pjoin(self.me_dir, 'HTML', run,'plots_parton.html')):
2946 to_delete.append(pjoin(self.me_dir, 'HTML', run,'plots_parton.html'))
2947 if nb_rm != len(to_delete):
2948 logger.warning('Be carefull that partonic information are on the point to be removed.')
2949 if 'all' in mode:
2950 pass
2951 else:
2952 if 'pythia' not in mode:
2953 to_delete = [f for f in to_delete if 'pythia' not in f]
2954 if 'pgs' not in mode:
2955 to_delete = [f for f in to_delete if 'pgs' not in f]
2956 if 'delphes' not in mode:
2957 to_delete = [f for f in to_delete if 'delphes' not in f]
2958 if 'parton' not in mode:
2959 to_delete = [f for f in to_delete if 'delphes' in f
2960 or 'pgs' in f
2961 or 'pythia' in f]
2962 if not self.force and len(to_delete):
2963 question = 'Do you want to delete the following files?\n %s' % \
2964 '\n '.join(to_delete)
2965 ans = self.ask(question, 'y', choices=['y','n'])
2966 else:
2967 ans = 'y'
2968
2969 if ans == 'y':
2970 for file2rm in to_delete:
2971 if os.path.exists(pjoin(self.me_dir, 'Events', run, file2rm)):
2972 try:
2973 os.remove(pjoin(self.me_dir, 'Events', run, file2rm))
2974 except Exception:
2975 shutil.rmtree(pjoin(self.me_dir, 'Events', run, file2rm))
2976 else:
2977 try:
2978 os.remove(pjoin(self.me_dir, 'HTML', run, file2rm))
2979 except Exception:
2980 shutil.rmtree(pjoin(self.me_dir, 'HTML', run, file2rm))
2981
2982
2983
2984
2985 if 'all' in mode or 'channel' in mode:
2986 try:
2987 if tag and self.results[run][0]['tag'] != tag:
2988 raise Exception, 'dummy'
2989 except Exception:
2990 pass
2991 else:
2992 to_delete = glob.glob(pjoin(self.me_dir, 'SubProcesses', '%s*' % run))
2993 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','%s*' % run))
2994 to_delete += glob.glob(pjoin(self.me_dir, 'SubProcesses', '*','*','%s*' % run))
2995
2996 if self.force or len(to_delete) == 0:
2997 ans = 'y'
2998 else:
2999 question = 'Do you want to delete the following files?\n %s' % \
3000 '\n '.join(to_delete)
3001 ans = self.ask(question, 'y', choices=['y','n'])
3002
3003 if ans == 'y':
3004 for file2rm in to_delete:
3005 os.remove(file2rm)
3006
3007 if 'banner' in mode:
3008 to_delete = glob.glob(pjoin(self.me_dir, 'Events', run, '*'))
3009 if tag:
3010
3011 try:
3012 os.remove(pjoin(self.me_dir, 'Events',run,'%s_%s_banner.txt' % (run,tag)))
3013 except Exception:
3014 logger.warning('fail to remove the banner')
3015
3016 if run in self.results:
3017 self.results.delete_run(run, tag)
3018 return
3019 elif any(['banner' not in os.path.basename(p) for p in to_delete]):
3020 if to_delete:
3021 raise MadGraph5Error, '''Some output still exists for this run.
3022 Please remove those output first. Do for example:
3023 remove %s all banner
3024 ''' % run
3025 else:
3026 shutil.rmtree(pjoin(self.me_dir, 'Events',run))
3027 if run in self.results:
3028 self.results.delete_run(run)
3029 return
3030 else:
3031 logger.info('''The banner is not removed. In order to remove it run:
3032 remove %s all banner %s''' % (run, tag and '--tag=%s ' % tag or ''))
3033
3034
3035 self.results.clean(mode, run, tag)
3036 self.update_status('', level='all')
3037
3038
3039
3040
3042 """Create the plot for a given run"""
3043
3044
3045 self.store_result()
3046 args = self.split_arg(line)
3047
3048 self.check_plot(args)
3049 logger.info('plot for run %s' % self.run_name)
3050 if not self.force:
3051 self.ask_edit_cards([], args, plot=True)
3052
3053 if any([arg in ['all','parton'] for arg in args]):
3054 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe')
3055 if os.path.exists(filename+'.gz'):
3056 misc.gunzip('%s.gz' % filename)
3057 if os.path.exists(filename):
3058 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
3059 self.create_plot('parton')
3060 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
3061 stdout= "%s.gz" % filename)
3062 else:
3063 logger.info('No valid files for partonic plot')
3064
3065 if any([arg in ['all','pythia'] for arg in args]):
3066 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
3067 '%s_pythia_events.lhe' % self.run_tag)
3068 if os.path.exists(filename+'.gz'):
3069 misc.gunzip("%s.gz" % filename)
3070 if os.path.exists(filename):
3071 shutil.move(filename, pjoin(self.me_dir, 'Events','pythia_events.lhe'))
3072 self.create_plot('Pythia')
3073 misc.gzip(pjoin(self.me_dir, 'Events','pythia_events.lhe'),
3074 stdout= "%s.gz" % filename)
3075 else:
3076 logger.info('No valid files for pythia plot')
3077
3078
3079 if any([arg in ['all','pgs'] for arg in args]):
3080 filename = pjoin(self.me_dir, 'Events', self.run_name,
3081 '%s_pgs_events.lhco' % self.run_tag)
3082 if os.path.exists(filename+'.gz'):
3083 misc.gunzip("%s.gz" % filename)
3084 if os.path.exists(filename):
3085 self.create_plot('PGS')
3086 misc.gzip(filename)
3087 else:
3088 logger.info('No valid files for pgs plot')
3089
3090 if any([arg in ['all','delphes'] for arg in args]):
3091 filename = pjoin(self.me_dir, 'Events', self.run_name,
3092 '%s_delphes_events.lhco' % self.run_tag)
3093 if os.path.exists(filename+'.gz'):
3094 misc.gunzip("%s.gz" % filename)
3095 if os.path.exists(filename):
3096 self.create_plot('Delphes')
3097 misc.gzip(filename)
3098 else:
3099 logger.info('No valid files for delphes plot')
3100
3101
3103 """Evaluate systematics variation weights for a given run"""
3104
3105
3106 self.store_result()
3107 args = self.split_arg(line)
3108
3109 self.check_syscalc(args)
3110 if self.ninitial == 1:
3111 logger.error('SysCalc can\'t be run for decay processes')
3112 return
3113
3114 logger.info('Calculating systematics for run %s' % self.run_name)
3115
3116 self.ask_edit_cards(['run_card'], args)
3117
3118 if any([arg in ['all','parton'] for arg in args]):
3119 filename = pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe')
3120 if os.path.exists(filename+'.gz'):
3121 misc.gunzip("%s.gz" % filename)
3122 if os.path.exists(filename):
3123 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
3124 self.run_syscalc('parton')
3125 misc.gzip(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
3126 stdout="%s.gz" % filename)
3127 else:
3128 logger.info('No valid files for parton level systematics run.')
3129
3130 if any([arg in ['all','pythia'] for arg in args]):
3131 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
3132 '%s_pythia_syst.dat' % self.run_tag)
3133 if os.path.exists(filename+'.gz'):
3134 misc.gunzip("%s.gz" % filename)
3135 if os.path.exists(filename):
3136 shutil.move(filename, pjoin(self.me_dir, 'Events','syst.dat'))
3137 try:
3138 self.run_syscalc('Pythia')
3139 except SysCalcError, error:
3140 logger.warning(str(error))
3141 return
3142 misc.gzip(pjoin(self.me_dir, 'Events','syst.dat'), "%s.gz" % filename)
3143 filename = pjoin(self.me_dir, 'Events' ,self.run_name,
3144 '%s_syscalc.dat' % self.run_tag)
3145 misc.gzip(pjoin(self.me_dir, 'Events','syscalc.dat'),
3146 stdout=filename)
3147 else:
3148 logger.info('No valid files for pythia level')
3149
3150
3152 """ tar the pythia results. This is done when we are quite sure that
3153 the pythia output will not be use anymore """
3154
3155 if not self.run_name:
3156 return
3157
3158 self.results.save()
3159
3160
3161 if not self.to_store:
3162 return
3163
3164 tag = self.run_card['run_tag']
3165 self.update_status('storring files of Previous run', level=None,\
3166 error=True)
3167 if 'event' in self.to_store:
3168 if not os.path.exists(pjoin(self.me_dir, 'Events',self.run_name, 'unweighted_events.lhe.gz')):
3169 misc.gzip(pjoin(self.me_dir,'Events',self.run_name,"unweighted_events.lhe"))
3170
3171 if 'pythia' in self.to_store:
3172 self.update_status('Storing Pythia files of Previous run', level='pythia', error=True)
3173
3174 p = pjoin(self.me_dir,'Events')
3175 n = self.run_name
3176 t = tag
3177 misc.gzip(pjoin(p,'pythia_events.hep'),
3178 stdout=pjoin(p,'%s/%s_pythia_events.hep' % (n,t)))
3179
3180 self.to_store.remove('pythia')
3181 self.update_status('Done', level='pythia',makehtml=False,error=True)
3182
3183 self.to_store = []
3184
3185 - def launch_job(self,exe, cwd=None, stdout=None, argument = [], remaining=0,
3186 run_type='', mode=None, **opt):
3187 """ """
3188 argument = [str(arg) for arg in argument]
3189 if mode is None:
3190 mode = self.cluster_mode
3191
3192
3193 if os.path.exists(exe) and not os.access(exe, os.X_OK):
3194 os.system('chmod +x %s ' % exe)
3195 elif (cwd and os.path.exists(pjoin(cwd, exe))) and not \
3196 os.access(pjoin(cwd, exe), os.X_OK):
3197 os.system('chmod +x %s ' % pjoin(cwd, exe))
3198
3199 if mode == 0:
3200 self.update_status((remaining, 1,
3201 self.total_jobs - remaining -1, run_type), level=None, force=False)
3202 start = time.time()
3203
3204 status = misc.call(['./'+exe] + argument, cwd=cwd,
3205 stdout=stdout, **opt)
3206 logger.info('%s run in %f s' % (exe, time.time() -start))
3207 if status:
3208 raise MadGraph5Error, '%s didn\'t stop properly. Stop all computation' % exe
3209
3210
3211 elif mode in [1,2]:
3212
3213 if 'ajob' in exe:
3214 input_files = ['madevent','input_app.txt','symfact.dat','iproc.dat',
3215 pjoin(self.me_dir, 'SubProcesses','randinit')]
3216 output_files = []
3217 required_output = []
3218
3219
3220
3221 input_files.append(self.get_pdf_input_filename())
3222
3223
3224 Gre = re.compile("\s*j=(G[\d\.\w]+)")
3225 Ire = re
3226 try :
3227 fsock = open(exe)
3228 except Exception:
3229 fsock = open(pjoin(cwd,exe))
3230 text = fsock.read()
3231 output_files = Gre.findall(text)
3232 if not output_files:
3233 Ire = re.compile("for i in ([\d\.\s]*) ; do")
3234 data = Ire.findall(text)
3235 data = ' '.join(data).split()
3236 for nb in data:
3237 output_files.append('G%s' % nb)
3238 required_output.append('G%s/results.dat' % nb)
3239 else:
3240 for G in output_files:
3241 if os.path.isdir(pjoin(cwd,G)):
3242 input_files.append(G)
3243 required_output.append('%s/results.dat' % G)
3244
3245
3246 self.cluster.submit2(exe, stdout=stdout, cwd=cwd,
3247 input_files=input_files, output_files=output_files,
3248 required_output=required_output)
3249
3250 else:
3251 self.cluster.submit(exe, stdout=stdout, cwd=cwd)
3252
3253
3254
3256 """Find if Madevent is in Group mode or not"""
3257
3258
3259
3260 file_path = pjoin(self.me_dir, 'Source', 'run_config.inc')
3261 text = open(file_path).read()
3262 if re.search(r'''s*parameter\s+\(ChanPerJob=2\)''', text, re.I+re.M):
3263 return 'group'
3264 else:
3265 return 'v4'
3266
3267
3268 - def monitor(self, run_type='monitor', mode=None, html=False):
3269 """ monitor the progress of running job """
3270
3271 starttime = time.time()
3272 if mode is None:
3273 mode = self.cluster_mode
3274 if mode > 0:
3275 if html:
3276 update_status = lambda idle, run, finish: \
3277 self.update_status((idle, run, finish, run_type), level=None,
3278 force=False, starttime=starttime)
3279 else:
3280 update_status = lambda idle, run, finish: None
3281 try:
3282 self.cluster.wait(self.me_dir, update_status)
3283 except Exception, error:
3284 logger.info(error)
3285 if not self.force:
3286 ans = self.ask('Cluster Error detected. Do you want to clean the queue?',
3287 default = 'y', choices=['y','n'])
3288 else:
3289 ans = 'y'
3290 if ans == 'y':
3291 self.cluster.remove()
3292 raise
3293 except KeyboardInterrupt, error:
3294 self.cluster.remove()
3295 raise
3296
3297
3298
3299
3378
3379
3380
3381
3382
3383 @staticmethod
3385 """check if the directory exists. if so return the path otherwise the
3386 default"""
3387
3388 if os.path.isdir(path):
3389 return path
3390 else:
3391 return default
3392
3393
3394 - def set_run_name(self, name, tag=None, level='parton', reload_card=False,
3395 allow_new_tag=True):
3396 """define the run name, the run_tag, the banner and the results."""
3397
3398
3399 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes'],
3400 'pythia': ['pythia','pgs','delphes'],
3401 'pgs': ['pgs'],
3402 'delphes':['delphes'],
3403 'plot':[],
3404 'syscalc':[]}
3405
3406
3407
3408 if name == self.run_name:
3409 if reload_card:
3410 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
3411 self.run_card = banner_mod.RunCard(run_card)
3412
3413
3414 if tag:
3415 self.run_card['run_tag'] = tag
3416 self.run_tag = tag
3417 self.results.add_run(self.run_name, self.run_card)
3418 else:
3419 for tag in upgrade_tag[level]:
3420 if getattr(self.results[self.run_name][-1], tag):
3421 tag = self.get_available_tag()
3422 self.run_card['run_tag'] = tag
3423 self.run_tag = tag
3424 self.results.add_run(self.run_name, self.run_card)
3425 break
3426 return
3427
3428
3429 if self.run_name:
3430 self.store_result()
3431
3432 self.run_name = name
3433
3434 new_tag = False
3435
3436 self.banner = banner_mod.recover_banner(self.results, level, name)
3437 if 'mgruncard' in self.banner:
3438 self.run_card = self.banner.charge_card('run_card')
3439 else:
3440
3441 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
3442 self.run_card = banner_mod.RunCard(run_card)
3443
3444 if tag:
3445 self.run_card['run_tag'] = tag
3446 new_tag = True
3447 elif not self.run_name in self.results and level =='parton':
3448 pass
3449 elif not self.run_name in self.results:
3450
3451 logger.warning('Trying to run data on unknown run.')
3452 self.results.add_run(name, self.run_card)
3453 self.results.update('add run %s' % name, 'all', makehtml=False)
3454 else:
3455 for tag in upgrade_tag[level]:
3456
3457 if getattr(self.results[self.run_name][-1], tag):
3458
3459 tag = self.get_available_tag()
3460 self.run_card['run_tag'] = tag
3461 new_tag = True
3462 break
3463 if not new_tag:
3464
3465 tag = self.results[self.run_name][-1]['tag']
3466 self.run_card['run_tag'] = tag
3467
3468 if allow_new_tag and (name in self.results and not new_tag):
3469 self.results.def_current(self.run_name)
3470 else:
3471 self.results.add_run(self.run_name, self.run_card)
3472
3473 self.run_tag = self.run_card['run_tag']
3474
3475
3476
3477 if level == 'parton':
3478 return
3479 elif level == 'pythia':
3480 return self.results[self.run_name][0]['tag']
3481 else:
3482 for i in range(-1,-len(self.results[self.run_name])-1,-1):
3483 tagRun = self.results[self.run_name][i]
3484 if tagRun.pythia:
3485 return tagRun['tag']
3486
3487
3488
3489
3490
3491
3492
3493
3494
3496 """ return the model name """
3497 if hasattr(self, 'model_name'):
3498 return self.model_name
3499
3500 model = 'sm'
3501 proc = []
3502 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')):
3503 line = line.split('#')[0]
3504
3505 if line.startswith('import') and 'model' in line:
3506 model = line.split()[2]
3507 proc = []
3508 elif line.startswith('generate'):
3509 proc.append(line.split(None,1)[1])
3510 elif line.startswith('add process'):
3511 proc.append(line.split(None,2)[2])
3512
3513 self.model = model
3514 self.process = proc
3515 return model
3516
3517
3518
3520 """Find the number of event in the run_card, and check that this is not
3521 too large"""
3522
3523
3524 nb_event = int(self.run_card['nevents'])
3525 if nb_event > 1000000:
3526 logger.warning("Attempting to generate more than 1M events")
3527 logger.warning("Limiting number to 1M. Use multi_run for larger statistics.")
3528 path = pjoin(self.me_dir, 'Cards', 'run_card.dat')
3529 os.system(r"""perl -p -i.bak -e "s/\d+\s*=\s*nevents/1000000 = nevents/" %s""" \
3530 % path)
3531 self.run_card['nevents'] = 1000000
3532
3533 return
3534
3535
3536
3538 """ change random number"""
3539
3540 self.random += 3
3541 if self.random > 30081*30081:
3542 raise MadGraph5Error,\
3543 'Random seed too large ' + str(self.random) + ' > 30081*30081'
3544
3545
3547 """save random number in appropirate file"""
3548
3549 fsock = open(pjoin(self.me_dir, 'SubProcesses','randinit'),'w')
3550 fsock.writelines('r=%s\n' % self.random)
3551
3552 - def do_quit(self, *args, **opts):
3556
3557
3559 """check for ckkw"""
3560
3561 lpp1 = self.run_card['lpp1']
3562 lpp2 = self.run_card['lpp2']
3563 e1 = self.run_card['ebeam1']
3564 e2 = self.run_card['ebeam2']
3565 pd = self.run_card['pdlabel']
3566 lha = self.run_card['lhaid']
3567 xq = self.run_card['xqcut']
3568 translation = {'e1': e1, 'e2':e2, 'pd':pd,
3569 'lha':lha, 'xq':xq}
3570
3571 if lpp1 or lpp2:
3572
3573 if pd.startswith("'"):
3574 pd = pd[1:]
3575 if pd.endswith("'"):
3576 pd = pd[:-1]
3577
3578 if xq >2 or xq ==2:
3579 xq = 2
3580
3581
3582 if pd == "lhapdf":
3583 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(lha)s-%(xq)s.dat.gz'
3584 else:
3585 issudfile = 'lib/issudgrid-%(e1)s-%(e2)s-%(pd)s-%(xq)s.dat.gz'
3586 if self.web:
3587 issudfile = pjoin(self.webbin, issudfile % translation)
3588 else:
3589 issudfile = pjoin(self.me_dir, issudfile % translation)
3590
3591 logger.info('Sudakov grid file: %s' % issudfile)
3592
3593
3594 if os.path.exists(issudfile):
3595 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat')
3596 misc.gunzip(issudfile, keep=True, stdout=path)
3597 else:
3598 msg = 'No sudakov grid file for parameter choice. Start to generate it. This might take a while'
3599 logger.info(msg)
3600 self.update_status('GENERATE SUDAKOF GRID', level='parton')
3601
3602 for i in range(-2,6):
3603 self.cluster.submit('%s/gensudgrid ' % self.dirbin,
3604 arguments = [i],
3605 cwd=self.me_dir,
3606 stdout=open(pjoin(self.me_dir, 'gensudgrid%s.log' % i,'w')))
3607 self.monitor()
3608 for i in range(-2,6):
3609 path = pjoin(self.me_dir, 'lib', 'issudgrid.dat')
3610 os.system('cat %s/gensudgrid%s.log >> %s' % (self.me_dir, path))
3611 misc.gzip(path, stdout=issudfile)
3612
3613
3614 - def create_root_file(self, input='unweighted_events.lhe',
3615 output='unweighted_events.root' ):
3616 """create the LHE root file """
3617 self.update_status('Creating root files', level='parton')
3618
3619 eradir = self.options['exrootanalysis_path']
3620 try:
3621 misc.call(['%s/ExRootLHEFConverter' % eradir,
3622 input, output],
3623 cwd=pjoin(self.me_dir, 'Events'))
3624 except Exception:
3625 logger.warning('fail to produce Root output [problem with ExRootAnalysis]')
3626
3627 - def run_syscalc(self, mode='parton', event_path=None, output=None):
3628 """create the syscalc output"""
3629
3630 logger.info('running syscalc on mode %s' % mode)
3631 if self.run_card['use_syst'] not in self.true:
3632 return
3633
3634 scdir = self.options['syscalc_path']
3635 tag = self.run_card['run_tag']
3636 card = pjoin(self.me_dir, 'bin','internal', 'syscalc_card.dat')
3637 template = open(pjoin(self.me_dir, 'bin','internal', 'syscalc_template.dat')).read()
3638 self.run_card['sys_pdf'] = self.run_card['sys_pdf'].split('#',1)[0].replace('&&',' \n ')
3639
3640 if not 'sys_scalecorrelation' in self.run_card:
3641 self.run_card['sys_scalecorrelation'] = -1
3642 open(card,'w').write(template % self.run_card)
3643
3644 if not scdir or \
3645 not os.path.exists(card):
3646 return False
3647 event_dir = pjoin(self.me_dir, 'Events')
3648
3649 if not event_path:
3650 if mode == 'parton':
3651 event_path = pjoin(event_dir,'unweighted_events.lhe')
3652 output = pjoin(event_dir, 'syscalc.lhe')
3653 elif mode == 'Pythia':
3654 if 'mgpythiacard' in self.banner:
3655 pat = re.compile('''^\s*qcut\s*=\s*([\+\-\d.e]*)''', re.M+re.I)
3656 data = pat.search(self.banner['mgpythiacard'])
3657 if data:
3658 qcut = float(data.group(1))
3659 xqcut = abs(self.run_card['xqcut'])
3660 for value in self.run_card['sys_matchscale'].split():
3661 if float(value) < qcut:
3662 raise SysCalcError, 'qcut value for sys_matchscale lower than qcut in pythia_card. Bypass syscalc'
3663 if float(value) < xqcut:
3664 raise SysCalcError, 'qcut value for sys_matchscale lower than xqcut in run_card. Bypass syscalc'
3665
3666
3667 event_path = pjoin(event_dir,'syst.dat')
3668 output = pjoin(event_dir, 'syscalc.dat')
3669 else:
3670 raise self.InvalidCmd, 'Invalid mode %s' % mode
3671
3672 if not os.path.exists(event_path):
3673 if os.path.exists(event_path+'.gz'):
3674 misc.gzip(event_path)
3675 else:
3676 raise SysCalcError, 'Events file %s does not exits' % event_path
3677
3678 self.update_status('Calculating systematics for %s level' % mode, level = mode.lower())
3679 try:
3680 proc = misc.call([os.path.join(scdir, 'sys_calc'),
3681 event_path, card, output],
3682 stdout = open(pjoin(event_dir, self.run_name, '%s_%s_syscalc.log' % (tag,mode)),'w'),
3683 stderr = subprocess.STDOUT,
3684 cwd=event_dir)
3685
3686 time.sleep(5)
3687 except OSError, error:
3688 logger.error('fail to run syscalc: %s. Please check that SysCalc is correctly installed.' % error)
3689 else:
3690 if mode == 'parton' and os.path.exists(output):
3691 files.mv(output, event_path)
3692 else:
3693 logger.warning('SysCalc Failed. Please read the associate log to see the reason. Did you install the associate PDF set?')
3694 self.update_status('End syscalc for %s level' % mode, level = mode.lower(),
3695 makehtml=False)
3696
3697 return True
3698
3699
3700
3701
3703 """Ask the question when launching generate_events/multi_run"""
3704
3705 available_mode = ['0']
3706 void = 'NOT INSTALLED'
3707 switch_order = ['pythia', 'pgs', 'delphes', 'madspin', 'reweight']
3708 switch = {'pythia': void, 'pgs': void, 'delphes': void,
3709 'madspin': void, 'reweight': void}
3710 description = {'pythia': 'Run the pythia shower/hadronization:',
3711 'pgs': 'Run PGS as detector simulator:',
3712 'delphes':'Run Delphes as detector simulator:',
3713 'madspin':'Decay particles with the MadSpin module:',
3714 'reweight':'Add weight to events based on coupling parameters:',
3715 }
3716 force_switch = {('pythia', 'OFF'): {'pgs': 'OFF', 'delphes': 'OFF'},
3717 ('pgs', 'ON'): {'pythia':'ON'},
3718 ('delphes', 'ON'): {'pythia': 'ON'}}
3719 switch_assign = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void )
3720
3721
3722
3723 if self.options['pythia-pgs_path']:
3724 available_mode.append('1')
3725 available_mode.append('2')
3726 if os.path.exists(pjoin(self.me_dir,'Cards','pythia_card.dat')):
3727 switch['pythia'] = 'ON'
3728 else:
3729 switch['pythia'] = 'OFF'
3730 if os.path.exists(pjoin(self.me_dir,'Cards','pgs_card.dat')):
3731 switch['pgs'] = 'ON'
3732 else:
3733 switch['pgs'] = 'OFF'
3734 if self.options['delphes_path']:
3735 available_mode.append('3')
3736 if os.path.exists(pjoin(self.me_dir,'Cards','delphes_card.dat')):
3737 switch['delphes'] = 'ON'
3738 else:
3739 switch['delphes'] = 'OFF'
3740
3741
3742 if not MADEVENT or self.options['mg5_path']:
3743 available_mode.append('4')
3744 available_mode.append('5')
3745 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')):
3746 switch['madspin'] = 'ON'
3747 else:
3748 switch['madspin'] = 'OFF'
3749 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')):
3750 switch['reweight'] = 'ON'
3751 else:
3752 switch['reweight'] = 'OFF'
3753
3754
3755
3756 options = list(available_mode) + ['auto', 'done']
3757 for id, key in enumerate(switch_order):
3758 if switch[key] != void:
3759 options += ['%s=%s' % (key, s) for s in ['ON','OFF']]
3760 options.append(key)
3761 options.append('parton')
3762
3763
3764 if mode or not self.force:
3765 answer = ''
3766 while answer not in ['0', 'done', 'auto']:
3767 if mode:
3768 answer = mode
3769 else:
3770 switch_format = " %i %-50s %10s=%s\n"
3771 question = "The following switches determine which programs are run:\n"
3772 for id, key in enumerate(switch_order):
3773 question += switch_format % (id+1, description[key], key, switch[key])
3774 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1)
3775 question += ' or set any switch explicitly (e.g. type \'madspin=ON\' at the prompt)\n'
3776 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n'
3777 answer = self.ask(question, '0', options)
3778 if answer.isdigit() and answer != '0':
3779 key = switch_order[int(answer) - 1]
3780 answer = '%s=%s' % (key, 'ON' if switch[key] == 'OFF' else 'OFF')
3781
3782 if '=' in answer:
3783 key, status = answer.split('=')
3784 switch[key] = status
3785 if (key, status) in force_switch:
3786 for key2, status2 in force_switch[(key, status)].items():
3787 if switch[key2] not in [status2, void]:
3788 logger.info('For coherence \'%s\' is set to \'%s\''
3789 % (key2, status2), '$MG:color:BLACK')
3790 switch[key2] = status2
3791 elif answer in ['0', 'auto', 'done']:
3792 continue
3793 else:
3794 logger.info('pass in %s only mode' % answer, '$MG:color:BLACK')
3795 switch_assign('madspin', 'OFF')
3796 switch_assign('reweight', 'OFF')
3797 if answer == 'parton':
3798 switch_assign('pythia', 'OFF')
3799 switch_assign('pgs', 'OFF')
3800 switch_assign('delphes', 'OFF')
3801 elif answer == 'pythia':
3802 switch_assign('pythia', 'ON')
3803 switch_assign('pgs', 'OFF')
3804 switch_assign('delphes', 'OFF')
3805 elif answer == 'pgs':
3806 switch_assign('pythia', 'ON')
3807 switch_assign('pgs', 'ON')
3808 switch_assign('delphes', 'OFF')
3809 elif answer == 'delphes':
3810 switch_assign('pythia', 'ON')
3811 switch_assign('pgs', 'OFF')
3812 switch_assign('delphes', 'ON')
3813 elif answer == 'madspin':
3814 switch_assign('madspin', 'ON')
3815 switch_assign('pythia', 'OFF')
3816 switch_assign('pgs', 'OFF')
3817 switch_assign('delphes', 'OF')
3818 elif answer == 'reweight':
3819 switch_assign('reweight', 'ON')
3820 switch_assign('pythia', 'OFF')
3821 switch_assign('pgs', 'OFF')
3822 switch_assign('delphes', 'OFF')
3823
3824
3825 if mode:
3826 answer = '0'
3827 else:
3828 answer = 'auto'
3829
3830
3831
3832
3833 cards = ['param_card.dat', 'run_card.dat']
3834 if switch['pythia'] == 'ON':
3835 cards.append('pythia_card.dat')
3836 if switch['pgs'] == 'ON':
3837 cards.append('pgs_card.dat')
3838 if switch['delphes'] == 'ON':
3839 cards.append('delphes_card.dat')
3840 delphes3 = True
3841 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
3842 delphes3 = False
3843 cards.append('delphes_trigger.dat')
3844 if switch['madspin'] == 'ON':
3845 cards.append('madspin_card.dat')
3846 if switch['reweight'] == 'ON':
3847 cards.append('reweight_card.dat')
3848 self.keep_cards(cards)
3849 if self.force:
3850 self.check_param_card(pjoin(self.me_dir,'Cards','param_card.dat' ))
3851 return
3852
3853 if answer == 'auto':
3854 self.ask_edit_cards(cards, mode='auto')
3855 else:
3856 self.ask_edit_cards(cards)
3857 return
3858
3859
3861 """Ask the question when launching pythia"""
3862
3863 available_mode = ['0', '1', '2']
3864 if self.options['delphes_path']:
3865 available_mode.append('3')
3866 name = {'0': 'auto', '1': 'pythia', '2':'pgs', '3':'delphes'}
3867 options = available_mode + [name[val] for val in available_mode]
3868 question = """Which programs do you want to run?
3869 0 / auto : running existing card
3870 1 / pythia : Pythia
3871 2 / pgs : Pythia + PGS\n"""
3872 if '3' in available_mode:
3873 question += """ 3 / delphes : Pythia + Delphes.\n"""
3874
3875 if not self.force:
3876 if not mode:
3877 mode = self.ask(question, '0', options)
3878 elif not mode:
3879 mode = 'auto'
3880
3881 if mode.isdigit():
3882 mode = name[mode]
3883
3884 auto = False
3885 if mode == 'auto':
3886 auto = True
3887 if os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
3888 mode = 'pgs'
3889 elif os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
3890 mode = 'delphes'
3891 else:
3892 mode = 'pythia'
3893 logger.info('Will run in mode %s' % mode)
3894
3895
3896
3897 cards = ['pythia_card.dat']
3898 if mode == 'pgs':
3899 cards.append('pgs_card.dat')
3900 if mode == 'delphes':
3901 cards.append('delphes_card.dat')
3902 delphes3 = True
3903 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
3904 delphes3 = False
3905 cards.append('delphes_trigger.dat')
3906 self.keep_cards(cards)
3907
3908 if self.force:
3909 return mode
3910
3911 if auto:
3912 self.ask_edit_cards(cards, mode='auto')
3913 else:
3914 self.ask_edit_cards(cards)
3915
3916 return mode
3917
3918
3919
3920
3921
3922
3923
3924
3925 -class MadEventCmdShell(MadEventCmd, cmd.CmdShell):
3926 """The command line processor of MadGraph"""
3927
3934
3935 name_to_pdg = {}
3936
3937 @classmethod
3940
3941 @staticmethod
3943 """return the list of Subprocesses"""
3944
3945 out = []
3946 for line in open(pjoin(me_dir,'SubProcesses', 'subproc.mg')):
3947 if not line:
3948 continue
3949 name = line.strip()
3950 if os.path.exists(pjoin(me_dir, 'SubProcesses', name)):
3951 out.append(pjoin(me_dir, 'SubProcesses', name))
3952
3953 return out
3954
3955
3956
3957 @staticmethod
3959 """ return the list of processes with their name"""
3960
3961 nb_sub = 0
3962 names = {}
3963 old_main = ''
3964
3965 if not os.path.exists(os.path.join(path,'processes.dat')):
3966 return SubProcesses.get_subP_info_v4(path)
3967
3968 for line in open(os.path.join(path,'processes.dat')):
3969 main = line[:8].strip()
3970 if main == 'mirror':
3971 main = old_main
3972 if line[8:].strip() == 'none':
3973 continue
3974 else:
3975 main = int(main)
3976 old_main = main
3977
3978 sub_proccess = line[8:]
3979 nb_sub += sub_proccess.count(',') + 1
3980 if main in names:
3981 names[main] += [sub_proccess.split(',')]
3982 else:
3983 names[main]= [sub_proccess.split(',')]
3984
3985 return names
3986
3987 @staticmethod
3989 """ return the list of processes with their name in case without grouping """
3990
3991 nb_sub = 0
3992 names = {'':[[]]}
3993 path = os.path.join(path, 'auto_dsig.f')
3994 found = 0
3995 for line in open(path):
3996 if line.startswith('C Process:'):
3997 found += 1
3998 names[''][0].append(line[15:])
3999 elif found >1:
4000 break
4001 return names
4002
4003
4004 @staticmethod
4006 """return the pdg codes of the particles present in the Subprocesses"""
4007
4008 all_ids = []
4009 for line in open(pjoin(path, 'leshouche.inc')):
4010 if not 'IDUP' in line:
4011 continue
4012 particles = re.search("/([\d,-]+)/", line)
4013 all_ids.append([int(p) for p in particles.group(1).split(',')])
4014 return all_ids
4015
4019 """The command for the gridpack --Those are not suppose to be use interactively--"""
4020
4021 - def __init__(self, me_dir = None, nb_event=0, seed=0, *completekey, **stdin):
4022 """Initialize the command and directly run"""
4023
4024
4025
4026 MadEventCmd.__init__(self, me_dir, *completekey, **stdin)
4027 self.run_mode = 0
4028 self.random = seed
4029 self.random_orig = self.random
4030 self.options['automatic_html_opening'] = False
4031
4032 if me_dir and nb_event and seed:
4033 self.launch(nb_event, seed)
4034 else:
4035 raise MadGraph5Error,\
4036 'Gridpack run failed: ' + str(me_dir) + str(nb_event) + \
4037 str(seed)
4038
4039 - def launch(self, nb_event, seed):
4040 """ launch the generation for the grid """
4041
4042
4043 logger.info('generate %s events' % nb_event)
4044 self.set_run_name('GridRun_%s' % seed)
4045 self.update_status('restoring default data', level=None)
4046 misc.call([pjoin(self.me_dir,'bin','internal','restore_data'),
4047 'default'],
4048 cwd=self.me_dir)
4049
4050
4051 self.update_status('Generating Events', level=None)
4052
4053
4054
4055 self.refine4grid(nb_event)
4056
4057
4058 self.exec_cmd('combine_events')
4059 self.exec_cmd('store_events')
4060 self.print_results_in_shell(self.results.current)
4061 self.exec_cmd('decay_events -from_cards', postcmd=False)
4062
4064 """Special refine for gridpack run."""
4065 self.nb_refine += 1
4066
4067 precision = nb_event
4068
4069
4070
4071 self.cluster_mode = 0
4072
4073
4074 self.save_random()
4075
4076 self.update_status('Refine results to %s' % precision, level=None)
4077 logger.info("Using random number seed offset = %s" % self.random)
4078
4079 self.total_jobs = 0
4080 subproc = [P for P in os.listdir(pjoin(self.me_dir,'SubProcesses')) if
4081 P.startswith('P') and os.path.isdir(pjoin(self.me_dir,'SubProcesses', P))]
4082 devnull = open(os.devnull, 'w')
4083 for nb_proc,subdir in enumerate(subproc):
4084 subdir = subdir.strip()
4085 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
4086 bindir = pjoin(os.path.relpath(self.dirbin, Pdir))
4087
4088 logger.info(' %s ' % subdir)
4089
4090 for match in glob.glob(pjoin(Pdir, '*ajob*')):
4091 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
4092 os.remove(pjoin(Pdir, match))
4093
4094
4095 logfile = pjoin(Pdir, 'gen_ximprove.log')
4096 misc.call([pjoin(bindir, 'gen_ximprove')],
4097 stdin=subprocess.PIPE,
4098 stdout=open(logfile,'w'),
4099 cwd=Pdir)
4100
4101 if os.path.exists(pjoin(Pdir, 'ajob1')):
4102 alljobs = glob.glob(pjoin(Pdir,'ajob*'))
4103 nb_tot = len(alljobs)
4104 self.total_jobs += nb_tot
4105 for i, job in enumerate(alljobs):
4106 job = os.path.basename(job)
4107 self.launch_job('%s' % job, cwd=Pdir, remaining=(nb_tot-i-1),
4108 run_type='Refine number %s on %s (%s/%s)' %
4109 (self.nb_refine, subdir, nb_proc+1, len(subproc)))
4110 if os.path.exists(pjoin(self.me_dir,'error')):
4111 self.monitor(html=True)
4112 raise MadEventError, \
4113 'Error detected in dir %s: %s' % \
4114 (Pdir, open(pjoin(self.me_dir,'error')).read())
4115 self.monitor(run_type='All job submitted for refine number %s' %
4116 self.nb_refine)
4117
4118 self.update_status("Combining runs", level='parton')
4119 try:
4120 os.remove(pjoin(Pdir, 'combine_runs.log'))
4121 except Exception:
4122 pass
4123
4124 bindir = pjoin(os.path.relpath(self.dirbin, pjoin(self.me_dir,'SubProcesses')))
4125 combine_runs.CombineRuns(self.me_dir)
4126
4127
4128 cross, error = sum_html.make_all_html_results(self)
4129 self.results.add_detail('cross', cross)
4130 self.results.add_detail('error', error)
4131
4132
4133 self.update_status('finish refine', 'parton', makehtml=False)
4134 devnull.close()
4135
4136
4137
4138 AskforEditCard = common_run.AskforEditCard
4139