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