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