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