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