1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """A user friendly command line interface to access MadGraph5_aMC@NLO features.
16 Uses the cmd package for command interpretation and tab completion.
17 """
18 from __future__ import division
19
20 import atexit
21 import glob
22 import logging
23 import math
24 import optparse
25 import os
26 import pydoc
27 import random
28 import re
29 import shutil
30 import subprocess
31 import sys
32 import traceback
33 import time
34 import signal
35 import tarfile
36 import copy
37 import datetime
38 import tarfile
39
40 try:
41 import readline
42 GNU_SPLITTING = ('GNU' in readline.__doc__)
43 except:
44 GNU_SPLITTING = True
45
46 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
47 root_path = os.path.split(root_path)[0]
48 sys.path.insert(0, os.path.join(root_path,'bin'))
49
50
51 pjoin = os.path.join
52
53 logger = logging.getLogger('madgraph.stdout')
54 logger_stderr = logging.getLogger('madgraph.stderr')
55
56 try:
57 import madgraph
58 except ImportError:
59 aMCatNLO = True
60 import internal.extended_cmd as cmd
61 import internal.common_run_interface as common_run
62 import internal.banner as banner_mod
63 import internal.misc as misc
64 from internal import InvalidCmd, MadGraph5Error
65 import internal.files as files
66 import internal.cluster as cluster
67 import internal.save_load_object as save_load_object
68 import internal.gen_crossxhtml as gen_crossxhtml
69 import internal.sum_html as sum_html
70 import internal.shower_card as shower_card
71 import internal.FO_analyse_card as analyse_card
72 import internal.histograms as histograms
73 else:
74
75 aMCatNLO = False
76 import madgraph.interface.extended_cmd as cmd
77 import madgraph.interface.common_run_interface as common_run
78 import madgraph.iolibs.files as files
79 import madgraph.iolibs.save_load_object as save_load_object
80 import madgraph.madevent.gen_crossxhtml as gen_crossxhtml
81 import madgraph.madevent.sum_html as sum_html
82 import madgraph.various.banner as banner_mod
83 import madgraph.various.cluster as cluster
84 import madgraph.various.misc as misc
85 import madgraph.various.shower_card as shower_card
86 import madgraph.various.FO_analyse_card as analyse_card
87 import madgraph.various.histograms as histograms
88 from madgraph import InvalidCmd, aMCatNLOError, MadGraph5Error
89
92
93
95 """compile the direcory p_dir
96 arguments is the tuple (me_dir, p_dir, mode, options, tests, exe, run_mode)
97 this function needs not to be a class method in order to do
98 the compilation on multicore"""
99
100 if len(arguments) == 1:
101 (me_dir, p_dir, mode, options, tests, exe, run_mode) = arguments[0]
102 elif len(arguments)==7:
103 (me_dir, p_dir, mode, options, tests, exe, run_mode) = arguments
104 else:
105 raise aMCatNLOError, 'not correct number of argument'
106 logger.info(' Compiling %s...' % p_dir)
107
108 this_dir = pjoin(me_dir, 'SubProcesses', p_dir)
109
110 try:
111
112
113 for test in tests:
114
115 if test == 'check_poles' and os.path.exists(pjoin(this_dir, 'parton_lum_0.f')):
116 continue
117 misc.compile([test], cwd = this_dir, job_specs = False)
118 input = pjoin(me_dir, '%s_input.txt' % test)
119
120 misc.call(['./%s' % (test)], cwd=this_dir,
121 stdin = open(input), stdout=open(pjoin(this_dir, '%s.log' % test), 'w'))
122
123 if not options['reweightonly']:
124 misc.compile(['gensym'], cwd=this_dir, job_specs = False)
125 open(pjoin(this_dir, 'gensym_input.txt'), 'w').write('%s\n' % run_mode)
126 misc.call(['./gensym'],cwd= this_dir,
127 stdin=open(pjoin(this_dir, 'gensym_input.txt')),
128 stdout=open(pjoin(this_dir, 'gensym.log'), 'w'))
129
130 misc.compile([exe], cwd=this_dir, job_specs = False)
131 if mode in ['aMC@NLO', 'aMC@LO', 'noshower', 'noshowerLO']:
132 misc.compile(['reweight_xsec_events'], cwd=this_dir, job_specs = False)
133
134 logger.info(' %s done.' % p_dir)
135 return 0
136 except MadGraph5Error, msg:
137 return msg
138
139
141 """check that the current fortran compiler is gfortran 4.6 or later.
142 If block, stops the execution, otherwise just print a warning"""
143
144 msg = 'In order to be able to run at NLO MadGraph5_aMC@NLO, you need to have ' + \
145 'gfortran 4.6 or later installed.\n%s has been detected\n'+\
146 'Note that You can still run all MadEvent run without any problem!'
147
148 if options['fortran_compiler']:
149 compiler = options['fortran_compiler']
150 elif misc.which('gfortran'):
151 compiler = 'gfortran'
152 else:
153 compiler = ''
154
155 if 'gfortran' not in compiler:
156 if block:
157 raise aMCatNLOError(msg % compiler)
158 else:
159 logger.warning(msg % compiler)
160 else:
161 curr_version = misc.get_gfortran_version(compiler)
162 if not ''.join(curr_version.split('.')) >= '46':
163 if block:
164 raise aMCatNLOError(msg % (compiler + ' ' + curr_version))
165 else:
166 logger.warning(msg % (compiler + ' ' + curr_version))
167
168
169
170
171
172
174 """Particularisation of the cmd command for aMCatNLO"""
175
176
177 next_possibility = {
178 'start': [],
179 }
180
181 debug_output = 'ME5_debug'
182 error_debug = 'Please report this bug on https://bugs.launchpad.net/madgraph5\n'
183 error_debug += 'More information is found in \'%(debug)s\'.\n'
184 error_debug += 'Please attach this file to your report.'
185
186 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/madgraph5\n'
187
188
189 keyboard_stop_msg = """stopping all operation
190 in order to quit MadGraph5_aMC@NLO please enter exit"""
191
192
193 InvalidCmd = InvalidCmd
194 ConfigurationError = aMCatNLOError
195
196 - def __init__(self, me_dir, options, *arg, **opt):
197 """Init history and line continuation"""
198
199
200 self.force = False
201
202
203
204 info = misc.get_pkg_info()
205 info_line = ""
206 if info and info.has_key('version') and info.has_key('date'):
207 len_version = len(info['version'])
208 len_date = len(info['date'])
209 if len_version + len_date < 30:
210 info_line = "#* VERSION %s %s %s *\n" % \
211 (info['version'],
212 (30 - len_version - len_date) * ' ',
213 info['date'])
214 else:
215 version = open(pjoin(root_path,'MGMEVersion.txt')).readline().strip()
216 info_line = "#* VERSION %s %s *\n" % \
217 (version, (24 - len(version)) * ' ')
218
219
220
221 self.history_header = \
222 '#************************************************************\n' + \
223 '#* MadGraph5_aMC@NLO *\n' + \
224 '#* *\n' + \
225 "#* * * *\n" + \
226 "#* * * * * *\n" + \
227 "#* * * * * 5 * * * * *\n" + \
228 "#* * * * * *\n" + \
229 "#* * * *\n" + \
230 "#* *\n" + \
231 "#* *\n" + \
232 info_line + \
233 "#* *\n" + \
234 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
235 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
236 "#* and *\n" + \
237 "#* http://amcatnlo.cern.ch *\n" + \
238 '#* *\n' + \
239 '#************************************************************\n' + \
240 '#* *\n' + \
241 '#* Command File for aMCatNLO *\n' + \
242 '#* *\n' + \
243 '#* run as ./bin/aMCatNLO.py filename *\n' + \
244 '#* *\n' + \
245 '#************************************************************\n'
246
247 if info_line:
248 info_line = info_line[1:]
249
250 logger.info(\
251 "************************************************************\n" + \
252 "* *\n" + \
253 "* W E L C O M E to M A D G R A P H 5 *\n" + \
254 "* a M C @ N L O *\n" + \
255 "* *\n" + \
256 "* * * *\n" + \
257 "* * * * * *\n" + \
258 "* * * * * 5 * * * * *\n" + \
259 "* * * * * *\n" + \
260 "* * * *\n" + \
261 "* *\n" + \
262 info_line + \
263 "* *\n" + \
264 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
265 "* http://amcatnlo.cern.ch *\n" + \
266 "* *\n" + \
267 "* Type 'help' for in-line help. *\n" + \
268 "* *\n" + \
269 "************************************************************")
270 super(CmdExtended, self).__init__(me_dir, options, *arg, **opt)
271
272
274 """return the history header"""
275 return self.history_header % misc.get_time_info()
276
278 """action to perform to close nicely on a keyboard interupt"""
279 try:
280 if hasattr(self, 'cluster'):
281 logger.info('rm jobs on queue')
282 self.cluster.remove()
283 if hasattr(self, 'results'):
284 self.update_status('Stop by the user', level=None, makehtml=True, error=True)
285 self.add_error_log_in_html(KeyboardInterrupt)
286 except:
287 pass
288
289 - def postcmd(self, stop, line):
290 """ Update the status of the run for finishing interactive command """
291
292
293 self.force = False
294
295 if not self.use_rawinput:
296 return stop
297
298
299 arg = line.split()
300 if len(arg) == 0:
301 return stop
302 elif str(arg[0]) in ['exit','quit','EOF']:
303 return stop
304
305 try:
306 self.update_status('Command \'%s\' done.<br> Waiting for instruction.' % arg[0],
307 level=None, error=True)
308 except Exception:
309 misc.sprint('self.update_status fails', log=logger)
310 pass
311
317
323
329
330
331
332
333
334
336 """ The Series of help routine for the aMCatNLOCmd"""
337
341
343 logger.info("syntax: banner_run Path|RUN [--run_options]")
344 logger.info("-- Reproduce a run following a given banner")
345 logger.info(" One of the following argument is require:")
346 logger.info(" Path should be the path of a valid banner.")
347 logger.info(" RUN should be the name of a run of the current directory")
348 self.run_options_help([('-f','answer all question by default'),
349 ('--name=X', 'Define the name associated with the new run')])
350
351
355
360
361
365
369
370
372 logger.info("syntax: open FILE ")
373 logger.info("-- open a file with the appropriate editor.")
374 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
375 logger.info(' the path to the last created/used directory is used')
376
378 if data:
379 logger.info('-- local options:')
380 for name, info in data:
381 logger.info(' %s : %s' % (name, info))
382
383 logger.info("-- session options:")
384 logger.info(" Note that those options will be kept for the current session")
385 logger.info(" --cluster : Submit to the cluster. Current cluster: %s" % self.options['cluster_type'])
386 logger.info(" --multicore : Run in multi-core configuration")
387 logger.info(" --nb_core=X : limit the number of core to use to X.")
388
389
390
391
392
393
394
396 """ The Series of check routine for the aMCatNLOCmd"""
397
399 """Check the validity of the line. args[0] is the run_directory"""
400
401 if options['force']:
402 self.force = True
403
404 if len(args) == 0:
405 self.help_shower()
406 raise self.InvalidCmd, 'Invalid syntax, please specify the run name'
407 if not os.path.isdir(pjoin(self.me_dir, 'Events', args[0])):
408 raise self.InvalidCmd, 'Directory %s does not exists' % \
409 pjoin(os.getcwd(), 'Events', args[0])
410
411 self.set_run_name(args[0], level= 'shower')
412 args[0] = pjoin(self.me_dir, 'Events', args[0])
413
415 """Check the argument for the plot command
416 plot run_name modes"""
417
418
419 madir = self.options['madanalysis_path']
420 td = self.options['td_path']
421
422 if not madir or not td:
423 logger.info('Retry to read configuration file to find madanalysis/td')
424 self.set_configuration()
425
426 madir = self.options['madanalysis_path']
427 td = self.options['td_path']
428
429 if not madir:
430 error_msg = 'No Madanalysis path correctly set.'
431 error_msg += 'Please use the set command to define the path and retry.'
432 error_msg += 'You can also define it in the configuration file.'
433 raise self.InvalidCmd(error_msg)
434 if not td:
435 error_msg = 'No path to td directory correctly set.'
436 error_msg += 'Please use the set command to define the path and retry.'
437 error_msg += 'You can also define it in the configuration file.'
438 raise self.InvalidCmd(error_msg)
439
440 if len(args) == 0:
441 if not hasattr(self, 'run_name') or not self.run_name:
442 self.help_plot()
443 raise self.InvalidCmd('No run name currently define. Please add this information.')
444 args.append('all')
445 return
446
447
448 if args[0] not in self._plot_mode:
449 self.set_run_name(args[0], level='plot')
450 del args[0]
451 if len(args) == 0:
452 args.append('all')
453 elif not self.run_name:
454 self.help_plot()
455 raise self.InvalidCmd('No run name currently define. Please add this information.')
456
457 for arg in args:
458 if arg not in self._plot_mode and arg != self.run_name:
459 self.help_plot()
460 raise self.InvalidCmd('unknown options %s' % arg)
461
463 """Check the argument for pythia command
464 syntax: pgs [NAME]
465 Note that other option are already remove at this point
466 """
467
468
469 if not self.options['pythia-pgs_path']:
470 logger.info('Retry to read configuration file to find pythia-pgs path')
471 self.set_configuration()
472
473 if not self.options['pythia-pgs_path'] or not \
474 os.path.exists(pjoin(self.options['pythia-pgs_path'],'src')):
475 error_msg = 'No pythia-pgs path correctly set.'
476 error_msg += 'Please use the set command to define the path and retry.'
477 error_msg += 'You can also define it in the configuration file.'
478 raise self.InvalidCmd(error_msg)
479
480 tag = [a for a in arg if a.startswith('--tag=')]
481 if tag:
482 arg.remove(tag[0])
483 tag = tag[0][6:]
484
485
486 if len(arg) == 0 and not self.run_name:
487 if self.results.lastrun:
488 arg.insert(0, self.results.lastrun)
489 else:
490 raise self.InvalidCmd('No run name currently define. Please add this information.')
491
492 if len(arg) == 1 and self.run_name == arg[0]:
493 arg.pop(0)
494
495 if not len(arg) and \
496 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')):
497 self.help_pgs()
498 raise self.InvalidCmd('''No file file pythia_events.hep currently available
499 Please specify a valid run_name''')
500
501 lock = None
502 if len(arg) == 1:
503 prev_tag = self.set_run_name(arg[0], tag, 'pgs')
504 filenames = glob.glob(pjoin(self.me_dir, 'Events', self.run_name,
505 'events_*.hep.gz'))
506 if not filenames:
507 raise self.InvalidCmd('No events file corresponding to %s run with tag %s. '% (self.run_name, prev_tag))
508 else:
509 input_file = filenames[0]
510 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep')
511 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'),
512 argument=['-c', input_file])
513 else:
514 if tag:
515 self.run_card['run_tag'] = tag
516 self.set_run_name(self.run_name, tag, 'pgs')
517
518 return lock
519
520
522 """Check the argument for pythia command
523 syntax: delphes [NAME]
524 Note that other option are already remove at this point
525 """
526
527
528 if not self.options['delphes_path']:
529 logger.info('Retry to read configuration file to find delphes path')
530 self.set_configuration()
531
532 if not self.options['delphes_path']:
533 error_msg = 'No delphes path correctly set.'
534 error_msg += 'Please use the set command to define the path and retry.'
535 error_msg += 'You can also define it in the configuration file.'
536 raise self.InvalidCmd(error_msg)
537
538 tag = [a for a in arg if a.startswith('--tag=')]
539 if tag:
540 arg.remove(tag[0])
541 tag = tag[0][6:]
542
543
544 if len(arg) == 0 and not self.run_name:
545 if self.results.lastrun:
546 arg.insert(0, self.results.lastrun)
547 else:
548 raise self.InvalidCmd('No run name currently define. Please add this information.')
549
550 if len(arg) == 1 and self.run_name == arg[0]:
551 arg.pop(0)
552
553 if not len(arg) and \
554 not os.path.exists(pjoin(self.me_dir,'Events','pythia_events.hep')):
555 self.help_pgs()
556 raise self.InvalidCmd('''No file file pythia_events.hep currently available
557 Please specify a valid run_name''')
558
559 if len(arg) == 1:
560 prev_tag = self.set_run_name(arg[0], tag, 'delphes')
561 filenames = glob.glob(pjoin(self.me_dir, 'Events', self.run_name,
562 'events_*.hep.gz'))
563 if not filenames:
564 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\
565 % (self.run_name, prev_tag,
566 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)))
567 else:
568 input_file = filenames[0]
569 output_file = pjoin(self.me_dir, 'Events', 'pythia_events.hep')
570 lock = cluster.asyncrone_launch('gunzip',stdout=open(output_file,'w'),
571 argument=['-c', input_file])
572 else:
573 if tag:
574 self.run_card['run_tag'] = tag
575 self.set_run_name(self.run_name, tag, 'delphes')
576
578 """check the validity of the line. args is ORDER,
579 ORDER being LO or NLO. If no mode is passed, NLO is used"""
580
581
582
583 if options['force']:
584 self.force = True
585
586 if not args:
587 args.append('NLO')
588 return
589
590 if len(args) > 1:
591 self.help_calculate_xsect()
592 raise self.InvalidCmd, 'Invalid Syntax: Too many argument'
593
594 elif len(args) == 1:
595 if not args[0] in ['NLO', 'LO']:
596 raise self.InvalidCmd, '%s is not a valid mode, please use "LO" or "NLO"' % args[1]
597 mode = args[0]
598
599
600 if options['multicore'] and options['cluster']:
601 raise self.InvalidCmd, 'options -m (--multicore) and -c (--cluster)' + \
602 ' are not compatible. Please choose one.'
603
604
606 """check the validity of the line. args is ORDER,
607 ORDER being LO or NLO. If no mode is passed, NLO is used"""
608
609
610
611 if not args:
612 args.append('NLO')
613 return
614
615 if len(args) > 1:
616 self.help_generate_events()
617 raise self.InvalidCmd, 'Invalid Syntax: Too many argument'
618
619 elif len(args) == 1:
620 if not args[0] in ['NLO', 'LO']:
621 raise self.InvalidCmd, '%s is not a valid mode, please use "LO" or "NLO"' % args[1]
622 mode = args[0]
623
624
625 if options['multicore'] and options['cluster']:
626 raise self.InvalidCmd, 'options -m (--multicore) and -c (--cluster)' + \
627 ' are not compatible. Please choose one.'
628
630 """check the validity of line"""
631
632 if len(args) == 0:
633 self.help_banner_run()
634 raise self.InvalidCmd('banner_run requires at least one argument.')
635
636 tag = [a[6:] for a in args if a.startswith('--tag=')]
637
638
639 if os.path.exists(args[0]):
640 type ='banner'
641 format = self.detect_card_type(args[0])
642 if format != 'banner':
643 raise self.InvalidCmd('The file is not a valid banner.')
644 elif tag:
645 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \
646 (args[0], tag))
647 if not os.path.exists(args[0]):
648 raise self.InvalidCmd('No banner associates to this name and tag.')
649 else:
650 name = args[0]
651 type = 'run'
652 banners = glob.glob(pjoin(self.me_dir,'Events', args[0], '*_banner.txt'))
653 if not banners:
654 raise self.InvalidCmd('No banner associates to this name.')
655 elif len(banners) == 1:
656 args[0] = banners[0]
657 else:
658
659 tags = [os.path.basename(p)[len(args[0])+1:-11] for p in banners]
660 tag = self.ask('which tag do you want to use?', tags[0], tags)
661 args[0] = pjoin(self.me_dir,'Events', args[0], '%s_%s_banner.txt' % \
662 (args[0], tag))
663
664 run_name = [arg[7:] for arg in args if arg.startswith('--name=')]
665 if run_name:
666 try:
667 self.exec_cmd('remove %s all banner -f' % run_name)
668 except Exception:
669 pass
670 self.set_run_name(args[0], tag=None, level='parton', reload_card=True)
671 elif type == 'banner':
672 self.set_run_name(self.find_available_run_name(self.me_dir))
673 elif type == 'run':
674 if not self.results[name].is_empty():
675 run_name = self.find_available_run_name(self.me_dir)
676 logger.info('Run %s is not empty so will use run_name: %s' % \
677 (name, run_name))
678 self.set_run_name(run_name)
679 else:
680 try:
681 self.exec_cmd('remove %s all banner -f' % run_name)
682 except Exception:
683 pass
684 self.set_run_name(name)
685
686
687
689 """check the validity of the line. args is MODE
690 MODE being LO, NLO, aMC@NLO or aMC@LO. If no mode is passed, auto is used"""
691
692
693
694 if options['force']:
695 self.force = True
696
697
698 if not args:
699 args.append('auto')
700 return
701
702 if len(args) > 1:
703 self.help_launch()
704 raise self.InvalidCmd, 'Invalid Syntax: Too many argument'
705
706 elif len(args) == 1:
707 if not args[0] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO','auto']:
708 raise self.InvalidCmd, '%s is not a valid mode, please use "LO", "NLO", "aMC@NLO" or "aMC@LO"' % args[0]
709 mode = args[0]
710
711
712 if options['multicore'] and options['cluster']:
713 raise self.InvalidCmd, 'options -m (--multicore) and -c (--cluster)' + \
714 ' are not compatible. Please choose one.'
715 if mode == 'NLO' and options['reweightonly']:
716 raise self.InvalidCmd, 'option -r (--reweightonly) needs mode "aMC@NLO" or "aMC@LO"'
717
718
720 """check the validity of the line. args is MODE
721 MODE being FO or MC. If no mode is passed, MC is used"""
722
723
724
725 if options['force']:
726 self.force = True
727
728 if not args:
729 args.append('MC')
730 return
731
732 if len(args) > 1:
733 self.help_compile()
734 raise self.InvalidCmd, 'Invalid Syntax: Too many argument'
735
736 elif len(args) == 1:
737 if not args[0] in ['MC', 'FO']:
738 raise self.InvalidCmd, '%s is not a valid mode, please use "FO" or "MC"' % args[0]
739 mode = args[0]
740
741
742
743
744
745
746
748 """ The Series of help routine for the MadGraphCmd"""
749
751 """auto-completion for launch command"""
752
753 args = self.split_arg(line[0:begidx])
754 if len(args) == 1:
755
756 return self.list_completion(text,['LO','NLO','aMC@NLO','aMC@LO'],line)
757 elif len(args) == 2 and line[begidx-1] == '@':
758 return self.list_completion(text,['LO','NLO'],line)
759 else:
760 opts = []
761 for opt in _launch_parser.option_list:
762 opts += opt._long_opts + opt._short_opts
763 return self.list_completion(text, opts, line)
764
766 "Complete the banner run command"
767 try:
768
769
770 args = self.split_arg(line[0:begidx], error=False)
771
772 if args[-1].endswith(os.path.sep):
773 return self.path_completion(text,
774 os.path.join('.',*[a for a in args \
775 if a.endswith(os.path.sep)]))
776
777
778 if len(args) > 1:
779
780 tags = glob.glob(pjoin(self.me_dir, 'Events' , args[1],'%s_*_banner.txt' % args[1]))
781 tags = ['%s' % os.path.basename(t)[len(args[1])+1:-11] for t in tags]
782
783 if args[-1] != '--tag=':
784 tags = ['--tag=%s' % t for t in tags]
785 else:
786 return self.list_completion(text, tags)
787 return self.list_completion(text, tags +['--name=','-f'], line)
788
789
790 possibilites = {}
791
792 comp = self.path_completion(text, os.path.join('.',*[a for a in args \
793 if a.endswith(os.path.sep)]))
794 if os.path.sep in line:
795 return comp
796 else:
797 possibilites['Path from ./'] = comp
798
799 run_list = glob.glob(pjoin(self.me_dir, 'Events', '*','*_banner.txt'))
800 run_list = [n.rsplit('/',2)[1] for n in run_list]
801 possibilites['RUN Name'] = self.list_completion(text, run_list)
802
803 return self.deal_multiple_categories(possibilites)
804
805
806 except Exception, error:
807 print error
808
809
822
835
837 """auto-completion for generate_events command
838 call the compeltion for launch"""
839 self.complete_launch(text, line, begidx, endidx)
840
841
843 args = self.split_arg(line[0:begidx])
844 if len(args) == 1:
845
846 data = glob.glob(pjoin(self.me_dir, 'Events', '*','events.lhe.gz'))
847 data = [n.rsplit('/',2)[1] for n in data]
848 tmp1 = self.list_completion(text, data)
849 if not self.run_name:
850 return tmp1
851
853 """ Complete the plot command """
854
855 args = self.split_arg(line[0:begidx], error=False)
856
857 if len(args) == 1:
858
859 data = glob.glob(pjoin(self.me_dir, 'Events', '*','events.lhe*'))
860 data = [n.rsplit('/',2)[1] for n in data]
861 tmp1 = self.list_completion(text, data)
862 if not self.run_name:
863 return tmp1
864
865 if len(args) > 1:
866 return self.list_completion(text, self._plot_mode)
867
869 "Complete the pgs command"
870 args = self.split_arg(line[0:begidx], error=False)
871 if len(args) == 1:
872
873 data = glob.glob(pjoin(self.me_dir, 'Events', '*', 'events_*.hep.gz'))
874 data = [n.rsplit('/',2)[1] for n in data]
875 tmp1 = self.list_completion(text, data)
876 if not self.run_name:
877 return tmp1
878 else:
879 tmp2 = self.list_completion(text, self._run_options + ['-f',
880 '--tag=' ,'--no_default'], line)
881 return tmp1 + tmp2
882 else:
883 return self.list_completion(text, self._run_options + ['-f',
884 '--tag=','--no_default'], line)
885
886 complete_delphes = complete_pgs
887
890
891
892
893
894 -class aMCatNLOCmd(CmdExtended, HelpToCmd, CompleteForCmd, common_run.CommonRunCmd):
895 """The command line processor of MadGraph"""
896
897
898 true = ['T','.true.',True,'true']
899
900 _run_options = ['--cluster','--multicore','--nb_core=','--nb_core=2', '-c', '-m']
901 _generate_options = ['-f', '--laststep=parton', '--laststep=pythia', '--laststep=pgs', '--laststep=delphes']
902 _calculate_decay_options = ['-f', '--accuracy=0.']
903 _set_options = ['stdout_level','fortran_compiler','cpp_compiler','timeout']
904 _plot_mode = ['all', 'parton','shower','pgs','delphes']
905 _clean_mode = _plot_mode + ['channel', 'banner']
906 _display_opts = ['run_name', 'options', 'variable']
907
908
909 web = False
910 cluster_mode = 0
911 queue = 'madgraph'
912 nb_core = None
913
914 next_possibility = {
915 'start': ['generate_events [OPTIONS]', 'calculate_crossx [OPTIONS]', 'launch [OPTIONS]',
916 'help generate_events'],
917 'generate_events': ['generate_events [OPTIONS]', 'shower'],
918 'launch': ['launch [OPTIONS]', 'shower'],
919 'shower' : ['generate_events [OPTIONS]']
920 }
921
922
923
924 - def __init__(self, me_dir = None, options = {}, *completekey, **stdin):
925 """ add information to the cmd """
926
927 self.start_time = 0
928 CmdExtended.__init__(self, me_dir, options, *completekey, **stdin)
929
930
931 self.mode = 'aMCatNLO'
932 self.nb_core = 0
933 self.prompt = "%s>"%os.path.basename(pjoin(self.me_dir))
934
935
936 if os.path.exists(pjoin(self.me_dir,'HTML','results.pkl')):
937 self.results = save_load_object.load_from_file(pjoin(self.me_dir,'HTML','results.pkl'))
938 self.results.resetall(self.me_dir)
939 self.last_mode = self.results[self.results.lastrun][-1]['run_mode']
940 else:
941 model = self.find_model_name()
942 process = self.process
943 self.results = gen_crossxhtml.AllResultsNLO(model, process, self.me_dir)
944 self.last_mode = ''
945 self.results.def_web_mode(self.web)
946
947 proc_card = open(pjoin(self.me_dir, 'Cards', 'proc_card_mg5.dat')).read()
948
949 if not '[real=QCD]' in proc_card:
950 check_compiler(self.options, block=True)
951
952
953
955 """ run the shower on a given parton level file """
956 argss = self.split_arg(line)
957 (options, argss) = _launch_parser.parse_args(argss)
958
959 options = options.__dict__
960 options['reweightonly'] = False
961 self.check_shower(argss, options)
962 evt_file = pjoin(os.getcwd(), argss[0], 'events.lhe')
963 self.ask_run_configuration('onlyshower', options)
964 self.run_mcatnlo(evt_file)
965
966 self.update_status('', level='all', update_results=True)
967
968
970 """Create the plot for a given run"""
971
972
973 args = self.split_arg(line)
974
975 self.check_plot(args)
976 logger.info('plot for run %s' % self.run_name)
977
978 if not self.force:
979 self.ask_edit_cards([], args, plot=True)
980
981 if any([arg in ['parton'] for arg in args]):
982 filename = pjoin(self.me_dir, 'Events', self.run_name, 'events.lhe')
983 if os.path.exists(filename+'.gz'):
984 misc.gunzip(filename)
985 if os.path.exists(filename):
986 logger.info('Found events.lhe file for run %s' % self.run_name)
987 shutil.move(filename, pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'))
988 self.create_plot('parton')
989 shutil.move(pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'), filename)
990 misc.gzip(filename)
991
992 if any([arg in ['all','parton'] for arg in args]):
993 filename = pjoin(self.me_dir, 'Events', self.run_name, 'MADatNLO.top')
994 if os.path.exists(filename):
995 logger.info('Found MADatNLO.top file for run %s' % \
996 self.run_name)
997 output = pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
998 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name, 'plots_parton')
999
1000 if not os.path.isdir(plot_dir):
1001 os.makedirs(plot_dir)
1002 top_file = pjoin(plot_dir, 'plots.top')
1003 files.cp(filename, top_file)
1004 madir = self.options['madanalysis_path']
1005 tag = self.run_card['run_tag']
1006 td = self.options['td_path']
1007 misc.call(['%s/plot' % self.dirbin, madir, td],
1008 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
1009 stderr = subprocess.STDOUT,
1010 cwd=plot_dir)
1011
1012 misc.call(['%s/plot_page-pl' % self.dirbin,
1013 os.path.basename(plot_dir),
1014 'parton'],
1015 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
1016 stderr = subprocess.STDOUT,
1017 cwd=pjoin(self.me_dir, 'HTML', self.run_name))
1018 shutil.move(pjoin(self.me_dir, 'HTML',self.run_name ,'plots.html'),
1019 output)
1020
1021 os.remove(pjoin(self.me_dir, 'Events', 'plots.top'))
1022
1023 if any([arg in ['all','shower'] for arg in args]):
1024 filenames = glob.glob(pjoin(self.me_dir, 'Events', self.run_name,
1025 'events_*.lhe.gz'))
1026 if len(filenames) != 1:
1027 filenames = glob.glob(pjoin(self.me_dir, 'Events', self.run_name,
1028 'events_*.hep.gz'))
1029 if len(filenames) != 1:
1030 logger.info('No shower level file found for run %s' % \
1031 self.run_name)
1032 return
1033 filename = filenames[0]
1034 misc.gunzip(filename, keep=True, stdout=pjoin(self.me_dir, 'Events','pythia_events.hep'))
1035
1036 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pythia_card.dat')):
1037 if aMCatNLO and not self.options['mg5_path']:
1038 raise "plotting NLO HEP file needs MG5 utilities"
1039
1040 files.cp(pjoin(self.options['mg5_path'], 'Template','LO', 'Cards', 'pythia_card_default.dat'),
1041 pjoin(self.me_dir, 'Cards', 'pythia_card.dat'))
1042 self.run_hep2lhe()
1043 else:
1044 filename = filenames[0]
1045 misc.gunzip(filename, keep=True, stdout=pjoin(self.me_dir, 'Events','pythia_events.hep'))
1046
1047 self.create_plot('shower')
1048 lhe_file_name = filename.replace('.hep.gz', '.lhe')
1049 shutil.move(pjoin(self.me_dir, 'Events','pythia_events.lhe'),
1050 lhe_file_name)
1051 misc.gzip(lhe_file_name)
1052
1053 if any([arg in ['all','pgs'] for arg in args]):
1054 filename = pjoin(self.me_dir, 'Events', self.run_name,
1055 '%s_pgs_events.lhco' % self.run_tag)
1056 if os.path.exists(filename+'.gz'):
1057 misc.gunzip(filename)
1058 if os.path.exists(filename):
1059 self.create_plot('PGS')
1060 misc.gzip(filename)
1061 else:
1062 logger.info('No valid files for pgs plot')
1063
1064 if any([arg in ['all','delphes'] for arg in args]):
1065 filename = pjoin(self.me_dir, 'Events', self.run_name,
1066 '%s_delphes_events.lhco' % self.run_tag)
1067 if os.path.exists(filename+'.gz'):
1068 misc.gunzip(filename)
1069 if os.path.exists(filename):
1070
1071 self.create_plot('Delphes')
1072
1073 misc.gzip(filename)
1074 else:
1075 logger.info('No valid files for delphes plot')
1076
1077
1078
1080 """Main commands: calculates LO/NLO cross-section, using madevent_mintFO
1081 this function wraps the do_launch one"""
1082
1083 self.start_time = time.time()
1084 argss = self.split_arg(line)
1085
1086 (options, argss) = _calculate_xsect_parser.parse_args(argss)
1087 options = options.__dict__
1088 options['reweightonly'] = False
1089 options['parton'] = True
1090 self.check_calculate_xsect(argss, options)
1091 self.do_launch(line, options, argss)
1092
1093
1095 """Make a run from the banner file"""
1096
1097 args = self.split_arg(line)
1098
1099 self.check_banner_run(args)
1100
1101
1102 for name in ['shower_card.dat', 'madspin_card.dat']:
1103 try:
1104 os.remove(pjoin(self.me_dir, 'Cards', name))
1105 except Exception:
1106 pass
1107
1108 banner_mod.split_banner(args[0], self.me_dir, proc_card=False)
1109
1110
1111 if not self.force:
1112 ans = self.ask('Do you want to modify the Cards/Run Type?', 'n', ['y','n'])
1113 if ans == 'n':
1114 self.force = True
1115
1116
1117 if self.force:
1118 mode_status = {'order': 'NLO', 'fixed_order': False, 'madspin':False, 'shower':True}
1119 banner = banner_mod.Banner(args[0])
1120 for line in banner['run_settings']:
1121 if '=' in line:
1122 mode, value = [t.strip() for t in line.split('=')]
1123 mode_status[mode] = value
1124 else:
1125 mode_status = {}
1126
1127
1128 self.do_launch('-n %s %s' % (self.run_name, '-f' if self.force else ''),
1129 switch=mode_status)
1130
1131
1133 """Main commands: generate events
1134 this function just wraps the do_launch one"""
1135 self.do_launch(line)
1136
1137
1138
1140 """Advanced commands: this is for creating the correct run_card.inc from the nlo format"""
1141
1142 self.check_param_card(pjoin(self.me_dir, 'Cards','param_card.dat'))
1143 return super(aMCatNLOCmd,self).do_treatcards(line, amcatnlo)
1144
1145
1147 """assign all configuration variable from file
1148 loop over the different config file if config_file not define """
1149 return super(aMCatNLOCmd,self).set_configuration(amcatnlo=amcatnlo, **opt)
1150
1151
1152 - def do_launch(self, line, options={}, argss=[], switch={}):
1153 """Main commands: launch the full chain
1154 options and args are relevant if the function is called from other
1155 functions, such as generate_events or calculate_xsect
1156 mode gives the list of switch needed for the computation (usefull for banner_run)
1157 """
1158
1159 if not argss and not options:
1160 self.start_time = time.time()
1161 argss = self.split_arg(line)
1162
1163 (options, argss) = _launch_parser.parse_args(argss)
1164 options = options.__dict__
1165 self.check_launch(argss, options)
1166
1167 if 'run_name' in options.keys() and options['run_name']:
1168 self.run_name = options['run_name']
1169
1170
1171 if os.path.isdir(pjoin(self.me_dir, 'Events', self.run_name)):
1172 logger.warning('Removing old run information in \n'+
1173 pjoin(self.me_dir, 'Events', self.run_name))
1174 files.rm(pjoin(self.me_dir, 'Events', self.run_name))
1175 self.results.delete_run(self.run_name)
1176 else:
1177 self.run_name = ''
1178
1179 if options['multicore']:
1180 self.cluster_mode = 2
1181 elif options['cluster']:
1182 self.cluster_mode = 1
1183
1184 if not switch:
1185 mode = argss[0]
1186 if mode in ['LO', 'NLO']:
1187 options['parton'] = True
1188 mode = self.ask_run_configuration(mode, options)
1189 else:
1190 mode = self.ask_run_configuration('auto', options, switch)
1191
1192 self.results.add_detail('run_mode', mode)
1193
1194 self.update_status('Starting run', level=None, update_results=True)
1195
1196 if self.options['automatic_html_opening']:
1197 misc.open_file(os.path.join(self.me_dir, 'crossx.html'))
1198 self.options['automatic_html_opening'] = False
1199
1200 if '+' in mode:
1201 mode = mode.split('+')[0]
1202 self.compile(mode, options)
1203 evt_file = self.run(mode, options)
1204
1205 if int(self.run_card['nevents']) == 0 and not mode in ['LO', 'NLO']:
1206 logger.info('No event file generated: grids have been set-up with a '\
1207 'relative precision of %s' % self.run_card['req_acc'])
1208 return
1209
1210 if not mode in ['LO', 'NLO']:
1211 assert evt_file == pjoin(self.me_dir,'Events', self.run_name, 'events.lhe'), '%s != %s' %(evt_file, pjoin(self.me_dir,'Events', self.run_name, 'events.lhe.gz'))
1212 self.exec_cmd('reweight -from_cards', postcmd=False)
1213 self.exec_cmd('decay_events -from_cards', postcmd=False)
1214 evt_file = pjoin(self.me_dir,'Events', self.run_name, 'events.lhe')
1215
1216 if not mode in ['LO', 'NLO', 'noshower', 'noshowerLO'] \
1217 and not options['parton']:
1218 self.run_mcatnlo(evt_file)
1219 elif mode == 'noshower':
1220 logger.warning("""You have chosen not to run a parton shower. NLO events without showering are NOT physical.
1221 Please, shower the Les Houches events before using them for physics analyses.""")
1222
1223
1224 self.update_status('', level='all', update_results=True)
1225 if int(self.run_card['ickkw']) == 3 and mode in ['noshower', 'aMC@NLO']:
1226 logger.warning("""You are running with FxFx merging enabled.
1227 To be able to merge samples of various multiplicities without double counting,
1228 you have to remove some events after showering 'by hand'.
1229 Please read http://amcatnlo.cern.ch/FxFx_merging.htm for more details.""")
1230
1231
1232
1233
1235 """Advanced commands: just compile the executables """
1236 argss = self.split_arg(line)
1237
1238 (options, argss) = _compile_parser.parse_args(argss)
1239 options = options.__dict__
1240 options['reweightonly'] = False
1241 options['nocompile'] = False
1242 self.check_compile(argss, options)
1243
1244 mode = {'FO': 'NLO', 'MC': 'aMC@NLO'}[argss[0]]
1245 self.ask_run_configuration(mode, options)
1246 self.compile(mode, options)
1247
1248
1249 self.update_status('', level='all', update_results=True)
1250
1252 """Have a nice results prints in the shell,
1253 data should be of type: gen_crossxhtml.OneTagResults"""
1254 if not data:
1255 return
1256 logger.info(" === Results Summary for run: %s tag: %s ===\n" % (data['run_name'],data['tag']))
1257 if self.ninitial == 1:
1258 logger.info(" Width : %.4g +- %.4g GeV" % (data['cross'], data['error']))
1259 else:
1260 logger.info(" Cross-section : %.4g +- %.4g pb" % (data['cross'], data['error']))
1261 logger.info(" Nb of events : %s" % data['nb_event'] )
1262
1263
1264
1265
1266
1267
1268
1269
1270 logger.info(" " )
1271
1273 """Have a nice results prints in the shell,
1274 data should be of type: gen_crossxhtml.OneTagResults"""
1275 if not data:
1276 return
1277
1278 fsock = open(path, mode)
1279
1280 fsock.write(" === Results Summary for run: %s tag: %s process: %s ===\n" % \
1281 (data['run_name'],data['tag'], os.path.basename(self.me_dir)))
1282
1283 if self.ninitial == 1:
1284 fsock.write(" Width : %.4g +- %.4g GeV\n" % (data['cross'], data['error']))
1285 else:
1286 fsock.write(" Cross-section : %.4g +- %.4g pb\n" % (data['cross'], data['error']))
1287 fsock.write(" Nb of events : %s\n" % data['nb_event'] )
1288
1289
1290
1291
1292
1293
1294 fsock.write(" \n" )
1295
1296
1297
1298
1299
1301 """Update random number seed with the value from the run_card.
1302 If this is 0, update the number according to a fresh one"""
1303 iseed = int(self.run_card['iseed'])
1304 if iseed == 0:
1305 randinit = open(pjoin(self.me_dir, 'SubProcesses', 'randinit'))
1306 iseed = int(randinit.read()[2:]) + 1
1307 randinit.close()
1308 randinit = open(pjoin(self.me_dir, 'SubProcesses', 'randinit'), 'w')
1309 randinit.write('r=%d' % iseed)
1310 randinit.close()
1311
1312
1313 - def run(self, mode, options):
1314 """runs aMC@NLO. Returns the name of the event file created"""
1315 logger.info('Starting run')
1316
1317 if not 'only_generation' in options.keys():
1318 options['only_generation'] = False
1319
1320 if mode in ['LO', 'NLO'] and self.run_card['iappl'] == 2 and not options['only_generation']:
1321 options['only_generation'] = True
1322 self.get_characteristics(pjoin(self.me_dir, 'SubProcesses', 'proc_characteristics'))
1323
1324 if self.cluster_mode == 1:
1325 cluster_name = self.options['cluster_type']
1326 self.cluster = cluster.from_name[cluster_name](**self.options)
1327 if self.cluster_mode == 2:
1328 try:
1329 import multiprocessing
1330 if not self.nb_core:
1331 try:
1332 self.nb_core = int(self.options['nb_core'])
1333 except TypeError:
1334 self.nb_core = multiprocessing.cpu_count()
1335 logger.info('Using %d cores' % self.nb_core)
1336 except ImportError:
1337 self.nb_core = 1
1338 logger.warning('Impossible to detect the number of cores => Using One.\n'+
1339 'Use set nb_core X in order to set this number and be able to'+
1340 'run in multicore.')
1341
1342 self.cluster = cluster.MultiCore(**self.options)
1343 self.update_random_seed()
1344
1345 folder_names = {'LO': ['born_G*'], 'NLO': ['all_G*'],
1346 'aMC@LO': ['GB*'], 'aMC@NLO': ['GF*']}
1347 folder_names['noshower'] = folder_names['aMC@NLO']
1348 folder_names['noshowerLO'] = folder_names['aMC@LO']
1349 job_dict = {}
1350 p_dirs = [d for d in \
1351 open(pjoin(self.me_dir, 'SubProcesses', 'subproc.mg')).read().split('\n') if d]
1352
1353 if not options['only_generation'] and not options['reweightonly']:
1354 self.update_status('Cleaning previous results', level=None)
1355 for dir in p_dirs:
1356 job_dict[dir] = [file for file in \
1357 os.listdir(pjoin(self.me_dir, 'SubProcesses', dir)) \
1358 if file.startswith('ajob')]
1359
1360 for obj in folder_names[mode]:
1361 to_rm = [file for file in \
1362 os.listdir(pjoin(self.me_dir, 'SubProcesses', dir)) \
1363 if file.startswith(obj[:-1]) and \
1364 (os.path.isdir(pjoin(self.me_dir, 'SubProcesses', dir, file)) or \
1365 os.path.exists(pjoin(self.me_dir, 'SubProcesses', dir, file)))]
1366
1367
1368
1369 to_always_rm = [file for file in \
1370 os.listdir(pjoin(self.me_dir, 'SubProcesses', dir)) \
1371 if file.startswith(obj[:-1]) and
1372 '_' in file and not '_G' in file and \
1373 (os.path.isdir(pjoin(self.me_dir, 'SubProcesses', dir, file)) or \
1374 os.path.exists(pjoin(self.me_dir, 'SubProcesses', dir, file)))]
1375
1376 if not options['only_generation'] and not options['reweightonly']:
1377 to_always_rm.extend(to_rm)
1378 if os.path.exists(pjoin(self.me_dir, 'SubProcesses', dir,'MadLoop5_resources.tar.gz')):
1379 to_always_rm.append(pjoin(self.me_dir, 'SubProcesses', dir,'MadLoop5_resources.tar.gz'))
1380 files.rm([pjoin(self.me_dir, 'SubProcesses', dir, d) for d in to_always_rm])
1381
1382 mcatnlo_status = ['Setting up grid', 'Computing upper envelope', 'Generating events']
1383
1384 if self.run_card['iappl'] == 2:
1385 self.applgrid_distribute(options,mode,p_dirs)
1386
1387 if options['reweightonly']:
1388 event_norm=self.run_card['event_norm']
1389 nevents=int(self.run_card['nevents'])
1390 return self.reweight_and_collect_events(options, mode, nevents, event_norm)
1391
1392 devnull = os.open(os.devnull, os.O_RDWR)
1393 if mode in ['LO', 'NLO']:
1394
1395 mode_dict = {'NLO': 'all', 'LO': 'born'}
1396 logger.info('Doing fixed order %s' % mode)
1397 req_acc = self.run_card['req_acc_FO']
1398 if not options['only_generation'] and req_acc != -1:
1399 self.write_madin_file(pjoin(self.me_dir, 'SubProcesses'), mode_dict[mode], 0, '-1', '6','0.10')
1400 self.update_status('Setting up grids', level=None)
1401 self.run_all(job_dict, [['0', mode_dict[mode], '0']], 'Setting up grids')
1402 elif not options['only_generation']:
1403 npoints = self.run_card['npoints_FO_grid']
1404 niters = self.run_card['niters_FO_grid']
1405 self.write_madin_file(pjoin(self.me_dir, 'SubProcesses'), mode_dict[mode], 0, npoints, niters)
1406 self.update_status('Setting up grids', level=None)
1407 self.run_all(job_dict, [['0', mode_dict[mode], '0']], 'Setting up grids')
1408
1409 npoints = self.run_card['npoints_FO']
1410 niters = self.run_card['niters_FO']
1411 self.write_madin_file(pjoin(self.me_dir, 'SubProcesses'), mode_dict[mode], -1, npoints, niters)
1412
1413 self.collect_log_files(folder_names[mode], 0)
1414 p = misc.Popen(['./combine_results_FO.sh', str(req_acc), '%s_G*' % mode_dict[mode]], \
1415 stdout=subprocess.PIPE, \
1416 cwd=pjoin(self.me_dir, 'SubProcesses'))
1417 output = p.communicate()
1418
1419 self.cross_sect_dict = self.read_results(output, mode)
1420 self.print_summary(options, 0, mode)
1421 cross, error = sum_html.make_all_html_results(self, ['%s*' % mode_dict[mode]])
1422 self.results.add_detail('cross', cross)
1423 self.results.add_detail('error', error)
1424
1425 self.update_status('Computing cross-section', level=None)
1426 self.run_all(job_dict, [['0', mode_dict[mode], '0', mode_dict[mode]]], 'Computing cross-section')
1427
1428
1429 self.collect_log_files(folder_names[mode], 1)
1430 p = misc.Popen(['./combine_results_FO.sh', '-1'] + folder_names[mode], \
1431 stdout=subprocess.PIPE,
1432 cwd=pjoin(self.me_dir, 'SubProcesses'))
1433 output = p.communicate()
1434 self.cross_sect_dict = self.read_results(output, mode)
1435
1436
1437 scale_pdf_info={}
1438 if self.run_card['reweight_scale'] or self.run_card['reweight_PDF']:
1439 data_files=[]
1440 for dir in p_dirs:
1441 for obj in folder_names[mode]:
1442 for file in os.listdir(pjoin(self.me_dir, 'SubProcesses', dir)):
1443 if file.startswith(obj[:-1]) and \
1444 (os.path.exists(pjoin(self.me_dir, 'SubProcesses', dir, file,'scale_pdf_dependence.dat'))):
1445 data_files.append(pjoin(dir,file,'scale_pdf_dependence.dat'))
1446 scale_pdf_info = self.pdf_scale_from_reweighting(data_files)
1447
1448 self.print_summary(options, 1, mode, scale_pdf_info)
1449
1450 files.cp(pjoin(self.me_dir, 'SubProcesses', 'res.txt'),
1451 pjoin(self.me_dir, 'Events', self.run_name))
1452
1453 if self.analyse_card['fo_analysis_format'].lower() == 'topdrawer':
1454 misc.call(['./combine_plots_FO.sh'] + folder_names[mode], \
1455 stdout=devnull,
1456 cwd=pjoin(self.me_dir, 'SubProcesses'))
1457 files.cp(pjoin(self.me_dir, 'SubProcesses', 'MADatNLO.top'),
1458 pjoin(self.me_dir, 'Events', self.run_name))
1459 logger.info('The results of this run and the TopDrawer file with the plots' + \
1460 ' have been saved in %s' % pjoin(self.me_dir, 'Events', self.run_name))
1461 elif self.analyse_card['fo_analysis_format'].lower() == 'hwu':
1462 self.combine_plots_HwU(folder_names[mode])
1463 files.cp(pjoin(self.me_dir, 'SubProcesses', 'MADatNLO.HwU'),
1464 pjoin(self.me_dir, 'Events', self.run_name))
1465 files.cp(pjoin(self.me_dir, 'SubProcesses', 'MADatNLO.gnuplot'),
1466 pjoin(self.me_dir, 'Events', self.run_name))
1467 try:
1468 misc.call(['gnuplot','MADatNLO.gnuplot'],\
1469 stdout=os.open(os.devnull, os.O_RDWR),\
1470 stderr=os.open(os.devnull, os.O_RDWR),\
1471 cwd=pjoin(self.me_dir, 'Events', self.run_name))
1472 except Exception:
1473 pass
1474
1475
1476 logger.info('The results of this run and the HwU and GnuPlot files with the plots' + \
1477 ' have been saved in %s' % pjoin(self.me_dir, 'Events', self.run_name))
1478 elif self.analyse_card['fo_analysis_format'].lower() == 'root':
1479 misc.call(['./combine_root.sh'] + folder_names[mode], \
1480 stdout=devnull,
1481 cwd=pjoin(self.me_dir, 'SubProcesses'))
1482 files.cp(pjoin(self.me_dir, 'SubProcesses', 'MADatNLO.root'),
1483 pjoin(self.me_dir, 'Events', self.run_name))
1484 logger.info('The results of this run and the ROOT file with the plots' + \
1485 ' have been saved in %s' % pjoin(self.me_dir, 'Events', self.run_name))
1486 else:
1487 logger.info('The results of this run' + \
1488 ' have been saved in %s' % pjoin(self.me_dir, 'Events', self.run_name))
1489
1490 cross, error = sum_html.make_all_html_results(self, folder_names[mode])
1491 self.results.add_detail('cross', cross)
1492 self.results.add_detail('error', error)
1493 if self.run_card['iappl'] != 0:
1494 self.applgrid_combine(cross,error)
1495 self.update_status('Run complete', level='parton', update_results=True)
1496
1497 return
1498
1499 elif mode in ['aMC@NLO','aMC@LO','noshower','noshowerLO']:
1500 shower = self.run_card['parton_shower'].upper()
1501 nevents = int(self.run_card['nevents'])
1502 req_acc = self.run_card['req_acc']
1503 if nevents == 0 and float(req_acc) < 0 :
1504 raise aMCatNLOError('Cannot determine the required accuracy from the number '\
1505 'of events, because 0 events requested. Please set '\
1506 'the "req_acc" parameter in the run_card to a value between 0 and 1')
1507 elif float(req_acc) >1 or float(req_acc) == 0 :
1508 raise aMCatNLOError('Required accuracy ("req_acc" in the run_card) should '\
1509 'be between larger than 0 and smaller than 1, '\
1510 'or set to -1 for automatic determination. Current value is %s' % req_acc)
1511
1512 elif float(req_acc) < 0 and nevents > 1000000 :
1513 req_acc='0.001'
1514
1515 shower_list = ['HERWIG6', 'HERWIGPP', 'PYTHIA6Q', 'PYTHIA6PT', 'PYTHIA8']
1516
1517 if not shower in shower_list:
1518 raise aMCatNLOError('%s is not a valid parton shower. Please use one of the following: %s' \
1519 % (shower, ', '.join(shower_list)))
1520
1521
1522 if shower == 'PYTHIA6PT' and self.proc_characteristics['has_fsr']:
1523 raise aMCatNLOError('PYTHIA6PT does not support processes with FSR')
1524
1525 if mode in ['aMC@NLO', 'aMC@LO']:
1526 logger.info('Doing %s matched to parton shower' % mode[4:])
1527 elif mode in ['noshower','noshowerLO']:
1528 logger.info('Generating events without running the shower.')
1529 elif options['only_generation']:
1530 logger.info('Generating events starting from existing results')
1531
1532
1533 for i, status in enumerate(mcatnlo_status):
1534
1535
1536 try:
1537 nevents_unweighted = open(pjoin(self.me_dir,
1538 'SubProcesses',
1539 'nevents_unweighted')).read().split('\n')
1540 except IOError:
1541 nevents_unweighted = []
1542
1543 split = i == 2 and \
1544 int(self.run_card['nevt_job']) > 0
1545
1546 if i == 2 or not options['only_generation']:
1547
1548
1549 if i==2 and nevents==0:
1550 self.print_summary(options, 2,mode)
1551 return
1552
1553 if split:
1554
1555 misc.call([pjoin(self.me_dir, 'bin', 'internal', 'split_jobs.py')] + \
1556 [str(self.run_card['nevt_job'])],
1557 stdout = devnull,
1558 cwd = pjoin(self.me_dir, 'SubProcesses'))
1559 assert os.path.exists(pjoin(self.me_dir, 'SubProcesses',
1560 'nevents_unweighted_splitted'))
1561
1562 self.update_status(status, level='parton')
1563 if mode in ['aMC@NLO', 'noshower']:
1564 self.write_madinMMC_file(pjoin(self.me_dir, 'SubProcesses'), 'all', i)
1565 self.run_all(job_dict, [['2', 'F', '%d' % i]], status, split_jobs = split)
1566
1567 elif mode in ['aMC@LO', 'noshowerLO']:
1568 self.write_madinMMC_file(
1569 pjoin(self.me_dir, 'SubProcesses'), 'born', i)
1570 self.run_all(job_dict,
1571 [['2', 'B', '%d' % i]],
1572 '%s at LO' % status, split_jobs = split)
1573
1574 if (i < 2 and not options['only_generation']) or i == 1 :
1575
1576 self.collect_log_files(folder_names[mode], i)
1577 p = misc.Popen(['./combine_results.sh'] + \
1578 ['%d' % i,'%d' % nevents, '%s' % req_acc ] + \
1579 folder_names[mode],
1580 stdout=subprocess.PIPE,
1581 cwd = pjoin(self.me_dir, 'SubProcesses'))
1582 output = p.communicate()
1583 files.cp(pjoin(self.me_dir, 'SubProcesses', 'res_%d.txt' % i), \
1584 pjoin(self.me_dir, 'Events', self.run_name))
1585
1586 self.cross_sect_dict = self.read_results(output, mode)
1587 self.print_summary(options, i, mode)
1588
1589 cross, error = sum_html.make_all_html_results(self, folder_names[mode])
1590 self.results.add_detail('cross', cross)
1591 self.results.add_detail('error', error)
1592
1593
1594 if split:
1595 self.check_event_files()
1596
1597 if self.cluster_mode == 1:
1598
1599 self.update_status(
1600 'Waiting while files are transferred back from the cluster nodes',
1601 level='parton')
1602 time.sleep(10)
1603 if split:
1604 files.cp(pjoin(self.me_dir, 'SubProcesses', 'nevents_unweighted_splitted'), \
1605 pjoin(self.me_dir, 'SubProcesses', 'nevents_unweighted'))
1606
1607
1608 event_norm=self.run_card['event_norm']
1609 self.collect_log_files(folder_names[mode], 2)
1610 return self.reweight_and_collect_events(options, mode, nevents, event_norm)
1611
1613 """Sums all the plots in the HwU format."""
1614
1615 logger.debug('Combining HwU plots.')
1616
1617 with open(pjoin(self.me_dir,'SubProcesses','dirs.txt')) as dirf:
1618 all_histo_paths = dirf.readlines()
1619 all_histo_paths = [pjoin(self.me_dir,'SubProcesses',
1620 path.rstrip(),"MADatNLO.HwU") for path in all_histo_paths]
1621
1622 histogram_list = histograms.HwUList(all_histo_paths[0])
1623
1624 for histo_path in all_histo_paths[1:]:
1625 for i, histo in enumerate(histograms.HwUList(histo_path)):
1626
1627 histo.test_plot_compability(histogram_list[i])
1628
1629 histogram_list[i] += histo
1630
1631
1632 histogram_list.output(pjoin(self.me_dir,'SubProcesses',"MADatNLO"),
1633 format = 'gnuplot')
1634
1636 """Combines the APPLgrids in all the SubProcess/P*/all_G*/ directories"""
1637 logger.debug('Combining APPLgrids \n')
1638 applcomb=pjoin(self.options['applgrid'].rstrip('applgrid-config'),
1639 'applgrid-combine')
1640 with open(pjoin(self.me_dir,'SubProcesses','dirs.txt')) as dirf:
1641 all_jobs=dirf.readlines()
1642 ngrids=len(all_jobs)
1643 nobs =len([name for name in os.listdir(pjoin(self.me_dir,'SubProcesses',
1644 all_jobs[0].rstrip())) if name.endswith("_out.root")])
1645 for obs in range(0,nobs):
1646 gdir = [pjoin(self.me_dir,'SubProcesses',job.rstrip(),"grid_obs_"+
1647 str(obs)+"_out.root") for job in all_jobs]
1648
1649 if self.run_card["iappl"] == 1:
1650 misc.call([applcomb,'-o', pjoin(self.me_dir,"Events",self.run_name,
1651 "aMCfast_obs_"+str(obs)+"_starting_grid.root"), '--optimise']+ gdir)
1652 elif self.run_card["iappl"] == 2:
1653 unc2_inv=pow(cross/error,2)
1654 unc2_inv_ngrids=pow(cross/error,2)*ngrids
1655 misc.call([applcomb,'-o', pjoin(self.me_dir,"Events",
1656 self.run_name,"aMCfast_obs_"+str(obs)+".root"),'-s',
1657 str(unc2_inv),'--weight',str(unc2_inv)]+ gdir)
1658 for job in all_jobs:
1659 os.remove(pjoin(self.me_dir,'SubProcesses',job.rstrip(),
1660 "grid_obs_"+str(obs)+"_in.root"))
1661 else:
1662 raise aMCatNLOError('iappl parameter can only be 0, 1 or 2')
1663
1664 for ggdir in gdir:
1665 os.remove(ggdir)
1666
1667
1669 """Distributes the APPLgrids ready to be filled by a second run of the code"""
1670
1671
1672 if not('appl_start_grid' in options.keys() and options['appl_start_grid']):
1673 gfiles=glob.glob(pjoin(self.me_dir, 'Events','*',
1674 'aMCfast_obs_0_starting_grid.root'))
1675 time_stamps={}
1676 for root_file in gfiles:
1677 time_stamps[root_file]=os.path.getmtime(root_file)
1678 options['appl_start_grid']= \
1679 max(time_stamps.iterkeys(), key=(lambda key:
1680 time_stamps[key])).split('/')[-2]
1681 logger.info('No --appl_start_grid option given. '+\
1682 'Guessing that start grid from run "%s" should be used.' \
1683 % options['appl_start_grid'])
1684
1685 if 'appl_start_grid' in options.keys() and options['appl_start_grid']:
1686 self.appl_start_grid = options['appl_start_grid']
1687 start_grid_dir=pjoin(self.me_dir, 'Events', self.appl_start_grid)
1688
1689 if not os.path.exists(pjoin(start_grid_dir,
1690 'aMCfast_obs_0_starting_grid.root')):
1691 raise self.InvalidCmd('APPLgrid file not found: %s' % \
1692 pjoin(start_grid_dir,'aMCfast_obs_0_starting_grid.root'))
1693 else:
1694 all_grids=[pjoin(start_grid_dir,name) for name in os.listdir( \
1695 start_grid_dir) if name.endswith("_starting_grid.root")]
1696 nobs =len(all_grids)
1697 gstring=" ".join(all_grids)
1698 if not hasattr(self, 'appl_start_grid') or not self.appl_start_grid:
1699 raise self.InvalidCmd('No APPLgrid name currently defined.'+
1700 'Please provide this information.')
1701 if mode == 'NLO':
1702 gdir='all_G'
1703 elif mode == 'LO':
1704 gdir='born_G'
1705
1706 for pdir in p_dirs:
1707 g_dirs = [file for file in os.listdir(pjoin(self.me_dir,
1708 "SubProcesses",pdir)) if file.startswith(gdir) and
1709 os.path.isdir(pjoin(self.me_dir,"SubProcesses",pdir, file))]
1710 for g_dir in g_dirs:
1711 for grid in all_grids:
1712 obs=grid.split('_')[-3]
1713 files.cp(grid,pjoin(self.me_dir,"SubProcesses",pdir,g_dir,
1714 'grid_obs_'+obs+'_in.root'))
1715
1716
1718 """collect the log files and put them in a single, html-friendly file
1719 inside the run_... directory"""
1720 step_list = ['Grid setting', 'Cross-section computation',
1721 'Event generation']
1722 log_file = pjoin(self.me_dir, 'Events', self.run_name,
1723 'alllogs_%d.html' % istep)
1724
1725 channel_dict = {}
1726 log_files = []
1727 for folder in folders:
1728 log_files += glob.glob(pjoin(self.me_dir, 'SubProcesses', 'P*',
1729 folder, 'log.txt'))
1730
1731 content = ''
1732
1733 outfile = open(log_file, 'w')
1734
1735 content += '<HTML><BODY>\n<font face="courier" size=2>'
1736 for log in log_files:
1737 channel_dict[os.path.dirname(log)] = [istep]
1738
1739 content += '<a name=%s></a>\n' % (os.path.dirname(log).replace(
1740 pjoin(self.me_dir,'SubProcesses'),''))
1741
1742 content += '<font color="red">\n'
1743 content += '<br>LOG file for integration channel %s, %s <br>' % \
1744 (os.path.dirname(log).replace(pjoin(self.me_dir,
1745 'SubProcesses'), ''),
1746 step_list[istep])
1747 content += '</font>\n'
1748
1749
1750 content += '<PRE>\n' + open(log).read() + '\n</PRE>'
1751 content +='<br>\n'
1752 outfile.write(content)
1753 content=''
1754
1755 outfile.write('</font>\n</BODY></HTML>\n')
1756 outfile.close()
1757
1758
1760 """extract results (cross-section, absolute cross-section and errors)
1761 from output, which should be formatted as
1762 Found 4 correctly terminated jobs
1763 random seed found in 'randinit' is 33
1764 Integrated abs(cross-section)
1765 7.94473937e+03 +- 2.9953e+01 (3.7702e-01%)
1766 Integrated cross-section
1767 6.63392298e+03 +- 3.7669e+01 (5.6782e-01%)
1768 for aMC@NLO/aMC@LO, and as
1769
1770 for NLO/LO
1771 The cross_sect_dict is returned"""
1772 res = {}
1773 if mode in ['aMC@LO', 'aMC@NLO', 'noshower', 'noshowerLO']:
1774 pat = re.compile(\
1775 '''Found (\d+) correctly terminated jobs
1776 random seed found in 'randinit' is (\d+)
1777 Integrated abs\(cross-section\)
1778 \s*(\d+\.\d+e[+-]\d+) \+\- (\d+\.\d+e[+-]\d+) \((\d+\.\d+e[+-]\d+)\%\)
1779 Integrated cross-section
1780 \s*(\-?\d+\.\d+e[+-]\d+) \+\- (\d+\.\d+e[+-]\d+) \((\-?\d+\.\d+e[+-]\d+)\%\)''')
1781 else:
1782 pat = re.compile(\
1783 '''Found (\d+) correctly terminated jobs
1784 \s*(\-?\d+\.\d+e[+-]\d+) \+\- (\d+\.\d+e[+-]\d+) \((\-?\d+\.\d+e[+-]\d+)\%\)''')
1785 pass
1786
1787 match = re.search(pat, output[0])
1788 if not match or output[1]:
1789 logger.info('Return code of the event collection: '+str(output[1]))
1790 logger.info('Output of the event collection:\n'+output[0])
1791 raise aMCatNLOError('An error occurred during the collection of results.\n' +
1792 'Please check the .log files inside the directories which failed.')
1793
1794
1795 if mode in ['aMC@LO', 'aMC@NLO', 'noshower', 'noshowerLO']:
1796 return {'randinit' : int(match.groups()[1]),
1797 'xseca' : float(match.groups()[2]),
1798 'erra' : float(match.groups()[3]),
1799 'xsect' : float(match.groups()[5]),
1800 'errt' : float(match.groups()[6])}
1801 else:
1802 return {'xsect' : float(match.groups()[1]),
1803 'errt' : float(match.groups()[2])}
1804
1805 - def print_summary(self, options, step, mode, scale_pdf_info={}):
1806 """print a summary of the results contained in self.cross_sect_dict.
1807 step corresponds to the mintMC step, if =2 (i.e. after event generation)
1808 some additional infos are printed"""
1809
1810 proc_card_lines = open(pjoin(self.me_dir, 'Cards', 'proc_card_mg5.dat')).read().split('\n')
1811 process = ''
1812 for line in proc_card_lines:
1813 if line.startswith('generate') or line.startswith('add process'):
1814 process = process+(line.replace('generate ', '')).replace('add process ','')+' ; '
1815 lpp = {0:'l', 1:'p', -1:'pbar'}
1816 proc_info = '\n Process %s\n Run at %s-%s collider (%s + %s GeV)' % \
1817 (process[:-3], lpp[self.run_card['lpp1']], lpp[self.run_card['lpp2']],
1818 self.run_card['ebeam1'], self.run_card['ebeam2'])
1819
1820
1821 if mode in ['aMC@NLO', 'aMC@LO', 'noshower', 'noshowerLO']:
1822 log_GV_files = glob.glob(pjoin(self.me_dir, \
1823 'SubProcesses', 'P*','G*','log_MINT*.txt'))
1824 all_log_files = glob.glob(pjoin(self.me_dir, \
1825 'SubProcesses', 'P*','G*','log*.txt'))
1826 elif mode == 'NLO':
1827 log_GV_files = glob.glob(pjoin(self.me_dir, \
1828 'SubProcesses', 'P*','all_G*','log*.txt'))
1829 all_log_files = sum([glob.glob(pjoin(self.me_dir,'SubProcesses', 'P*',
1830 '%sG*'%foldName,'log*.txt')) for foldName in ['all_']],[])
1831 elif mode == 'LO':
1832 log_GV_files = ''
1833 all_log_files = sum([glob.glob(pjoin(self.me_dir,'SubProcesses', 'P*',
1834 '%sG*'%foldName,'log*.txt')) for foldName in ['born_']],[])
1835 else:
1836 raise aMCatNLOError, 'Running mode %s not supported.'%mode
1837
1838
1839 if mode in ['aMC@NLO', 'aMC@LO', 'noshower', 'noshowerLO']:
1840 status = ['Determining the number of unweighted events per channel',
1841 'Updating the number of unweighted events per channel',
1842 'Summary:']
1843 if step != 2:
1844 message = status[step] + '\n\n Intermediate results:' + \
1845 ('\n Random seed: %(randinit)d' + \
1846 '\n Total cross-section: %(xsect)8.3e +- %(errt)6.1e pb' + \
1847 '\n Total abs(cross-section): %(xseca)8.3e +- %(erra)6.1e pb \n') \
1848 % self.cross_sect_dict
1849 else:
1850
1851 message = '\n ' + status[step] + proc_info + \
1852 '\n Total cross-section: %(xsect)8.3e +- %(errt)6.1e pb' % \
1853 self.cross_sect_dict
1854
1855 if self.run_card['nevents']>=10000 and self.run_card['reweight_scale']:
1856 message = message + \
1857 ('\n Ren. and fac. scale uncertainty: +%0.1f%% -%0.1f%%') % \
1858 (scale_pdf_info['scale_upp'], scale_pdf_info['scale_low'])
1859 if self.run_card['nevents']>=10000 and self.run_card['reweight_PDF']:
1860 message = message + \
1861 ('\n PDF uncertainty: +%0.1f%% -%0.1f%%') % \
1862 (scale_pdf_info['pdf_upp'], scale_pdf_info['pdf_low'])
1863
1864 neg_frac = (self.cross_sect_dict['xseca'] - self.cross_sect_dict['xsect'])/\
1865 (2. * self.cross_sect_dict['xseca'])
1866 message = message + \
1867 ('\n Number of events generated: %s' + \
1868 '\n Parton shower to be used: %s' + \
1869 '\n Fraction of negative weights: %4.2f' + \
1870 '\n Total running time : %s') % \
1871 (self.run_card['nevents'],
1872 self.run_card['parton_shower'].upper(),
1873 neg_frac,
1874 misc.format_timer(time.time()-self.start_time))
1875
1876 elif mode in ['NLO', 'LO']:
1877 status = ['Results after grid setup (cross-section is non-physical):',
1878 'Final results and run summary:']
1879 if step == 0:
1880 message = '\n ' + status[step] + \
1881 '\n Total cross-section: %(xsect)8.3e +- %(errt)6.1e pb' % \
1882 self.cross_sect_dict
1883 elif step == 1:
1884 message = '\n ' + status[step] + proc_info + \
1885 '\n Total cross-section: %(xsect)8.3e +- %(errt)6.1e pb' % \
1886 self.cross_sect_dict
1887 if self.run_card['reweight_scale']:
1888 if int(self.run_card['ickkw'])!=-1:
1889 message = message + \
1890 ('\n Ren. and fac. scale uncertainty: +%0.1f%% -%0.1f%%') % \
1891 (scale_pdf_info['scale_upp'], scale_pdf_info['scale_low'])
1892 else:
1893 message = message + \
1894 ('\n Soft and hard scale dependence (added in quadrature): +%0.1f%% -%0.1f%%') % \
1895 (scale_pdf_info['scale_upp_quad'], scale_pdf_info['scale_low_quad'])
1896 if self.run_card['reweight_PDF']:
1897 message = message + \
1898 ('\n PDF uncertainty: +%0.1f%% -%0.1f%%') % \
1899 (scale_pdf_info['pdf_upp'], scale_pdf_info['pdf_low'])
1900
1901 if (mode in ['NLO', 'LO'] and step!=1) or \
1902 (mode in ['aMC@NLO', 'aMC@LO', 'noshower', 'noshowerLO'] and step!=2):
1903 logger.info(message+'\n')
1904 return
1905
1906
1907
1908
1909 try:
1910 message, debug_msg = \
1911 self.compile_advanced_stats(log_GV_files, all_log_files, message)
1912 except Exception as e:
1913 debug_msg = 'Advanced statistics collection failed with error "%s"'%str(e)
1914
1915 logger.debug(debug_msg+'\n')
1916 logger.info(message+'\n')
1917
1918
1919 evt_path = pjoin(self.me_dir, 'Events', self.run_name)
1920 open(pjoin(evt_path, 'summary.txt'),'w').write(message+'\n')
1921 open(pjoin(evt_path, '.full_summary.txt'),
1922 'w').write(message+'\n\n'+debug_msg+'\n')
1923
1924 self.archive_files(evt_path,mode)
1925
1927 """ Copies in the Events/Run_<xxx> directory relevant files characterizing
1928 the run."""
1929
1930 files_to_arxiv = [pjoin('Cards','param_card.dat'),
1931 pjoin('Cards','MadLoopParams.dat'),
1932 pjoin('Cards','FKS_params.dat'),
1933 pjoin('Cards','run_card.dat'),
1934 pjoin('Subprocesses','setscales.f'),
1935 pjoin('Subprocesses','cuts.f')]
1936
1937 if mode in ['NLO', 'LO']:
1938 files_to_arxiv.append(pjoin('Cards','FO_analyse_card.dat'))
1939
1940 if not os.path.exists(pjoin(evt_path,'RunMaterial')):
1941 os.mkdir(pjoin(evt_path,'RunMaterial'))
1942
1943 for path in files_to_arxiv:
1944 if os.path.isfile(pjoin(self.me_dir,path)):
1945 files.cp(pjoin(self.me_dir,path),pjoin(evt_path,'RunMaterial'))
1946 misc.call(['tar','-czpf','RunMaterial.tar.gz','RunMaterial'],cwd=evt_path)
1947 shutil.rmtree(pjoin(evt_path,'RunMaterial'))
1948
1950 """ This functions goes through the log files given in arguments and
1951 compiles statistics about MadLoop stability, virtual integration
1952 optimization and detection of potential error messages into a nice
1953 debug message to printed at the end of the run """
1954
1955
1956
1957 stats = {'UPS':{}, 'Errors':[], 'virt_stats':{}, 'timings':{}}
1958 mint_search = re.compile(r"MINT(?P<ID>\d*).txt")
1959
1960
1961
1962
1963
1964
1965
1966 UPS_stat_finder = re.compile(
1967 r"Satistics from MadLoop:.*"+\
1968 r"Total points tried\:\s+(?P<ntot>\d+).*"+\
1969 r"Stability unknown\:\s+(?P<nsun>\d+).*"+\
1970 r"Stable PS point\:\s+(?P<nsps>\d+).*"+\
1971 r"Unstable PS point \(and rescued\)\:\s+(?P<nups>\d+).*"+\
1972 r"Exceptional PS point \(unstable and not rescued\)\:\s+(?P<neps>\d+).*"+\
1973 r"Double precision used\:\s+(?P<nddp>\d+).*"+\
1974 r"Quadruple precision used\:\s+(?P<nqdp>\d+).*"+\
1975 r"Initialization phase\-space points\:\s+(?P<nini>\d+).*"+\
1976 r"Unknown return code \(100\)\:\s+(?P<n100>\d+).*"+\
1977 r"Unknown return code \(10\)\:\s+(?P<n10>\d+).*",re.DOTALL)
1978
1979 unit_code_meaning = { 0 : 'Not identified (CTModeRun != -1)',
1980 1 : 'CutTools (double precision)',
1981 2 : 'PJFry++',
1982 3 : 'IREGI',
1983 4 : 'Golem95',
1984 9 : 'CutTools (quadruple precision)'}
1985 RetUnit_finder =re.compile(
1986 r"#Unit\s*(?P<unit>\d+)\s*=\s*(?P<n_occurences>\d+)")
1987
1988
1989 for gv_log in log_GV_files:
1990 channel_name = '/'.join(gv_log.split('/')[-5:-1])
1991 log=open(gv_log,'r').read()
1992 UPS_stats = re.search(UPS_stat_finder,log)
1993 for retunit_stats in re.finditer(RetUnit_finder, log):
1994 if channel_name not in stats['UPS'].keys():
1995 stats['UPS'][channel_name] = [0]*10+[[0]*10]
1996 stats['UPS'][channel_name][10][int(retunit_stats.group('unit'))] \
1997 += int(retunit_stats.group('n_occurences'))
1998 if not UPS_stats is None:
1999 try:
2000 stats['UPS'][channel_name][0] += int(UPS_stats.group('ntot'))
2001 stats['UPS'][channel_name][1] += int(UPS_stats.group('nsun'))
2002 stats['UPS'][channel_name][2] += int(UPS_stats.group('nsps'))
2003 stats['UPS'][channel_name][3] += int(UPS_stats.group('nups'))
2004 stats['UPS'][channel_name][4] += int(UPS_stats.group('neps'))
2005 stats['UPS'][channel_name][5] += int(UPS_stats.group('nddp'))
2006 stats['UPS'][channel_name][6] += int(UPS_stats.group('nqdp'))
2007 stats['UPS'][channel_name][7] += int(UPS_stats.group('nini'))
2008 stats['UPS'][channel_name][8] += int(UPS_stats.group('n100'))
2009 stats['UPS'][channel_name][9] += int(UPS_stats.group('n10'))
2010 except KeyError:
2011 stats['UPS'][channel_name] = [int(UPS_stats.group('ntot')),
2012 int(UPS_stats.group('nsun')),int(UPS_stats.group('nsps')),
2013 int(UPS_stats.group('nups')),int(UPS_stats.group('neps')),
2014 int(UPS_stats.group('nddp')),int(UPS_stats.group('nqdp')),
2015 int(UPS_stats.group('nini')),int(UPS_stats.group('n100')),
2016 int(UPS_stats.group('n10')),[0]*10]
2017 debug_msg = ""
2018 if len(stats['UPS'].keys())>0:
2019 nTotPS = sum([chan[0] for chan in stats['UPS'].values()],0)
2020 nTotsun = sum([chan[1] for chan in stats['UPS'].values()],0)
2021 nTotsps = sum([chan[2] for chan in stats['UPS'].values()],0)
2022 nTotups = sum([chan[3] for chan in stats['UPS'].values()],0)
2023 nToteps = sum([chan[4] for chan in stats['UPS'].values()],0)
2024 nTotddp = sum([chan[5] for chan in stats['UPS'].values()],0)
2025 nTotqdp = sum([chan[6] for chan in stats['UPS'].values()],0)
2026 nTotini = sum([chan[7] for chan in stats['UPS'].values()],0)
2027 nTot100 = sum([chan[8] for chan in stats['UPS'].values()],0)
2028 nTot10 = sum([chan[9] for chan in stats['UPS'].values()],0)
2029 nTot1 = [sum([chan[10][i] for chan in stats['UPS'].values()],0) \
2030 for i in range(10)]
2031 UPSfracs = [(chan[0] , 0.0 if chan[1][0]==0 else \
2032 float(chan[1][4]*100)/chan[1][0]) for chan in stats['UPS'].items()]
2033 maxUPS = max(UPSfracs, key = lambda w: w[1])
2034
2035 tmpStr = ""
2036 tmpStr += '\n Number of loop ME evaluations (by MadLoop): %d'%nTotPS
2037 tmpStr += '\n Stability unknown: %d'%nTotsun
2038 tmpStr += '\n Stable PS point: %d'%nTotsps
2039 tmpStr += '\n Unstable PS point (and rescued): %d'%nTotups
2040 tmpStr += '\n Unstable PS point (and not rescued): %d'%nToteps
2041 tmpStr += '\n Only double precision used: %d'%nTotddp
2042 tmpStr += '\n Quadruple precision used: %d'%nTotqdp
2043 tmpStr += '\n Initialization phase-space points: %d'%nTotini
2044 tmpStr += '\n Reduction methods used:'
2045 red_methods = [(unit_code_meaning[i],nTot1[i]) for i in \
2046 unit_code_meaning.keys() if nTot1[i]>0]
2047 for method, n in sorted(red_methods, key= lambda l: l[1], reverse=True):
2048 tmpStr += '\n > %s%s%s'%(method,' '*(33-len(method)),n)
2049 if nTot100 != 0:
2050 debug_msg += '\n Unknown return code (100): %d'%nTot100
2051 if nTot10 != 0:
2052 debug_msg += '\n Unknown return code (10): %d'%nTot10
2053 nUnknownUnit = sum(nTot1[u] for u in range(10) if u \
2054 not in unit_code_meaning.keys())
2055 if nUnknownUnit != 0:
2056 debug_msg += '\n Unknown return code (1): %d'\
2057 %nUnknownUnit
2058
2059 if maxUPS[1]>0.001:
2060 message += tmpStr
2061 message += '\n Total number of unstable PS point detected:'+\
2062 ' %d (%4.2f%%)'%(nToteps,float(100*nToteps)/nTotPS)
2063 message += '\n Maximum fraction of UPS points in '+\
2064 'channel %s (%4.2f%%)'%maxUPS
2065 message += '\n Please report this to the authors while '+\
2066 'providing the file'
2067 message += '\n %s'%str(pjoin(os.path.dirname(self.me_dir),
2068 maxUPS[0],'UPS.log'))
2069 else:
2070 debug_msg += tmpStr
2071
2072
2073
2074
2075
2076
2077 virt_tricks_finder = re.compile(
2078 r"accumulated results Virtual ratio\s*=\s*-?(?P<v_ratio>[\d\+-Eed\.]*)"+\
2079 r"\s*\+/-\s*-?[\d\+-Eed\.]*\s*\(\s*-?(?P<v_ratio_err>[\d\+-Eed\.]*)\s*\%\)\s*\n"+\
2080 r"accumulated results ABS virtual\s*=\s*-?(?P<v_abs_contr>[\d\+-Eed\.]*)"+\
2081 r"\s*\+/-\s*-?[\d\+-Eed\.]*\s*\(\s*-?(?P<v_abs_contr_err>[\d\+-Eed\.]*)\s*\%\)")
2082
2083 virt_frac_finder = re.compile(r"update virtual fraction to\s*:\s*"+\
2084 "-?(?P<v_frac>[\d\+-Eed\.]*)\s*-?(?P<v_average>[\d\+-Eed\.]*)")
2085
2086 channel_contr_finder = re.compile(r"Final result \[ABS\]\s*:\s*-?(?P<v_contr>[\d\+-Eed\.]*)")
2087
2088 channel_contr_list = {}
2089 for gv_log in log_GV_files:
2090 logfile=open(gv_log,'r')
2091 log = logfile.read()
2092 logfile.close()
2093 channel_name = '/'.join(gv_log.split('/')[-3:-1])
2094 vf_stats = None
2095 for vf_stats in re.finditer(virt_frac_finder, log):
2096 pass
2097 if not vf_stats is None:
2098 v_frac = float(vf_stats.group('v_frac'))
2099 v_average = float(vf_stats.group('v_average'))
2100 try:
2101 if v_frac < stats['virt_stats']['v_frac_min'][0]:
2102 stats['virt_stats']['v_frac_min']=(v_frac,channel_name)
2103 if v_frac > stats['virt_stats']['v_frac_max'][0]:
2104 stats['virt_stats']['v_frac_max']=(v_frac,channel_name)
2105 stats['virt_stats']['v_frac_avg'][0] += v_frac
2106 stats['virt_stats']['v_frac_avg'][1] += 1
2107 except KeyError:
2108 stats['virt_stats']['v_frac_min']=[v_frac,channel_name]
2109 stats['virt_stats']['v_frac_max']=[v_frac,channel_name]
2110 stats['virt_stats']['v_frac_avg']=[v_frac,1]
2111
2112
2113 ccontr_stats = None
2114 for ccontr_stats in re.finditer(channel_contr_finder, log):
2115 pass
2116 if not ccontr_stats is None:
2117 contrib = float(ccontr_stats.group('v_contr'))
2118 try:
2119 if contrib>channel_contr_list[channel_name]:
2120 channel_contr_list[channel_name]=contrib
2121 except KeyError:
2122 channel_contr_list[channel_name]=contrib
2123
2124
2125
2126
2127 average_contrib = 0.0
2128 for value in channel_contr_list.values():
2129 average_contrib += value
2130 if len(channel_contr_list.values()) !=0:
2131 average_contrib = average_contrib / len(channel_contr_list.values())
2132
2133 relevant_log_GV_files = []
2134 excluded_channels = set([])
2135 all_channels = set([])
2136 for log_file in log_GV_files:
2137 channel_name = '/'.join(log_file.split('/')[-3:-1])
2138 all_channels.add(channel_name)
2139 try:
2140 if channel_contr_list[channel_name] > (0.1*average_contrib):
2141 relevant_log_GV_files.append(log_file)
2142 else:
2143 excluded_channels.add(channel_name)
2144 except KeyError:
2145 relevant_log_GV_files.append(log_file)
2146
2147
2148 for gv_log in relevant_log_GV_files:
2149 logfile=open(gv_log,'r')
2150 log = logfile.read()
2151 logfile.close()
2152 channel_name = '/'.join(gv_log.split('/')[-3:-1])
2153
2154 vt_stats = None
2155 for vt_stats in re.finditer(virt_tricks_finder, log):
2156 pass
2157 if not vt_stats is None:
2158 vt_stats_group = vt_stats.groupdict()
2159 v_ratio = float(vt_stats.group('v_ratio'))
2160 v_ratio_err = float(vt_stats.group('v_ratio_err'))
2161 v_contr = float(vt_stats.group('v_abs_contr'))
2162 v_contr_err = float(vt_stats.group('v_abs_contr_err'))
2163 try:
2164 if v_ratio < stats['virt_stats']['v_ratio_min'][0]:
2165 stats['virt_stats']['v_ratio_min']=(v_ratio,channel_name)
2166 if v_ratio > stats['virt_stats']['v_ratio_max'][0]:
2167 stats['virt_stats']['v_ratio_max']=(v_ratio,channel_name)
2168 if v_ratio < stats['virt_stats']['v_ratio_err_min'][0]:
2169 stats['virt_stats']['v_ratio_err_min']=(v_ratio_err,channel_name)
2170 if v_ratio > stats['virt_stats']['v_ratio_err_max'][0]:
2171 stats['virt_stats']['v_ratio_err_max']=(v_ratio_err,channel_name)
2172 if v_contr < stats['virt_stats']['v_contr_min'][0]:
2173 stats['virt_stats']['v_contr_min']=(v_contr,channel_name)
2174 if v_contr > stats['virt_stats']['v_contr_max'][0]:
2175 stats['virt_stats']['v_contr_max']=(v_contr,channel_name)
2176 if v_contr_err < stats['virt_stats']['v_contr_err_min'][0]:
2177 stats['virt_stats']['v_contr_err_min']=(v_contr_err,channel_name)
2178 if v_contr_err > stats['virt_stats']['v_contr_err_max'][0]:
2179 stats['virt_stats']['v_contr_err_max']=(v_contr_err,channel_name)
2180 except KeyError:
2181 stats['virt_stats']['v_ratio_min']=[v_ratio,channel_name]
2182 stats['virt_stats']['v_ratio_max']=[v_ratio,channel_name]
2183 stats['virt_stats']['v_ratio_err_min']=[v_ratio_err,channel_name]
2184 stats['virt_stats']['v_ratio_err_max']=[v_ratio_err,channel_name]
2185 stats['virt_stats']['v_contr_min']=[v_contr,channel_name]
2186 stats['virt_stats']['v_contr_max']=[v_contr,channel_name]
2187 stats['virt_stats']['v_contr_err_min']=[v_contr_err,channel_name]
2188 stats['virt_stats']['v_contr_err_max']=[v_contr_err,channel_name]
2189
2190 vf_stats = None
2191 for vf_stats in re.finditer(virt_frac_finder, log):
2192 pass
2193 if not vf_stats is None:
2194 v_frac = float(vf_stats.group('v_frac'))
2195 v_average = float(vf_stats.group('v_average'))
2196 try:
2197 if v_average < stats['virt_stats']['v_average_min'][0]:
2198 stats['virt_stats']['v_average_min']=(v_average,channel_name)
2199 if v_average > stats['virt_stats']['v_average_max'][0]:
2200 stats['virt_stats']['v_average_max']=(v_average,channel_name)
2201 stats['virt_stats']['v_average_avg'][0] += v_average
2202 stats['virt_stats']['v_average_avg'][1] += 1
2203 except KeyError:
2204 stats['virt_stats']['v_average_min']=[v_average,channel_name]
2205 stats['virt_stats']['v_average_max']=[v_average,channel_name]
2206 stats['virt_stats']['v_average_avg']=[v_average,1]
2207
2208 try:
2209 debug_msg += '\n\n Statistics on virtual integration optimization : '
2210
2211 debug_msg += '\n Maximum virt fraction computed %.3f (%s)'\
2212 %tuple(stats['virt_stats']['v_frac_max'])
2213 debug_msg += '\n Minimum virt fraction computed %.3f (%s)'\
2214 %tuple(stats['virt_stats']['v_frac_min'])
2215 debug_msg += '\n Average virt fraction computed %.3f'\
2216 %float(stats['virt_stats']['v_frac_avg'][0]/float(stats['virt_stats']['v_frac_avg'][1]))
2217 debug_msg += '\n Stats below exclude negligible channels (%d excluded out of %d)'%\
2218 (len(excluded_channels),len(all_channels))
2219 debug_msg += '\n Maximum virt ratio used %.2f (%s)'\
2220 %tuple(stats['virt_stats']['v_average_max'])
2221 debug_msg += '\n Maximum virt ratio found from grids %.2f (%s)'\
2222 %tuple(stats['virt_stats']['v_ratio_max'])
2223 tmpStr = '\n Max. MC err. on virt ratio from grids %.1f %% (%s)'\
2224 %tuple(stats['virt_stats']['v_ratio_err_max'])
2225 debug_msg += tmpStr
2226
2227
2228
2229
2230
2231
2232
2233
2234 tmpStr = '\n Maximum MC error on abs virt %.1f %% (%s)'\
2235 %tuple(stats['virt_stats']['v_contr_err_max'])
2236 debug_msg += tmpStr
2237
2238
2239
2240
2241 except KeyError:
2242 debug_msg += '\n Could not find statistics on the integration optimization. '
2243
2244
2245
2246
2247
2248 timing_stat_finder = re.compile(r"\s*Time spent in\s*(?P<name>\w*)\s*:\s*"+\
2249 "(?P<time>[\d\+-Eed\.]*)\s*")
2250
2251 for logf in log_GV_files:
2252 logfile=open(logf,'r')
2253 log = logfile.read()
2254 logfile.close()
2255 channel_name = '/'.join(logf.split('/')[-3:-1])
2256 mint = re.search(mint_search,logf)
2257 if not mint is None:
2258 channel_name = channel_name+' [step %s]'%mint.group('ID')
2259
2260 for time_stats in re.finditer(timing_stat_finder, log):
2261 try:
2262 stats['timings'][time_stats.group('name')][channel_name]+=\
2263 float(time_stats.group('time'))
2264 except KeyError:
2265 if time_stats.group('name') not in stats['timings'].keys():
2266 stats['timings'][time_stats.group('name')] = {}
2267 stats['timings'][time_stats.group('name')][channel_name]=\
2268 float(time_stats.group('time'))
2269
2270
2271 Tstr = lambda secs: str(datetime.timedelta(seconds=int(secs)))
2272 try:
2273 totTimeList = [(time, chan) for chan, time in \
2274 stats['timings']['Total'].items()]
2275 except KeyError:
2276 totTimeList = []
2277
2278 totTimeList.sort()
2279 if len(totTimeList)>0:
2280 debug_msg += '\n\n Inclusive timing profile :'
2281 debug_msg += '\n Overall slowest channel %s (%s)'%\
2282 (Tstr(totTimeList[-1][0]),totTimeList[-1][1])
2283 debug_msg += '\n Average channel running time %s'%\
2284 Tstr(sum([el[0] for el in totTimeList])/len(totTimeList))
2285 debug_msg += '\n Aggregated total running time %s'%\
2286 Tstr(sum([el[0] for el in totTimeList]))
2287 else:
2288 debug_msg += '\n\n Inclusive timing profile non available.'
2289
2290 sorted_keys = sorted(stats['timings'].keys(), key= lambda stat: \
2291 sum(stats['timings'][stat].values()), reverse=True)
2292 for name in sorted_keys:
2293 if name=='Total':
2294 continue
2295 if sum(stats['timings'][name].values())<=0.0:
2296 debug_msg += '\n Zero time record for %s.'%name
2297 continue
2298 try:
2299 TimeList = [((100.0*time/stats['timings']['Total'][chan]),
2300 chan) for chan, time in stats['timings'][name].items()]
2301 except KeyError, ZeroDivisionError:
2302 debug_msg += '\n\n Timing profile for %s unavailable.'%name
2303 continue
2304 TimeList.sort()
2305 debug_msg += '\n Timing profile for <%s> :'%name
2306 try:
2307 debug_msg += '\n Overall fraction of time %.3f %%'%\
2308 float((100.0*(sum(stats['timings'][name].values())/
2309 sum(stats['timings']['Total'].values()))))
2310 except KeyError, ZeroDivisionError:
2311 debug_msg += '\n Overall fraction of time unavailable.'
2312 debug_msg += '\n Largest fraction of time %.3f %% (%s)'%\
2313 (TimeList[-1][0],TimeList[-1][1])
2314 debug_msg += '\n Smallest fraction of time %.3f %% (%s)'%\
2315 (TimeList[0][0],TimeList[0][1])
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326 err_finder = re.compile(\
2327 r"(?<!of\spaper\sfor\s)\bERROR\b(?!\scalculation\.)",re.IGNORECASE)
2328 for log in all_log_files:
2329 logfile=open(log,'r')
2330 nErrors = len(re.findall(err_finder, logfile.read()))
2331 logfile.close()
2332 if nErrors != 0:
2333 stats['Errors'].append((str(log),nErrors))
2334
2335 nErrors = sum([err[1] for err in stats['Errors']],0)
2336 if nErrors != 0:
2337 debug_msg += '\n WARNING:: A total of %d error%s ha%s been '\
2338 %(nErrors,'s' if nErrors>1 else '','ve' if nErrors>1 else 's')+\
2339 'found in the following log file%s:'%('s' if \
2340 len(stats['Errors'])>1 else '')
2341 for error in stats['Errors'][:3]:
2342 log_name = '/'.join(error[0].split('/')[-5:])
2343 debug_msg += '\n > %d error%s in %s'%\
2344 (error[1],'s' if error[1]>1 else '',log_name)
2345 if len(stats['Errors'])>3:
2346 nRemainingErrors = sum([err[1] for err in stats['Errors']][3:],0)
2347 nRemainingLogs = len(stats['Errors'])-3
2348 debug_msg += '\n And another %d error%s in %d other log file%s'%\
2349 (nRemainingErrors, 's' if nRemainingErrors>1 else '',
2350 nRemainingLogs, 's ' if nRemainingLogs>1 else '')
2351
2352 return message, debug_msg
2353
2354
2356 """this function calls the reweighting routines and creates the event file in the
2357 Event dir. Return the name of the event file created
2358 """
2359 scale_pdf_info={}
2360 if self.run_card['reweight_scale'] or self.run_card['reweight_PDF'] :
2361 scale_pdf_info = self.run_reweight(options['reweightonly'])
2362
2363 self.update_status('Collecting events', level='parton', update_results=True)
2364 misc.compile(['collect_events'],
2365 cwd=pjoin(self.me_dir, 'SubProcesses'))
2366 p = misc.Popen(['./collect_events'], cwd=pjoin(self.me_dir, 'SubProcesses'),
2367 stdin=subprocess.PIPE,
2368 stdout=open(pjoin(self.me_dir, 'collect_events.log'), 'w'))
2369 if event_norm.lower() == 'sum':
2370 p.communicate(input = '1\n')
2371 elif event_norm.lower() == 'unity':
2372 p.communicate(input = '3\n')
2373 else:
2374 p.communicate(input = '2\n')
2375
2376
2377 filename = open(pjoin(self.me_dir, 'collect_events.log')).read().split()[-1]
2378
2379 if not os.path.exists(pjoin(self.me_dir, 'SubProcesses', filename)):
2380 raise aMCatNLOError('An error occurred during event generation. ' + \
2381 'The event file has not been created. Check collect_events.log')
2382 evt_file = pjoin(self.me_dir, 'Events', self.run_name, 'events.lhe.gz')
2383 misc.gzip(pjoin(self.me_dir, 'SubProcesses', filename), stdout=evt_file)
2384 if not options['reweightonly']:
2385 self.print_summary(options, 2, mode, scale_pdf_info)
2386 logger.info('The %s file has been generated.\n' % (evt_file))
2387 self.results.add_detail('nb_event', nevents)
2388 self.update_status('Events generated', level='parton', update_results=True)
2389 return evt_file[:-3]
2390
2391
2393 """runs mcatnlo on the generated event file, to produce showered-events
2394 """
2395 logger.info('Preparing MCatNLO run')
2396 try:
2397 misc.gunzip(evt_file)
2398 except Exception:
2399 pass
2400
2401 self.banner = banner_mod.Banner(evt_file)
2402 shower = self.banner.get_detail('run_card', 'parton_shower').upper()
2403
2404
2405
2406 if int(int(self.banner.get_detail('run_card', 'nevents')) / \
2407 self.shower_card['nsplit_jobs']) * self.shower_card['nsplit_jobs'] \
2408 != int(self.banner.get_detail('run_card', 'nevents')):
2409 logger.warning(\
2410 'nsplit_jobs in the shower card is not a divisor of the number of events.\n' + \
2411 'Setting it to 1.')
2412 self.shower_card['nsplit_jobs'] = 1
2413
2414
2415 if self.shower_card['nevents'] > 0 and \
2416 self.shower_card['nevents'] < int(self.banner.get_detail('run_card', 'nevents')) and \
2417 self.shower_card['nsplit_jobs'] != 1:
2418 logger.warning(\
2419 'Only a part of the events will be showered.\n' + \
2420 'Setting nsplit_jobs in the shower_card to 1.')
2421 self.shower_card['nsplit_jobs'] = 1
2422
2423 self.banner_to_mcatnlo(evt_file)
2424
2425
2426
2427
2428 if 'fastjet' in self.shower_card['extralibs']:
2429
2430 if not 'stdc++' in self.shower_card['extralibs']:
2431 logger.warning('Linking FastJet: adding stdc++ to EXTRALIBS')
2432 self.shower_card['extralibs'] += ' stdc++'
2433
2434 try:
2435
2436 p = subprocess.Popen([self.options['fastjet'], '--prefix'], \
2437 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
2438 output, error = p.communicate()
2439
2440 output = output[:-1]
2441
2442 if not pjoin(output, 'lib') in self.shower_card['extrapaths']:
2443 logger.warning('Linking FastJet: updating EXTRAPATHS')
2444 self.shower_card['extrapaths'] += ' ' + pjoin(output, 'lib')
2445 if not pjoin(output, 'include') in self.shower_card['includepaths']:
2446 logger.warning('Linking FastJet: updating INCLUDEPATHS')
2447 self.shower_card['includepaths'] += ' ' + pjoin(output, 'include')
2448
2449 include_line = '#include "fastjet/ClusterSequence.hh"//INCLUDE_FJ'
2450 namespace_line = 'namespace fj = fastjet;//NAMESPACE_FJ'
2451 except Exception:
2452 logger.warning('Linking FastJet: using fjcore')
2453
2454 self.shower_card['extralibs'] = self.shower_card['extralibs'].replace('fastjet', '')
2455 if not 'fjcore.o' in self.shower_card['analyse']:
2456 self.shower_card['analyse'] += ' fjcore.o'
2457
2458 include_line = '#include "fjcore.hh"//INCLUDE_FJ'
2459 namespace_line = 'namespace fj = fjcore;//NAMESPACE_FJ'
2460
2461 fjwrapper_lines = open(pjoin(self.me_dir, 'MCatNLO', 'srcCommon', 'myfastjetfortran.cc')).read().split('\n')
2462 for line in fjwrapper_lines:
2463 if '//INCLUDE_FJ' in line:
2464 fjwrapper_lines[fjwrapper_lines.index(line)] = include_line
2465 if '//NAMESPACE_FJ' in line:
2466 fjwrapper_lines[fjwrapper_lines.index(line)] = namespace_line
2467 open(pjoin(self.me_dir, 'MCatNLO', 'srcCommon', 'myfastjetfortran.cc'), 'w').write(\
2468 '\n'.join(fjwrapper_lines) + '\n')
2469
2470 extrapaths = self.shower_card['extrapaths'].split()
2471
2472
2473 if shower in ['HERWIGPP', 'PYTHIA8']:
2474 path_dict = {'HERWIGPP': ['hepmc_path',
2475 'thepeg_path',
2476 'hwpp_path'],
2477 'PYTHIA8': ['pythia8_path']}
2478
2479 if not all([self.options[ppath] for ppath in path_dict[shower]]):
2480 raise aMCatNLOError('Some paths are missing in the configuration file.\n' + \
2481 ('Please make sure you have set these variables: %s' % ', '.join(path_dict[shower])))
2482
2483 if shower == 'HERWIGPP':
2484 extrapaths.append(pjoin(self.options['hepmc_path'], 'lib'))
2485
2486 if shower == 'PYTHIA8' and not os.path.exists(pjoin(self.options['pythia8_path'], 'xmldoc')):
2487 extrapaths.append(pjoin(self.options['pythia8_path'], 'lib'))
2488
2489 if 'LD_LIBRARY_PATH' in os.environ.keys():
2490 ldlibrarypath = os.environ['LD_LIBRARY_PATH']
2491 else:
2492 ldlibrarypath = ''
2493 ldlibrarypath += ':' + ':'.join(extrapaths)
2494 os.putenv('LD_LIBRARY_PATH', ldlibrarypath)
2495
2496 shower_card_path = pjoin(self.me_dir, 'MCatNLO', 'shower_card.dat')
2497 self.shower_card.write_card(shower, shower_card_path)
2498
2499
2500 if os.path.exists(pjoin(self.me_dir, 'MCatNLO', 'shower_card_set.dat')):
2501 files.mv(pjoin(self.me_dir, 'MCatNLO', 'shower_card_set.dat'),
2502 pjoin(self.me_dir, 'MCatNLO', 'shower_card.dat'))
2503
2504 mcatnlo_log = pjoin(self.me_dir, 'mcatnlo.log')
2505 self.update_status('Compiling MCatNLO for %s...' % shower, level='shower')
2506 misc.call(['./MCatNLO_MadFKS.inputs'], stdout=open(mcatnlo_log, 'w'),
2507 stderr=open(mcatnlo_log, 'w'),
2508 cwd=pjoin(self.me_dir, 'MCatNLO'))
2509
2510 exe = 'MCATNLO_%s_EXE' % shower
2511 if not os.path.exists(pjoin(self.me_dir, 'MCatNLO', exe)) and \
2512 not os.path.exists(pjoin(self.me_dir, 'MCatNLO', 'Pythia8.exe')):
2513 print open(mcatnlo_log).read()
2514 raise aMCatNLOError('Compilation failed, check %s for details' % mcatnlo_log)
2515 logger.info(' ... done')
2516
2517
2518 count = 1
2519 while os.path.isdir(pjoin(self.me_dir, 'MCatNLO', 'RUN_%s_%d' % \
2520 (shower, count))):
2521 count += 1
2522 rundir = pjoin(self.me_dir, 'MCatNLO', 'RUN_%s_%d' % \
2523 (shower, count))
2524 os.mkdir(rundir)
2525 files.cp(shower_card_path, rundir)
2526
2527
2528
2529 event_files = glob.glob(pjoin(self.me_dir, 'Events', self.run_name,
2530 'events_*.lhe'))
2531 if max(len(event_files), 1) != self.shower_card['nsplit_jobs']:
2532 logger.info('Cleaning old files and splitting the event file...')
2533
2534 files.rm([f for f in event_files if 'events.lhe' not in f])
2535 if self.shower_card['nsplit_jobs'] > 1:
2536 misc.compile(['split_events'], cwd = pjoin(self.me_dir, 'Utilities'))
2537 p = misc.Popen([pjoin(self.me_dir, 'Utilities', 'split_events')],
2538 stdin=subprocess.PIPE,
2539 stdout=open(pjoin(self.me_dir, 'Events', self.run_name, 'split_events.log'), 'w'),
2540 cwd=pjoin(self.me_dir, 'Events', self.run_name))
2541 p.communicate(input = 'events.lhe\n%d\n' % self.shower_card['nsplit_jobs'])
2542 logger.info('Splitting done.')
2543 event_files = glob.glob(pjoin(self.me_dir, 'Events', self.run_name,
2544 'events_*.lhe'))
2545
2546 event_files.sort()
2547
2548 self.update_status('Showering events...', level='shower')
2549 logger.info('(Running in %s)' % rundir)
2550 if shower != 'PYTHIA8':
2551 files.mv(pjoin(self.me_dir, 'MCatNLO', exe), rundir)
2552 files.mv(pjoin(self.me_dir, 'MCatNLO', 'MCATNLO_%s_input' % shower), rundir)
2553 else:
2554
2555 files.mv(pjoin(self.me_dir, 'MCatNLO', 'Pythia8.cmd'), rundir)
2556 files.mv(pjoin(self.me_dir, 'MCatNLO', 'Pythia8.exe'), rundir)
2557 if os.path.exists(pjoin(self.options['pythia8_path'], 'xmldoc')):
2558 files.ln(pjoin(self.options['pythia8_path'], 'examples', 'config.sh'), rundir)
2559 files.ln(pjoin(self.options['pythia8_path'], 'xmldoc'), rundir)
2560 else:
2561 files.ln(pjoin(self.options['pythia8_path'], 'share/Pythia8/xmldoc'), rundir)
2562
2563 if shower == 'HERWIGPP':
2564 try:
2565 files.ln(pjoin(self.options['hwpp_path'], 'bin', 'Herwig++'), rundir)
2566 except Exception:
2567 raise aMCatNLOError('The Herwig++ path set in the configuration file is not valid.')
2568
2569 if os.path.exists(pjoin(self.me_dir, 'MCatNLO', 'HWPPAnalyzer', 'HepMCFortran.so')):
2570 files.cp(pjoin(self.me_dir, 'MCatNLO', 'HWPPAnalyzer', 'HepMCFortran.so'), rundir)
2571
2572 files.ln(evt_file, rundir, 'events.lhe')
2573 for i, f in enumerate(event_files):
2574 files.ln(f, rundir,'events_%d.lhe' % (i + 1))
2575
2576 if not self.shower_card['analyse']:
2577
2578 out_id = 'HEP'
2579 else:
2580
2581 if "HwU" in self.shower_card['analyse']:
2582 out_id = 'HWU'
2583 else:
2584 out_id = 'TOP'
2585
2586
2587 open(pjoin(rundir, 'shower.sh'), 'w').write(\
2588 open(pjoin(self.me_dir, 'MCatNLO', 'shower_template.sh')).read() \
2589 % {'extralibs': ':'.join(extrapaths)})
2590 subprocess.call(['chmod', '+x', pjoin(rundir, 'shower.sh')])
2591
2592 if event_files:
2593 arg_list = [[shower, out_id, self.run_name, '%d' % (i + 1)] \
2594 for i in range(len(event_files))]
2595 else:
2596 arg_list = [[shower, out_id, self.run_name]]
2597
2598 self.run_all({rundir: 'shower.sh'}, arg_list, 'shower')
2599 self.njobs = 1
2600 self.wait_for_complete('shower')
2601
2602
2603 message = ''
2604 warning = ''
2605 to_gzip = [evt_file]
2606 if out_id == 'HEP':
2607
2608 if shower in ['PYTHIA8', 'HERWIGPP']:
2609 hep_format = 'HEPMC'
2610 ext = 'hepmc'
2611 else:
2612 hep_format = 'StdHEP'
2613 ext = 'hep'
2614
2615 hep_file = '%s_%s_0.%s.gz' % \
2616 (pjoin(os.path.dirname(evt_file), 'events'), shower, ext)
2617 count = 0
2618
2619
2620
2621 while os.path.exists(hep_file) or \
2622 os.path.exists(hep_file.replace('.%s.gz' % ext, '__1.%s.gz' % ext)) :
2623 count +=1
2624 hep_file = '%s_%s_%d.%s.gz' % \
2625 (pjoin(os.path.dirname(evt_file), 'events'), shower, count, ext)
2626
2627 try:
2628 if self.shower_card['nsplit_jobs'] == 1:
2629 files.mv(os.path.join(rundir, 'events.%s.gz' % ext), hep_file)
2630 message = ('The file %s has been generated. \nIt contains showered' + \
2631 ' and hadronized events in the %s format obtained' + \
2632 ' showering the parton-level event file %s.gz with %s') % \
2633 (hep_file, hep_format, evt_file, shower)
2634 else:
2635 hep_list = []
2636 for i in range(self.shower_card['nsplit_jobs']):
2637 hep_list.append(hep_file.replace('.%s.gz' % ext, '__%d.%s.gz' % (i + 1, ext)))
2638 files.mv(os.path.join(rundir, 'events_%d.%s.gz' % (i + 1, ext)), hep_list[-1])
2639 message = ('The following files have been generated:\n %s\nThey contain showered' + \
2640 ' and hadronized events in the %s format obtained' + \
2641 ' showering the (split) parton-level event file %s.gz with %s') % \
2642 ('\n '.join(hep_list), hep_format, evt_file, shower)
2643
2644 except OSError, IOError:
2645 raise aMCatNLOError('No file has been generated, an error occurred.'+\
2646 ' More information in %s' % pjoin(os.getcwd(), 'amcatnlo_run.log'))
2647
2648
2649 if hep_format == 'StdHEP':
2650 try:
2651 self.do_plot('%s -f' % self.run_name)
2652 except Exception, error:
2653 logger.info("Fail to make the plot. Continue...")
2654 pass
2655
2656 elif out_id == 'TOP' or out_id == 'HWU':
2657
2658 if out_id=='TOP':
2659 ext='top'
2660 elif out_id=='HWU':
2661 ext='HwU'
2662 topfiles = []
2663 top_tars = [tarfile.TarFile(f) for f in glob.glob(pjoin(rundir, 'histfile*.tar'))]
2664 for top_tar in top_tars:
2665 topfiles.extend(top_tar.getnames())
2666
2667
2668 if len(top_tars) != self.shower_card['nsplit_jobs']:
2669 raise aMCatNLOError('%d job(s) expected, %d file(s) found' % \
2670 (self.shower_card['nsplit_jobs'], len(top_tars)))
2671
2672
2673
2674 filename = 'plot_%s_%d_' % (shower, 1)
2675 count = 1
2676 while os.path.exists(pjoin(self.me_dir, 'Events',
2677 self.run_name, '%s0.%s' % (filename,ext))) or \
2678 os.path.exists(pjoin(self.me_dir, 'Events',
2679 self.run_name, '%s0__1.%s' % (filename,ext))):
2680 count += 1
2681 filename = 'plot_%s_%d_' % (shower, count)
2682
2683 if out_id=='TOP':
2684 hist_format='TopDrawer format'
2685 elif out_id=='HWU':
2686 hist_format='HwU and GnuPlot formats'
2687
2688 if not topfiles:
2689
2690 warning = 'No .top file has been generated. For the results of your ' +\
2691 'run, please check inside %s' % rundir
2692 elif self.shower_card['nsplit_jobs'] == 1:
2693
2694 top_tars[0].extractall(path = rundir)
2695 plotfiles = []
2696 for i, file in enumerate(topfiles):
2697 if out_id=='TOP':
2698 plotfile = pjoin(self.me_dir, 'Events', self.run_name,
2699 '%s%d.top' % (filename, i))
2700 files.mv(pjoin(rundir, file), plotfile)
2701 elif out_id=='HWU':
2702 histogram_list=histograms.HwUList(pjoin(rundir,file))
2703 histogram_list.output(pjoin(self.me_dir,'Events',self.run_name,
2704 '%s%d'% (filename,i)),format = 'gnuplot')
2705 try:
2706 misc.call(['gnuplot','%s%d.gnuplot' % (filename,i)],\
2707 stdout=os.open(os.devnull, os.O_RDWR),\
2708 stderr=os.open(os.devnull, os.O_RDWR),\
2709 cwd=pjoin(self.me_dir, 'Events', self.run_name))
2710 except Exception:
2711 pass
2712 plotfile=pjoin(self.me_dir,'Events',self.run_name,
2713 '%s%d.HwU'% (filename,i))
2714 plotfiles.append(plotfile)
2715
2716 ffiles = 'files'
2717 have = 'have'
2718 if len(plotfiles) == 1:
2719 ffiles = 'file'
2720 have = 'has'
2721
2722 message = ('The %s %s %s been generated, with histograms in the' + \
2723 ' %s, obtained by showering the parton-level' + \
2724 ' file %s.gz with %s.') % (ffiles, ', '.join(plotfiles), have, \
2725 hist_format, evt_file, shower)
2726 else:
2727
2728 topfiles_set = set(topfiles)
2729 plotfiles = []
2730 for j, top_tar in enumerate(top_tars):
2731 top_tar.extractall(path = rundir)
2732 for i, file in enumerate(topfiles_set):
2733 plotfile = pjoin(self.me_dir, 'Events', self.run_name,
2734 '%s%d__%d.%s' % (filename, i, j + 1,ext))
2735 files.mv(pjoin(rundir, file), plotfile)
2736 plotfiles.append(plotfile)
2737
2738
2739 if self.shower_card['combine_td']:
2740 misc.compile(['sum_plots'], cwd = pjoin(self.me_dir, 'Utilities'))
2741
2742 if self.banner.get('run_card', 'event_norm').lower() == 'sum':
2743 norm = 1.
2744 elif self.banner.get('run_card', 'event_norm').lower() == 'average':
2745 norm = 1./float(self.shower_card['nsplit_jobs'])
2746
2747 plotfiles2 = []
2748 for i, file in enumerate(topfiles_set):
2749 filelist = ['%s%d__%d.%s' % (filename, i, j + 1,ext) \
2750 for j in range(self.shower_card['nsplit_jobs'])]
2751 if out_id=='TOP':
2752 infile="%d\n%s\n%s\n" % \
2753 (self.shower_card['nsplit_jobs'],
2754 '\n'.join(filelist),
2755 '\n'.join([str(norm)] * self.shower_card['nsplit_jobs']))
2756 p = misc.Popen([pjoin(self.me_dir, 'Utilities', 'sum_plots')],
2757 stdin=subprocess.PIPE,
2758 stdout=os.open(os.devnull, os.O_RDWR),
2759 cwd=pjoin(self.me_dir, 'Events', self.run_name))
2760 p.communicate(input = infile)
2761 files.mv(pjoin(self.me_dir, 'Events', self.run_name, 'sum.top'),
2762 pjoin(self.me_dir, 'Events', self.run_name, '%s%d.top' % (filename, i)))
2763 elif out_id=='HWU':
2764 histogram_list=histograms.HwUList(plotfiles[0])
2765 for ii, histo in enumerate(histogram_list):
2766 histogram_list[ii] = histo*norm
2767 for histo_path in plotfiles[1:]:
2768 for ii, histo in enumerate(histograms.HwUList(histo_path)):
2769
2770 histo.test_plot_compability(histogram_list[ii])
2771
2772 histogram_list[ii] += histo*norm
2773
2774 histogram_list.output(pjoin(self.me_dir,'Events',self.run_name,'%s%d'% (filename, i)),
2775 format = 'gnuplot')
2776 try:
2777 misc.call(['gnuplot','%s%d.gnuplot' % (filename, i)],\
2778 stdout=os.open(os.devnull, os.O_RDWR),\
2779 stderr=os.open(os.devnull, os.O_RDWR),\
2780 cwd=pjoin(self.me_dir, 'Events', self.run_name))
2781 except Exception:
2782 pass
2783
2784 plotfiles2.append(pjoin(self.me_dir, 'Events', self.run_name, '%s%d.%s' % (filename, i,ext)))
2785 tar = tarfile.open(
2786 pjoin(self.me_dir, 'Events', self.run_name, '%s%d.tar.gz' % (filename, i)), 'w:gz')
2787 for f in filelist:
2788 tar.add(pjoin(self.me_dir, 'Events', self.run_name, f), arcname=f)
2789 files.rm([pjoin(self.me_dir, 'Events', self.run_name, f) for f in filelist])
2790
2791 tar.close()
2792
2793 ffiles = 'files'
2794 have = 'have'
2795 if len(plotfiles2) == 1:
2796 ffiles = 'file'
2797 have = 'has'
2798
2799 message = ('The %s %s %s been generated, with histograms in the' + \
2800 ' %s, obtained by showering the parton-level' + \
2801 ' file %s.gz with %s.\n' + \
2802 'The files from the different shower ' + \
2803 'jobs (before combining them) can be found inside %s.') % \
2804 (ffiles, ', '.join(plotfiles2), have, hist_format,\
2805 evt_file, shower,
2806 ', '.join([f.replace('%s' % ext, 'tar.gz') for f in plotfiles2]))
2807
2808 else:
2809 message = ('The following files have been generated:\n %s\n' + \
2810 'They contain histograms in the' + \
2811 ' %s, obtained by showering the parton-level' + \
2812 ' file %s.gz with %s.') % ('\n '.join(plotfiles), \
2813 hist_format, evt_file, shower)
2814
2815
2816 run_dir_path = pjoin(rundir, self.run_name)
2817 if os.path.exists(pjoin(run_dir_path,'RunMaterial.tar.gz')):
2818 misc.call(['tar','-xzpf','RunMaterial.tar.gz'],cwd=run_dir_path)
2819 files.cp(pjoin(self.me_dir,'Cards','shower_card.dat'),
2820 pjoin(run_dir_path,'RunMaterial','shower_card_for_%s_%d.dat'\
2821 %(shower, count)))
2822 misc.call(['tar','-czpf','RunMaterial.tar.gz','RunMaterial'],
2823 cwd=run_dir_path)
2824 shutil.rmtree(pjoin(run_dir_path,'RunMaterial'))
2825
2826 for f in to_gzip:
2827 misc.gzip(f)
2828 if message:
2829 logger.info(message)
2830 if warning:
2831 logger.warning(warning)
2832
2833 self.update_status('Run complete', level='shower', update_results=True)
2834
2835
2836
2837 - def set_run_name(self, name, tag=None, level='parton', reload_card=False):
2838 """define the run name, the run_tag, the banner and the results."""
2839
2840
2841 upgrade_tag = {'parton': ['parton','pythia','pgs','delphes','shower'],
2842 'pythia': ['pythia','pgs','delphes'],
2843 'shower': ['shower'],
2844 'pgs': ['pgs'],
2845 'delphes':['delphes'],
2846 'plot':[]}
2847
2848
2849
2850 if name == self.run_name:
2851 if reload_card:
2852 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
2853 self.run_card = banner_mod.RunCardNLO(run_card)
2854
2855
2856 if tag:
2857 self.run_card['run_tag'] = tag
2858 self.run_tag = tag
2859 self.results.add_run(self.run_name, self.run_card)
2860 else:
2861 for tag in upgrade_tag[level]:
2862 if getattr(self.results[self.run_name][-1], tag):
2863 tag = self.get_available_tag()
2864 self.run_card['run_tag'] = tag
2865 self.run_tag = tag
2866 self.results.add_run(self.run_name, self.run_card)
2867 break
2868 return
2869
2870
2871 if self.run_name:
2872 self.store_result()
2873
2874 self.run_name = name
2875
2876
2877 run_card = pjoin(self.me_dir, 'Cards','run_card.dat')
2878 self.run_card = banner_mod.RunCardNLO(run_card)
2879
2880 new_tag = False
2881
2882 self.banner = banner_mod.recover_banner(self.results, level, self.run_name, tag)
2883 if tag:
2884 self.run_card['run_tag'] = tag
2885 new_tag = True
2886 elif not self.run_name in self.results and level =='parton':
2887 pass
2888 elif not self.run_name in self.results:
2889
2890 logger.warning('Trying to run data on unknown run.')
2891 self.results.add_run(name, self.run_card)
2892 self.results.update('add run %s' % name, 'all', makehtml=True)
2893 else:
2894 for tag in upgrade_tag[level]:
2895
2896 if getattr(self.results[self.run_name][-1], tag):
2897
2898 tag = self.get_available_tag()
2899 self.run_card['run_tag'] = tag
2900 new_tag = True
2901 break
2902 if not new_tag:
2903
2904 tag = self.results[self.run_name][-1]['tag']
2905 self.run_card['run_tag'] = tag
2906
2907
2908 if name in self.results and not new_tag:
2909 self.results.def_current(self.run_name)
2910 else:
2911 self.results.add_run(self.run_name, self.run_card)
2912
2913 self.run_tag = self.run_card['run_tag']
2914
2915
2916
2917 if level == 'parton':
2918 return
2919 elif level == 'pythia':
2920 return self.results[self.run_name][0]['tag']
2921 else:
2922 for i in range(-1,-len(self.results[self.run_name])-1,-1):
2923 tagRun = self.results[self.run_name][i]
2924 if tagRun.pythia:
2925 return tagRun['tag']
2926
2927
2929 """ tar the pythia results. This is done when we are quite sure that
2930 the pythia output will not be use anymore """
2931
2932 if not self.run_name:
2933 return
2934
2935 self.results.save()
2936
2937 if not self.to_store:
2938 return
2939
2940 tag = self.run_card['run_tag']
2941
2942 self.to_store = []
2943
2944
2946 """reads the info in the init block and returns them in a dictionary"""
2947 ev_file = open(evt_file)
2948 init = ""
2949 found = False
2950 while True:
2951 line = ev_file.readline()
2952 if "<init>" in line:
2953 found = True
2954 elif found and not line.startswith('#'):
2955 init += line
2956 if "</init>" in line or "<event>" in line:
2957 break
2958 ev_file.close()
2959
2960
2961
2962
2963
2964
2965 init_dict = {}
2966 init_dict['idbmup1'] = int(init.split()[0])
2967 init_dict['idbmup2'] = int(init.split()[1])
2968 init_dict['ebmup1'] = float(init.split()[2])
2969 init_dict['ebmup2'] = float(init.split()[3])
2970 init_dict['pdfgup1'] = int(init.split()[4])
2971 init_dict['pdfgup2'] = int(init.split()[5])
2972 init_dict['pdfsup1'] = int(init.split()[6])
2973 init_dict['pdfsup2'] = int(init.split()[7])
2974 init_dict['idwtup'] = int(init.split()[8])
2975 init_dict['nprup'] = int(init.split()[9])
2976
2977 return init_dict
2978
2979
2981 """creates the mcatnlo input script using the values set in the header of the event_file.
2982 It also checks if the lhapdf library is used"""
2983 shower = self.banner.get('run_card', 'parton_shower').upper()
2984 pdlabel = self.banner.get('run_card', 'pdlabel')
2985 itry = 0
2986 nevents = self.shower_card['nevents']
2987 init_dict = self.get_init_dict(evt_file)
2988
2989 if nevents < 0 or \
2990 nevents > int(self.banner.get_detail('run_card', 'nevents')):
2991 nevents = int(self.banner.get_detail('run_card', 'nevents'))
2992
2993 nevents = nevents / self.shower_card['nsplit_jobs']
2994
2995 mcmass_dict = {}
2996 for line in [l for l in self.banner['montecarlomasses'].split('\n') if l]:
2997 pdg = int(line.split()[0])
2998 mass = float(line.split()[1])
2999 mcmass_dict[pdg] = mass
3000
3001 content = 'EVPREFIX=%s\n' % pjoin(os.path.split(evt_file)[1])
3002 content += 'NEVENTS=%d\n' % nevents
3003 content += 'NEVENTS_TOT=%d\n' % (int(self.banner.get_detail('run_card', 'nevents')) /\
3004 self.shower_card['nsplit_jobs'])
3005 content += 'MCMODE=%s\n' % shower
3006 content += 'PDLABEL=%s\n' % pdlabel
3007 content += 'ALPHAEW=%s\n' % self.banner.get_detail('param_card', 'sminputs', 1).value
3008
3009
3010 content += 'TMASS=%s\n' % self.banner.get_detail('param_card', 'mass', 6).value
3011 content += 'TWIDTH=%s\n' % self.banner.get_detail('param_card', 'decay', 6).value
3012 content += 'ZMASS=%s\n' % self.banner.get_detail('param_card', 'mass', 23).value
3013 content += 'ZWIDTH=%s\n' % self.banner.get_detail('param_card', 'decay', 23).value
3014 content += 'WMASS=%s\n' % self.banner.get_detail('param_card', 'mass', 24).value
3015 content += 'WWIDTH=%s\n' % self.banner.get_detail('param_card', 'decay', 24).value
3016 try:
3017 content += 'HGGMASS=%s\n' % self.banner.get_detail('param_card', 'mass', 25).value
3018 content += 'HGGWIDTH=%s\n' % self.banner.get_detail('param_card', 'decay', 25).value
3019 except KeyError:
3020 content += 'HGGMASS=120.\n'
3021 content += 'HGGWIDTH=0.00575308848\n'
3022 content += 'beammom1=%s\n' % self.banner.get_detail('run_card', 'ebeam1')
3023 content += 'beammom2=%s\n' % self.banner.get_detail('run_card', 'ebeam2')
3024 content += 'BEAM1=%s\n' % self.banner.get_detail('run_card', 'lpp1')
3025 content += 'BEAM2=%s\n' % self.banner.get_detail('run_card', 'lpp2')
3026 content += 'DMASS=%s\n' % mcmass_dict[1]
3027 content += 'UMASS=%s\n' % mcmass_dict[2]
3028 content += 'SMASS=%s\n' % mcmass_dict[3]
3029 content += 'CMASS=%s\n' % mcmass_dict[4]
3030 content += 'BMASS=%s\n' % mcmass_dict[5]
3031 try:
3032 content += 'EMASS=%s\n' % mcmass_dict[11]
3033 content += 'MUMASS=%s\n' % mcmass_dict[13]
3034 content += 'TAUMASS=%s\n' % mcmass_dict[15]
3035 except KeyError:
3036
3037 mcmass_lines = [l for l in \
3038 open(pjoin(self.me_dir, 'SubProcesses', 'MCmasses_%s.inc' % shower.upper())
3039 ).read().split('\n') if l]
3040 new_mcmass_dict = {}
3041 for l in mcmass_lines:
3042 key, val = l.split('=')
3043 new_mcmass_dict[key.strip()] = val.replace('d', 'e').strip()
3044 content += 'EMASS=%s\n' % new_mcmass_dict['mcmass(11)']
3045 content += 'MUMASS=%s\n' % new_mcmass_dict['mcmass(13)']
3046 content += 'TAUMASS=%s\n' % new_mcmass_dict['mcmass(15)']
3047
3048 content += 'GMASS=%s\n' % mcmass_dict[21]
3049 content += 'EVENT_NORM=%s\n' % self.banner.get_detail('run_card', 'event_norm').lower()
3050
3051 if int(self.shower_card['pdfcode']) > 1 or \
3052 (pdlabel=='lhapdf' and int(self.shower_card['pdfcode'])==1):
3053
3054
3055
3056
3057 self.link_lhapdf(pjoin(self.me_dir, 'lib'))
3058 lhapdfpath = subprocess.Popen([self.options['lhapdf'], '--prefix'],
3059 stdout = subprocess.PIPE).stdout.read().strip()
3060 content += 'LHAPDFPATH=%s\n' % lhapdfpath
3061 pdfsetsdir = self.get_lhapdf_pdfsetsdir()
3062 if self.shower_card['pdfcode']==1:
3063 lhaid_list = [max([init_dict['pdfsup1'],init_dict['pdfsup2']])]
3064 content += 'PDFCODE=%s\n' % max([init_dict['pdfsup1'],init_dict['pdfsup2']])
3065 else:
3066 lhaid_list = [abs(int(self.shower_card['pdfcode']))]
3067 content += 'PDFCODE=%s\n' % self.shower_card['pdfcode']
3068 self.copy_lhapdf_set(lhaid_list, pdfsetsdir)
3069 elif int(self.shower_card['pdfcode'])==1:
3070
3071
3072
3073
3074
3075
3076 try:
3077 lhapdfpath = subprocess.Popen([self.options['lhapdf'], '--prefix'],
3078 stdout = subprocess.PIPE).stdout.read().strip()
3079 self.link_lhapdf(pjoin(self.me_dir, 'lib'))
3080 content += 'LHAPDFPATH=%s\n' % lhapdfpath
3081 pdfsetsdir = self.get_lhapdf_pdfsetsdir()
3082 lhaid_list = [max([init_dict['pdfsup1'],init_dict['pdfsup2']])]
3083 content += 'PDFCODE=%s\n' % max([init_dict['pdfsup1'],init_dict['pdfsup2']])
3084 self.copy_lhapdf_set(lhaid_list, pdfsetsdir)
3085 except Exception:
3086 logger.warning('Trying to shower events using the same PDF in the shower as used in the generation'+\
3087 ' of the events using LHAPDF. However, no valid LHAPDF installation found with the'+\
3088 ' needed PDF set. Will use default internal PDF for the shower instead. To use the'+\
3089 ' same set as was used in the event generation install LHAPDF and set the path using'+\
3090 ' "set /path_to_lhapdf/bin/lhapdf-config" from the MadGraph5_aMC@NLO python shell')
3091 content += 'LHAPDFPATH=\n'
3092 content += 'PDFCODE=0\n'
3093 else:
3094 content += 'LHAPDFPATH=\n'
3095 content += 'PDFCODE=0\n'
3096
3097 content += 'ICKKW=%s\n' % self.banner.get_detail('run_card', 'ickkw')
3098 content += 'PTJCUT=%s\n' % self.banner.get_detail('run_card', 'ptj')
3099
3100 if self.options['pythia8_path']:
3101 content+='PY8PATH=%s\n' % self.options['pythia8_path']
3102 if self.options['hwpp_path']:
3103 content+='HWPPPATH=%s\n' % self.options['hwpp_path']
3104 if self.options['thepeg_path']:
3105 content+='THEPEGPATH=%s\n' % self.options['thepeg_path']
3106 if self.options['hepmc_path']:
3107 content+='HEPMCPATH=%s\n' % self.options['hepmc_path']
3108
3109 output = open(pjoin(self.me_dir, 'MCatNLO', 'banner.dat'), 'w')
3110 output.write(content)
3111 output.close()
3112 return shower
3113
3114
3116 """runs the reweight_xsec_events eecutables on each sub-event file generated
3117 to compute on the fly scale and/or PDF uncertainities"""
3118 logger.info(' Doing reweight')
3119
3120 nev_unw = pjoin(self.me_dir, 'SubProcesses', 'nevents_unweighted')
3121
3122 if only:
3123 if os.path.exists(nev_unw + '.orig'):
3124 files.cp(nev_unw + '.orig', nev_unw)
3125 else:
3126 raise aMCatNLOError('Cannot find event file information')
3127
3128
3129 file = open(nev_unw)
3130 lines = file.read().split('\n')
3131 file.close()
3132
3133 files.cp(nev_unw, nev_unw + '.orig')
3134
3135
3136 evt_files = [line.split()[0] for line in lines[:-1] if line.split()[1] != '0']
3137
3138 job_dict = {}
3139 exe = 'reweight_xsec_events.local'
3140 for i, evt_file in enumerate(evt_files):
3141 path, evt = os.path.split(evt_file)
3142 files.ln(pjoin(self.me_dir, 'SubProcesses', exe), \
3143 pjoin(self.me_dir, 'SubProcesses', path))
3144 job_dict[path] = [exe]
3145
3146 self.run_all(job_dict, [[evt, '1']], 'Running reweight')
3147
3148
3149 for evt_file in evt_files:
3150 last_line = subprocess.Popen(['tail', '-n1', '%s.rwgt' % \
3151 pjoin(self.me_dir, 'SubProcesses', evt_file)], \
3152 stdout = subprocess.PIPE).stdout.read().strip()
3153 if last_line != "</LesHouchesEvents>":
3154 raise aMCatNLOError('An error occurred during reweight. Check the' + \
3155 '\'reweight_xsec_events.output\' files inside the ' + \
3156 '\'SubProcesses/P*/G*/ directories for details')
3157
3158
3159 newfile = open(nev_unw, 'w')
3160 for line in lines:
3161 if line:
3162 newfile.write(line.replace(line.split()[0], line.split()[0] + '.rwgt') + '\n')
3163 newfile.close()
3164
3165 return self.pdf_scale_from_reweighting(evt_files)
3166
3168 """This function takes the files with the scale and pdf values
3169 written by the reweight_xsec_events.f code
3170 (P*/G*/pdf_scale_dependence.dat) and computes the overall
3171 scale and PDF uncertainty (the latter is computed using the
3172 Hessian method (if lhaid<90000) or Gaussian (if lhaid>90000))
3173 and returns it in percents. The expected format of the file
3174 is: n_scales xsec_scale_central xsec_scale1 ... n_pdf
3175 xsec_pdf0 xsec_pdf1 ...."""
3176 scale_pdf_info={}
3177 scales=[]
3178 pdfs=[]
3179 numofpdf = 0
3180 numofscales = 0
3181 for evt_file in evt_files:
3182 path, evt=os.path.split(evt_file)
3183 data_file=open(pjoin(self.me_dir, 'SubProcesses', path, 'scale_pdf_dependence.dat')).read()
3184 lines = data_file.replace("D", "E").split("\n")
3185 if not numofscales:
3186 numofscales = int(lines[0])
3187 if not numofpdf:
3188 numofpdf = int(lines[2])
3189 scales_this = [float(val) for val in lines[1].split()]
3190 pdfs_this = [float(val) for val in lines[3].split()]
3191
3192 if numofscales != len(scales_this) or numofpdf !=len(pdfs_this):
3193
3194 logger.info(data_file)
3195 logger.info((' Expected # of scales: %d\n'+
3196 ' Found # of scales: %d\n'+
3197 ' Expected # of pdfs: %d\n'+
3198 ' Found # of pdfs: %d\n') %
3199 (numofscales, len(scales_this), numofpdf, len(pdfs_this)))
3200 raise aMCatNLOError('inconsistent scale_pdf_dependence.dat')
3201 if not scales:
3202 scales = [0.] * numofscales
3203 if not pdfs:
3204 pdfs = [0.] * numofpdf
3205
3206 scales = [a + b for a, b in zip(scales, scales_this)]
3207 pdfs = [a + b for a, b in zip(pdfs, pdfs_this)]
3208
3209
3210 if numofscales>0 and numofpdf==0:
3211 cntrl_val=scales[0]
3212 elif numofpdf>0 and numofscales==0:
3213 cntrl_val=pdfs[0]
3214 elif numofpdf>0 and numofscales>0:
3215 if abs(1-scales[0]/pdfs[0])>0.0001:
3216 raise aMCatNLOError('Central values for scale and PDF variation not identical')
3217 else:
3218 cntrl_val=scales[0]
3219
3220
3221 if numofscales>0:
3222 if cntrl_val != 0.0:
3223
3224 scale_pdf_info['scale_upp'] = (max(scales)/cntrl_val-1)*100
3225 scale_pdf_info['scale_low'] = (1-min(scales)/cntrl_val)*100
3226
3227 scale_pdf_info['scale_upp_quad'] = ((cntrl_val+math.sqrt(math.pow(max(scales[0]-cntrl_val,scales[1]-cntrl_val,scales[2]-cntrl_val),2)+math.pow(max(scales[0]-cntrl_val,scales[3]-cntrl_val,scales[6]-cntrl_val),2)))/cntrl_val-1)*100
3228 scale_pdf_info['scale_low_quad'] = (1-(cntrl_val-math.sqrt(math.pow(min(scales[0]-cntrl_val,scales[1]-cntrl_val,scales[2]-cntrl_val),2)+math.pow(min(scales[0]-cntrl_val,scales[3]-cntrl_val,scales[6]-cntrl_val),2)))/cntrl_val)*100
3229 else:
3230 scale_pdf_info['scale_upp'] = 0.0
3231 scale_pdf_info['scale_low'] = 0.0
3232
3233
3234 lhaid=int(self.run_card['lhaid'])
3235 pdf_upp=0.0
3236 pdf_low=0.0
3237 if lhaid <= 90000:
3238
3239 if numofpdf>1:
3240 for i in range(int(numofpdf/2)):
3241 pdf_upp=pdf_upp+math.pow(max(0.0,pdfs[2*i+1]-cntrl_val,pdfs[2*i+2]-cntrl_val),2)
3242 pdf_low=pdf_low+math.pow(max(0.0,cntrl_val-pdfs[2*i+1],cntrl_val-pdfs[2*i+2]),2)
3243 if cntrl_val != 0.0:
3244 scale_pdf_info['pdf_upp'] = math.sqrt(pdf_upp)/cntrl_val*100
3245 scale_pdf_info['pdf_low'] = math.sqrt(pdf_low)/cntrl_val*100
3246 else:
3247 scale_pdf_info['pdf_upp'] = 0.0
3248 scale_pdf_info['pdf_low'] = 0.0
3249
3250 else:
3251
3252 pdf_stdev=0.0
3253 for i in range(int(numofpdf-1)):
3254 pdf_stdev = pdf_stdev + pow(pdfs[i+1] - cntrl_val,2)
3255 pdf_stdev = math.sqrt(pdf_stdev/int(numofpdf-2))
3256 if cntrl_val != 0.0:
3257 scale_pdf_info['pdf_upp'] = pdf_stdev/cntrl_val*100
3258 else:
3259 scale_pdf_info['pdf_upp'] = 0.0
3260 scale_pdf_info['pdf_low'] = scale_pdf_info['pdf_upp']
3261 return scale_pdf_info
3262
3263
3265 """this function waits for jobs on cluster to complete their run."""
3266
3267 starttime = time.time()
3268
3269 update_status = lambda i, r, f: self.update_status((i, r, f, run_type),
3270 starttime=starttime, level='parton', update_results=True)
3271 try:
3272 self.cluster.wait(self.me_dir, update_status)
3273 except:
3274 self.cluster.remove()
3275 raise
3276
3277 - def run_all(self, job_dict, arg_list, run_type='monitor', split_jobs = False):
3278 """runs the jobs in job_dict (organized as folder: [job_list]), with arguments args"""
3279 njob_split = 0
3280 self.ijob = 0
3281
3282
3283
3284 self.split_folders = {}
3285
3286 if run_type != 'shower':
3287 self.njobs = sum(len(jobs) for jobs in job_dict.values()) * len(arg_list)
3288 for args in arg_list:
3289 for Pdir, jobs in job_dict.items():
3290 for job in jobs:
3291 if not split_jobs:
3292 self.run_exe(job, args, run_type, cwd=pjoin(self.me_dir, 'SubProcesses', Pdir) )
3293 else:
3294 for n in self.find_jobs_to_split(Pdir, job, args[1]):
3295 self.run_exe(job, args + [n], run_type, cwd=pjoin(self.me_dir, 'SubProcesses', Pdir) )
3296 njob_split += 1
3297
3298 if self.cluster_mode == 2:
3299 time.sleep(1)
3300 if njob_split > 0:
3301 self.njobs = njob_split
3302 else:
3303 self.njobs = len(arg_list)
3304 for args in arg_list:
3305 [(cwd, exe)] = job_dict.items()
3306 self.run_exe(exe, args, run_type, cwd)
3307
3308 self.wait_for_complete(run_type)
3309
3310
3311
3313 """check the integrity of the event files after splitting, and resubmit
3314 those which are not nicely terminated"""
3315 to_resubmit = []
3316 for dir in self.split_folders.keys():
3317 last_line = ''
3318 try:
3319 last_line = subprocess.Popen(
3320 ['tail', '-n1', pjoin(dir, 'events.lhe')], \
3321 stdout = subprocess.PIPE).stdout.read().strip()
3322 except IOError:
3323 pass
3324
3325 if last_line != "</LesHouchesEvents>":
3326 to_resubmit.append(dir)
3327
3328 self.njobs = 0
3329 if to_resubmit:
3330 run_type = 'Resubmitting broken jobs'
3331 logger.info('Some event files are broken, corresponding jobs will be resubmitted.')
3332 logger.debug('Resubmitting\n' + '\n'.join(to_resubmit) + '\n')
3333 for dir in to_resubmit:
3334 files.rm([dir])
3335 job = self.split_folders[dir][0]
3336 args = self.split_folders[dir][1:]
3337 run_type = 'monitor'
3338 cwd = os.path.split(dir)[0]
3339 self.run_exe(job, args, run_type, cwd=cwd )
3340 self.njobs +=1
3341
3342 self.wait_for_complete(run_type)
3343
3344
3346 """looks into the nevents_unweighed_splitted file to check how many
3347 split jobs are needed for this (pdir, job). arg is F, B or V"""
3348
3349 splittings = []
3350 ajob = open(pjoin(self.me_dir, 'SubProcesses', pdir, job)).read()
3351 pattern = re.compile('for i in (\d+) ; do')
3352 match = re.search(pattern, ajob)
3353 channel = match.groups()[0]
3354
3355
3356 nevents_file = open(pjoin(self.me_dir, 'SubProcesses', 'nevents_unweighted_splitted')).read()
3357
3358
3359 pattern = re.compile(r"%s_(\d+)/events.lhe" % \
3360 pjoin(pdir, 'G%s%s' % (arg,channel)))
3361 matches = re.findall(pattern, nevents_file)
3362 for m in matches:
3363 splittings.append(m)
3364 return splittings
3365
3366
3367 - def run_exe(self, exe, args, run_type, cwd=None):
3368 """this basic function launch locally/on cluster exe with args as argument.
3369 """
3370
3371
3372 execpath = None
3373 if cwd and os.path.exists(pjoin(cwd, exe)):
3374 execpath = pjoin(cwd, exe)
3375 elif not cwd and os.path.exists(exe):
3376 execpath = exe
3377 else:
3378 raise aMCatNLOError('Cannot find executable %s in %s' \
3379 % (exe, os.getcwd()))
3380
3381 if self.cluster_mode == 1 and not os.access(execpath, os.X_OK):
3382 subprocess.call(['chmod', '+x', exe], cwd=cwd)
3383
3384 if self.cluster_mode == 0:
3385
3386 misc.call(['./'+exe] + args, cwd=cwd)
3387 self.ijob += 1
3388 self.update_status((max([self.njobs - self.ijob - 1, 0]),
3389 min([1, self.njobs - self.ijob]),
3390 self.ijob, run_type), level='parton')
3391
3392
3393 elif 'reweight' in exe:
3394
3395
3396 input_files, output_files = [], []
3397 pdfinput = self.get_pdf_input_filename()
3398 if os.path.exists(pdfinput):
3399 input_files.append(pdfinput)
3400 input_files.append(pjoin(os.path.dirname(exe), os.path.pardir, 'reweight_xsec_events'))
3401 input_files.append(pjoin(cwd, os.path.pardir, 'leshouche_info.dat'))
3402 input_files.append(args[0])
3403 output_files.append('%s.rwgt' % os.path.basename(args[0]))
3404 output_files.append('reweight_xsec_events.output')
3405 output_files.append('scale_pdf_dependence.dat')
3406
3407 return self.cluster.submit2(exe, args, cwd=cwd,
3408 input_files=input_files, output_files=output_files,
3409 required_output=output_files)
3410
3411 elif 'ajob' in exe:
3412
3413
3414 if type(args[0]) == str:
3415 input_files, output_files, required_output, args = self.getIO_ajob(exe,cwd, args)
3416
3417 self.cluster.submit2(exe, args, cwd=cwd,
3418 input_files=input_files, output_files=output_files,
3419 required_output=required_output)
3420
3421
3422 subfolder=output_files[-1].split('/')[0]
3423 if len(args) == 4 and '_' in subfolder:
3424 self.split_folders[pjoin(cwd,subfolder)] = [exe] + args
3425
3426 elif 'shower' in exe:
3427
3428
3429
3430 input_files, output_files = [], []
3431 shower = args[0]
3432
3433 if shower == 'PYTHIA8':
3434 input_files.append(pjoin(cwd, 'Pythia8.exe'))
3435 input_files.append(pjoin(cwd, 'Pythia8.cmd'))
3436 if os.path.exists(pjoin(self.options['pythia8_path'], 'xmldoc')):
3437 input_files.append(pjoin(cwd, 'config.sh'))
3438 input_files.append(pjoin(self.options['pythia8_path'], 'xmldoc'))
3439 else:
3440 input_files.append(pjoin(self.options['pythia8_path'], 'share/Pythia8/xmldoc'))
3441 else:
3442 input_files.append(pjoin(cwd, 'MCATNLO_%s_EXE' % shower))
3443 input_files.append(pjoin(cwd, 'MCATNLO_%s_input' % shower))
3444 if shower == 'HERWIGPP':
3445 input_files.append(pjoin(cwd, 'Herwig++'))
3446 input_files.append(pjoin(cwd, 'HepMCFortran.so'))
3447 if len(args) == 3:
3448 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, 'events.lhe.gz')):
3449 input_files.append(pjoin(self.me_dir, 'Events', self.run_name, 'events.lhe.gz'))
3450 elif os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, 'events.lhe')):
3451 input_files.append(pjoin(self.me_dir, 'Events', self.run_name, 'events.lhe'))
3452 else:
3453 raise aMCatNLOError, 'Event file not present in %s' % \
3454 pjoin(self.me_dir, 'Events', self.run_name)
3455 else:
3456 input_files.append(pjoin(cwd, 'events_%s.lhe' % args[3]))
3457
3458 if len(args) == 3:
3459 output_files.append('mcatnlo_run.log')
3460 else:
3461 output_files.append('mcatnlo_run_%s.log' % args[3])
3462 if args[1] == 'HEP':
3463 if len(args) == 3:
3464 fname = 'events'
3465 else:
3466 fname = 'events_%s' % args[3]
3467 if shower in ['PYTHIA8', 'HERWIGPP']:
3468 output_files.append(fname + '.hepmc.gz')
3469 else:
3470 output_files.append(fname + '.hep.gz')
3471 elif args[1] == 'TOP' or args[1] == 'HWU':
3472 if len(args) == 3:
3473 fname = 'histfile'
3474 else:
3475 fname = 'histfile_%s' % args[3]
3476 output_files.append(fname + '.tar')
3477 else:
3478 raise aMCatNLOError, 'Not a valid output argument for shower job : %d' % args[1]
3479
3480 self.cluster.submit2(exe, args, cwd=cwd,
3481 input_files=input_files, output_files=output_files)
3482
3483 else:
3484 return self.cluster.submit(exe, args, cwd=cwd)
3485
3487
3488
3489
3490 keep_fourth_arg = False
3491 output_files = []
3492 required_output = []
3493 input_files = [pjoin(self.me_dir, 'SubProcesses', 'randinit'),
3494 pjoin(cwd, 'symfact.dat'),
3495 pjoin(cwd, 'iproc.dat'),
3496 pjoin(cwd, 'initial_states_map.dat'),
3497 pjoin(cwd, 'configs_and_props_info.dat'),
3498 pjoin(cwd, 'leshouche_info.dat'),
3499 pjoin(cwd, 'FKS_params.dat')]
3500
3501 if os.path.exists(pjoin(cwd,'nevents.tar')):
3502 input_files.append(pjoin(cwd,'nevents.tar'))
3503
3504 if os.path.exists(pjoin(self.me_dir,'SubProcesses','OLE_order.olc')):
3505 input_files.append(pjoin(cwd, 'OLE_order.olc'))
3506
3507
3508 if os.path.exists(pjoin(cwd,'MadLoop5_resources')) and \
3509 cluster.need_transfer(self.options):
3510 input_files.append(pjoin(cwd, 'MadLoop5_resources.tar.gz'))
3511 tf=tarfile.open(pjoin(cwd,'MadLoop5_resources.tar.gz'),'w:gz',
3512 dereference=True)
3513 tf.add(pjoin(cwd,'MadLoop5_resources'),arcname='MadLoop5_resources')
3514 tf.close()
3515
3516 Ire = re.compile("for i in ([\d\s]*) ; do")
3517 try :
3518 fsock = open(exe)
3519 except IOError:
3520 fsock = open(pjoin(cwd,exe))
3521 text = fsock.read()
3522 data = Ire.findall(text)
3523 subdir = ' '.join(data).split()
3524
3525 if args[0] == '0':
3526
3527 input_files.append(pjoin(cwd, 'madevent_mintFO'))
3528 input_files.append(pjoin(self.me_dir, 'SubProcesses','madin.%s' % args[1]))
3529
3530 for i in subdir:
3531 current = '%s_G%s' % (args[1],i)
3532 if os.path.exists(pjoin(cwd,current)):
3533 input_files.append(pjoin(cwd, current))
3534 output_files.append(current)
3535
3536 required_output.append('%s/results.dat' % current)
3537 required_output.append('%s/log.txt' % current)
3538 required_output.append('%s/mint_grids' % current)
3539 required_output.append('%s/grid.MC_integer' % current)
3540 if len(args) == 4:
3541 required_output.append('%s/scale_pdf_dependence.dat' % current)
3542 args[2] = '-1'
3543
3544 base = '%s_G%s' % (args[3],i)
3545 if args[0] == '0':
3546 to_move = ['grid.MC_integer','mint_grids']
3547 elif args[0] == '1':
3548 to_move = ['mint_grids', 'grid.MC_integer']
3549 else:
3550 to_move = []
3551 if self.run_card['iappl'] == 2:
3552 for grid in glob.glob(pjoin(cwd,base,'grid_obs_*_in.root')):
3553 to_move.append(grid)
3554 if not os.path.exists(pjoin(cwd,current)):
3555 os.mkdir(pjoin(cwd,current))
3556 input_files.append(pjoin(cwd, current))
3557 for name in to_move:
3558 files.cp(pjoin(cwd,base, name),
3559 pjoin(cwd,current))
3560 files.cp(pjoin(cwd,base, 'grid.MC_integer'),
3561 pjoin(cwd,current))
3562
3563 elif args[0] == '2':
3564
3565 input_files.append(pjoin(cwd, 'madevent_mintMC'))
3566 if args[2] in ['0','2']:
3567 input_files.append(pjoin(self.me_dir, 'SubProcesses','madinMMC_%s.2' % args[1]))
3568
3569 for i in subdir:
3570 current = 'G%s%s' % (args[1], i)
3571 if os.path.exists(pjoin(cwd,current)):
3572 input_files.append(pjoin(cwd, current))
3573 output_files.append(current)
3574 if len(args) == 4 and args[3] in ['H','S','V','B','F']:
3575
3576 base = '%s_%s' % (args[3],i)
3577 files.ln(pjoin(cwd,base,'mint_grids'), name = 'preset_mint_grids',
3578 starting_dir=pjoin(cwd,current))
3579 files.ln(pjoin(cwd,base,'grid.MC_integer'),
3580 starting_dir=pjoin(cwd,current))
3581 elif len(args) ==4:
3582 keep_fourth_arg = True
3583
3584 output_files.append('G%s%s_%s' % (args[1], i, args[3]))
3585 required_output.append('G%s%s_%s/log_MINT%s.txt' % (args[1], i, args[3],args[2]))
3586
3587 else:
3588 required_output.append('%s/log_MINT%s.txt' % (current,args[2]))
3589 if args[2] in ['0','1']:
3590 required_output.append('%s/results.dat' % current)
3591 if args[2] == '1':
3592 output_files.append('%s/results.dat' % current)
3593
3594 else:
3595 raise aMCatNLOError, 'not valid arguments: %s' %(', '.join(args))
3596
3597
3598 pdfinput = self.get_pdf_input_filename()
3599 if os.path.exists(pdfinput):
3600 input_files.append(pdfinput)
3601
3602 if len(args) == 4 and not keep_fourth_arg:
3603 args = args[:3]
3604
3605 return input_files, output_files, required_output, args
3606
3608 """writes the madinMMC_?.2 file"""
3609
3610 run_modes = ['born', 'virt', 'novi', 'all', 'viSB', 'novB']
3611 if run_mode not in run_modes:
3612 raise aMCatNLOError('%s is not a valid mode for run. Please use one of the following: %s' \
3613 % (run_mode, ', '.join(run_modes)))
3614 mint_modes = [0, 1, 2]
3615 if mint_mode not in mint_modes:
3616 raise aMCatNLOError('%s is not a valid mode for mintMC. Please use one of the following: %s' \
3617 % (mint_mode, ', '.join(mint_modes)))
3618 if run_mode in ['born']:
3619 name_suffix = 'B'
3620 elif run_mode in ['virt', 'viSB']:
3621 name_suffix = 'V'
3622 else:
3623 name_suffix = 'F'
3624
3625 content = \
3626 """-1 12 ! points, iterations
3627 0.03 ! desired fractional accuracy
3628 1 -0.1 ! alpha, beta for Gsoft
3629 -1 -0.1 ! alpha, beta for Gazi
3630 1 ! Suppress amplitude (0 no, 1 yes)?
3631 1 ! Exact helicity sum (0 yes, n = number/event)?
3632 1 ! Enter Configuration Number:
3633 %1d ! MINT imode: 0 to set-up grids, 1 to perform integral, 2 generate events
3634 1 1 1 ! if imode is 1: Folding parameters for xi_i, phi_i and y_ij
3635 %s ! all, born, real, virt
3636 """ \
3637 % (mint_mode, run_mode)
3638 file = open(pjoin(path, 'madinMMC_%s.2' % name_suffix), 'w')
3639 file.write(content)
3640 file.close()
3641
3642 - def write_madin_file(self, path, run_mode, vegas_mode, npoints, niters, accuracy='0'):
3643 """writes the madin.run_mode file"""
3644
3645 run_modes = ['born', 'virt', 'novi', 'all', 'viSB', 'novB', 'grid']
3646 if run_mode not in run_modes:
3647 raise aMCatNLOError('%s is not a valid mode for run. Please use one of the following: %s' \
3648 % (run_mode, ', '.join(run_modes)))
3649 name_suffix = run_mode
3650
3651 content = \
3652 """%s %s ! points, iterations
3653 %s ! accuracy
3654 2 ! 0 fixed grid 2 adjust
3655 1 ! 1 suppress amp, 0 doesnt
3656 1 ! 0 for exact hel sum
3657 1 ! hel configuration numb
3658 'test'
3659 1 ! 1 to save grids
3660 %s ! 0 to exclude, 1 for new run, 2 to restart, 3 to reset w/ keeping grid
3661 %s ! all, born, real, virt
3662 """ \
3663 % (npoints,niters,accuracy,vegas_mode,run_mode)
3664 file = open(pjoin(path, 'madin.%s' % name_suffix), 'w')
3665 file.write(content)
3666 file.close()
3667
3668 - def compile(self, mode, options):
3669 """compiles aMC@NLO to compute either NLO or NLO matched to shower, as
3670 specified in mode"""
3671
3672 os.mkdir(pjoin(self.me_dir, 'Events', self.run_name))
3673
3674 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name,
3675 '%s_%s_banner.txt' % (self.run_name, self.run_tag)))
3676
3677 self.get_characteristics(pjoin(self.me_dir,
3678 'SubProcesses', 'proc_characteristics'))
3679
3680
3681 amcatnlo_log = pjoin(self.me_dir, 'compile_amcatnlo.log')
3682 madloop_log = pjoin(self.me_dir, 'compile_madloop.log')
3683 reweight_log = pjoin(self.me_dir, 'compile_reweight.log')
3684 test_log = pjoin(self.me_dir, 'test.log')
3685
3686 self.update_status('Compiling the code', level=None, update_results=True)
3687
3688
3689 libdir = pjoin(self.me_dir, 'lib')
3690 sourcedir = pjoin(self.me_dir, 'Source')
3691
3692
3693 files.rm([amcatnlo_log, madloop_log, reweight_log, test_log])
3694
3695 if '+' in mode:
3696 mode = mode.split('+')[0]
3697 if mode in ['NLO', 'LO']:
3698 exe = 'madevent_mintFO'
3699 tests = ['test_ME']
3700 self.analyse_card.write_card(pjoin(self.me_dir, 'SubProcesses', 'analyse_opts'))
3701 elif mode in ['aMC@NLO', 'aMC@LO','noshower','noshowerLO']:
3702 exe = 'madevent_mintMC'
3703 tests = ['test_ME', 'test_MC']
3704
3705 open(pjoin(self.me_dir, 'SubProcesses', 'analyse_opts'),'w').write('FO_ANALYSE=analysis_dummy.o dbook.o open_output_files_dummy.o HwU_dummy.o\n')
3706
3707
3708 p_dirs = [d for d in \
3709 open(pjoin(self.me_dir, 'SubProcesses', 'subproc.mg')).read().split('\n') if d]
3710
3711 self.do_treatcards('', amcatnlo=True)
3712
3713
3714 if all([os.path.exists(pjoin(self.me_dir, 'SubProcesses', p_dir, exe)) \
3715 for p_dir in p_dirs]) and options['nocompile']:
3716 return
3717
3718
3719 if os.path.exists(pjoin(libdir, 'PDFsets')):
3720 files.rm(pjoin(libdir, 'PDFsets'))
3721
3722
3723 if self.run_card['pdlabel'] == 'lhapdf' and \
3724 (self.banner.get_detail('run_card', 'lpp1') != 0 or \
3725 self.banner.get_detail('run_card', 'lpp2') != 0):
3726
3727 self.link_lhapdf(libdir, [pjoin('SubProcesses', p) for p in p_dirs])
3728 pdfsetsdir = self.get_lhapdf_pdfsetsdir()
3729 lhaid_list = [int(self.run_card['lhaid'])]
3730 if self.run_card['reweight_PDF']:
3731 lhaid_list.append(int(self.run_card['PDF_set_min']))
3732 lhaid_list.append(int(self.run_card['PDF_set_max']))
3733 self.copy_lhapdf_set(lhaid_list, pdfsetsdir)
3734
3735 else:
3736 if self.run_card['lpp1'] == 1 == self.run_card['lpp2']:
3737 logger.info('Using built-in libraries for PDFs')
3738 if self.run_card['lpp1'] == 0 == self.run_card['lpp2']:
3739 logger.info('Lepton-Lepton collision: Ignoring \'pdlabel\' and \'lhaid\' in the run_card.')
3740 try:
3741 del os.environ['lhapdf']
3742 except KeyError:
3743 pass
3744
3745
3746 if self.run_card['iappl'] != 0:
3747 os.environ['applgrid'] = 'True'
3748
3749 for code in ['applgrid','amcfast']:
3750 try:
3751 p = subprocess.Popen([self.options[code], '--version'], \
3752 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
3753 except OSError:
3754 raise aMCatNLOError(('No valid %s installation found. \n' + \
3755 'Please set the path to %s-config by using \n' + \
3756 'MG5_aMC> set <absolute-path-to-%s>/bin/%s-config \n') % (code,code,code,code))
3757 else:
3758 output, _ = p.communicate()
3759 if code is 'applgrid' and output < '1.4.63':
3760 raise aMCatNLOError('Version of APPLgrid is too old. Use 1.4.69 or later.'\
3761 +' You are using %s',output)
3762 if code is 'amcfast' and output < '1.1.1':
3763 raise aMCatNLOError('Version of aMCfast is too old. Use 1.1.1 or later.'\
3764 +' You are using %s',output)
3765
3766
3767 appllibs=" APPLLIBS=$(shell %s --ldflags) $(shell %s --ldcflags) \n" \
3768 % (self.options['amcfast'],self.options['applgrid'])
3769 text=open(pjoin(self.me_dir,'Source','make_opts'),'r').readlines()
3770 text_out=[]
3771 for line in text:
3772 if line.strip().startswith('APPLLIBS=$'):
3773 line=appllibs
3774 text_out.append(line)
3775 open(pjoin(self.me_dir,'Source','make_opts'),'w').writelines(text_out)
3776 else:
3777 try:
3778 del os.environ['applgrid']
3779 except KeyError:
3780 pass
3781
3782 try:
3783 os.environ['fastjet_config'] = self.options['fastjet']
3784 except (TypeError, KeyError):
3785 if 'fastjet_config' in os.environ:
3786 del os.environ['fastjet_config']
3787 os.unsetenv('fastjet_config')
3788
3789
3790 self.update_status('Compiling source...', level=None)
3791 misc.compile(['clean4pdf'], cwd = sourcedir)
3792 misc.compile(cwd = sourcedir)
3793 if os.path.exists(pjoin(libdir, 'libdhelas.a')) \
3794 and os.path.exists(pjoin(libdir, 'libgeneric.a')) \
3795 and os.path.exists(pjoin(libdir, 'libmodel.a')) \
3796 and os.path.exists(pjoin(libdir, 'libpdf.a')):
3797 logger.info(' ...done, continuing with P* directories')
3798 else:
3799 raise aMCatNLOError('Compilation failed')
3800
3801
3802 MCatNLO_libdir = pjoin(self.me_dir, 'MCatNLO', 'lib')
3803 if not os.path.exists(os.path.realpath(pjoin(MCatNLO_libdir, 'libstdhep.a'))) or \
3804 not os.path.exists(os.path.realpath(pjoin(MCatNLO_libdir, 'libFmcfio.a'))):
3805 if os.path.exists(pjoin(sourcedir,'StdHEP')):
3806 logger.info('Compiling StdHEP (can take a couple of minutes) ...')
3807 misc.compile(['StdHEP'], cwd = sourcedir)
3808 logger.info(' ...done.')
3809 else:
3810 raise aMCatNLOError('Could not compile StdHEP because its'+\
3811 ' source directory could not be found in the SOURCE folder.\n'+\
3812 " Check the MG5_aMC option 'output_dependencies.'")
3813
3814
3815 if not os.path.exists(os.path.realpath(pjoin(libdir, 'libcts.a'))) or \
3816 not os.path.exists(os.path.realpath(pjoin(libdir, 'mpmodule.mod'))):
3817 if os.path.exists(pjoin(sourcedir,'CutTools')):
3818 logger.info('Compiling CutTools (can take a couple of minutes) ...')
3819 misc.compile(['CutTools'], cwd = sourcedir)
3820 logger.info(' ...done.')
3821 else:
3822 raise aMCatNLOError('Could not compile CutTools because its'+\
3823 ' source directory could not be found in the SOURCE folder.\n'+\
3824 " Check the MG5_aMC option 'output_dependencies.'")
3825 if not os.path.exists(os.path.realpath(pjoin(libdir, 'libcts.a'))) or \
3826 not os.path.exists(os.path.realpath(pjoin(libdir, 'mpmodule.mod'))):
3827 raise aMCatNLOError('CutTools compilation failed.')
3828
3829
3830
3831 compiler_log_path = pjoin(os.path.dirname((os.path.realpath(pjoin(
3832 libdir, 'libcts.a')))),'compiler_version.log')
3833 if os.path.exists(compiler_log_path):
3834 compiler_version_used = open(compiler_log_path,'r').read()
3835 if not str(misc.get_gfortran_version(misc.detect_current_compiler(\
3836 pjoin(sourcedir,'make_opts')))) in compiler_version_used:
3837 if os.path.exists(pjoin(sourcedir,'CutTools')):
3838 logger.info('CutTools was compiled with a different fortran'+\
3839 ' compiler. Re-compiling it now...')
3840 misc.compile(['cleanCT'], cwd = sourcedir)
3841 misc.compile(['CutTools'], cwd = sourcedir)
3842 logger.info(' ...done.')
3843 else:
3844 raise aMCatNLOError("CutTools installation in %s"\
3845 %os.path.realpath(pjoin(libdir, 'libcts.a'))+\
3846 " seems to have been compiled with a different compiler than"+\
3847 " the one specified in MG5_aMC. Please recompile CutTools.")
3848
3849
3850 if not os.path.exists(os.path.realpath(pjoin(libdir, 'libiregi.a'))) \
3851 and os.path.exists(pjoin(sourcedir,'IREGI')):
3852 logger.info('Compiling IREGI (can take a couple of minutes) ...')
3853 misc.compile(['IREGI'], cwd = sourcedir)
3854 logger.info(' ...done.')
3855
3856 if os.path.exists(pjoin(libdir, 'libiregi.a')):
3857
3858
3859 compiler_log_path = pjoin(os.path.dirname((os.path.realpath(pjoin(
3860 libdir, 'libiregi.a')))),'compiler_version.log')
3861 if os.path.exists(compiler_log_path):
3862 compiler_version_used = open(compiler_log_path,'r').read()
3863 if not str(misc.get_gfortran_version(misc.detect_current_compiler(\
3864 pjoin(sourcedir,'make_opts')))) in compiler_version_used:
3865 if os.path.exists(pjoin(sourcedir,'IREGI')):
3866 logger.info('IREGI was compiled with a different fortran'+\
3867 ' compiler. Re-compiling it now...')
3868 misc.compile(['cleanIR'], cwd = sourcedir)
3869 misc.compile(['IREGI'], cwd = sourcedir)
3870 logger.info(' ...done.')
3871 else:
3872 raise aMCatNLOError("IREGI installation in %s"\
3873 %os.path.realpath(pjoin(libdir, 'libiregi.a'))+\
3874 " seems to have been compiled with a different compiler than"+\
3875 " the one specified in MG5_aMC. Please recompile IREGI.")
3876
3877
3878 if self.proc_characteristics['has_loops'] and \
3879 not os.path.exists(pjoin(self.me_dir,'OLP_virtuals')):
3880 os.environ['madloop'] = 'true'
3881 if mode in ['NLO', 'aMC@NLO', 'noshower']:
3882 tests.append('check_poles')
3883 else:
3884 os.unsetenv('madloop')
3885
3886
3887 self.update_status('Compiling directories...', level=None)
3888
3889 for test in tests:
3890 self.write_test_input(test)
3891
3892 try:
3893 import multiprocessing
3894 if not self.nb_core:
3895 try:
3896 self.nb_core = int(self.options['nb_core'])
3897 except TypeError:
3898 self.nb_core = multiprocessing.cpu_count()
3899 except ImportError:
3900 self.nb_core = 1
3901
3902 compile_options = copy.copy(self.options)
3903 compile_options['nb_core'] = self.nb_core
3904 compile_cluster = cluster.MultiCore(**compile_options)
3905 logger.info('Compiling on %d cores' % self.nb_core)
3906
3907 update_status = lambda i, r, f: self.donothing(i,r,f)
3908 for p_dir in p_dirs:
3909 compile_cluster.submit(prog = compile_dir,
3910 argument = [self.me_dir, p_dir, mode, options,
3911 tests, exe, self.options['run_mode']])
3912 try:
3913 compile_cluster.wait(self.me_dir, update_status)
3914 except Exception, error:
3915 logger.warning("Fail to compile the Subprocesses")
3916 if __debug__:
3917 raise
3918 compile_cluster.remove()
3919 self.do_quit('')
3920
3921 logger.info('Checking test output:')
3922 for p_dir in p_dirs:
3923 logger.info(p_dir)
3924 for test in tests:
3925 logger.info(' Result for %s:' % test)
3926
3927 this_dir = pjoin(self.me_dir, 'SubProcesses', p_dir)
3928
3929 self.check_tests(test, this_dir)
3930
3931
3934
3935
3937 """just call the correct parser for the test log.
3938 Skip check_poles for LOonly folders"""
3939 if test in ['test_ME', 'test_MC']:
3940 return self.parse_test_mx_log(pjoin(dir, '%s.log' % test))
3941 elif test == 'check_poles' and not os.path.exists(pjoin(dir,'parton_lum_0.f')):
3942 return self.parse_check_poles_log(pjoin(dir, '%s.log' % test))
3943
3944
3946 """read and parse the test_ME/MC.log file"""
3947 content = open(log).read()
3948 if 'FAILED' in content:
3949 logger.info('Output of the failing test:\n'+content[:-1],'$MG:color:BLACK')
3950 raise aMCatNLOError('Some tests failed, run cannot continue.\n' + \
3951 'Please check that widths of final state particles (e.g. top) have been' + \
3952 ' set to 0 in the param_card.dat.')
3953 else:
3954 lines = [l for l in content.split('\n') if 'PASSED' in l]
3955 logger.info(' Passed.')
3956 logger.debug('\n'+'\n'.join(lines))
3957
3958
3960 """reads and parse the check_poles.log file"""
3961 content = open(log).read()
3962 npass = 0
3963 nfail = 0
3964 for line in content.split('\n'):
3965 if 'PASSED' in line:
3966 npass +=1
3967 tolerance = float(line.split()[1])
3968 if 'FAILED' in line:
3969 nfail +=1
3970 tolerance = float(line.split()[1])
3971
3972 if nfail + npass == 0:
3973 logger.warning('0 points have been tried')
3974 return
3975
3976 if float(nfail)/float(nfail+npass) > 0.1:
3977 raise aMCatNLOError('Poles do not cancel, run cannot continue')
3978 else:
3979 logger.info(' Poles successfully cancel for %d points over %d (tolerance=%2.1e)' \
3980 %(npass, nfail+npass, tolerance))
3981
3982
4003
4004
4005
4006
4008 """ return the model name """
4009 if hasattr(self, 'model_name'):
4010 return self.model_name
4011
4012 model = 'sm'
4013 proc = []
4014 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')):
4015 line = line.split('#')[0]
4016
4017 if line.startswith('import') and 'model' in line:
4018 model = line.split()[2]
4019 proc = []
4020 elif line.startswith('generate'):
4021 proc.append(line.split(None,1)[1])
4022 elif line.startswith('add process'):
4023 proc.append(line.split(None,2)[2])
4024
4025 self.model = model
4026 self.process = proc
4027 return model
4028
4029
4030
4031
4033 """Ask the question when launching generate_events/multi_run"""
4034
4035 if 'parton' not in options:
4036 options['parton'] = False
4037 if 'reweightonly' not in options:
4038 options['reweightonly'] = False
4039
4040
4041 void = 'NOT INSTALLED'
4042 switch_order = ['order', 'fixed_order', 'shower','madspin', 'reweight']
4043 switch_default = {'order': 'NLO', 'fixed_order': 'OFF', 'shower': void,
4044 'madspin': void}
4045 if not switch:
4046 switch = switch_default
4047 else:
4048 switch.update(dict((k,value) for k,v in switch_default.items() if k not in switch))
4049
4050 default_switch = ['ON', 'OFF']
4051 allowed_switch_value = {'order': ['LO', 'NLO'],
4052 'fixed_order': default_switch,
4053 'shower': default_switch,
4054 'madspin': default_switch,
4055 'reweight': default_switch}
4056
4057 description = {'order': 'Perturbative order of the calculation:',
4058 'fixed_order': 'Fixed order (no event generation and no MC@[N]LO matching):',
4059 'shower': 'Shower the generated events:',
4060 'madspin': 'Decay particles with the MadSpin module:',
4061 'reweight': 'Add weights to the events based on changing model parameters:'}
4062
4063 force_switch = {('shower', 'ON'): {'fixed_order': 'OFF'},
4064 ('madspin', 'ON'): {'fixed_order':'OFF'},
4065 ('reweight', 'ON'): {'fixed_order':'OFF'},
4066 ('fixed_order', 'ON'): {'shower': 'OFF', 'madspin': 'OFF', 'reweight':'OFF'}
4067 }
4068 special_values = ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'noshower', 'noshowerLO']
4069
4070 assign_switch = lambda key, value: switch.__setitem__(key, value if switch[key] != void else void )
4071
4072
4073 if mode == 'auto':
4074 mode = None
4075 if not mode and (options['parton'] or options['reweightonly']):
4076 mode = 'noshower'
4077
4078
4079 available_mode = ['0', '1', '2']
4080 available_mode.append('3')
4081 if os.path.exists(pjoin(self.me_dir, 'Cards', 'shower_card.dat')):
4082 switch['shower'] = 'ON'
4083 else:
4084 switch['shower'] = 'OFF'
4085
4086 if not aMCatNLO or self.options['mg5_path']:
4087 available_mode.append('4')
4088 if os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')):
4089 switch['madspin'] = 'ON'
4090 else:
4091 switch['madspin'] = 'OFF'
4092 if misc.has_f2py() or self.options['f2py_compiler']:
4093 available_mode.append('5')
4094 if os.path.exists(pjoin(self.me_dir,'Cards','reweight_card.dat')):
4095 switch['reweight'] = 'ON'
4096 else:
4097 switch['reweight'] = 'OFF'
4098 else:
4099 switch['reweight'] = 'Not available (requires NumPy)'
4100
4101
4102 if 'do_reweight' in options and options['do_reweight']:
4103 if switch['reweight'] == "OFF":
4104 switch['reweight'] = "ON"
4105 elif switch['reweight'] != "ON":
4106 logger.critical("Cannot run REWEIGHT: %s" % switch['reweight'])
4107 if 'do_madspin' in options and options['do_madspin']:
4108 if switch['madspin'] == "OFF":
4109 switch['madspin'] = 'ON'
4110 elif switch['madspin'] != "ON":
4111 logger.critical("Cannot run MadSpin module: %s" % switch['reweight'])
4112
4113
4114 answers = list(available_mode) + ['auto', 'done']
4115 alias = {}
4116 for id, key in enumerate(switch_order):
4117 if switch[key] != void and switch[key] in allowed_switch_value[key]:
4118 answers += ['%s=%s' % (key, s) for s in allowed_switch_value[key]]
4119
4120 alias.update(dict(('%s=%s' % (key, s.lower()), '%s=%s' % (key, s))
4121 for s in allowed_switch_value[key]))
4122 answers += special_values
4123
4124 def create_question(switch):
4125 switch_format = " %i %-61s %12s=%s\n"
4126 question = "The following switches determine which operations are executed:\n"
4127 for id, key in enumerate(switch_order):
4128 question += switch_format % (id+1, description[key], key, switch[key])
4129 question += ' Either type the switch number (1 to %s) to change its default setting,\n' % (id+1)
4130 question += ' or set any switch explicitly (e.g. type \'order=LO\' at the prompt)\n'
4131 question += ' Type \'0\', \'auto\', \'done\' or just press enter when you are done.\n'
4132 return question
4133
4134
4135 def modify_switch(mode, answer, switch):
4136 if '=' in answer:
4137 key, status = answer.split('=')
4138 switch[key] = status
4139 if (key, status) in force_switch:
4140 for key2, status2 in force_switch[(key, status)].items():
4141 if switch[key2] not in [status2, void]:
4142 logger.info('For coherence \'%s\' is set to \'%s\''
4143 % (key2, status2), '$MG:color:BLACK')
4144 switch[key2] = status2
4145 elif answer in ['0', 'auto', 'done']:
4146 return
4147 elif answer in special_values:
4148 logger.info('Enter mode value: Go to the related mode', '$MG:color:BLACK')
4149
4150
4151 if answer == 'LO':
4152 switch['order'] = 'LO'
4153 switch['fixed_order'] = 'ON'
4154 assign_switch('shower', 'OFF')
4155 elif answer == 'NLO':
4156 switch['order'] = 'NLO'
4157 switch['fixed_order'] = 'ON'
4158 assign_switch('shower', 'OFF')
4159 elif answer == 'aMC@NLO':
4160 switch['order'] = 'NLO'
4161 switch['fixed_order'] = 'OFF'
4162 assign_switch('shower', 'ON')
4163 elif answer == 'aMC@LO':
4164 switch['order'] = 'LO'
4165 switch['fixed_order'] = 'OFF'
4166 assign_switch('shower', 'ON')
4167 elif answer == 'noshower':
4168 switch['order'] = 'NLO'
4169 switch['fixed_order'] = 'OFF'
4170 assign_switch('shower', 'OFF')
4171 elif answer == 'noshowerLO':
4172 switch['order'] = 'LO'
4173 switch['fixed_order'] = 'OFF'
4174 assign_switch('shower', 'OFF')
4175 if mode:
4176 return
4177 return switch
4178
4179
4180 modify_switch(mode, self.last_mode, switch)
4181 if switch['madspin'] == 'OFF' and os.path.exists(pjoin(self.me_dir,'Cards','madspin_card.dat')):
4182 assign_switch('madspin', 'ON')
4183
4184 if not self.force:
4185 answer = ''
4186 while answer not in ['0', 'done', 'auto', 'onlyshower']:
4187 question = create_question(switch)
4188 if mode:
4189 answer = mode
4190 else:
4191 answer = self.ask(question, '0', answers, alias=alias)
4192 if answer.isdigit() and answer != '0':
4193 key = switch_order[int(answer) - 1]
4194 opt1 = allowed_switch_value[key][0]
4195 opt2 = allowed_switch_value[key][1]
4196 answer = '%s=%s' % (key, opt1 if switch[key] == opt2 else opt2)
4197
4198 if not modify_switch(mode, answer, switch):
4199 break
4200
4201
4202 if not mode or mode == 'auto':
4203 if switch['order'] == 'LO':
4204 if switch['shower'] == 'ON':
4205 mode = 'aMC@LO'
4206 elif switch['fixed_order'] == 'ON':
4207 mode = 'LO'
4208 else:
4209 mode = 'noshowerLO'
4210 elif switch['order'] == 'NLO':
4211 if switch['shower'] == 'ON':
4212 mode = 'aMC@NLO'
4213 elif switch['fixed_order'] == 'ON':
4214 mode = 'NLO'
4215 else:
4216 mode = 'noshower'
4217 logger.info('will run in mode: %s' % mode)
4218
4219 if mode == 'noshower':
4220 logger.warning("""You have chosen not to run a parton shower. NLO events without showering are NOT physical.
4221 Please, shower the Les Houches events before using them for physics analyses.""")
4222
4223
4224
4225 cards = ['param_card.dat', 'run_card.dat']
4226 ignore = []
4227 if mode in ['LO', 'NLO']:
4228 options['parton'] = True
4229 ignore = ['shower_card.dat', 'madspin_card.dat']
4230 cards.append('FO_analyse_card.dat')
4231 else:
4232 if switch['madspin'] == 'ON':
4233 cards.append('madspin_card.dat')
4234 if switch['reweight'] == 'ON':
4235 cards.append('reweight_card.dat')
4236 if 'aMC@' in mode:
4237 cards.append('shower_card.dat')
4238 if mode == 'onlyshower':
4239 cards = ['shower_card.dat']
4240 if options['reweightonly']:
4241 cards = ['run_card.dat']
4242
4243 self.keep_cards(cards, ignore)
4244
4245 if mode =='onlyshower':
4246 cards = ['shower_card.dat']
4247
4248 if not options['force'] and not self.force:
4249 self.ask_edit_cards(cards, plot=False)
4250
4251 self.banner = banner_mod.Banner()
4252
4253
4254 for card in cards:
4255 self.banner.add(pjoin(self.me_dir, 'Cards', card))
4256
4257 run_settings = '\n'.join(['%s = %s' % (k, v) for (k, v) in switch.items()])
4258 self.banner.add_text('run_settings', run_settings)
4259
4260 if not mode =='onlyshower':
4261 self.run_card = self.banner.charge_card('run_card')
4262 self.run_tag = self.run_card['run_tag']
4263
4264 if not hasattr(self, 'run_name') or not self.run_name:
4265 self.run_name = self.find_available_run_name(self.me_dir)
4266
4267 if self.run_name.startswith('run_'):
4268 if mode in ['LO','aMC@LO','noshowerLO']:
4269 self.run_name += '_LO'
4270 self.set_run_name(self.run_name, self.run_tag, 'parton')
4271 if int(self.run_card['ickkw']) == 3 and mode in ['LO', 'aMC@LO', 'noshowerLO']:
4272 raise self.InvalidCmd("""FxFx merging (ickkw=3) not allowed at LO""")
4273 elif int(self.run_card['ickkw']) == 3 and mode in ['aMC@NLO', 'noshower']:
4274 logger.warning("""You are running with FxFx merging enabled. To be able to merge
4275 samples of various multiplicities without double counting, you
4276 have to remove some events after showering 'by hand'. Please
4277 read http://amcatnlo.cern.ch/FxFx_merging.htm for more details.""")
4278 if self.run_card['parton_shower'].upper() == 'PYTHIA6Q':
4279 raise self.InvalidCmd("""FxFx merging does not work with Q-squared ordered showers.""")
4280 elif self.run_card['parton_shower'].upper() != 'HERWIG6' and self.run_card['parton_shower'].upper() != 'PYTHIA8':
4281 question="FxFx merging not tested for %s shower. Do you want to continue?\n" % self.run_card['parton_shower'] + \
4282 "Type \'n\' to stop or \'y\' to continue"
4283 answers = ['n','y']
4284 answer = self.ask(question, 'n', answers, alias=alias)
4285 if answer == 'n':
4286 error = '''Stop opertation'''
4287 self.ask_run_configuration(mode, options)
4288
4289 elif int(self.run_card['ickkw']) == -1 and mode in ['aMC@NLO', 'noshower']:
4290
4291 raise self.InvalidCmd("""NNLL+NLO jet veto runs (ickkw=-1) only possible for fNLO or LO.""")
4292 if 'aMC@' in mode or mode == 'onlyshower':
4293 self.shower_card = self.banner.charge_card('shower_card')
4294
4295 elif mode in ['LO', 'NLO']:
4296 analyse_card_path = pjoin(self.me_dir, 'Cards','FO_analyse_card.dat')
4297 self.analyse_card = self.banner.charge_card('FO_analyse_card')
4298
4299
4300 return mode
4301
4302
4303
4304
4305
4307 """The command line processor of MadGraph"""
4308
4309 _compile_usage = "compile [MODE] [options]\n" + \
4310 "-- compiles aMC@NLO \n" + \
4311 " MODE can be either FO, for fixed-order computations, \n" + \
4312 " or MC for matching with parton-shower monte-carlos. \n" + \
4313 " (if omitted, it is set to MC)\n"
4314 _compile_parser = misc.OptionParser(usage=_compile_usage)
4315 _compile_parser.add_option("-f", "--force", default=False, action='store_true',
4316 help="Use the card present in the directory for the launch, without editing them")
4317
4318 _launch_usage = "launch [MODE] [options]\n" + \
4319 "-- execute aMC@NLO \n" + \
4320 " MODE can be either LO, NLO, aMC@NLO or aMC@LO (if omitted, it is asked in a separate question)\n" + \
4321 " If mode is set to LO/NLO, no event generation will be performed, but only the \n" + \
4322 " computation of the total cross-section and the filling of parton-level histograms \n" + \
4323 " specified in the DIRPATH/SubProcesses/madfks_plot.f file.\n" + \
4324 " If mode is set to aMC@LO/aMC@NLO, after the cross-section computation, a .lhe \n" + \
4325 " event file is generated which will be showered with the MonteCarlo specified \n" + \
4326 " in the run_card.dat\n"
4327
4328 _launch_parser = misc.OptionParser(usage=_launch_usage)
4329 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
4330 help="Use the card present in the directory for the launch, without editing them")
4331 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
4332 help="Submit the jobs on the cluster")
4333 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
4334 help="Submit the jobs on multicore mode")
4335 _launch_parser.add_option("-x", "--nocompile", default=False, action='store_true',
4336 help="Skip compilation. Ignored if no executable is found")
4337 _launch_parser.add_option("-r", "--reweightonly", default=False, action='store_true',
4338 help="Skip integration and event generation, just run reweight on the" + \
4339 " latest generated event files (see list in SubProcesses/nevents_unweighted)")
4340 _launch_parser.add_option("-p", "--parton", default=False, action='store_true',
4341 help="Stop the run after the parton level file generation (you need " + \
4342 "to shower the file in order to get physical results)")
4343 _launch_parser.add_option("-o", "--only_generation", default=False, action='store_true',
4344 help="Skip grid set up, just generate events starting from " + \
4345 "the last available results")
4346 _launch_parser.add_option("-n", "--name", default=False, dest='run_name',
4347 help="Provide a name to the run")
4348 _launch_parser.add_option("-a", "--appl_start_grid", default=False, dest='appl_start_grid',
4349 help="For use with APPLgrid only: start from existing grids")
4350 _launch_parser.add_option("-R", "--reweight", default=False, dest='do_reweight', action='store_true',
4351 help="Run the reweight module (reweighting by different model parameter")
4352 _launch_parser.add_option("-M", "--madspin", default=False, dest='do_madspin', action='store_true',
4353 help="Run the madspin package")
4354
4355
4356
4357 _generate_events_usage = "generate_events [MODE] [options]\n" + \
4358 "-- execute aMC@NLO \n" + \
4359 " MODE can be either LO, NLO, aMC@NLO or aMC@LO (if omitted, it is asked in a separate question)\n" + \
4360 " If mode is set to LO/NLO, no event generation will be performed, but only the \n" + \
4361 " computation of the total cross-section and the filling of parton-level histograms \n" + \
4362 " specified in the DIRPATH/SubProcesses/madfks_plot.f file.\n" + \
4363 " If mode is set to aMC@LO/aMC@NLO, after the cross-section computation, a .lhe \n" + \
4364 " event file is generated which will be showered with the MonteCarlo specified \n" + \
4365 " in the run_card.dat\n"
4366
4367 _generate_events_parser = misc.OptionParser(usage=_generate_events_usage)
4368 _generate_events_parser.add_option("-f", "--force", default=False, action='store_true',
4369 help="Use the card present in the directory for the generate_events, without editing them")
4370 _generate_events_parser.add_option("-c", "--cluster", default=False, action='store_true',
4371 help="Submit the jobs on the cluster")
4372 _generate_events_parser.add_option("-m", "--multicore", default=False, action='store_true',
4373 help="Submit the jobs on multicore mode")
4374 _generate_events_parser.add_option("-x", "--nocompile", default=False, action='store_true',
4375 help="Skip compilation. Ignored if no executable is found")
4376 _generate_events_parser.add_option("-r", "--reweightonly", default=False, action='store_true',
4377 help="Skip integration and event generation, just run reweight on the" + \
4378 " latest generated event files (see list in SubProcesses/nevents_unweighted)")
4379 _generate_events_parser.add_option("-p", "--parton", default=False, action='store_true',
4380 help="Stop the run after the parton level file generation (you need " + \
4381 "to shower the file in order to get physical results)")
4382 _generate_events_parser.add_option("-o", "--only_generation", default=False, action='store_true',
4383 help="Skip grid set up, just generate events starting from " + \
4384 "the last available results")
4385 _generate_events_parser.add_option("-n", "--name", default=False, dest='run_name',
4386 help="Provide a name to the run")
4387
4388
4389
4390 _calculate_xsect_usage = "calculate_xsect [ORDER] [options]\n" + \
4391 "-- calculate cross-section up to ORDER.\n" + \
4392 " ORDER can be either LO or NLO (if omitted, it is set to NLO). \n"
4393
4394 _calculate_xsect_parser = misc.OptionParser(usage=_calculate_xsect_usage)
4395 _calculate_xsect_parser.add_option("-f", "--force", default=False, action='store_true',
4396 help="Use the card present in the directory for the launch, without editing them")
4397 _calculate_xsect_parser.add_option("-c", "--cluster", default=False, action='store_true',
4398 help="Submit the jobs on the cluster")
4399 _calculate_xsect_parser.add_option("-m", "--multicore", default=False, action='store_true',
4400 help="Submit the jobs on multicore mode")
4401 _calculate_xsect_parser.add_option("-x", "--nocompile", default=False, action='store_true',
4402 help="Skip compilation. Ignored if no executable is found")
4403 _calculate_xsect_parser.add_option("-n", "--name", default=False, dest='run_name',
4404 help="Provide a name to the run")
4405 _calculate_xsect_parser.add_option("-a", "--appl_start_grid", default=False, dest='appl_start_grid',
4406 help="For use with APPLgrid only: start from existing grids")
4407 _calculate_xsect_parser.add_option("-o", "--only_generation", default=False, action='store_true',
4408 help="Skip grid set up, just generate events starting from " + \
4409 "the last available results")
4410
4411 _shower_usage = 'shower run_name [options]\n' + \
4412 '-- do shower/hadronization on parton-level file generated for run run_name\n' + \
4413 ' all the information (e.g. number of events, MonteCarlo, ...\n' + \
4414 ' are directly read from the header of the event file\n'
4415 _shower_parser = misc.OptionParser(usage=_shower_usage)
4416 _shower_parser.add_option("-f", "--force", default=False, action='store_true',
4417 help="Use the shower_card present in the directory for the launch, without editing")
4418