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