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
462 group_processes = False
463
464 if self._export_format in ['NLO']:
465 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
466 output_type='amcatnlo',group_subprocesses=group_processes)
467
468
469 if not force and not noclean and os.path.isdir(self._export_dir)\
470 and self._export_format in ['NLO']:
471
472 logger.info('INFO: directory %s already exists.' % self._export_dir)
473 logger.info('If you continue this directory will be deleted and replaced.')
474 answer = self.ask('Do you want to continue?', 'y', ['y','n'],
475 timeout=self.options['timeout'])
476 if answer != 'y':
477 raise self.InvalidCmd('Stopped by user request')
478
479
480
481 if os.path.exists(self._export_dir):
482 shutil.rmtree(self._export_dir)
483
484
485 if self._export_format in ['NLO']:
486 self._curr_exporter.copy_fkstemplate()
487
488
489 self._done_export = False
490
491
492 self.export(nojpeg, main_file_name, group_processes=group_processes)
493
494
495 self.finalize(nojpeg)
496
497
498 if self.options['OLP']!='MadLoop':
499 self._curr_exporter.generate_virtuals_from_OLP(
500 self._curr_matrix_elements,self._export_dir,self.options['OLP'])
501
502
503 self._done_export = (self._export_dir, self._export_format)
504
505
506 self._export_dir = None
507
508
509 - def export(self, nojpeg = False, main_file_name = "", group_processes=False):
559
560
561
562 ndiags, cpu_time = generate_matrix_elements(self, group=group_processes)
563 calls = 0
564
565 path = self._export_dir
566
567 if self._export_format in ['NLO']:
568 path = os.path.join(path, 'SubProcesses')
569
570
571 self._fks_directories = []
572 proc_charac = banner_mod.ProcCharacteristic()
573 for charac in ['has_isr', 'has_fsr', 'has_loops']:
574 proc_charac[charac] = self._curr_matrix_elements[charac]
575 proc_charac.write(pjoin(path, 'proc_characteristics'))
576
577 for ime, me in \
578 enumerate(self._curr_matrix_elements.get('matrix_elements')):
579
580 calls = calls + \
581 self._curr_exporter.generate_directories_fks(me,
582 self._curr_fortran_model,
583 ime, len(self._curr_matrix_elements.get('matrix_elements')),
584 path,self.options['OLP'])
585 self._fks_directories.extend(self._curr_exporter.fksdirs)
586 card_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
587 'procdef_mg5.dat')
588
589 if self.options['loop_optimized_output'] and \
590 len(self._curr_matrix_elements.get_virt_matrix_elements()) > 0:
591 self._curr_exporter.write_coef_specs_file(\
592 self._curr_matrix_elements.get_virt_matrix_elements())
593 if self._generate_info:
594 self._curr_exporter.write_procdef_mg5(card_path,
595 self._curr_model['name'],
596 self._generate_info)
597 try:
598 cmd.Cmd.onecmd(self, 'history .')
599 except Exception:
600 logger.debug('fail to run command \"history cmd\"')
601 pass
602 subproc_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
603 'initial_states_map.dat')
604 self._curr_exporter.write_init_map(subproc_path,
605 self._curr_matrix_elements.get('initial_states'))
606
607 cpu_time1 = time.time()
608
609
611 """Main commands: Ask for editing the parameters and then execute the code (NLO or aMC@(N)LO)
612 """
613 old_cwd = os.getcwd()
614 argss = self.split_arg(line)
615
616 (options, argss) = _launch_parser.parse_args(argss)
617 options = options.__dict__
618 self.check_launch(argss, options)
619 if not os.path.isdir(os.path.join(os.getcwd(), argss[0], 'Events')):
620 self.do_switch('ML5')
621 return mg_interface.MadGraphCmd.do_launch(self,line)
622
623
624
625
626 if options['interactive']:
627 if hasattr(self, 'do_shell'):
628 ME = run_interface.aMCatNLOCmdShell(me_dir=argss[0], options=self.options)
629 else:
630 ME = run_interface.aMCatNLOCmd(me_dir=argss[0],options=self.options)
631 ME.pass_in_web_mode()
632
633 config_line = [l for l in self.history if l.strip().startswith('set')]
634 for line in config_line:
635 ME.exec_cmd(line)
636 stop = self.define_child_cmd_interface(ME)
637 return stop
638
639 ext_program = launch_ext.aMCatNLOLauncher(argss[0], self, run_mode=argss[1], **options)
640 ext_program.run()
641
642
643
646
647 _launch_usage = "launch [DIRPATH] [MODE] [options]\n" + \
648 "-- execute the aMC@NLO output present in DIRPATH\n" + \
649 " By default DIRPATH is the latest created directory\n" + \
650 " MODE can be either LO, NLO, aMC@NLO or aMC@LO (if omitted, it is asked in a separate question)\n" + \
651 " If mode is set to LO/NLO, no event generation will be performed, but only the \n" + \
652 " computation of the total cross-section and the filling of parton-level histograms \n" + \
653 " specified in the DIRPATH/SubProcesses/madfks_plot.f file.\n" + \
654 " If mode is set to aMC@LO/aMC@NLO, after the cross-section computation, a .lhe \n" + \
655 " event file is generated which will be showered with the MonteCarlo specified \n" + \
656 " in the run_card.dat\n"
657
658 _launch_parser = misc.OptionParser(usage=_launch_usage)
659 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
660 help="Use the card present in the directory for the launch, without editing them")
661 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
662 help="Submit the jobs on the cluster")
663 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
664 help="Use interactive consol")
665 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
666 help="Submit the jobs on multicore mode")
667 _launch_parser.add_option("-x", "--nocompile", default=False, action='store_true',
668 help="Skip compilation. Ignored if no executable is found")
669 _launch_parser.add_option("-r", "--reweightonly", default=False, action='store_true',
670 help="Skip integration and event generation, just run reweight on the" + \
671 " latest generated event files (see list in SubProcesses/nevents_unweighted)")
672 _launch_parser.add_option("-p", "--parton", default=False, action='store_true',
673 help="Stop the run after the parton level file generation (you need " + \
674 "to shower the file in order to get physical results)")
675 _launch_parser.add_option("-o", "--only_generation", default=False, action='store_true',
676 help="Skip grid set up, just generate events starting from " + \
677 "the last available results")
678
679
680 _launch_parser.add_option("-n", "--name", default=False, dest='name',
681 help="Provide a name to the run")
682 _launch_parser.add_option("-a", "--appl_start_grid", default=False, dest='appl_start_grid',
683 help="For use with APPLgrid only: start from existing grids")
684 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true',
685 help="Run the reweight module (reweighting by different model parameter")
686 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true',
687 help="Run the madspin package")
688