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