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