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