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