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 import os
20 import logging
21 import pydoc
22 import sys
23 import time
24 import optparse
25 import subprocess
26 import shutil
27
28 import madgraph
29 from madgraph import MG4DIR, MG5DIR, MadGraph5Error
30 import madgraph.interface.extended_cmd as cmd
31 import madgraph.interface.madgraph_interface as mg_interface
32 import madgraph.interface.madevent_interface as me_interface
33 import madgraph.interface.amcatnlo_run_interface as run_interface
34 import madgraph.interface.launch_ext_program as launch_ext
35 import madgraph.interface.loop_interface as Loop_interface
36 import madgraph.fks.fks_base as fks_base
37 import madgraph.fks.fks_helas_objects as fks_helas
38 import madgraph.iolibs.export_fks as export_fks
39 import madgraph.iolibs.export_v4 as export_v4
40 import madgraph.loop.loop_base_objects as loop_base_objects
41 import madgraph.core.diagram_generation as diagram_generation
42 import madgraph.core.helas_objects as helas_objects
43 import madgraph.various.cluster as cluster
44 import madgraph.various.misc as misc
45 import madgraph.various.banner as banner_mod
46
47
48 pjoin = os.path.join
49
50
51 logger = logging.getLogger('cmdprint')
52 logger_stderr = logging.getLogger('fatalerror')
53
54 -class CheckFKS(mg_interface.CheckValidForCmd):
55
56
58 """ Check the arguments of the display diagrams command in the context
59 of the Loop interface."""
60
61 mg_interface.MadGraphCmd.check_display(self,args)
62
63 if args[0] in ['diagrams', 'processes'] and len(args)>=3 \
64 and args[1] not in ['born','loop','virt','real']:
65 raise self.InvalidCmd("Can only display born, loop (virt) or real diagrams, not %s."%args[1])
66
67 if len(args) > 1:
68 if args[1] == 'virt':
69 args[1] = 'loop'
70
76
84
86 """ check the validity of the line"""
87
88 self._export_format = 'NLO'
89 forbidden_formats = ['madevent', 'standalone']
90
91
92 if not hasattr(self, '_fks_multi_proc') or not self._fks_multi_proc:
93 text = 'No processes generated. Please generate a process first.'
94 raise self.InvalidCmd(text)
95
96 if not self._curr_model:
97 text = 'No model found. Please import a model first and then retry.'
98 raise self.InvalidCmd(text)
99
100 if args and args[0][0] != '-':
101 if args[0] in forbidden_formats:
102 text = 'You generated a NLO process, which cannot be exported in %s mode.\n' % args[0]
103 text+= 'Please use the command "output DIR_NAME".\n'
104 raise self.InvalidCmd(text)
105
106
107 path = args.pop(0)
108
109 if path == 'auto':
110 self.get_default_path()
111 elif path != 'auto':
112 self._export_dir = path
113 else:
114
115 self.get_default_path()
116
117 self._export_dir = os.path.realpath(self._export_dir)
118
119
121 """check the validity of the line. args are DIR and MODE
122 MODE being LO, NLO, aMC@NLO or aMC@LO. If no mode is passed, aMC@NLO is used"""
123
124
125
126 if not args:
127 if self._done_export:
128 args.append(self._done_export[0])
129 args.append('auto')
130
131 return
132 else:
133 self.help_launch()
134 raise self.InvalidCmd, \
135 'No default location available, please specify location.'
136
137 if len(args) > 2:
138 self.help_launch()
139 return self.InvalidCmd, 'Invalid Syntax: Too many argument'
140
141 elif len(args) == 2:
142 if not args[1] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'auto']:
143 raise self.InvalidCmd, '%s is not a valid mode, please use "LO", "NLO", "aMC@NLO" or "aMC@LO"' % args[1]
144 else:
145
146 if args[0] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'auto'] and self._done_export:
147 args.insert(0, self._done_export[0])
148 elif os.path.isdir(args[0]) or os.path.isdir(pjoin(MG5DIR, args[0]))\
149 or os.path.isdir(pjoin(MG4DIR, args[0])):
150 args.append('auto')
151 else:
152 self.help_launch()
153 raise self.InvalidCmd, '%s is not a valid process directory nor run mode' % args[0]
154
155 mode = args[1]
156
157
158 if os.path.isdir(args[0]):
159 path = os.path.realpath(args[0])
160 elif os.path.isdir(pjoin(MG5DIR,args[0])):
161 path = pjoin(MG5DIR,args[0])
162 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
163 path = pjoin(MG4DIR,args[0])
164 else:
165 raise self.InvalidCmd, '%s is not a valid directory' % args[0]
166 args[0] = path
167
168
169 self._done_export = [path, mode]
170
171
172 if options['multicore'] and options['cluster']:
173 raise self.InvalidCmd, 'options -m (--multicore) and -c (--cluster)' + \
174 ' are not compatible. Please choose one.'
175 if mode == 'NLO' and options['reweightonly']:
176 raise self.InvalidCmd, 'option -r (--reweightonly) needs mode "aMC@NLO" or "aMC@LO"'
177
178
179 -class CheckFKSWeb(mg_interface.CheckValidForCmdWeb, CheckFKS):
181
183
185 """Complete the display command in the context of the FKS interface"""
186
187 args = self.split_arg(line[0:begidx])
188
189 if len(args) == 2 and args[1] in ['diagrams', 'processes']:
190 return self.list_completion(text, ['born', 'loop', 'virt', 'real'])
191 else:
192 return mg_interface.MadGraphCmd.complete_display(self, text, line,
193 begidx, endidx)
194
195
197 """Complete the output command in the context of the FKS interface"""
198
199 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
200 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
201 'mg5', 'DECAY', 'EventConverter', 'Models',
202 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha',
203 'madgraph', 'bin', 'tests', 'input', 'vendor', 'models']
204
205
206 args = self.split_arg(line[0:begidx])
207 if len(args) >= 1:
208 if len(args) > 1 and args[1] == 'aloha':
209 try:
210 return self.aloha_complete_output(text, line, begidx, endidx)
211 except Exception, error:
212 print error
213
214 if args[-1].endswith(os.path.sep):
215 return [name for name in self.path_completion(text,
216 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
217 only_dirs = True) if name not in forbidden_names]
218
219
220 content = [name for name in self.path_completion(text, '.', only_dirs = True) \
221 if name not in forbidden_names]
222 return self.list_completion(text, content)
223
224
226 """ complete the launch command"""
227 args = self.split_arg(line[0:begidx])
228
229
230 if args[-1].endswith(os.path.sep):
231 return self.path_completion(text,
232 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
233 only_dirs = True)
234
235 if len(args) == 1:
236 out = {'Path from ./': self.path_completion(text, '.', only_dirs = True)}
237 if MG5DIR != os.path.realpath('.'):
238 out['Path from %s' % MG5DIR] = self.path_completion(text,
239 MG5DIR, only_dirs = True, relative=False)
240 if MG4DIR and MG4DIR != os.path.realpath('.') and MG4DIR != MG5DIR:
241 out['Path from %s' % MG4DIR] = self.path_completion(text,
242 MG4DIR, only_dirs = True, relative=False)
243
244 if len(args) == 2:
245 modes = ['aMC@NLO', 'NLO', 'aMC@LO', 'LO']
246 return self.list_completion(text, modes, line)
247
248
249 if len(args) >= 3:
250 out={}
251
252 if line[0:begidx].endswith('--laststep='):
253 opt = ['parton', 'pythia', 'pgs','delphes','auto']
254 out['Options'] = self.list_completion(text, opt, line)
255 else:
256
257 opt = ['-f', '-c', '-m', '-i', '-x', '-r', '-p', '-o', '-n', 'a',
258 '--force', '--cluster', '--multicore', '--interactive',
259 '--nocompile', '--reweightonly', '--parton', '--only_generation', '--name', '--appl_start_grid']
260 out['Options'] = self.list_completion(text, opt, line)
261
262
263 return self.deal_multiple_categories(out)
264
265 -class HelpFKS(mg_interface.HelpToCmd):
266
268 mg_interface.MadGraphCmd.help_display(self)
269 logger.info(" In aMC@NLO5, after display diagrams, the user can add the option")
270 logger.info(" \"born\", \"virt\" or \"real\" to display only the corresponding diagrams.")
271
275
276 -class aMCatNLOInterface(CheckFKS, CompleteFKS, HelpFKS, Loop_interface.CommonLoopInterface):
277
278 _fks_display_opts = ['real_diagrams', 'born_diagrams', 'virt_diagrams',
279 'real_processes', 'born_processes', 'virt_processes']
280
281 _nlo_modes_for_completion = ['all','real']
282
283 - def __init__(self, mgme_dir = '', *completekey, **stdin):
289
291 """ Special tasks when switching to this interface """
292
293
294
295
296
297
298 self.history.clean(remove_bef_last='import',
299 to_keep=['set','load','import', 'define'])
300
301 self._done_export=False
302 self._curr_amps = diagram_generation.AmplitudeList()
303 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
304 self._v4_export_formats = []
305 self._nlo_modes_for_completion = ['all','real']
306 self._export_formats = [ 'madevent', 'aloha' ]
307
308
309 self.validate_model(loop_type='real_init', stop=False)
310
311
312
313 self._cuttools_dir=str(pjoin(self._mgme_dir,'vendor','CutTools'))
314 if not os.path.isdir(pjoin(self._cuttools_dir, 'src','cts')):
315 logger.warning(('Warning: Directory %s is not a valid CutTools directory.'+\
316 'Using default CutTools instead.') % \
317 self._cuttools_dir)
318 self._cuttools_dir=str(pjoin(self._mgme_dir,'vendor','CutTools'))
319
320 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
321 if not os.path.isdir(self._iregi_dir):
322 logger.warning(('Warning: Directory %s is not a valid IREGI directory.'+\
323 'Using default IREGI instead.')%\
324 self._iregi_dir)
325 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
326
328
329 args = self.split_arg(line)
330
331 self.check_display(args)
332
333 if args[0] in ['diagrams', 'processes', 'diagrams_text']:
334 get_amps_dict = {'real': self._fks_multi_proc.get_real_amplitudes,
335 'born': self._fks_multi_proc.get_born_amplitudes,
336 'loop': self._fks_multi_proc.get_virt_amplitudes}
337 if args[0] == 'diagrams':
338 if len(args)>=2 and args[1] in get_amps_dict.keys():
339 get_amps = get_amps_dict[args[1]]
340 self._curr_amps = get_amps()
341
342 if args[1] == 'loop' and len(self._curr_amps) == 0:
343 raise self.InvalidCmd('No virtuals have been generated')
344 self.draw(' '.join(args[2:]),type = args[1])
345 else:
346 for diag_type, get_amps in get_amps_dict.items():
347 self._curr_amps = get_amps()
348 self.draw(' '.join(args[1:]), type=diag_type)
349
350 self._curr_amps = diagram_generation.AmplitudeList()
351
352 if args[0] == 'diagrams_text':
353 if len(args)>=2 and args[1] in get_amps_dict.keys():
354 get_amps = get_amps_dict[args[1]]
355 self._curr_amps = get_amps()
356
357 if args[1] in ['virt', 'loop'] and len(self._curr_amps) == 0:
358 raise self.InvalidCmd('No virtuals have been generated')
359 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
360 else:
361 text = 'Born diagrams:\n'
362 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['born']())
363 text += '\n\nReal diagrams:'
364 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['real']())
365 text += '\n\nLoop diagrams:\n'
366 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['virt']())
367 pydoc.pager(text)
368
369
370 self._curr_amps = diagram_generation.AmplitudeList()
371
372 elif args[0] == 'processes':
373 if len(args)>=2 and args[1] in get_amps_dict.keys():
374 get_amps = get_amps_dict[args[1]]
375 self._curr_amps = get_amps()
376
377 if args[1] in ['virt', 'loop'] and len(self._curr_amps) == 0:
378 raise self.InvalidCmd('No virtuals have been generated')
379 print '\n'.join(amp.nice_string_processes() for amp in self._curr_amps)
380 else:
381 print 'Born processes:'
382 print '\n'.join(amp.nice_string_processes() for amp in get_amps_dict['born']())
383 print 'Real processes:'
384 print '\n'.join(amp.nice_string_processes() for amp in get_amps_dict['real']())
385 print 'Loop processes:'
386 print '\n'.join(amp.nice_string_processes() for amp in get_amps_dict['loop']())
387
388 self._curr_amps = diagram_generation.AmplitudeList()
389
390 else:
391 mg_interface.MadGraphCmd.do_display(self,line,output)
392
393 - def do_add(self, line, *args,**opt):
394
395 args = self.split_arg(line)
396
397 self.check_add(args)
398
399 if args[0] == 'model':
400 return self.add_model(args[1:])
401 elif args[0] != 'process':
402 raise self.InvalidCmd("The add command can only be used with process or model")
403 else:
404 line = ' '.join(args[1:])
405
406 proc_type=self.extract_process_type(line)
407 if proc_type[1] not in ['real', 'LOonly']:
408 run_interface.check_compiler(self.options, block=False)
409 self.validate_model(proc_type[1])
410
411
412
413 collect_mirror_procs = False
414 ignore_six_quark_processes = self.options['ignore_six_quark_processes']
415 if ',' in line:
416 myprocdef, line = mg_interface.MadGraphCmd.extract_decay_chain_process(self,line)
417 if myprocdef.are_decays_perturbed():
418 raise MadGraph5Error("Decay processes cannot be perturbed")
419 else:
420 myprocdef = mg_interface.MadGraphCmd.extract_process(self,line)
421
422 self.proc_validity(myprocdef,'aMCatNLO_%s'%proc_type[1])
423
424
425
426
427
428
429
430
431
432
433 try:
434 self._fks_multi_proc.add(fks_base.FKSMultiProcess(myprocdef,
435 collect_mirror_procs,
436 ignore_six_quark_processes,
437 OLP=self.options['OLP']))
438 except AttributeError:
439 self._fks_multi_proc = fks_base.FKSMultiProcess(myprocdef,
440 collect_mirror_procs,
441 ignore_six_quark_processes,
442 OLP=self.options['OLP'])
443
444
446 """Main commands: Initialize a new Template or reinitialize one"""
447
448 args = self.split_arg(line)
449
450 self.check_output(args)
451
452 noclean = '-noclean' in args
453 force = '-f' in args
454 nojpeg = '-nojpeg' in args
455 main_file_name = ""
456 try:
457 main_file_name = args[args.index('-name') + 1]
458 except Exception:
459 pass
460
461 self.options['group_subprocesses'] = False
462
463 if self._export_format in ['NLO']:
464 self._curr_exporter = export_v4.ExportV4Factory(\
465 self, noclean, output_type='amcatnlo')
466
467 if not force and not noclean and os.path.isdir(self._export_dir)\
468 and self._export_format in ['NLO']:
469
470 logger.info('INFO: directory %s already exists.' % self._export_dir)
471 logger.info('If you continue this directory will be deleted and replaced.')
472 answer = self.ask('Do you want to continue?', 'y', ['y','n'],
473 timeout=self.options['timeout'])
474 if answer != 'y':
475 raise self.InvalidCmd('Stopped by user request')
476
477
478
479 if os.path.exists(self._export_dir):
480 shutil.rmtree(self._export_dir)
481
482
483 if self._export_format in ['NLO']:
484 self._curr_exporter.copy_fkstemplate()
485
486
487 self._done_export = False
488
489
490 self.export(nojpeg, main_file_name)
491
492
493 self.finalize(nojpeg)
494
495
496 if self.options['OLP']!='MadLoop':
497 self._curr_exporter.generate_virtuals_from_OLP(
498 self._curr_matrix_elements,self._export_dir,self.options['OLP'])
499
500
501 self._done_export = (self._export_dir, self._export_format)
502
503
504 self._export_dir = None
505
506
507 - def export(self, nojpeg = False, main_file_name = ""):
564
565
566
567 ndiags, cpu_time = generate_matrix_elements(self)
568 calls = 0
569
570 path = self._export_dir
571
572 if self._export_format in ['NLO']:
573 path = os.path.join(path, 'SubProcesses')
574
575
576 self._fks_directories = []
577 proc_charac = banner_mod.ProcCharacteristic()
578 for charac in ['has_isr', 'has_fsr', 'has_loops']:
579 proc_charac[charac] = self._curr_matrix_elements[charac]
580 proc_charac.write(pjoin(path, 'proc_characteristics'))
581
582 for ime, me in \
583 enumerate(self._curr_matrix_elements.get('matrix_elements')):
584
585 calls = calls + \
586 self._curr_exporter.generate_directories_fks(me,
587 self._curr_fortran_model,
588 ime, len(self._curr_matrix_elements.get('matrix_elements')),
589 path,self.options['OLP'])
590 self._fks_directories.extend(self._curr_exporter.fksdirs)
591 card_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
592 'procdef_mg5.dat')
593
594 if self.options['loop_optimized_output'] and \
595 len(self._curr_matrix_elements.get_virt_matrix_elements()) > 0:
596 self._curr_exporter.write_coef_specs_file(\
597 self._curr_matrix_elements.get_virt_matrix_elements())
598 if self._generate_info:
599 self._curr_exporter.write_procdef_mg5(card_path,
600 self._curr_model['name'],
601 self._generate_info)
602 try:
603 cmd.Cmd.onecmd(self, 'history .')
604 except Exception:
605 logger.debug('fail to run command \"history cmd\"')
606 pass
607 subproc_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
608 'initial_states_map.dat')
609 self._curr_exporter.write_init_map(subproc_path,
610 self._curr_matrix_elements.get('initial_states'))
611
612 cpu_time1 = time.time()
613
614
616 """Main commands: Ask for editing the parameters and then execute the code (NLO or aMC@(N)LO)
617 """
618 old_cwd = os.getcwd()
619 argss = self.split_arg(line)
620
621 (options, argss) = _launch_parser.parse_args(argss)
622 options = options.__dict__
623 self.check_launch(argss, options)
624 if not os.path.isdir(os.path.join(os.getcwd(), argss[0], 'Events')):
625 self.do_switch('ML5')
626 return mg_interface.MadGraphCmd.do_launch(self,line)
627
628
629
630
631 if options['interactive']:
632 if hasattr(self, 'do_shell'):
633 ME = run_interface.aMCatNLOCmdShell(me_dir=argss[0], options=self.options)
634 else:
635 ME = run_interface.aMCatNLOCmd(me_dir=argss[0],options=self.options)
636 ME.pass_in_web_mode()
637
638 config_line = [l for l in self.history if l.strip().startswith('set')]
639 for line in config_line:
640 ME.exec_cmd(line)
641 stop = self.define_child_cmd_interface(ME)
642 return stop
643
644 ext_program = launch_ext.aMCatNLOLauncher(argss[0], self, run_mode=argss[1], **options)
645 ext_program.run()
646
647
648
651
652 _launch_usage = "launch [DIRPATH] [MODE] [options]\n" + \
653 "-- execute the aMC@NLO output present in DIRPATH\n" + \
654 " By default DIRPATH is the latest created directory\n" + \
655 " MODE can be either LO, NLO, aMC@NLO or aMC@LO (if omitted, it is asked in a separate question)\n" + \
656 " If mode is set to LO/NLO, no event generation will be performed, but only the \n" + \
657 " computation of the total cross-section and the filling of parton-level histograms \n" + \
658 " specified in the DIRPATH/SubProcesses/madfks_plot.f file.\n" + \
659 " If mode is set to aMC@LO/aMC@NLO, after the cross-section computation, a .lhe \n" + \
660 " event file is generated which will be showered with the MonteCarlo specified \n" + \
661 " in the run_card.dat\n"
662
663 _launch_parser = misc.OptionParser(usage=_launch_usage)
664 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
665 help="Use the card present in the directory for the launch, without editing them")
666 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
667 help="Submit the jobs on the cluster")
668 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
669 help="Use interactive consol")
670 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
671 help="Submit the jobs on multicore mode")
672 _launch_parser.add_option("-x", "--nocompile", default=False, action='store_true',
673 help="Skip compilation. Ignored if no executable is found")
674 _launch_parser.add_option("-r", "--reweightonly", default=False, action='store_true',
675 help="Skip integration and event generation, just run reweight on the" + \
676 " latest generated event files (see list in SubProcesses/nevents_unweighted)")
677 _launch_parser.add_option("-p", "--parton", default=False, action='store_true',
678 help="Stop the run after the parton level file generation (you need " + \
679 "to shower the file in order to get physical results)")
680 _launch_parser.add_option("-o", "--only_generation", default=False, action='store_true',
681 help="Skip grid set up, just generate events starting from " + \
682 "the last available results")
683
684
685 _launch_parser.add_option("-n", "--name", default=False, dest='name',
686 help="Provide a name to the run")
687 _launch_parser.add_option("-a", "--appl_start_grid", default=False, dest='appl_start_grid',
688 help="For use with APPLgrid only: start from existing grids")
689