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