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 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
473
476
479
482
485
486 - def do_history(self, *args, **opts):
487 return self.cmd.do_history(self, *args, **opts)
488
491
493 args = cmd.Cmd.split_arg(line)
494
495 if len(args) >=1:
496 if os.path.isdir(args[0]):
497 path = os.path.realpath(args[0])
498 elif os.path.isdir(pjoin(MG5DIR,args[0])):
499 path = pjoin(MG5DIR,args[0])
500 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
501 path = pjoin(MG4DIR,args[0])
502 else:
503 path=None
504
505 if path:
506 type = self.cmd.find_output_type(self, path)
507 if type in ['standalone', 'standalone_cpp', 'pythia8', 'madevent']:
508 self.change_principal_cmd('MadGraph')
509 elif type == 'aMC@NLO':
510 self.change_principal_cmd('aMC@NLO')
511 elif type == 'MadLoop':
512 self.change_principal_cmd('MadLoop')
513
514 return self.cmd.do_launch(self, line, *argss, **opts)
515
518
521
524
527
528 - def do_set(self, *args, **opts):
530
533
536
539
542
545
548
551
554
555 - def help_history(self, *args, **opts):
556 return self.cmd.help_history(self, *args, **opts)
557
560
563
566
569
572
575
578
581
584
587
590
593
596
599
602
605
606 -class MasterCmd(Switcher, LoopCmd.LoopInterface, amcatnloCmd.aMCatNLOInterface, cmd.CmdShell):
607
608 - def __init__(self, main='MadGraph', *args, **opt):
619
623
634
660
661
662 -class MasterCmdWeb(MGcmd.MadGraphCmdWeb, Switcher, LoopCmd.LoopInterfaceWeb):
663
665
666 if '_CONDOR_SCRATCH_DIR' in os.environ:
667 self.writing_dir = pjoin(os.environ['_CONDOR_SCRATCH_DIR'], \
668 os.path.pardir)
669 else:
670 self.writing_dir = pjoin(os.environ['MADGRAPH_DATA'],
671 os.environ['REMOTE_USER'])
672
673
674
675 Switcher.__init__(self, mgme_dir = '', *arg, **opt)
676
677 self.options['timeout'] = 1
678
689
692
693 - def finalize(self, nojpeg, flaglist=[]):
694 """Finalize web generation"""
695
696 if flaglist != []:
697 raise Exception
698 self.cmd.finalize(self, nojpeg, online = True)
699
701 """Finalize web generation"""
702
703 opts['online'] = True
704 self.cmd.finalize(self, nojpeg, opts)
705
706
708 """Generate an amplitude for a given process"""
709
710 try:
711 Switcher.do_generate(self, line)
712 except:
713
714 files.cp(self._export_dir+'/HTML/stop.jpg',self._export_dir+'/HTML/card.jpg')
715 raise
716
717
719 """Generate an amplitude for a given process and add to
720 existing amplitudes
721 syntax:
722 """
723 try:
724 Switcher.do_add(self, line)
725 except:
726
727 files.cp(self._export_dir+'/HTML/stop.jpg',self._export_dir+'/HTML/card.jpg')
728 raise
729
730
732
733 """Force to use the web configuration file only"""
734 config_path = pjoin(os.environ['MADGRAPH_BASE'], 'mg5_configuration.txt')
735 return Switcher.set_configuration(self, config_path=config_path, final=final)
736
737 - def do_save(self, line, check=True, **opt):
752
754 """block all install"""
755 return
756