1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """A user friendly command line interface to access all MadGraph5_aMC@NLO features.
16 Uses the cmd package for command interpretation and tab completion.
17 """
18
19
20 from __future__ import absolute_import
21 import atexit
22 import logging
23 import optparse
24 import os
25 import pydoc
26 import re
27 import subprocess
28 import sys
29 import traceback
30 import time
31
32 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
33 root_path = os.path.split(root_path)[0]
34 sys.path.insert(0, root_path)
35
36
37 pjoin = os.path.join
38
39 import madgraph
40 import madgraph.core.diagram_generation as diagram_generation
41 import madgraph.core.helas_objects as helas_objects
42 import madgraph.loop.loop_base_objects as loop_base_objects
43 import madgraph.interface.extended_cmd as cmd
44 import madgraph.interface.madgraph_interface as MGcmd
45 import madgraph.interface.loop_interface as LoopCmd
46 import madgraph.interface.amcatnlo_interface as amcatnloCmd
47 import madgraph.fks.fks_base as fks_base
48 import madgraph.iolibs.files as files
49 import madgraph.various.misc as misc
50
51 from madgraph import MG4DIR, MG5DIR, MadGraph5Error, InvalidCmd
52
53 logger = logging.getLogger('cmdprint')
57 """ Helping class containing all the switching routine """
58
59 - def __init__(self, main='MadGraph', *args, **opt):
64
65 interface_names= {'MadGraph':('MG5_aMC',MGcmd.MadGraphCmd),
66 'MadLoop':('MG5_aMC',LoopCmd.LoopInterface),
67 'aMC@NLO':('MG5_aMC',amcatnloCmd.aMCatNLOInterface)}
68
69 _switch_opts = list(interface_names.keys())
70 current_interface = None
71
72
73
74 - def setup(self, *args, **opts):
75 """ Function to initialize the interface when switched to it. It is not
76 the same as __init__ as this latter functions would call its mother
77 from madgraph_interface and this is only desirable for the first
78 initialization when launching MG5 """
79 return self.cmd.setup(self, *args, **opts)
80
82 """redefine all the command to call directly the appropriate child"""
83
84 if hasattr(self, 'plugin') and self.plugin:
85 return True
86
87 correct = True
88
89
90 overwritable = []
91
92 self.to_preserve = [key for key,method in Switcher.__dict__.items() if
93 hasattr(method, '__call__') ]
94 self.to_preserve += ['do_shell', 'help_shell', 'complete_shell']
95
96 ff = open(pjoin(os.getcwd(), 'additional_command'), 'w')
97
98 for key in dir(self):
99
100 if key in self.to_preserve:
101 continue
102 if not (key.startswith('do_') or key.startswith('complete_') or \
103 key.startswith('help_') or key.startswith('check_') or \
104 key in overwritable):
105 continue
106 text = """\
107 def %(key)s(self, *args, **opts):
108 return self.cmd.%(key)s(self, *args, **opts)
109
110 """ % {'key': key}
111 logger.warning("""Command %s not define in the Master.
112 The line to add to the master_interface.py are written in 'additional_command' file""" % key)
113 ff.write(text)
114 correct = False
115
116
117
118
119 define = {}
120 for mother in MasterCmd.__mro__:
121 if mother.__name__ in ['OriginalCmd', 'BasicCmd', 'CmdExtended', 'Cmd']:
122 continue
123
124
125 for data in mother.__dict__:
126
127 if data in Switcher.__dict__ or data.startswith('__'):
128 continue
129 if data in MasterCmd.__dict__:
130
131 continue
132 if data not in define:
133 define[data] = mother.__name__
134 else:
135 logger.warning('%s define in %s and in %s but not in Switcher.' % (data, define[data], mother.__name__))
136 correct = False
137
138
139 define = {}
140 for mother in MasterCmdWeb.__mro__:
141 if mother.__name__ in ['OriginalCmd', 'BasicCmd', 'CmdExtended', 'Cmd']:
142 continue
143 for data in mother.__dict__:
144
145 if data in Switcher.__dict__ or data.startswith('__'):
146 continue
147 if data in MasterCmdWeb.__dict__:
148
149 continue
150 if data not in define:
151 define[data] = mother.__name__
152 else:
153 logger.warning('%s define in %s and in %s but not in Switcher.' % (data, define[data], mother.__name__))
154 correct = False
155
156 if not correct:
157 raise Exception('The Cmd interface has dangerous features. Please see previous warnings and correct those.')
158
159
160
161 @staticmethod
163 """Extract from a string what is the type of the computation. This
164 returns a tuple (mode, option, pert_orders) where mode can be either 'NLO' or 'tree'
165 and option 'all', 'real' or 'virt'."""
166
167
168
169 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
170 line2 = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
171
172
173
174
175 loopRE = re.compile(r"^(.*)(?P<loop>\[(\s*(?P<option>\w+)\s*=)?(?P<orders>.+)?\])(.*)$")
176
177 res=loopRE.search(re.split('%s\-\-', line,1)[0])
178 if res:
179 orders=res.group('orders').split() if res.group('orders') else []
180 if res.group('option') and len(res.group('option').split())==1:
181 if res.group('option').split()[0]=='tree':
182 return ('tree',res.group('option').split()[0],orders)
183 else:
184 return ('NLO',res.group('option').split()[0],orders)
185 else:
186
187
188
189 if orders == ['LOonly']:
190 return ('NLO', 'LOonly', ['QCD'])
191 elif len(orders)>0:
192 return ('NLO','all',orders)
193 else:
194 return ('tree',None,[])
195 else:
196 return ('tree',None,[])
197
198
199
200 - def do_add(self, line, *args, **opts):
201
202 allow_switch = True
203 if self._curr_amps:
204 allow_switch = False
205
206 argss = cmd.Cmd.split_arg(line)
207 if len(argss)>=1 and argss[0] in ['process','timing','profile']:
208 proc_line = ' '.join(argss[1:])
209 (type,nlo_mode,orders)=self.extract_process_type(proc_line)
210 if type=='NLO':
211 if not nlo_mode in self._valid_nlo_modes: raise self.InvalidCMD( \
212 'The NLO mode %s is not valid. Please choose one among: %s' \
213 % (nlo_mode, ' '.join(self._valid_nlo_modes)))
214 elif nlo_mode in ['all', 'real', 'LOonly']:
215 self.change_principal_cmd('aMC@NLO', allow_switch)
216 elif nlo_mode in ['virt', 'sqrvirt']:
217 self.change_principal_cmd('MadLoop', allow_switch)
218 elif nlo_mode == 'noborn':
219 if self.current_interface == "MadGraph":
220 allow_switch = True
221 self.change_principal_cmd('MadLoop', allow_switch)
222 self.cmd.validate_model(self, loop_type=nlo_mode,
223 coupling_type=orders)
224 self.change_principal_cmd('MadGraph', allow_switch)
225 return self.cmd.create_loop_induced(self, line, *args, **opts)
226 else:
227 self.change_principal_cmd('MadGraph', allow_switch)
228 try:
229 return self.cmd.do_add(self, line, *args, **opts)
230 except fks_base.NoBornException:
231 logger.info("---------------------------------------------------------------------------", '$MG:BOLD')
232 logger.info(" No Born diagrams found. Now switching to the loop-induced mode. ", '$MG:BOLD')
233 logger.info(" Please also cite ref. 'arXiv:1507.00020' when using results from this mode. ", '$MG:BOLD')
234 logger.info("---------------------------------------------------------------------------", '$MG:BOLD')
235 self.change_principal_cmd('MadGraph',allow_switch)
236 return self.cmd.create_loop_induced(self, line, *args, **opts)
237
238
239 - def do_check(self, line, *args, **opts):
259
279
293
295 """ treat output aloha in order to use always the one in MG5 """
296 if line.strip().startswith('aloha'):
297 MGcmd.MadGraphCmd.do_output(self, line, *args, **opts)
298 else:
299 self.cmd.do_output(self, line, *args, **opts)
300
306
307
308
309
310
311
312 - def export(self, *args, **opts):
314
317
320
323
326
329
332
335
338
341
344
347
350
353
356
359
362
365
366 - def check_history(self, *args, **opts):
367 return self.cmd.check_history(self, *args, **opts)
368
371
374
377
380
383
386
389
392
395
398
401
404
407
410
413
416
419
422
425
426 - def complete_history(self, *args, **opts):
427 return self.cmd.complete_history(self, *args, **opts)
428
431
434
437
440
443
446
449
452
455
457 """Not in help """
458 return self.cmd.do_switch(self, *args, **opts)
459
460 - def do_EOF(self, *args, **opts):
462
465
468
471
474
477
480
481 - def do_history(self, *args, **opts):
482 return self.cmd.do_history(self, *args, **opts)
483
486
488 args = cmd.Cmd.split_arg(line)
489
490 if len(args) >=1:
491 if os.path.isdir(args[0]):
492 path = os.path.realpath(args[0])
493 elif os.path.isdir(pjoin(MG5DIR,args[0])):
494 path = pjoin(MG5DIR,args[0])
495 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
496 path = pjoin(MG4DIR,args[0])
497 else:
498 path=None
499
500 if path:
501 type = self.cmd.find_output_type(self, path)
502 if type in ['standalone', 'standalone_cpp', 'pythia8', 'madevent']:
503 self.change_principal_cmd('MadGraph')
504 elif type == 'aMC@NLO':
505 self.change_principal_cmd('aMC@NLO')
506 elif type == 'MadLoop':
507 self.change_principal_cmd('MadLoop')
508
509 return self.cmd.do_launch(self, line, *argss, **opts)
510
513
516
519
522
523 - def do_set(self, *args, **opts):
525
528
531
534
537
540
543
546
549
550 - def help_history(self, *args, **opts):
551 return self.cmd.help_history(self, *args, **opts)
552
555
558
561
564
567
570
573
576
579
582
585
588
591
594
597
600
601 -class MasterCmd(Switcher, LoopCmd.LoopInterface, amcatnloCmd.aMCatNLOInterface, cmd.CmdShell):
602
603 - def __init__(self, main='MadGraph', *args, **opt):
614
618
629
655
656
657 -class MasterCmdWeb(MGcmd.MadGraphCmdWeb, Switcher, LoopCmd.LoopInterfaceWeb):
658
660
661 if '_CONDOR_SCRATCH_DIR' in os.environ:
662 self.writing_dir = pjoin(os.environ['_CONDOR_SCRATCH_DIR'], \
663 os.path.pardir)
664 else:
665 self.writing_dir = pjoin(os.environ['MADGRAPH_DATA'],
666 os.environ['REMOTE_USER'])
667
668
669
670 Switcher.__init__(self, mgme_dir = '', *arg, **opt)
671
672 self.options['timeout'] = 1
673
684
687
688 - def finalize(self, nojpeg, flaglist=[]):
689 """Finalize web generation"""
690
691 if flaglist != []:
692 raise Exception
693 self.cmd.finalize(self, nojpeg, online = True)
694
696 """Finalize web generation"""
697
698 opts['online'] = True
699 self.cmd.finalize(self, nojpeg, opts)
700
701
703 """Generate an amplitude for a given process"""
704
705 try:
706 Switcher.do_generate(self, line)
707 except:
708
709 files.cp(self._export_dir+'/HTML/stop.jpg',self._export_dir+'/HTML/card.jpg')
710 raise
711
712
714 """Generate an amplitude for a given process and add to
715 existing amplitudes
716 syntax:
717 """
718 try:
719 Switcher.do_add(self, line)
720 except:
721
722 files.cp(self._export_dir+'/HTML/stop.jpg',self._export_dir+'/HTML/card.jpg')
723 raise
724
725
727
728 """Force to use the web configuration file only"""
729 config_path = pjoin(os.environ['MADGRAPH_BASE'], 'mg5_configuration.txt')
730 return Switcher.set_configuration(self, config_path=config_path, final=final)
731
732 - def do_save(self, line, check=True, **opt):
747
749 """block all install"""
750 return
751