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