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 from __future__ import absolute_import
20 from __future__ import print_function
21 import os
22 import logging
23 import pydoc
24 import sys
25 import time
26 import optparse
27 import subprocess
28 import shutil
29 import copy
30 import multiprocessing
31 import signal
32 import tempfile
33 import itertools
34 import os
35 import six.moves.cPickle
36
37
38 import madgraph
39 from madgraph import MG4DIR, MG5DIR, MadGraph5Error
40 import madgraph.interface.extended_cmd as cmd
41 import madgraph.interface.madgraph_interface as mg_interface
42 import madgraph.interface.madevent_interface as me_interface
43 import madgraph.interface.extended_cmd as extended_cmd
44 import madgraph.interface.amcatnlo_run_interface as run_interface
45 import madgraph.interface.launch_ext_program as launch_ext
46 import madgraph.interface.loop_interface as Loop_interface
47 import madgraph.fks.fks_common as fks_common
48 import madgraph.fks.fks_base as fks_base
49 import madgraph.fks.fks_helas_objects as fks_helas
50 import madgraph.iolibs.export_fks as export_fks
51 import madgraph.iolibs.export_v4 as export_v4
52 import madgraph.iolibs.helas_call_writers as helas_call_writers
53 import madgraph.loop.loop_base_objects as loop_base_objects
54 import madgraph.core.diagram_generation as diagram_generation
55 import madgraph.core.helas_objects as helas_objects
56
57 import madgraph.various.cluster as cluster
58 import madgraph.various.misc as misc
59 import madgraph.various.banner as banner_mod
60 from six.moves import range
61
62
63 pjoin = os.path.join
64
65
66 logger = logging.getLogger('cmdprint')
67 logger_stderr = logging.getLogger('fatalerror')
68
69
70 glob_directories_map = []
72
73 arglist = glob_directories_map[i]
74
75 curr_exporter = arglist[0]
76 mefile = arglist[1]
77 curr_fortran_model = arglist[2]
78 ime = arglist[3]
79 nme = arglist[4]
80 path = arglist[5]
81 olpopts = arglist[6]
82
83 infile = open(mefile,'rb')
84 me = six.moves.cPickle.load(infile)
85 infile.close()
86
87 calls = curr_exporter.generate_directories_fks(me, curr_fortran_model, ime, nme, path, olpopts)
88
89 nexternal = curr_exporter.proc_characteristic['nexternal']
90 ninitial = curr_exporter.proc_characteristic['ninitial']
91 max_n_matched_jets = curr_exporter.proc_characteristic['max_n_matched_jets']
92 splitting_types = curr_exporter.proc_characteristic['splitting_types']
93
94 processes = me.born_me.get('processes')
95
96
97 max_loop_vertex_rank = -99
98 if me.virt_matrix_element:
99 max_loop_vertex_rank = me.virt_matrix_element.get_max_loop_vertex_rank()
100 if six.PY2:
101 return [calls, curr_exporter.fksdirs, max_loop_vertex_rank, ninitial, nexternal, processes, max_n_matched_jets, splitting_types]
102 else:
103 return [calls, curr_exporter.fksdirs, max_loop_vertex_rank, ninitial, nexternal, None,max_n_matched_jets, splitting_types]
104
105 -class CheckFKS(mg_interface.CheckValidForCmd):
106
107
109 """ Check the arguments of the display diagrams command in the context
110 of the Loop interface."""
111
112 mg_interface.MadGraphCmd.check_display(self,args)
113
114 if args[0] in ['diagrams', 'processes'] and len(args)>=3 \
115 and args[1] not in ['born','loop','virt','real']:
116 raise self.InvalidCmd("Can only display born, loop (virt) or real diagrams, not %s."%args[1])
117
118 if len(args) > 1:
119 if args[1] == 'virt':
120 args[1] = 'loop'
121
127
135
137 """ check the validity of the line"""
138
139 self._export_format = 'NLO'
140 forbidden_formats = ['madevent', 'standalone']
141
142
143 if not hasattr(self, '_fks_multi_proc') or not self._fks_multi_proc:
144 text = 'No processes generated. Please generate a process first.'
145 raise self.InvalidCmd(text)
146
147 if not self._curr_model:
148 text = 'No model found. Please import a model first and then retry.'
149 raise self.InvalidCmd(text)
150
151 if args and args[0][0] != '-':
152 if args[0] in forbidden_formats:
153 text = 'You generated a NLO process, which cannot be exported in %s mode.\n' % args[0]
154 text+= 'Please use the command "output DIR_NAME".\n'
155 raise self.InvalidCmd(text)
156
157
158 path = args.pop(0)
159
160 if path == 'auto':
161 self.get_default_path()
162 elif path != 'auto':
163 self._export_dir = path
164 else:
165
166 self.get_default_path()
167
168 self._export_dir = os.path.realpath(self._export_dir)
169
170
172 """check the validity of the line. args are DIR and MODE
173 MODE being LO, NLO, aMC@NLO or aMC@LO. If no mode is passed, aMC@NLO is used"""
174
175
176
177 if not args:
178 if self._done_export:
179 args.append(self._done_export[0])
180 args.append('auto')
181
182 return
183 else:
184 self.help_launch()
185 raise self.InvalidCmd('No default location available, please specify location.')
186
187 if len(args) > 2:
188 self.help_launch()
189 return self.InvalidCmd, 'Invalid Syntax: Too many argument'
190
191 elif len(args) == 2:
192 if not args[1] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'auto']:
193 raise self.InvalidCmd('%s is not a valid mode, please use "LO", "NLO", "aMC@NLO" or "aMC@LO"' % args[1])
194 else:
195
196 if args[0] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'auto'] and self._done_export:
197 args.insert(0, self._done_export[0])
198 elif os.path.isdir(args[0]) or os.path.isdir(pjoin(MG5DIR, args[0]))\
199 or os.path.isdir(pjoin(MG4DIR, args[0])):
200 args.append('auto')
201 else:
202 self.help_launch()
203 raise self.InvalidCmd('%s is not a valid process directory nor run mode' % args[0])
204
205 mode = args[1]
206
207
208 if os.path.isdir(args[0]):
209 path = os.path.realpath(args[0])
210 elif os.path.isdir(pjoin(MG5DIR,args[0])):
211 path = pjoin(MG5DIR,args[0])
212 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
213 path = pjoin(MG4DIR,args[0])
214 else:
215 raise self.InvalidCmd('%s is not a valid directory' % args[0])
216 args[0] = path
217
218
219 self._done_export = [path, mode]
220
221
222 if options['multicore'] and options['cluster']:
223 raise self.InvalidCmd('options -m (--multicore) and -c (--cluster)' + \
224 ' are not compatible. Please choose one.')
225 if mode == 'NLO' and options['reweightonly']:
226 raise self.InvalidCmd('option -r (--reweightonly) needs mode "aMC@NLO" or "aMC@LO"')
227
228
229 -class CheckFKSWeb(mg_interface.CheckValidForCmdWeb, CheckFKS):
231
233
235 """Complete the display command in the context of the FKS interface"""
236
237 args = self.split_arg(line[0:begidx])
238
239 if len(args) == 2 and args[1] in ['diagrams', 'processes']:
240 return self.list_completion(text, ['born', 'loop', 'virt', 'real'])
241 else:
242 return mg_interface.MadGraphCmd.complete_display(self, text, line,
243 begidx, endidx)
244
245
247 """Complete the output command in the context of the FKS interface"""
248
249 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
250 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
251 'mg5', 'DECAY', 'EventConverter', 'Models',
252 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha',
253 'madgraph', 'bin', 'tests', 'input', 'vendor', 'models']
254
255
256 args = self.split_arg(line[0:begidx])
257 if len(args) >= 1:
258 if len(args) > 1 and args[1] == 'aloha':
259 try:
260 return self.aloha_complete_output(text, line, begidx, endidx)
261 except Exception as error:
262 print(error)
263
264 if args[-1].endswith(os.path.sep):
265 return [name for name in self.path_completion(text,
266 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
267 only_dirs = True) if name not in forbidden_names]
268
269
270 content = [name for name in self.path_completion(text, '.', only_dirs = True) \
271 if name not in forbidden_names]
272 return self.list_completion(text, content)
273
274
276 """ complete the launch command"""
277 args = self.split_arg(line[0:begidx])
278
279
280 if args[-1].endswith(os.path.sep):
281 return self.path_completion(text,
282 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
283 only_dirs = True)
284
285 if len(args) == 1:
286 out = {'Path from ./': self.path_completion(text, '.', only_dirs = True)}
287 if MG5DIR != os.path.realpath('.'):
288 out['Path from %s' % MG5DIR] = self.path_completion(text,
289 MG5DIR, only_dirs = True, relative=False)
290 if MG4DIR and MG4DIR != os.path.realpath('.') and MG4DIR != MG5DIR:
291 out['Path from %s' % MG4DIR] = self.path_completion(text,
292 MG4DIR, only_dirs = True, relative=False)
293
294 if len(args) == 2:
295 modes = ['aMC@NLO', 'NLO', 'aMC@LO', 'LO']
296 return self.list_completion(text, modes, line)
297
298
299 if len(args) >= 3:
300 out={}
301
302 if line[0:begidx].endswith('--laststep='):
303 opt = ['parton', 'pythia', 'pgs','delphes','auto']
304 out['Options'] = self.list_completion(text, opt, line)
305 else:
306
307 opt = ['-f', '-c', '-m', '-i', '-x', '-r', '-p', '-o', '-n', 'a',
308 '--force', '--cluster', '--multicore', '--interactive',
309 '--nocompile', '--reweightonly', '--parton', '--only_generation', '--name', '--appl_start_grid']
310 out['Options'] = self.list_completion(text, opt, line)
311
312
313 return self.deal_multiple_categories(out, formatting)
314
315 -class HelpFKS(mg_interface.HelpToCmd):
316
318 mg_interface.MadGraphCmd.help_display(self)
319 logger.info(" In aMC@NLO5, after display diagrams, the user can add the option")
320 logger.info(" \"born\", \"virt\" or \"real\" to display only the corresponding diagrams.")
321
325
326 -class aMCatNLOInterface(CheckFKS, CompleteFKS, HelpFKS, Loop_interface.CommonLoopInterface):
327
328 _fks_display_opts = ['real_diagrams', 'born_diagrams', 'virt_diagrams',
329 'real_processes', 'born_processes', 'virt_processes']
330
331 _nlo_modes_for_completion = ['all','real']
332 display_expansion = False
333
334 - def __init__(self, mgme_dir = '', *completekey, **stdin):
335 """ Special init tasks for the Loop Interface """
336 mg_interface.MadGraphCmd.__init__(self, mgme_dir = '', *completekey, **stdin)
337 self.setup()
338
340 """ Special tasks when switching to this interface """
341
342
343
344
345
346
347 self.history.clean(remove_bef_last='import',
348 to_keep=['set','load','import', 'define'])
349
350 self._done_export=False
351 self._curr_amps = diagram_generation.AmplitudeList()
352 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
353 self._v4_export_formats = []
354 self._nlo_modes_for_completion = ['all','real']
355 self._export_formats = [ 'madevent', 'aloha' ]
356
357
358 self.validate_model(loop_type='real_init', stop=False)
359
360
361
362 self._cuttools_dir=str(pjoin(self._mgme_dir,'vendor','CutTools'))
363 if not os.path.isdir(pjoin(self._cuttools_dir, 'src','cts')):
364 logger.warning(('Warning: Directory %s is not a valid CutTools directory.'+\
365 'Using default CutTools instead.') % \
366 self._cuttools_dir)
367 self._cuttools_dir=str(pjoin(self._mgme_dir,'vendor','CutTools'))
368
369 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
370 if not os.path.isdir(self._iregi_dir):
371 logger.warning(('Warning: Directory %s is not a valid IREGI directory.'+\
372 'Using default IREGI instead.')%\
373 self._iregi_dir)
374 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
375
377
378 args = self.split_arg(line)
379
380 self.check_display(args)
381
382 if args[0] in ['diagrams', 'processes', 'diagrams_text']:
383 get_amps_dict = {'real': self._fks_multi_proc.get_real_amplitudes,
384 'born': self._fks_multi_proc.get_born_amplitudes,
385 'loop': self._fks_multi_proc.get_virt_amplitudes}
386 if args[0] == 'diagrams':
387 if len(args)>=2 and args[1] in list(get_amps_dict.keys()):
388 get_amps = get_amps_dict[args[1]]
389 self._curr_amps = get_amps()
390
391 if args[1] == 'loop' and len(self._curr_amps) == 0:
392 raise self.InvalidCmd('No virtuals have been generated')
393 self.draw(' '.join(args[2:]), Dtype = args[1])
394 else:
395 for diag_type, get_amps in get_amps_dict.items():
396 self._curr_amps = get_amps()
397 if self._curr_amps:
398 self.draw(' '.join(args[1:]), Dtype=diag_type)
399
400
401 self._curr_amps = diagram_generation.AmplitudeList()
402
403 if args[0] == 'diagrams_text':
404 if len(args)>=2 and args[1] in list(get_amps_dict.keys()):
405 get_amps = get_amps_dict[args[1]]
406 self._curr_amps = get_amps()
407
408 if args[1] in ['virt', 'loop'] and len(self._curr_amps) == 0:
409 raise self.InvalidCmd('No virtuals have been generated')
410 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
411 else:
412 text = 'Born diagrams:\n'
413 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['born']())
414 text += '\n\nReal diagrams:'
415 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['real']())
416 text += '\n\nLoop diagrams:\n'
417 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['loop']())
418 pydoc.pager(text)
419
420
421 self._curr_amps = diagram_generation.AmplitudeList()
422
423 elif args[0] == 'processes':
424 if len(args)>=2 and args[1] in list(get_amps_dict.keys()):
425 get_amps = get_amps_dict[args[1]]
426 self._curr_amps = get_amps()
427
428 if args[1] in ['virt', 'loop'] and len(self._curr_amps) == 0:
429 raise self.InvalidCmd('No virtuals have been generated')
430 print('\n'.join(amp.nice_string_processes() for amp in self._curr_amps))
431 else:
432 print('Born processes:')
433 print('\n'.join(amp.nice_string_processes() for amp in get_amps_dict['born']()))
434 print('Real processes:')
435 print('\n'.join(amp.nice_string_processes() for amp in get_amps_dict['real']()))
436 print('Loop processes:')
437 print('\n'.join(amp.nice_string_processes() for amp in get_amps_dict['loop']()))
438
439 self._curr_amps = diagram_generation.AmplitudeList()
440
441 else:
442 mg_interface.MadGraphCmd.do_display(self,line,output)
443
444 - def do_add(self, line, *args,**opt):
445
446 args = self.split_arg(line)
447
448 self.check_add(args)
449
450 if args[0] == 'model':
451 return self.add_model(args[1:])
452 elif args[0] != 'process':
453 raise self.InvalidCmd("The add command can only be used with process or model")
454 else:
455 line = ' '.join(args[1:])
456
457 proc_type=self.extract_process_type(line)
458 if proc_type[1] not in ['real', 'LOonly']:
459 run_interface.check_compiler(self.options, block=False)
460
461
462
463 if not aMCatNLOInterface.display_expansion:
464 if proc_type[2] != ['QCD'] and proc_type[1] == 'all':
465 aMCatNLOInterface.display_expansion = True
466 if 'QED' in proc_type[2]:
467 logger.info(
468 """------------------------------------------------------------------------
469 This computation involves NLO EW corrections.
470 Please also cite ref. 'arXiv:1804.10017' when using results from this code.
471 ------------------------------------------------------------------------
472 """, '$MG:BOLD')
473 else:
474 logger.info(
475 """------------------------------------------------------------------------
476 This computation involve not SM-QCD corrections at NLO.
477 Please also cite ref. 'arXiv:1804.10017' when using results from this code.
478 ------------------------------------------------------------------------
479 """, '$MG:BOLD')
480
481
482 geninfo = self._generate_info
483 self.validate_model(proc_type[1], coupling_type=proc_type[2])
484 self._generate_info = geninfo
485
486
487
488 collect_mirror_procs = False
489 ignore_six_quark_processes = self.options['ignore_six_quark_processes']
490 if ',' in line:
491 myprocdef, line = mg_interface.MadGraphCmd.extract_decay_chain_process(self,line)
492 if myprocdef.are_decays_perturbed():
493 raise MadGraph5Error("Decay processes cannot be perturbed")
494 else:
495 myprocdef = mg_interface.MadGraphCmd.extract_process(self,line)
496
497 self.proc_validity(myprocdef,'aMCatNLO_%s'%proc_type[1])
498
499
500
501
502
503 if myprocdef['orders'] and not all([o in list(myprocdef['orders'].keys()) for o in myprocdef['model'].get_coupling_orders()]):
504 for o in myprocdef['model'].get_coupling_orders():
505 if o not in list(myprocdef['orders'].keys()):
506 myprocdef['orders'][o] = self.options['default_unset_couplings']
507 logger.warning(('%s order is missing in the process definition. It will be set to "default unser couplings": %s\n' + \
508 'If this is not what you need, please regenerate with the correct orders.') % (o,myprocdef['orders'][o]))
509
510
511 if not myprocdef['squared_orders'] and not myprocdef['orders']:
512
513
514 weighted = diagram_generation.MultiProcess.find_optimal_process_orders(myprocdef)
515 if not weighted:
516 raise MadGraph5Error('\nProcess orders cannot be determined automatically. \n' + \
517 'Please specify them from the command line.')
518
519
520 qed, qcd = fks_common.get_qed_qcd_orders_from_weighted(len(myprocdef['legs']),
521 self._curr_model.get('order_hierarchy'),
522 weighted['WEIGHTED'])
523
524 if qed < 0 or qcd < 0:
525 raise MadGraph5Error('\nAutomatic process-order determination lead to negative constraints:\n' + \
526 ('QED: %d, QCD: %d\n' % (qed, qcd)) + \
527 'Please specify the coupling orders from the command line.')
528 if self.options['nlo_mixed_expansion']:
529 orders = {'QED': 2*qed, 'QCD': 2*qcd}
530
531 for o in myprocdef['model'].get_coupling_orders():
532 if o not in ['QED', 'QCD']:
533 orders[o] = 0
534
535 myprocdef.set('squared_orders', orders)
536
537 logger.info(('Setting the born squared orders automatically in the process definition to %s.\n' + \
538 'If this is not what you need, please regenerate with the correct orders.'),
539 ' '.join(['%s^2<=%s' %(k,v) if v else '%s=%s' % (k,v) for k,v in myprocdef['squared_orders'].items()]),
540 '$MG:BOLD')
541 else:
542 orders = {'QED': qed, 'QCD': qcd}
543 sqorders = {'QED': 2*qed, 'QCD': 2*qcd}
544
545 for o in myprocdef['model'].get_coupling_orders():
546 if o not in ['QED', 'QCD']:
547 orders[o] = 0
548 sqorders[o] = 0
549
550 myprocdef.set('orders', orders)
551 myprocdef.set('squared_orders', sqorders)
552
553 logger.info(('Setting the born orders automatically in the process definition to %s.\n' + \
554 'If this is not what you need, please regenerate with the correct orders.'),
555 ' '.join(['%s<=%s' %(k,v) if v else '%s=%s' % (k,v) for k,v in myprocdef['orders'].items()]),
556 '$MG:BOLD')
557
558
559
560 for k, v in myprocdef['orders'].items():
561 if k not in myprocdef['squared_orders'].keys():
562 myprocdef['squared_orders'][k] = 2*v
563 logger.warning('Order %s is not constrained as squared_orders. Using: %s^2=%d' % (k,k,2*v) )
564
565
566
567 for o in myprocdef['model'].get('coupling_orders'):
568 if o not in myprocdef['squared_orders'].keys():
569 logger.warning('No squared order constraint for order %s. Setting to 0' % o)
570 myprocdef['squared_orders'][o] = 0
571
572 myprocdef['born_sq_orders'] = copy.copy(myprocdef['squared_orders'])
573
574
575
576 myprocdef['split_orders'] += [o for o in myprocdef['model'].get('coupling_orders') \
577 if o not in myprocdef['split_orders']]
578
579
580 if not myprocdef['squared_orders']:
581 logger.warning('No squared orders have been provided, will be guessed by the order constraints')
582 for ord, val in myprocdef['orders'].items():
583 myprocdef['squared_orders'][ord] = 2 * val
584
585
586 for pert in myprocdef['perturbation_couplings']:
587
588 if not self.options['nlo_mixed_expansion'] and pert not in proc_type[2]:
589 continue
590
591
592
593 if list(myprocdef['orders'].keys()) != ['WEIGHTED']:
594 try:
595 myprocdef['orders'][pert] += 1
596 except KeyError:
597
598
599
600 pass
601 try:
602 myprocdef['squared_orders'][pert] += 2
603 except KeyError:
604
605
606 myprocdef['squared_orders'][pert] = 2
607
608
609 if 'WEIGHTED' in list(myprocdef['orders'].keys()):
610 myprocdef['orders']['WEIGHTED'] += 1 * \
611 max([myprocdef.get('model').get('order_hierarchy')[ord] for \
612 ord in myprocdef['perturbation_couplings']])
613
614 myprocdef['squared_orders']['WEIGHTED'] += 2 * \
615 max([myprocdef.get('model').get('order_hierarchy')[ord] for \
616 ord in myprocdef['perturbation_couplings']])
617
618
619
620
621
622
623 if not myprocdef['orders'] and self.options['nlo_mixed_expansion']:
624 myprocdef['perturbation_couplings'] = list(myprocdef['model']['coupling_orders'])
625
626 self._curr_proc_defs.append(myprocdef)
627
628
629
630
631
632
633
634 if self.options['low_mem_multicore_nlo_generation']:
635 if self.options['nb_core']:
636 self.ncores_for_proc_gen = int(self.options['nb_core'])
637 else:
638 self.ncores_for_proc_gen = -1
639 else:
640 self.ncores_for_proc_gen = 0
641
642
643 fks_options = {'OLP': self.options['OLP'],
644 'ignore_six_quark_processes': self.options['ignore_six_quark_processes'],
645 'init_lep_split': self.options['include_lepton_initiated_processes'],
646 'ncores_for_proc_gen': self.ncores_for_proc_gen,
647 'nlo_mixed_expansion': self.options['nlo_mixed_expansion']}
648
649 fksproc =fks_base.FKSMultiProcess(myprocdef,fks_options)
650 try:
651 self._fks_multi_proc.add(fksproc)
652 except AttributeError:
653 self._fks_multi_proc = fksproc
654
655 if not aMCatNLOInterface.display_expansion and self.options['nlo_mixed_expansion']:
656 base = {}
657 for amp in self._fks_multi_proc.get_born_amplitudes():
658 nb_part = len(amp['process']['legs'])
659 for diag in amp['diagrams']:
660 if nb_part not in base:
661 base[nb_part] = diag.get('orders')
662 elif base[nb_part] != diag.get('orders'):
663 aMCatNLOInterface.display_expansion = True
664 logger.info(
665 """------------------------------------------------------------------------
666 This computation can involve not only purely SM-QCD corrections at NLO.
667 Please also cite ref. 'arXiv:1804.10017' when using results from this code.
668 ------------------------------------------------------------------------
669 """, '$MG:BOLD')
670 break
671 else:
672 continue
673 break
674
675
676
677
679 """Main commands: Initialize a new Template or reinitialize one"""
680
681 args = self.split_arg(line)
682
683 self.check_output(args)
684
685 noclean = '-noclean' in args
686 force = '-f' in args
687 nojpeg = '-nojpeg' in args
688 main_file_name = ""
689 try:
690 main_file_name = args[args.index('-name') + 1]
691 except Exception:
692 pass
693
694
695 group_processes = False
696
697 if self._export_format in ['NLO']:
698 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
699 output_type='amcatnlo',group_subprocesses=group_processes)
700
701 self._curr_exporter.pass_information_from_cmd(self)
702
703
704 if not force and not noclean and os.path.isdir(self._export_dir)\
705 and self._export_format in ['NLO']:
706
707 logger.info('INFO: directory %s already exists.' % self._export_dir)
708 logger.info('If you continue this directory will be deleted and replaced.')
709 answer = self.ask('Do you want to continue?', 'y', ['y','n'],
710 timeout=self.options['timeout'])
711 if answer != 'y':
712 raise self.InvalidCmd('Stopped by user request')
713
714
715
716 if os.path.exists(self._export_dir):
717 shutil.rmtree(self._export_dir)
718
719
720 if self._export_format in ['NLO']:
721 self._curr_exporter.copy_fkstemplate()
722
723
724 self._done_export = False
725
726
727 self.export(nojpeg, main_file_name, group_processes=group_processes)
728
729
730 self._curr_exporter.pass_information_from_cmd(self)
731
732
733 self.finalize(nojpeg)
734
735
736 if self.options['OLP']!='MadLoop':
737 self._curr_exporter.generate_virtuals_from_OLP(
738 self.born_processes_for_olp,self._export_dir,self.options['OLP'])
739
740
741 self._done_export = (self._export_dir, self._export_format)
742
743
744 self._export_dir = None
745
746
747 - def export(self, nojpeg = False, main_file_name = "", group_processes=False):
818
819
820
821 ndiags, cpu_time = generate_matrix_elements(self, group=group_processes)
822 calls = 0
823
824 path = self._export_dir
825
826 if self._export_format in ['NLO']:
827 path = os.path.join(path, 'SubProcesses')
828
829
830 self._fks_directories = []
831 proc_charac = self._curr_exporter.proc_characteristic
832 for charac in ['has_isr', 'has_fsr', 'has_loops']:
833 proc_charac[charac] = self._curr_matrix_elements[charac]
834
835
836
837 global glob_directories_map
838 glob_directories_map = []
839
840
841 self.born_processes_for_olp = []
842 self.born_processes = []
843 for ime, me in \
844 enumerate(self._curr_matrix_elements.get('matrix_elements')):
845 if not self.options['low_mem_multicore_nlo_generation']:
846
847 calls = calls + \
848 self._curr_exporter.generate_directories_fks(me,
849 self._curr_helas_model,
850 ime, len(self._curr_matrix_elements.get('matrix_elements')),
851 path,self.options['OLP'])
852 self._fks_directories.extend(self._curr_exporter.fksdirs)
853 self.born_processes_for_olp.append(me.born_me.get('processes')[0])
854 self.born_processes.append(me.born_me.get('processes'))
855 else:
856 glob_directories_map.append(\
857 [self._curr_exporter, me, self._curr_helas_model,
858 ime, len(self._curr_matrix_elements.get('matrix_elements')),
859 path, self.options['OLP']])
860
861 if self.options['low_mem_multicore_nlo_generation']:
862
863 logger.info('Writing directories...')
864 if six.PY3:
865 ctx = multiprocessing.get_context('fork')
866 else:
867 ctx = multiprocessing
868 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
869 if self.ncores_for_proc_gen < 0:
870 pool = ctx.Pool(maxtasksperchild=1)
871 else:
872 pool = ctx.Pool(processes=self.ncores_for_proc_gen,maxtasksperchild=1)
873 signal.signal(signal.SIGINT, original_sigint_handler)
874 try:
875
876
877 diroutputmap = pool.map_async(generate_directories_fks_async,
878 list(range(len(glob_directories_map)))).get(9999999)
879 except KeyboardInterrupt:
880 pool.terminate()
881 raise KeyboardInterrupt
882
883 pool.close()
884 pool.join()
885
886
887 for mefile in self._curr_matrix_elements.get('matrix_elements'):
888 os.remove(mefile)
889
890 for charac in ['nexternal', 'ninitial', 'splitting_types']:
891 proc_charac[charac] = self._curr_exporter.proc_characteristic[charac]
892
893
894
895 proc_charac['nexternal'] = max([diroutput[4] for diroutput in diroutputmap])
896 ninitial_set = set([diroutput[3] for diroutput in diroutputmap])
897 if len(ninitial_set) != 1:
898 raise MadGraph5Error("Invalid ninitial values: %s" % ' ,'.join(list(ninitial_set)))
899 proc_charac['ninitial'] = list(ninitial_set)[0]
900
901
902 njet_set = set([int(diroutput[6]) for diroutput in diroutputmap])
903 proc_charac['max_n_matched_jets'] = max(njet_set)
904
905 self.born_processes = []
906 self.born_processes_for_olp = []
907 max_loop_vertex_ranks = []
908
909
910 splitting_types = set(proc_charac['splitting_types'])
911 for diroutput in diroutputmap:
912 splitting_types = splitting_types.union(set(diroutput[7]))
913 calls = calls + diroutput[0]
914 self._fks_directories.extend(diroutput[1])
915 max_loop_vertex_ranks.append(diroutput[2])
916 if six.PY2:
917 self.born_processes.extend(diroutput[4])
918 self.born_processes_for_olp.append(diroutput[4][0])
919
920
921 proc_charac['splitting_types'] = list(splitting_types)
922
923 else:
924 max_loop_vertex_ranks = [me.get_max_loop_vertex_rank() for \
925 me in self._curr_matrix_elements.get_virt_matrix_elements()]
926
927 card_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
928 'procdef_mg5.dat')
929
930 if self.options['loop_optimized_output'] and \
931 len(max_loop_vertex_ranks) > 0:
932 self._curr_exporter.write_coef_specs_file(max_loop_vertex_ranks)
933 if self._generate_info:
934 self._curr_exporter.write_procdef_mg5(card_path,
935 self._curr_model['name'],
936 self._generate_info)
937 try:
938 cmd.Cmd.onecmd(self, 'history .')
939 except Exception:
940 logger.debug('fail to run command \"history cmd\"')
941 pass
942 subproc_path = os.path.join(path, os.path.pardir, 'SubProcesses', \
943 'initial_states_map.dat')
944 nmaxpdf = self._curr_exporter.write_init_map(subproc_path,
945 self._curr_matrix_elements.get('initial_states'))
946 self._curr_exporter.write_maxproc_files(nmaxpdf,
947 os.path.join(path, os.path.pardir, 'SubProcesses'))
948
949 cpu_time1 = time.time()
950
951
953 """Main commands: Ask for editing the parameters and then execute the code (NLO or aMC@(N)LO)
954 """
955 old_cwd = os.getcwd()
956 argss = self.split_arg(line)
957
958 (options, argss) = _launch_parser.parse_args(argss)
959 options = options.__dict__
960 self.check_launch(argss, options)
961 if not os.path.isdir(os.path.join(os.getcwd(), argss[0], 'Events')):
962 self.do_switch('ML5')
963 return mg_interface.MadGraphCmd.do_launch(self,line)
964
965
966
967
968 if options['interactive']:
969 if isinstance(self, extended_cmd.CmdShell):
970 ME = run_interface.aMCatNLOCmdShell(me_dir=argss[0], options=self.options)
971 else:
972 ME = run_interface.aMCatNLOCmd(me_dir=argss[0],options=self.options)
973 ME.pass_in_web_mode()
974
975 config_line = [l for l in self.history if l.strip().startswith('set')]
976 for line in config_line:
977 ME.exec_cmd(line)
978 stop = self.define_child_cmd_interface(ME)
979 return stop
980
981 ext_program = launch_ext.aMCatNLOLauncher(argss[0], self, run_mode=argss[1],
982 shell = isinstance(self, extended_cmd.CmdShell),
983 **options)
984 ext_program.run()
985
986
987
990
991 _launch_usage = "launch [DIRPATH] [MODE] [options]\n" + \
992 "-- execute the aMC@NLO output present in DIRPATH\n" + \
993 " By default DIRPATH is the latest created directory\n" + \
994 " MODE can be either LO, NLO, aMC@NLO or aMC@LO (if omitted, it is asked in a separate question)\n" + \
995 " If mode is set to LO/NLO, no event generation will be performed, but only the \n" + \
996 " computation of the total cross-section and the filling of parton-level histograms \n" + \
997 " specified in the DIRPATH/SubProcesses/madfks_plot.f file.\n" + \
998 " If mode is set to aMC@LO/aMC@NLO, after the cross-section computation, a .lhe \n" + \
999 " event file is generated which will be showered with the MonteCarlo specified \n" + \
1000 " in the run_card.dat\n"
1001
1002 _launch_parser = misc.OptionParser(usage=_launch_usage)
1003 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
1004 help="Use the card present in the directory for the launch, without editing them")
1005 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
1006 help="Submit the jobs on the cluster")
1007 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
1008 help="Use interactive consol")
1009 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
1010 help="Submit the jobs on multicore mode")
1011 _launch_parser.add_option("-x", "--nocompile", default=False, action='store_true',
1012 help="Skip compilation. Ignored if no executable is found")
1013 _launch_parser.add_option("-r", "--reweightonly", default=False, action='store_true',
1014 help="Skip integration and event generation, just run reweight on the" + \
1015 " latest generated event files (see list in SubProcesses/nevents_unweighted)")
1016 _launch_parser.add_option("-p", "--parton", default=False, action='store_true',
1017 help="Stop the run after the parton level file generation (you need " + \
1018 "to shower the file in order to get physical results)")
1019 _launch_parser.add_option("-o", "--only_generation", default=False, action='store_true',
1020 help="Skip grid set up, just generate events starting from " + \
1021 "the last available results")
1022
1023
1024 _launch_parser.add_option("-n", "--name", default=False, dest='name',
1025 help="Provide a name to the run")
1026 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true',
1027 help="Run the reweight module (reweighting by different model parameter")
1028 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true',
1029 help="Run the madspin package")
1030