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 import atexit
21 import logging
22 import optparse
23 import os
24 import pydoc
25 import re
26 import subprocess
27 import sys
28 import traceback
29 import time
30
31 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
32 root_path = os.path.split(root_path)[0]
33 sys.path.insert(0, root_path)
34
35
36 pjoin = os.path.join
37
38 import madgraph
39 import madgraph.core.diagram_generation as diagram_generation
40 import madgraph.core.helas_objects as helas_objects
41 import madgraph.loop.loop_base_objects as loop_base_objects
42 import madgraph.interface.extended_cmd as cmd
43 import madgraph.interface.madgraph_interface as MGcmd
44 import madgraph.interface.loop_interface as LoopCmd
45 import madgraph.interface.amcatnlo_interface as amcatnloCmd
46 import madgraph.fks.fks_base as fks_base
47 import madgraph.iolibs.files as files
48 import madgraph.various.misc as misc
49
50 from madgraph import MG4DIR, MG5DIR, MadGraph5Error
51
52 logger = logging.getLogger('cmdprint')
56 """ Helping class containing all the switching routine """
57
58 - def __init__(self, main='MadGraph', *args, **opt):
63
64 interface_names= {'MadGraph':('MG5_aMC',MGcmd.MadGraphCmd),
65 'MadLoop':('MG5_aMC',LoopCmd.LoopInterface),
66 'aMC@NLO':('MG5_aMC',amcatnloCmd.aMCatNLOInterface)}
67
68 _switch_opts = interface_names.keys()
69 current_interface = None
70
71
72
73 - def setup(self, *args, **opts):
74 """ Function to initialize the interface when switched to it. It is not
75 the same as __init__ as this latter functions would call its mother
76 from madgraph_interface and this is only desirable for the first
77 initialization when launching MG5 """
78 return self.cmd.setup(self, *args, **opts)
79
81 """redefine all the command to call directly the appropriate child"""
82
83 if hasattr(self, 'plugin') and self.plugin:
84 return True
85
86 correct = True
87
88
89 overwritable = []
90
91 self.to_preserve = [key for key,method in Switcher.__dict__.items() if
92 hasattr(method, '__call__') ]
93 self.to_preserve += ['do_shell', 'help_shell', 'complete_shell']
94
95 ff = open(pjoin(os.getcwd(), 'additional_command'), 'w')
96
97 for key in dir(self):
98
99 if key in self.to_preserve:
100 continue
101 if not (key.startswith('do_') or key.startswith('complete_') or \
102 key.startswith('help_') or key.startswith('check_') or \
103 key in overwritable):
104 continue
105 text = """\
106 def %(key)s(self, *args, **opts):
107 return self.cmd.%(key)s(self, *args, **opts)
108
109 """ % {'key': key}
110 logger.warning("""Command %s not define in the Master.
111 The line to add to the master_interface.py are written in 'additional_command' file""" % key)
112 ff.write(text)
113 correct = False
114
115
116
117
118 define = {}
119 for mother in MasterCmd.__mro__:
120 if mother.__name__ in ['OriginalCmd', 'BasicCmd', 'CmdExtended', 'Cmd']:
121 continue
122
123
124 for data in mother.__dict__:
125
126 if data in Switcher.__dict__ or data.startswith('__'):
127 continue
128 if data in MasterCmd.__dict__:
129
130 continue
131 if data not in define:
132 define[data] = mother.__name__
133 else:
134 logger.warning('%s define in %s and in %s but not in Switcher.' % (data, define[data], mother.__name__))
135 correct = False
136
137
138 define = {}
139 for mother in MasterCmdWeb.__mro__:
140 if mother.__name__ in ['OriginalCmd', 'BasicCmd', 'CmdExtended', 'Cmd']:
141 continue
142 for data in mother.__dict__:
143
144 if data in Switcher.__dict__ or data.startswith('__'):
145 continue
146 if data in MasterCmdWeb.__dict__:
147
148 continue
149 if data not in define:
150 define[data] = mother.__name__
151 else:
152 logger.warning('%s define in %s and in %s but not in Switcher.' % (data, define[data], mother.__name__))
153 correct = False
154
155 if not correct:
156 raise Exception, 'The Cmd interface has dangerous features. Please see previous warnings and correct those.'
157
158
159
160 @staticmethod
162 """Extract from a string what is the type of the computation. This
163 returns a tuple (mode, option, pert_orders) where mode can be either 'NLO' or 'tree'
164 and option 'all', 'real' or 'virt'."""
165
166
167
168 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
169 line2 = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
170
171
172
173
174 loopRE = re.compile(r"^(.*)(?P<loop>\[(\s*(?P<option>\w+)\s*=)?(?P<orders>.+)?\])(.*)$")
175
176 res=loopRE.search(line.split('--')[0])
177 if res:
178 orders=res.group('orders').split() if res.group('orders') else []
179 if res.group('option') and len(res.group('option').split())==1:
180 if res.group('option').split()[0]=='tree':
181 return ('tree',res.group('option').split()[0],orders)
182 else:
183 return ('NLO',res.group('option').split()[0],orders)
184 else:
185
186
187
188 if orders == ['LOonly']:
189 return ('NLO', 'LOonly', ['QCD'])
190 elif len(orders)>0:
191 return ('NLO','all',orders)
192 else:
193 return ('tree',None,[])
194 else:
195 return ('tree',None,[])
196
197
198
199 - def do_add(self, line, *args, **opts):
200
201 argss = cmd.Cmd.split_arg(line)
202 if len(argss)>=1 and argss[0] in ['process','timing','profile']:
203 proc_line = ' '.join(argss[1:])
204 (type,nlo_mode,orders)=self.extract_process_type(proc_line)
205 if type=='NLO':
206 if not nlo_mode in self._valid_nlo_modes: raise self.InvalidCMD( \
207 'The NLO mode %s is not valid. Please choose one among: %s' \
208 % (nlo_mode, ' '.join(self._valid_nlo_modes)))
209 elif nlo_mode in ['all', 'real', 'LOonly']:
210 self.change_principal_cmd('aMC@NLO')
211 elif nlo_mode in ['virt', 'sqrvirt']:
212 self.change_principal_cmd('MadLoop')
213 elif nlo_mode == 'noborn':
214 self.change_principal_cmd('MadLoop')
215 self.cmd.validate_model(self, loop_type=nlo_mode,
216 coupling_type=orders)
217 self.change_principal_cmd('MadGraph')
218 return self.cmd.create_loop_induced(self, line, *args, **opts)
219 else:
220 self.change_principal_cmd('MadGraph')
221 try:
222 return self.cmd.do_add(self, line, *args, **opts)
223 except fks_base.NoBornException:
224 logger.info("------------------------------------------------------------------------", '$MG:BOLD')
225 logger.info(" No Born diagrams found. Now switching to the loop-induced mode. ", '$MG:BOLD')
226 logger.info(" Please cite ref. 'arXiv:1507.00020' when using results from this mode. ", '$MG:BOLD')
227 logger.info("------------------------------------------------------------------------", '$MG:BOLD')
228 self.change_principal_cmd('MadGraph')
229 return self.cmd.create_loop_induced(self, line, *args, **opts)
230
231
232 - def do_check(self, line, *args, **opts):
252
272
286
288 """ treat output aloha in order to use always the one in MG5 """
289 if line.strip().startswith('aloha'):
290 MGcmd.MadGraphCmd.do_output(self, line, *args, **opts)
291 else:
292 self.cmd.do_output(self, line, *args, **opts)
293
299
300
301
302
303
304
305 - def export(self, *args, **opts):
307
310
313
316
319
322
325
328
331
334
337
340
343
346
349
352
355
358
359 - def check_history(self, *args, **opts):
360 return self.cmd.check_history(self, *args, **opts)
361
364
367
370
373
376
379
382
385
388
391
394
397
400
403
406
409
412
413 - def complete_history(self, *args, **opts):
414 return self.cmd.complete_history(self, *args, **opts)
415
418
421
424
427
430
433
436
439
442
444 """Not in help """
445 return self.cmd.do_switch(self, *args, **opts)
446
447 - def do_EOF(self, *args, **opts):
449
452
455
458
461
462 - def do_history(self, *args, **opts):
463 return self.cmd.do_history(self, *args, **opts)
464
467
469 args = cmd.Cmd.split_arg(line)
470
471 if len(args) >=1:
472 if os.path.isdir(args[0]):
473 path = os.path.realpath(args[0])
474 elif os.path.isdir(pjoin(MG5DIR,args[0])):
475 path = pjoin(MG5DIR,args[0])
476 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
477 path = pjoin(MG4DIR,args[0])
478 else:
479 path=None
480
481 if path:
482 type = self.cmd.find_output_type(self, path)
483 if type in ['standalone', 'standalone_cpp', 'pythia8', 'madevent']:
484 self.change_principal_cmd('MadGraph')
485 elif type == 'aMC@NLO':
486 self.change_principal_cmd('aMC@NLO')
487 elif type == 'MadLoop':
488 self.change_principal_cmd('MadLoop')
489
490 return self.cmd.do_launch(self, line, *argss, **opts)
491
494
497
500
503
504 - def do_set(self, *args, **opts):
506
509
512
515
518
521
524
527
530
531 - def help_history(self, *args, **opts):
532 return self.cmd.help_history(self, *args, **opts)
533
536
539
542
545
548
551
554
557
560
563
566
569
572
575
578
581
582 -class MasterCmd(Switcher, LoopCmd.LoopInterface, amcatnloCmd.aMCatNLOInterface, cmd.CmdShell):
583
584 - def __init__(self, main='MadGraph', *args, **opt):
595
599
610
630
631
632 -class MasterCmdWeb(MGcmd.MadGraphCmdWeb, Switcher, LoopCmd.LoopInterfaceWeb):
633
635
636 if os.environ.has_key('_CONDOR_SCRATCH_DIR'):
637 self.writing_dir = pjoin(os.environ['_CONDOR_SCRATCH_DIR'], \
638 os.path.pardir)
639 else:
640 self.writing_dir = pjoin(os.environ['MADGRAPH_DATA'],
641 os.environ['REMOTE_USER'])
642
643
644
645 Switcher.__init__(self, mgme_dir = '', *arg, **opt)
646
647 self.options['timeout'] = 1
648
659
662
663 - def finalize(self, nojpeg, flaglist=[]):
664 """Finalize web generation"""
665
666 if flaglist != []:
667 raise Exception
668 self.cmd.finalize(self, nojpeg, online = True)
669
671 """Finalize web generation"""
672
673 opts['online'] = True
674 self.cmd.finalize(self, nojpeg, opts)
675
676
678 """Generate an amplitude for a given process"""
679
680 try:
681 Switcher.do_generate(self, line)
682 except:
683
684 files.cp(self._export_dir+'/HTML/stop.jpg',self._export_dir+'/HTML/card.jpg')
685 raise
686
687
689 """Generate an amplitude for a given process and add to
690 existing amplitudes
691 syntax:
692 """
693 try:
694 Switcher.do_add(self, line)
695 except:
696
697 files.cp(self._export_dir+'/HTML/stop.jpg',self._export_dir+'/HTML/card.jpg')
698 raise
699
700
702
703 """Force to use the web configuration file only"""
704 config_path = pjoin(os.environ['MADGRAPH_BASE'], 'mg5_configuration.txt')
705 return Switcher.set_configuration(self, config_path=config_path, final=final)
706
707 - def do_save(self, line, check=True, **opt):
722
724 """block all install"""
725 return
726