1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """A user friendly command line interface to access MadGraph5_aMC@NLO features at LO.
16 Uses the cmd package for command interpretation and tab completion.
17 """
18 from __future__ import division
19
20 import atexit
21 import collections
22 import cmath
23 import glob
24 import logging
25 import optparse
26 import os
27 import pydoc
28 import random
29 import re
30 import signal
31 import subprocess
32 import copy
33 import sys
34 import shutil
35 import StringIO
36 import traceback
37 import time
38 import inspect
39 import urllib
40
41
42
43 pjoin = os.path.join
44
45 try:
46 import readline
47 GNU_SPLITTING = ('GNU' in readline.__doc__)
48 except:
49 GNU_SPLITTING = True
50
51 import aloha
52 import madgraph
53 from madgraph import MG4DIR, MG5DIR, MadGraph5Error
54
55
56 import madgraph.core.base_objects as base_objects
57 import madgraph.core.diagram_generation as diagram_generation
58 import madgraph.loop.loop_diagram_generation as loop_diagram_generation
59 import madgraph.loop.loop_base_objects as loop_base_objects
60 import madgraph.core.drawing as draw_lib
61 import madgraph.core.helas_objects as helas_objects
62
63 import madgraph.iolibs.drawing_eps as draw
64 import madgraph.iolibs.export_cpp as export_cpp
65 import madgraph.iolibs.export_v4 as export_v4
66 import madgraph.loop.loop_exporters as loop_exporters
67 import madgraph.iolibs.helas_call_writers as helas_call_writers
68 import madgraph.iolibs.file_writers as writers
69 import madgraph.iolibs.files as files
70 import madgraph.iolibs.group_subprocs as group_subprocs
71 import madgraph.iolibs.import_v4 as import_v4
72 import madgraph.iolibs.save_load_object as save_load_object
73
74 import madgraph.interface.extended_cmd as cmd
75 import madgraph.interface.tutorial_text as tutorial_text
76 import madgraph.interface.tutorial_text_nlo as tutorial_text_nlo
77 import madgraph.interface.tutorial_text_madloop as tutorial_text_madloop
78 import madgraph.interface.launch_ext_program as launch_ext
79 import madgraph.interface.madevent_interface as madevent_interface
80 import madgraph.interface.amcatnlo_run_interface as amcatnlo_run
81
82 import madgraph.various.process_checks as process_checks
83 import madgraph.various.banner as banner_module
84 import madgraph.various.misc as misc
85 import madgraph.various.cluster as cluster
86
87 import models as ufomodels
88 import models.import_ufo as import_ufo
89 import models.write_param_card as param_writer
90 import models.check_param_card as check_param_card
91 import models.model_reader as model_reader
92
93 import aloha.aloha_fct as aloha_fct
94 import aloha.create_aloha as create_aloha
95 import aloha.aloha_lib as aloha_lib
96
97 import mg5decay.decay_objects as decay_objects
98
99
100 logger = logging.getLogger('cmdprint')
101 logger_mg = logging.getLogger('madgraph')
102 logger_stderr = logging.getLogger('fatalerror')
103 logger_tuto = logging.getLogger('tutorial')
104
105 logger_tuto_nlo = logging.getLogger('tutorial_aMCatNLO')
106
107
108 logger_tuto_madloop = logging.getLogger('tutorial_MadLoop')
114 """Particularisation of the cmd command for MG5"""
115
116
117 next_possibility = {
118 'start': ['import model ModelName', 'import command PATH',
119 'import proc_v4 PATH', 'tutorial'],
120 'import model' : ['generate PROCESS','define MULTIPART PART1 PART2 ...',
121 'display particles', 'display interactions'],
122 'define': ['define MULTIPART PART1 PART2 ...', 'generate PROCESS',
123 'display multiparticles'],
124 'generate': ['add process PROCESS','output [OUTPUT_TYPE] [PATH]','display diagrams'],
125 'add process':['output [OUTPUT_TYPE] [PATH]', 'display processes'],
126 'output':['launch','open index.html','history PATH', 'exit'],
127 'display': ['generate PROCESS', 'add process PROCESS', 'output [OUTPUT_TYPE] [PATH]'],
128 'import proc_v4' : ['launch','exit'],
129 'launch': ['open index.html','exit'],
130 'tutorial': ['generate PROCESS', 'import model MODEL', 'help TOPIC']
131 }
132
133 debug_output = 'MG5_debug'
134 error_debug = 'Please report this bug on https://bugs.launchpad.net/madgraph5\n'
135 error_debug += 'More information is found in \'%(debug)s\'.\n'
136 error_debug += 'Please attach this file to your report.'
137
138 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/madgraph5\n'
139
140 keyboard_stop_msg = """stopping all operation
141 in order to quit mg5 please enter exit"""
142
143
144 InvalidCmd = madgraph.InvalidCmd
145 ConfigurationError = MadGraph5Error
146
148 """Init history and line continuation"""
149
150
151
152 info = misc.get_pkg_info()
153 info_line = ""
154
155 if info.has_key('version') and info.has_key('date'):
156 len_version = len(info['version'])
157 len_date = len(info['date'])
158 if len_version + len_date < 30:
159 info_line = "#* VERSION %s %s %s *\n" % \
160 (info['version'],
161 (30 - len_version - len_date) * ' ',
162 info['date'])
163
164
165
166 self.history_header = banner_module.ProcCard.history_header % {'info_line': info_line}
167 banner_module.ProcCard.history_header = self.history_header
168
169 if info_line:
170 info_line = info_line[1:]
171
172 logger.info(\
173 "************************************************************\n" + \
174 "* *\n" + \
175 "* W E L C O M E to *\n" + \
176 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
177 "* *\n" + \
178 "* *\n" + \
179 "* * * *\n" + \
180 "* * * * * *\n" + \
181 "* * * * * 5 * * * * *\n" + \
182 "* * * * * *\n" + \
183 "* * * *\n" + \
184 "* *\n" + \
185 info_line + \
186 "* *\n" + \
187 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
188 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
189 "* and *\n" + \
190 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \
191 "* *\n" + \
192 "* Type 'help' for in-line help. *\n" + \
193 "* Type 'tutorial' to learn how MG5 works *\n" + \
194 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \
195 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \
196 "* *\n" + \
197 "************************************************************")
198
199 cmd.Cmd.__init__(self, *arg, **opt)
200
201 self.history = banner_module.ProcCard()
202
203
205 """Default action if line is not recognized"""
206
207
208 log=True
209 if line.startswith('p') or line.startswith('e'):
210 logger.warning("Command %s not recognized. Did you mean \'generate %s\'?. Please try again" %
211 (line.split()[0], line))
212 log=False
213 return super(CmdExtended,self).default(line, log=log)
214
215 - def postcmd(self,stop, line):
216 """ finishing a command
217 This looks if the command add a special post part.
218 This looks if we have to write an additional text for the tutorial."""
219
220 stop = super(CmdExtended, self).postcmd(stop, line)
221
222 if stop == False:
223 return False
224
225 args=line.split()
226
227 if len(args)==0:
228 return stop
229
230
231
232
233 if len(args)==1:
234 command=args[0]
235 else:
236 command = args[0]+'_'+args[1].split('.')[0]
237
238 try:
239 logger_tuto.info(getattr(tutorial_text, command).replace('\n','\n\t'))
240 except Exception:
241 try:
242 logger_tuto.info(getattr(tutorial_text, args[0]).replace('\n','\n\t'))
243 except Exception:
244 pass
245
246 try:
247 logger_tuto_nlo.info(getattr(tutorial_text_nlo, command).replace('\n','\n\t'))
248 except Exception:
249 try:
250 logger_tuto_nlo.info(getattr(tutorial_text_nlo, args[0]).replace('\n','\n\t'))
251 except Exception:
252 pass
253
254 try:
255 logger_tuto_madloop.info(getattr(tutorial_text_madloop, command).replace('\n','\n\t'))
256 except Exception:
257 try:
258 logger_tuto_madloop.info(getattr(tutorial_text_madloop, args[0]).replace('\n','\n\t'))
259 except Exception:
260 pass
261
262 return stop
263
264
266 """return the history header"""
267 return self.history_header % misc.get_time_info()
268
273 """ The Series of help routine for the MadGraphCmd"""
274
276 logger.info("syntax: save %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
277 logger.info("-- save information as file FILENAME",'$MG:color:BLACK')
278 logger.info(" FILENAME is optional for saving 'options'.")
279 logger.info(' By default it uses ./input/mg5_configuration.txt')
280 logger.info(' If you put "global" for FILENAME it will use ~/.mg5/mg5_configuration.txt')
281 logger.info(' If this files exists, it is uses by all MG5 on the system but continues')
282 logger.info(' to read the local options files.')
283
285 logger.info("syntax: load %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
286 logger.info("-- load information from file FILENAME",'$MG:color:BLACK')
287
289 logger.info("syntax: import " + "|".join(self._import_formats) + \
290 " FILENAME",'$MG:color:BLUE')
291 logger.info("-- imports file(s) in various formats",'$MG:color:GREEN')
292 logger.info("")
293 logger.info(" import model MODEL[-RESTRICTION] [OPTIONS]:",'$MG:color:BLACK')
294 logger.info(" Import a UFO model.")
295 logger.info(" MODEL should be a valid UFO model name")
296 logger.info(" Model restrictions are specified by MODEL-RESTRICTION")
297 logger.info(" with the file restrict_RESTRICTION.dat in the model dir.")
298 logger.info(" By default, restrict_default.dat is used.")
299 logger.info(" Specify model_name-full to get unrestricted model.")
300 logger.info(" '--modelname' keeps the original particle names for the model")
301 logger.info("")
302 logger.info(" import model_v4 MODEL [--modelname] :",'$MG:color:BLACK')
303 logger.info(" Import an MG4 model.")
304 logger.info(" Model should be the name of the model")
305 logger.info(" or the path to theMG4 model directory")
306 logger.info(" '--modelname' keeps the original particle names for the model")
307 logger.info("")
308 logger.info(" import proc_v4 [PATH] :",'$MG:color:BLACK')
309 logger.info(" Execute MG5 based on a proc_card.dat in MG4 format.")
310 logger.info(" Path to the proc_card is optional if you are in a")
311 logger.info(" madevent directory")
312 logger.info("")
313 logger.info(" import command PATH :",'$MG:color:BLACK')
314 logger.info(" Execute the list of command in the file at PATH")
315 logger.info("")
316 logger.info(" import banner PATH [--no_launch]:",'$MG:color:BLACK')
317 logger.info(" Rerun the exact same run define in the valid banner.")
318
320 logger.info("syntax: install " + "|".join(self._install_opts),'$MG:color:BLUE')
321 logger.info("-- Download the last version of the program and install it")
322 logger.info(" locally in the current MadGraph5_aMC@NLO version. In order to have")
323 logger.info(" a successful installation, you will need to have an up-to-date")
324 logger.info(" F77 and/or C and Root compiler.")
325 logger.info(" ")
326 logger.info(" \"install update\"",'$MG:color:BLACK')
327 logger.info(" check if your MG5 installation is the latest one.")
328 logger.info(" If not it load the difference between your current version and the latest one,")
329 logger.info(" and apply it to the code. Two options are available for this command:")
330 logger.info(" -f: didn't ask for confirmation if it founds an update.")
331 logger.info(" --timeout=: Change the maximum time allowed to reach the server.")
332
334 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLUE')
335 logger.info("-- display a the status of various internal state variables")
336 logger.info(" for particles/interactions you can specify the name or id of the")
337 logger.info(" particles/interactions to receive more details information.")
338 logger.info(" Example: display particles e+.",'$MG:color:GREEN')
339 logger.info(" > For \"checks\", can specify only to see failed checks.")
340 logger.info(" > For \"diagrams\", you can specify where the file will be written.")
341 logger.info(" Example: display diagrams ./",'$MG:color:GREEN')
342
343
345 """help for launch command"""
346
347
348
349 logger.info("syntax: launch <dir_path> <options>",'$MG:color:BLUE')
350 logger.info("-- execute the aMC@NLO/madevent/standalone/pythia8 output present in dir_path",'$MG:color:BLACK')
351 logger.info("By default, dir_path points to the last created directory.")
352 logger.info("(for pythia8, it should be the Pythia 8 main directory)")
353 logger.info("")
354 logger.info("Launch on madevent/pythia8/standalone outputs:",'$MG:color:BLACK')
355 logger.info(" o Example: launch PROC_sm_1 --name=run2",'$MG:color:GREEN')
356 logger.info(" o Example: launch ../pythia8",'$MG:color:GREEN')
357 logger.info(" > Options:")
358 logger.info(" -h, --help show this help message and exit")
359 logger.info(" -f, --force Use the card present in the directory in order")
360 logger.info(" to launch the different program")
361 logger.info(" -n NAME, --name=NAME Provide a name to the run (for madevent run)")
362 logger.info(" -c, --cluster submit the job on the cluster")
363 logger.info(" -m, --multicore submit the job on multicore core")
364 logger.info(" -i, --interactive Use Interactive Console [if available]")
365 logger.info(" -s LASTSTEP, --laststep=LASTSTEP")
366 logger.info(" last program run in MadEvent run.")
367 logger.info(" [auto|parton|pythia|pgs|delphes]")
368 logger.info("")
369 logger.info("Launch on MadLoop standalone output:",'$MG:color:BLACK')
370 logger.info(" o Example: launch PROC_loop_sm_1 -f",'$MG:color:GREEN')
371 logger.info(" > Simple check of a single Phase-space points.")
372 logger.info(" > You will be asked whether you want to edit the MadLoop ")
373 logger.info(" and model param card as well as the PS point, unless ")
374 logger.info(" the -f option is specified. All other options are ")
375 logger.info(" irrelevant for this kind of launch.")
376 logger.info("")
377 logger.info("Launch on aMC@NLO output:",'$MG:color:BLACK')
378 logger.info(" > launch <dir_path> <mode> <options>",'$MG:color:BLUE')
379 logger.info(" o Example: launch MyProc aMC@NLO -f -p",'$MG:color:GREEN')
380
382 logger.info("syntax: tutorial [" + "|".join(self._tutorial_opts) + "]",'$MG:color:BLUE')
383 logger.info("-- start/stop the MG5 tutorial mode (or stop any other mode)")
384 logger.info("-- aMCatNLO: start aMC@NLO tutorial mode")
385 logger.info("-- MadLoop: start MadLoop tutorial mode")
386
388 logger.info("syntax: open FILE ",'$MG:color:BLUE')
389 logger.info("-- open a file with the appropriate editor.",'$MG:color:BLACK')
390 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
391 logger.info(' the path to the last created/used directory is used')
392 logger.info(' The program used to open those files can be chosen in the')
393 logger.info(' configuration file ./input/mg5_configuration.txt')
394
396 logger.info("syntax: customize_model --save=NAME",'$MG:color:BLUE')
397 logger.info("-- Open an invite where you options to tweak the model.",'$MG:color:BLACK')
398 logger.info(" If you specify the option --save=NAME, this tweak will be")
399 logger.info(" available for future import with the command 'import model XXXX-NAME'")
400
402 logger.info("syntax: output [" + "|".join(self._export_formats) + \
403 "] [path|.|auto] [options]",'$MG:color:BLUE')
404 logger.info("-- Output any generated process(es) to file.",'$MG:color:BLACK')
405 logger.info(" Default mode is madevent. Default path is \'.\' or auto.")
406 logger.info(" mode:",'$MG:color:BLACK')
407 logger.info(" - For MadLoop and aMC@NLO runs, there is only one mode and")
408 logger.info(" it is set by default.")
409 logger.info(" - If mode is madevent, create a MadEvent process directory.")
410 logger.info(" - If mode is standalone, create a Standalone directory")
411 logger.info(" - If mode is matrix, output the matrix.f files for all")
412 logger.info(" generated processes in directory \"path\".")
413 logger.info(" - If mode is standalone_cpp, create a standalone C++")
414 logger.info(" directory in \"path\".")
415 logger.info(" - If mode is pythia8, output all files needed to generate")
416 logger.info(" the processes using Pythia 8. The files are written in")
417 logger.info(" the Pythia 8 directory (default).")
418 logger.info(" NOTE: The Pythia 8 directory is set in the ./input/mg5_configuration.txt")
419 logger.info(" - If mode is aloha: Special syntax output:")
420 logger.info(" syntax: aloha [ROUTINE] [--options]" )
421 logger.info(" valid options for aloha output are:")
422 logger.info(" --format=Fortran|Python|Cpp : defining the output language")
423 logger.info(" --output= : defining output directory")
424 logger.info(" path: The path of the process directory.",'$MG:color:BLACK')
425 logger.info(" If you put '.' as path, your pwd will be used.")
426 logger.info(" If you put 'auto', an automatic directory PROC_XX_n will be created.")
427 logger.info(" options:",'$MG:color:BLACK')
428 logger.info(" -f: force cleaning of the directory if it already exists")
429 logger.info(" -d: specify other MG/ME directory")
430 logger.info(" -noclean: no cleaning performed in \"path\".")
431 logger.info(" -nojpeg: no jpeg diagrams will be generated.")
432 logger.info(" -name: the postfix of the main file in pythia8 mode.")
433 logger.info(" Examples:",'$MG:color:GREEN')
434 logger.info(" output",'$MG:color:GREEN')
435 logger.info(" output standalone MYRUN -f",'$MG:color:GREEN')
436 logger.info(" output pythia8 ../pythia8/ -name qcdprocs",'$MG:color:GREEN')
437
439 logger.info("syntax: check [" + "|".join(self._check_opts) + "] [param_card] process_definition [--energy=] [--split_orders=] [--reduction=]",'$MG:color:BLUE')
440 logger.info("-- check a process or set of processes.",'$MG:color:BLACK')
441 logger.info("General options:",'$MG:color:BLACK')
442 logger.info("o full:",'$MG:color:GREEN')
443 logger.info(" Perform all four checks described below:")
444 logger.info(" permutation, brs, gauge and lorentz_invariance.")
445 logger.info("o permutation:",'$MG:color:GREEN')
446 logger.info(" Check that the model and MG5 are working properly")
447 logger.info(" by generating permutations of the process and checking")
448 logger.info(" that the resulting matrix elements give the same value.")
449 logger.info("o gauge:",'$MG:color:GREEN')
450 logger.info(" Check that processes with massless gauge bosons are")
451 logger.info(" gauge invariant (comparing Feynman and unitary gauges)")
452 logger.info(" This check if for now not available for loop processes.")
453 logger.info("o brs:",'$MG:color:GREEN')
454 logger.info(" Check that the Ward identities are satisfied if the ")
455 logger.info(" process has at least one massless gauge boson as an")
456 logger.info(" external particle.")
457 logger.info("o lorentz_invariance:",'$MG:color:GREEN')
458 logger.info(" Check that the amplitude is lorentz invariant by")
459 logger.info(" comparing the amplitiude in different frames")
460 logger.info("Comments",'$MG:color:GREEN')
461 logger.info(" > If param_card is given, that param_card is used ")
462 logger.info(" instead of the default values for the model.")
463 logger.info(" If that file is an (LHE) event file. The param_card of the banner")
464 logger.info(" is used and the first event compatible with the requested process")
465 logger.info(" is used for the computation of the square matrix elements")
466 logger.info(" > \"--energy=\" allows to change the default value of sqrt(S).")
467 logger.info(" > Except for the 'gauge' test, all checks above are also")
468 logger.info(" available for loop processes with ML5 ('virt=' mode)")
469 logger.info("Example: check full p p > j j",'$MG:color:GREEN')
470 logger.info("Options for loop processes only:",'$MG:color:BLACK')
471 logger.info("o timing:",'$MG:color:GREEN')
472 logger.info(" Generate and output a process and returns detailed")
473 logger.info(" information about the code and a timing benchmark.")
474 logger.info("o stability:",'$MG:color:GREEN')
475 logger.info(" Generate and output a process and returns detailed")
476 logger.info(" statistics about the numerical stability of the code.")
477 logger.info("o profile:",'$MG:color:GREEN')
478 logger.info(" Performs both the timing and stability analysis at once")
479 logger.info(" and outputs the result in a log file without prompting")
480 logger.info(" it to the user.")
481 logger.info("Comments",'$MG:color:GREEN')
482 logger.info(" > These checks are only available for ML5 ('virt=' mode)")
483 logger.info(" > For the 'profile' and 'stability' checks, you can chose")
484 logger.info(" how many PS points should be used for the statistic by")
485 logger.info(" specifying it as an integer just before the [param_card]")
486 logger.info(" optional argument.")
487 logger.info(" > Notice multiparticle labels cannot be used with these checks.")
488 logger.info(" > \"--reduction=\" allows to change what reduction methods should be used.")
489 logger.info(" > \"--split_orders=\" allows to change what specific combination of coupling orders to consider.")
490 logger.info(" > For process syntax, please see help generate.")
491 logger.info(" > In order to save the directory generated or the reuse an existing one")
492 logger.info(" previously generated with the check command, one can add the '-reuse' ")
493 logger.info(" keyword just after the specification of the type of check desired.")
494 logger.info("Example: check profile g g > t t~ [virt=QCD]",'$MG:color:GREEN')
495
496
498
499 logger.info("-- generate diagrams for a given process",'$MG:color:BLUE')
500 logger.info("General leading-order syntax:",'$MG:color:BLACK')
501 logger.info(" o generate INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2^2=ORDER2 @N")
502 logger.info(" o Example: generate l+ vl > w+ > l+ vl a $ z / a h QED=3 QCD=0 @1",'$MG:color:GREEN')
503 logger.info(" > Alternative required s-channels can be separated by \"|\":")
504 logger.info(" b b~ > W+ W- | H+ H- > ta+ vt ta- vt~")
505 logger.info(" > If no coupling orders are given, MG5 will try to determine")
506 logger.info(" orders to ensure maximum number of QCD vertices.")
507 logger.info(" > Desired coupling orders combination can be specified directly for")
508 logger.info(" the squared matrix element by appending '^2' to the coupling name.")
509 logger.info(" For example, 'p p > j j QED^2==2 QCD^==2' selects the QED-QCD")
510 logger.info(" interference terms only. The other two operators '<=' and '>' are")
511 logger.info(" supported. Finally, a negative value COUP^2==-I refers to the")
512 logger.info(" N^(-I+1)LO term in the expansion of the COUP order.")
513 logger.info(" > To generate a second process use the \"add process\" command")
514 logger.info("Decay chain syntax:",'$MG:color:BLACK')
515 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
516 logger.info(" o Example: generate p p > t~ t QED=0, (t~ > W- b~, W- > l- vl~), t > j j b @2",'$MG:color:GREEN')
517 logger.info(" > Note that identical particles will all be decayed.")
518 logger.info("Loop processes syntax:",'$MG:color:BLACK')
519 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
520 logger.info(" o Example: generate p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
521 logger.info(" > Notice that in this format, decay chains are not allowed.")
522 logger.info(" > The LoopOrder(s) defined specify the kind of loops to consider (only QCD for now).")
523 logger.info(" > The coupling restrictions before '[' restrict the orders of born *amplitudes*.")
524 logger.info(" So that in the example above QCD=2 restricts the born amplitude to have at")
525 logger.info(" most QCD=2 and loop amplitudes at most QCD=2+2 (because QCD loops are considered)")
526 logger.info(" > The coupling restrictions after ']' restrict the orders of the matrix element, ")
527 logger.info(" namely the squared amplitudes. In the example above QCD=6 correspond to born")
528 logger.info(" amplitudes with QCD=2 squared against loop amplitudes with QCD=4, adding up to 6.")
529 logger.info(" > The optional <NLO_mode=> can be any of the following ('all=' by default if absent):")
530 logger.info(" all= : Generate all the real-emission and loop diagrams, ready for aMC@NLO runs.")
531 logger.info(" virt= : Generate only the loop diagrams, read for MadLoop standalone checks/runs.")
532 logger.info(" real= : Generate only the real-emission diagrams, for use with alternative OLP. ")
533 logger.info(" > For processes without born amplitudes (i.e. loop-induced like g g > z), please use ")
534 logger.info(" the 'virt=' NLO mode. aMC@NLO cannot integrate these processes, but standalone MadLoop5")
535 logger.info(" can still handle these.")
536
538 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
539 logger.info(" OR merge two model",'$MG:color:BLUE')
540 logger.info('')
541 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
542 logger.info("General leading-order syntax:",'$MG:color:BLACK')
543 logger.info(" o add process INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2 @N")
544 logger.info(" o Example: add process l+ vl > w+ > l+ vl a $ z / a h QED=3 QCD=0 @1",'$MG:color:GREEN')
545 logger.info(" > Alternative required s-channels can be separated by \"|\":")
546 logger.info(" b b~ > W+ W- | H+ H- > ta+ vt ta- vt~")
547 logger.info(" > If no coupling orders are given, MG5 will try to determine")
548 logger.info(" orders to ensure maximum number of QCD vertices.")
549 logger.info(" > Note that if there are more than one non-QCD coupling type,")
550 logger.info(" coupling orders need to be specified by hand.")
551 logger.info("Decay chain syntax:",'$MG:color:BLACK')
552 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
553 logger.info(" o Example: add process p p > t~ t QED=0, (t~ > W- b~, W- > l- vl~), t > j j b @2",'$MG:color:GREEN')
554 logger.info(" > Note that identical particles will all be decayed.")
555 logger.info("Loop processes syntax:",'$MG:color:BLACK')
556 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
557 logger.info(" o Example: add process p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
558 logger.info(" > Notice that in this format, decay chains are not allowed.")
559 logger.info(" > The LoopOrder(s) defined specify the kind of loops to consider (only QCD for now).")
560 logger.info(" > The coupling restrictions before '[' restrict the orders of born *amplitudes*.")
561 logger.info(" So that in the example above QCD=2 restricts the born amplitude to have at")
562 logger.info(" most QCD=2 and loop amplitudes at most QCD=2+2 (because QCD loops are considered)")
563 logger.info(" > The coupling restrictions after ']' restrict the orders of the matrix element, ")
564 logger.info(" namely the squared amplitudes. In the example above QCD=6 correspond to born")
565 logger.info(" amplitudes with QCD=2 squared against loop amplitudes with QCD=4, adding up to 6.")
566 logger.info(" > The optional <NLO_mode=> can be any of the following ('all=' by default if absent):")
567 logger.info(" all= : Generate all the real-emission and loop diagrams, ready for aMC@NLO runs.")
568 logger.info(" virt= : Generate only the loop diagrams, read for MadLoop standalone checks/runs.")
569 logger.info(" real= : Generate only the real-emission diagrams, for use with alternative OLP. ")
570 logger.info(" > For processes without born amplitudes (i.e. loop-induced like g g > z), please use ")
571 logger.info(" the 'virt=' NLO mode. aMC@NLO cannot integrate these processes, but standalone MadLoop5")
572 logger.info(" can still handle these.")
573
574 logger.info("-- merge two model to create a new one", '$MG:color:BLUE')
575 logger.info("syntax:",'$MG:color:BLACK')
576 logger.info(" o add model MODELNAME [OPTIONS]")
577 logger.info(" o Example: add model taudecay",'$MG:color:GREEN')
578 logger.info(" > Merge the two model in a single one. If that same merge was done before.")
579 logger.info(" > Just reload the previous merge. (WARNING: This doesn't check if those model are modified)")
580 logger.info(" > Options:")
581 logger.info(" --output= : Specify the name of the directory where the merge is done.")
582 logger.info(" This allow to do \"import NAME\" to load that merge.")
583 logger.info(" --recreate : Force to recreated the merge model even if the merge model directory already exists.")
584
586 logger.info("syntax: calculate_width PART [other particles] [OPTIONS]")
587 logger.info(" Computes the width and partial width for a set of particles")
588 logger.info(" Returns a valid param_card with this information.")
589 logger.info(" ")
590 logger.info(" PART: name of the particle you want to calculate width")
591 logger.info(" you can enter either the name or pdg code.\n")
592 logger.info(" Various options:\n")
593 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
594 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
595 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
596 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
597 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
598 logger.info(" default: 4.0025")
599 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
600 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
601 logger.info(" --precision_channel=X: requested numerical precision for each channel")
602 logger.info(" default: 0.01")
603 logger.info(" --path=X: path for param_card")
604 logger.info(" default: take value from the model")
605 logger.info(" --output=X: path where to write the resulting card. ")
606 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
607 logger.info("")
608 logger.info(" example: calculate_width h --body_decay=2 --output=./param_card")
609
611 logger.info("syntax: decay_diagram PART [other particles] [OPTIONS]")
612 logger.info(" Returns the amplitude required for the computation of the widths")
613 logger.info(" ")
614 logger.info(" PART: name of the particle you want to calculate width")
615 logger.info(" you can enter either the name or pdg code.\n")
616 logger.info(" Various options:\n")
617 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
618 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
619 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
620 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
621 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
622 logger.info(" default: 4.0025")
623 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
624 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
625 logger.info(" --precision_channel=X: requested numerical precision for each channel")
626 logger.info(" default: 0.01")
627 logger.info(" --path=X: path for param_card")
628 logger.info(" default: take value from the model")
629 logger.info(" --output=X: path where to write the resulting card. ")
630 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
631 logger.info("")
632 logger.info(" example: calculate_width h --body_decay=2 --output=./param_card")
633
635 logger.info("-- define a multiparticle",'$MG:color:BLUE')
636 logger.info("Syntax: define multipart_name [=] part_name_list")
637 logger.info("Example: define p = g u u~ c c~ d d~ s s~ b b~",'$MG:color:GREEN')
638 logger.info("Special syntax: Use | for OR (used for required s-channels)")
639 logger.info("Special syntax: Use / to remove particles. Example: define q = p / g")
640
642 logger.info("-- set options for generation or output.",'$MG:color:BLUE')
643 logger.info("syntax: set <option_name> <option_value>",'$MG:color:BLACK')
644 logger.info("Possible options are: ")
645 for opts in [self._set_options[i*3:(i+1)*3] for i in \
646 range((len(self._set_options)//4)+1)]:
647 logger.info("%s"%(','.join(opts)),'$MG:color:GREEN')
648 logger.info("Details of each option:")
649 logger.info("group_subprocesses True/False/Auto: ",'$MG:color:BLACK')
650 logger.info(" > (default Auto) Smart grouping of subprocesses into ")
651 logger.info(" directories, mirroring of initial states, and ")
652 logger.info(" combination of integration channels.")
653 logger.info(" > Example: p p > j j j w+ gives 5 directories and 184 channels",'$MG:color:GREEN')
654 logger.info(" (cf. 65 directories and 1048 channels for regular output)",'$MG:color:GREEN')
655 logger.info(" > Auto means False for decay computation and True for collisions.")
656 logger.info("ignore_six_quark_processes multi_part_label",'$MG:color:BLACK')
657 logger.info(" > (default none) ignore processes with at least 6 of any")
658 logger.info(" of the quarks given in multi_part_label.")
659 logger.info(" > These processes give negligible contribution to the")
660 logger.info(" cross section but have subprocesses/channels.")
661 logger.info("stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL",'$MG:color:BLACK')
662 logger.info(" > change the default level for printed information")
663 logger.info("fortran_compiler NAME",'$MG:color:BLACK')
664 logger.info(" > (default None) Force a specific fortran compiler.")
665 logger.info(" If None, it tries first g77 and if not present gfortran")
666 logger.info(" but loop output use gfortran.")
667 logger.info("loop_optimized_output True|False",'$MG:color:BLACK')
668 logger.info(" > Exploits the open loop thechnique for considerable")
669 logger.info(" improvement.")
670 logger.info(" > CP relations among helicites are detected and the helicity")
671 logger.info(" filter has more potential.")
672 logger.info("gauge unitary|Feynman",'$MG:color:BLACK')
673 logger.info(" > (default unitary) choose the gauge of the non QCD part.")
674 logger.info(" > For loop processes, only Feynman gauge is employable.")
675 logger.info("complex_mass_scheme True|False",'$MG:color:BLACK')
676 logger.info(" > (default False) Set complex mass scheme.")
677 logger.info(" > Complex mass scheme is not yet supported for loop processes.")
678 logger.info("timeout VALUE",'$MG:color:BLACK')
679 logger.info(" > (default 20) Seconds allowed to answer questions.")
680 logger.info(" > Note that pressing tab always stops the timer.")
681 logger.info("cluster_temp_path PATH",'$MG:color:BLACK')
682 logger.info(" > (default None) [Used in Madevent Output]")
683 logger.info(" > Allow to perform the run in PATH directory")
684 logger.info(" > This allow to not run on the central disk. ")
685 logger.info(" > This is not used by condor cluster (since condor has")
686 logger.info(" its own way to prevent it).")
687 logger.info("OLP ProgramName",'$MG:color:BLACK')
688 logger.info(" > (default 'MadLoop') [Used for virtual generation]")
689 logger.info(" > Chooses what One-Loop Program to use for the virtual")
690 logger.info(" > matrix element generation via the BLAH accord.")
691 logger.info("output_dependencies <mode>",'$MG:color:BLACK')
692 logger.info(" > (default 'external') [Use for NLO outputs]")
693 logger.info(" > Choses how the external dependences (such as CutTools)")
694 logger.info(" > of NLO outputs are handled. Possible values are:")
695 logger.info(" o external: Some of the libraries the output depends")
696 logger.info(" on are links to their installation in MG5 root dir.")
697 logger.info(" o internal: All libraries the output depends on are")
698 logger.info(" copied and compiled locally in the output directory.")
699 logger.info(" o environment_paths: The location of all libraries the ")
700 logger.info(" output depends on should be found in your env. paths.")
701
707 """ The Series of help routine for the MadGraphCmd"""
708
710 """a class for read/write errors"""
711
713 """check the validity of line
714 syntax: add process PROCESS | add model MODELNAME
715 """
716
717 if len(args) < 2:
718 self.help_add()
719 raise self.InvalidCmd('\"add\" requires at least two arguments')
720
721 if args[0] not in ['model', 'process']:
722 raise self.InvalidCmd('\"add\" requires the argument \"process\" or \"model\"')
723
724 if args[0] == 'process':
725 return self.check_generate(args)
726
727 if args[0] == 'model':
728 pass
729
730
732 """check the validity of line
733 syntax: define multipart_name [ part_name_list ]
734 """
735
736 if len(args) < 2:
737 self.help_define()
738 raise self.InvalidCmd('\"define\" command requires at least two arguments')
739
740 if args[1] == '=':
741 del args[1]
742 if len(args) < 2:
743 self.help_define()
744 raise self.InvalidCmd('\"define\" command requires at least one particles name after \"=\"')
745
746 if '=' in args:
747 self.help_define()
748 raise self.InvalidCmd('\"define\" command requires symbols \"=\" at the second position')
749
750 if not self._curr_model:
751 logger.info('No model currently active. Try with the Standard Model')
752 self.do_import('model sm')
753
754 if self._curr_model['particles'].find_name(args[0]):
755 raise self.InvalidCmd("label %s is a particle name in this model\n\
756 Please retry with another name." % args[0])
757
759 """check the validity of line
760 syntax: display XXXXX
761 """
762
763 if len(args) < 1:
764 self.help_display()
765 raise self.InvalidCmd, 'display requires an argument specifying what to display'
766 if args[0] not in self._display_opts:
767 self.help_display()
768 raise self.InvalidCmd, 'Invalid arguments for display command: %s' % args[0]
769
770 if not self._curr_model:
771 raise self.InvalidCmd("No model currently active, please import a model!")
772
773
774 if (args[0] in ['processes', 'diagrams'] and not self._curr_amps and not self._fks_multi_proc):
775 raise self.InvalidCmd("No process generated, please generate a process!")
776 if args[0] == 'checks' and not self._comparisons:
777 raise self.InvalidCmd("No check results to display.")
778
779 if args[0] == 'variable' and len(args) !=2:
780 raise self.InvalidCmd('variable need a variable name')
781
782
784 """check the validity of line
785 syntax: draw DIRPATH [option=value]
786 """
787
788 if len(args) < 1:
789 args.append('/tmp')
790
791 if not self._curr_amps:
792 raise self.InvalidCmd("No process generated, please generate a process!")
793
794 if not os.path.isdir(args[0]):
795 raise self.InvalidCmd( "%s is not a valid directory for export file" % args[0])
796
798 """check the validity of args"""
799
800 if not self._curr_model:
801 raise self.InvalidCmd("No model currently active, please import a model!")
802
803 if self._model_v4_path:
804 raise self.InvalidCmd(\
805 "\"check\" not possible for v4 models")
806
807 if len(args) < 2:
808 self.help_check()
809 raise self.InvalidCmd("\"check\" requires a process.")
810
811 if args[0] not in self._check_opts:
812 args.insert(0, 'full')
813
814 param_card = None
815 if args[0] not in ['stability','profile','timing'] and os.path.isfile(args[1]):
816 param_card = args.pop(1)
817
818 if len(args)>1:
819 if args[1] != "-reuse":
820 args.insert(1, '-no_reuse')
821 else:
822 args.append('-no_reuse')
823
824 if args[0] in ['timing'] and os.path.isfile(args[2]):
825 param_card = args.pop(2)
826 misc.sprint(param_card)
827 if args[0] in ['stability', 'profile'] and len(args)>1:
828
829
830
831 try:
832 int(args[2])
833 except ValueError:
834 args.insert(2, '100')
835
836 if args[0] in ['stability', 'profile'] and os.path.isfile(args[3]):
837 param_card = args.pop(3)
838
839 if any([',' in elem for elem in args]):
840 raise self.InvalidCmd('Decay chains not allowed in check')
841
842 user_options = {'--energy':'1000','--split_orders':'-1',
843 '--reduction':'1|2|3|4'}
844 for arg in args[:]:
845 if arg.startswith('--') and '=' in arg:
846 key, value = arg.split('=')
847 if key not in user_options:
848 raise self.InvalidCmd, "unknown option %s" % key
849 user_options[key] = value
850 args.remove(arg)
851
852 self.check_process_format(" ".join(args[1:]))
853
854 for option, value in user_options.items():
855 args.append('%s=%s'%(option,value))
856
857 return param_card
858
883
884
922
923
936
937
938
984
985
986
988 """check that the install command is valid"""
989
990 if len(args) < 1:
991 self.help_install()
992 raise self.InvalidCmd('install command require at least one argument')
993
994 if args[0] not in self._install_opts:
995 if not args[0].startswith('td'):
996 self.help_install()
997 raise self.InvalidCmd('Not recognize program %s ' % args[0])
998
999 if args[0] in ["ExRootAnalysis", "Delphes", "Delphes2"]:
1000 if not misc.which('root'):
1001 raise self.InvalidCmd(
1002 '''In order to install ExRootAnalysis, you need to install Root on your computer first.
1003 please follow information on http://root.cern.ch/drupal/content/downloading-root''')
1004 if 'ROOTSYS' not in os.environ:
1005 raise self.InvalidCmd(
1006 '''The environment variable ROOTSYS is not configured.
1007 You can set it by adding the following lines in your .bashrc [.bash_profile for mac]:
1008 export ROOTSYS=%s
1009 export PATH=$PATH:$ROOTSYS/bin
1010 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib
1011 export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$ROOTSYS/lib
1012 This will take effect only in a NEW terminal
1013 ''' % os.path.realpath(pjoin(misc.which('root'), \
1014 os.path.pardir, os.path.pardir)))
1015
1016
1018 """check the validity of the line"""
1019
1020
1021 if not( 0 <= int(options.cluster) <= 2):
1022 return self.InvalidCmd, 'cluster mode should be between 0 and 2'
1023
1024 if not args:
1025 if self._done_export:
1026 mode = self.find_output_type(self._done_export[0])
1027 if mode != self._done_export[1]:
1028 print mode, self._done_export[1]
1029 raise self.InvalidCmd, \
1030 '%s not valid directory for launch' % self._done_export[0]
1031 args.append(self._done_export[1])
1032 args.append(self._done_export[0])
1033 return
1034 else:
1035 logger.warning('output command missing, run it automatically (with default argument)')
1036 self.do_output('')
1037 logger.warning('output done: running launch')
1038 return self.check_launch(args, options)
1039
1040 if len(args) != 1:
1041 self.help_launch()
1042 return self.InvalidCmd, 'Invalid Syntax: Too many argument'
1043
1044
1045 if os.path.isdir(args[0]):
1046 path = os.path.realpath(args[0])
1047 elif os.path.isdir(pjoin(MG5DIR,args[0])):
1048 path = pjoin(MG5DIR,args[0])
1049 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
1050 path = pjoin(MG4DIR,args[0])
1051 else:
1052 raise self.InvalidCmd, '%s is not a valid directory' % args[0]
1053
1054 mode = self.find_output_type(path)
1055
1056 args[0] = mode
1057 args.append(path)
1058
1059 self._done_export = [path, mode]
1060
1061
1063 """ identify the import type of a given path
1064 valid output: model/model_v4/proc_v4/command"""
1065
1066 possibility = [pjoin(MG5DIR,'models',path), \
1067 pjoin(MG5DIR,'models',path+'_v4'), path]
1068 if '-' in path:
1069 name = path.rsplit('-',1)[0]
1070 possibility = [pjoin(MG5DIR,'models',name), name] + possibility
1071
1072 for name in possibility:
1073 if os.path.isdir(name):
1074 if os.path.exists(pjoin(name,'particles.py')):
1075 return 'model'
1076 elif os.path.exists(pjoin(name,'particles.dat')):
1077 return 'model_v4'
1078
1079
1080 if os.path.isfile(path):
1081 text = open(path).read()
1082 pat = re.compile('(Begin process|<MGVERSION>)', re.I)
1083 matches = pat.findall(text)
1084 if not matches:
1085 return 'command'
1086 elif len(matches) > 1:
1087 return 'banner'
1088 elif matches[0].lower() == 'begin process':
1089 return 'proc_v4'
1090 else:
1091 return 'banner'
1092 else:
1093 return 'proc_v4'
1094
1095
1096
1097
1099 """ identify the type of output of a given directory:
1100 valid output: madevent/standalone/standalone_cpp"""
1101
1102 card_path = pjoin(path,'Cards')
1103 bin_path = pjoin(path,'bin')
1104 src_path = pjoin(path,'src')
1105 include_path = pjoin(path,'include')
1106 subproc_path = pjoin(path,'SubProcesses')
1107 mw_path = pjoin(path,'Source','MadWeight')
1108
1109 if os.path.isfile(pjoin(include_path, 'Pythia.h')):
1110 return 'pythia8'
1111 elif not os.path.isdir(os.path.join(path, 'SubProcesses')):
1112 raise self.InvalidCmd, '%s : Not a valid directory' % path
1113
1114 if os.path.isdir(src_path):
1115 return 'standalone_cpp'
1116 elif os.path.isdir(mw_path):
1117 return 'madweight'
1118 elif os.path.isfile(pjoin(bin_path,'madevent')):
1119 return 'madevent'
1120 elif os.path.isfile(pjoin(bin_path,'aMCatNLO')):
1121 return 'aMC@NLO'
1122 elif os.path.isdir(card_path):
1123 return 'standalone'
1124
1125 raise self.InvalidCmd, '%s : Not a valid directory' % path
1126
1133
1135 """check the validity of the line"""
1136
1137
1138 if len(args) >1 :
1139 self.help_customize_model()
1140 raise self.InvalidCmd('No argument expected for this command')
1141
1142 if len(args):
1143 if not args[0].startswith('--save='):
1144 self.help_customize_model()
1145 raise self.InvalidCmd('Wrong argument for this command')
1146 if '-' in args[0][6:]:
1147 raise self.InvalidCmd('The name given in save options can\'t contain \'-\' symbol.')
1148
1149 if self._model_v4_path:
1150 raise self.InvalidCmd('Restriction of Model is not supported by v4 model.')
1151
1152
1154 """ check the validity of the line"""
1155
1156 if len(args) == 0:
1157 args.append('options')
1158
1159 if args[0] not in self._save_opts and args[0] != 'global':
1160 self.help_save()
1161 raise self.InvalidCmd('wrong \"save\" format')
1162 elif args[0] == 'global':
1163 args.insert(0, 'options')
1164
1165 if args[0] != 'options' and len(args) != 2:
1166 self.help_save()
1167 raise self.InvalidCmd('wrong \"save\" format')
1168 elif args[0] != 'options' and len(args) == 2:
1169 basename = os.path.dirname(args[1])
1170 if not os.path.exists(basename):
1171 raise self.InvalidCmd('%s is not a valid path, please retry' % \
1172 args[1])
1173
1174 if args[0] == 'options':
1175 has_path = None
1176 for arg in args[1:]:
1177 if arg in ['--auto', '--all']:
1178 continue
1179 elif arg.startswith('--'):
1180 raise self.InvalidCmd('unknow command for \'save options\'')
1181 elif arg == 'global':
1182 if os.environ.has_key('HOME'):
1183 args.remove('global')
1184 args.insert(1,pjoin(os.environ['HOME'],'.mg5','mg5_configuration.txt'))
1185 has_path = True
1186 else:
1187 basename = os.path.dirname(arg)
1188 if not os.path.exists(basename):
1189 raise self.InvalidCmd('%s is not a valid path, please retry' % \
1190 arg)
1191 elif has_path:
1192 raise self.InvalidCmd('only one path is allowed')
1193 else:
1194 args.remove(arg)
1195 args.insert(1, arg)
1196 has_path = True
1197 if not has_path:
1198 args.insert(1, pjoin(MG5DIR,'input','mg5_configuration.txt'))
1199
1200
1202 """ check the validity of the line"""
1203
1204 if len(args) == 1 and args[0] in ['complex_mass_scheme',\
1205 'loop_optimized_output']:
1206 args.append('True')
1207
1208 if len(args) > 2 and '=' == args[1]:
1209 args.pop(1)
1210
1211 if len(args) < 2:
1212 self.help_set()
1213 raise self.InvalidCmd('set needs an option and an argument')
1214
1215 if args[1] == 'default':
1216 if args[0] in self.options_configuration:
1217 default = self.options_configuration[args[0]]
1218 elif args[0] in self.options_madgraph:
1219 default = self.options_madgraph[args[0]]
1220 elif args[0] in self.options_madevent:
1221 default = self.options_madevent[args[0]]
1222 else:
1223 raise self.InvalidCmd('%s doesn\'t have a valid default value' % args[0])
1224 if log:
1225 logger.info('Pass parameter %s to it\'s default value: %s' %
1226 (args[0], default))
1227 args[1] = str(default)
1228
1229 if args[0] not in self._set_options:
1230 if not args[0] in self.options and not args[0] in self.options:
1231 self.help_set()
1232 raise self.InvalidCmd('Possible options for set are %s' % \
1233 self._set_options)
1234
1235 if args[0] in ['group_subprocesses']:
1236 if args[1] not in ['False', 'True', 'Auto']:
1237 raise self.InvalidCmd('%s needs argument False, True or Auto' % \
1238 args[0])
1239 if args[0] in ['ignore_six_quark_processes']:
1240 if args[1] not in self._multiparticles.keys() and args[1] != 'False':
1241 raise self.InvalidCmd('ignore_six_quark_processes needs ' + \
1242 'a multiparticle name as argument')
1243
1244 if args[0] in ['stdout_level']:
1245 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] and \
1246 not args[1].isdigit():
1247 raise self.InvalidCmd('output_level needs ' + \
1248 'a valid level')
1249
1250 if args[0] in ['timeout']:
1251 if not args[1].isdigit():
1252 raise self.InvalidCmd('timeout values should be a integer')
1253
1254 if args[0] in ['loop_optimized_output']:
1255 if args[1] not in ['True', 'False']:
1256 raise self.InvalidCmd('loop_optimized_output needs argument True or False')
1257
1258 if args[0] in ['gauge']:
1259 if args[1] not in ['unitary','Feynman']:
1260 raise self.InvalidCmd('gauge needs argument unitary or Feynman.')
1261
1262 if args[0] in ['timeout']:
1263 if not args[1].isdigit():
1264 raise self.InvalidCmd('timeout values should be a integer')
1265
1266 if args[0] in ['OLP']:
1267 if args[1] not in MadGraphCmd._OLP_supported:
1268 raise self.InvalidCmd('OLP value should be one of %s'\
1269 %str(MadGraphCmd._OLP_supported))
1270
1271 if args[0] in ['output_dependencies']:
1272 if args[1] not in MadGraphCmd._output_dependencies_supported:
1273 raise self.InvalidCmd('output_dependencies value should be one of %s'\
1274 %str(MadGraphCmd._output_dependencies_supported))
1275
1277 """ check the validity of the line """
1278
1279 if len(args) != 1:
1280 self.help_open()
1281 raise self.InvalidCmd('OPEN command requires exactly one argument')
1282
1283 if args[0].startswith('./'):
1284 if not os.path.isfile(args[0]):
1285 raise self.InvalidCmd('%s: not such file' % args[0])
1286 return True
1287
1288
1289 if not self._done_export:
1290 if not os.path.isfile(args[0]):
1291 self.help_open()
1292 raise self.InvalidCmd('No command \"output\" or \"launch\" used. Impossible to associate this name to a file')
1293 else:
1294 return True
1295
1296 path = self._done_export[0]
1297 if os.path.isfile(pjoin(path,args[0])):
1298 args[0] = pjoin(path,args[0])
1299 elif os.path.isfile(pjoin(path,'Cards',args[0])):
1300 args[0] = pjoin(path,'Cards',args[0])
1301 elif os.path.isfile(pjoin(path,'HTML',args[0])):
1302 args[0] = pjoin(path,'HTML',args[0])
1303
1304 elif '_card.dat' in args[0]:
1305 name = args[0].replace('_card.dat','_card_default.dat')
1306 if os.path.isfile(pjoin(path,'Cards', name)):
1307 files.cp(path + '/Cards/' + name, path + '/Cards/'+ args[0])
1308 args[0] = pjoin(path,'Cards', args[0])
1309 else:
1310 raise self.InvalidCmd('No default path for this file')
1311 elif not os.path.isfile(args[0]):
1312 raise self.InvalidCmd('No default path for this file')
1313
1314
1316 """ check the validity of the line"""
1317
1318
1319 if args and args[0] in self._export_formats:
1320 self._export_format = args.pop(0)
1321 else:
1322 self._export_format = 'madevent'
1323
1324 if not self._curr_model:
1325 text = 'No model found. Please import a model first and then retry.'
1326 raise self.InvalidCmd(text)
1327
1328 if self._model_v4_path and \
1329 (self._export_format not in self._v4_export_formats):
1330 text = " The Model imported (MG4 format) does not contain enough\n "
1331 text += " information for this type of output. In order to create\n"
1332 text += " output for " + args[0] + ", you have to use a UFO model.\n"
1333 text += " Those model can be imported with MG5> import model NAME."
1334 logger.warning(text)
1335 raise self.InvalidCmd('')
1336
1337 if self._export_format == 'aloha':
1338 return
1339
1340
1341 if not self._curr_amps:
1342 text = 'No processes generated. Please generate a process first.'
1343 raise self.InvalidCmd(text)
1344
1345
1346
1347
1348
1349 if args and args[0][0] != '-':
1350
1351 path = args.pop(0)
1352 forbiden_chars = ['>','<',';','&']
1353 for char in forbiden_chars:
1354 if char in path:
1355 raise self.InvalidCmd('%s is not allowed in the output path' % char)
1356
1357 if path == 'auto' and self._export_format in \
1358 ['madevent', 'madweight', 'standalone', 'standalone_cpp']:
1359 self.get_default_path()
1360 if '-noclean' not in args and os.path.exists(self._export_dir):
1361 args.append('-noclean')
1362 elif path != 'auto':
1363 self._export_dir = path
1364 elif path == 'auto':
1365 if self.options['pythia8_path']:
1366 self._export_dir = self.options['pythia8_path']
1367 else:
1368 self._export_dir = '.'
1369 else:
1370 if self._export_format != 'pythia8':
1371
1372 self.get_default_path()
1373 if '-noclean' not in args and os.path.exists(self._export_dir):
1374 args.append('-noclean')
1375 else:
1376 if self.options['pythia8_path']:
1377 self._export_dir = self.options['pythia8_path']
1378 else:
1379 self._export_dir = '.'
1380
1381 self._export_dir = os.path.realpath(self._export_dir)
1382
1383
1385 """ check and format calculate decay width:
1386 Expected format: NAME [other names] [--options]
1387 # fill the options if not present.
1388 # NAME can be either (anti-)particle name, multiparticle, pid
1389 """
1390
1391 if len(args)<1:
1392 self.help_compute_widths()
1393 raise self.InvalidCmd('''compute_widths requires at least the name of one particle.
1394 If you want to compute the width of all particles, type \'compute_widths all\'''')
1395
1396 particles = set()
1397 options = {'path':None, 'output':None,
1398 'min_br':None, 'body_decay':4.0025, 'precision_channel':0.01}
1399
1400 for i,arg in enumerate(args):
1401 if arg.startswith('--'):
1402 if not '=' in arg:
1403 raise self.InvalidCmd('Options required an equal (and then the value)')
1404 arg, value = arg.split('=')
1405 if arg[2:] not in options:
1406 raise self.InvalidCmd('%s not valid options' % arg)
1407 options[arg[2:]] = value
1408 continue
1409
1410 if arg.isdigit():
1411 p = self._curr_model.get_particle(int(arg))
1412 if not p:
1413 raise self.InvalidCmd('Model doesn\'t have pid %s for any particle' % arg)
1414 particles.add(abs(int(arg)))
1415 elif arg in self._multiparticles:
1416 particles.update([abs(id) for id in self._multiparticles[args[0]]])
1417 else:
1418 for p in self._curr_model['particles']:
1419 if p['name'] == arg or p['antiname'] == arg:
1420 particles.add(abs(p.get_pdg_code()))
1421 break
1422 else:
1423 if arg == 'all':
1424
1425 particles.update([abs(p.get_pdg_code())
1426 for p in self._curr_model['particles']])
1427 else:
1428 raise self.InvalidCmd('%s invalid particle name' % arg)
1429
1430 if options['path'] and not os.path.isfile(options['path']):
1431
1432 if os.path.exists(pjoin(MG5DIR, options['path'])):
1433 options['path'] = pjoin(MG5DIR, options['path'])
1434 elif self._model_v4_path and os.path.exists(pjoin(self._model_v4_path, options['path'])):
1435 options['path'] = pjoin(self._curr_model_v4_path, options['path'])
1436 elif os.path.exists(pjoin(self._curr_model.path, options['path'])):
1437 options['path'] = pjoin(self._curr_model.path, options['path'])
1438
1439 if os.path.isdir(options['path']) and os.path.isfile(pjoin(options['path'], 'param_card.dat')):
1440 options['path'] = pjoin(options['path'], 'param_card.dat')
1441 elif not os.path.isfile(options['path']):
1442 raise self.InvalidCmd('%s is not a valid path' % args[2])
1443
1444 if madevent_interface.MadEventCmd.detect_card_type(options['path']) != 'param_card.dat':
1445 raise self.InvalidCmd('%s should be a path to a param_card' % options['path'])
1446
1447 if not options['path']:
1448 param_card_text = self._curr_model.write_param_card()
1449 if not options['output']:
1450 dirpath = self._curr_model.get('modelpath')
1451 options['path'] = pjoin(dirpath, 'param_card.dat')
1452 else:
1453 options['path'] = options['output']
1454 ff = open(options['path'],'w')
1455 ff.write(param_card_text)
1456 ff.close()
1457 if not options['output']:
1458 options['output'] = options['path']
1459
1460 if not options['min_br']:
1461 options['min_br'] = (float(options['body_decay']) % 1) / 5
1462 return particles, options
1463
1464
1465 check_decay_diagram = check_compute_widths
1466
1468 """Set self._export_dir to the default (\'auto\') path"""
1469
1470 if self._export_format in ['madevent', 'standalone']:
1471
1472
1473 if 'TemplateVersion.txt' in os.listdir('.'):
1474
1475 self._export_dir = os.path.realpath('.')
1476 return
1477 elif 'TemplateVersion.txt' in os.listdir('..'):
1478
1479 self._export_dir = os.path.realpath('..')
1480 return
1481 elif self.stdin != sys.stdin:
1482
1483 input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
1484 print "Not standard stdin, use input path"
1485 if input_path[-2] == 'Cards':
1486 self._export_dir = os.path.sep.join(input_path[:-2])
1487 if 'TemplateVersion.txt' in self._export_dir:
1488 return
1489
1490
1491 if self._export_format == 'NLO':
1492 name_dir = lambda i: 'PROCNLO_%s_%s' % \
1493 (self._curr_model['name'], i)
1494 auto_path = lambda i: pjoin(self.writing_dir,
1495 name_dir(i))
1496 elif self._export_format.startswith('madevent'):
1497 name_dir = lambda i: 'PROC_%s_%s' % \
1498 (self._curr_model['name'], i)
1499 auto_path = lambda i: pjoin(self.writing_dir,
1500 name_dir(i))
1501 elif self._export_format == 'standalone':
1502 name_dir = lambda i: 'PROC_SA_%s_%s' % \
1503 (self._curr_model['name'], i)
1504 auto_path = lambda i: pjoin(self.writing_dir,
1505 name_dir(i))
1506 elif self._export_format == 'madweight':
1507 name_dir = lambda i: 'PROC_MW_%s_%s' % \
1508 (self._curr_model['name'], i)
1509 auto_path = lambda i: pjoin(self.writing_dir,
1510 name_dir(i))
1511 elif self._export_format == 'standalone_cpp':
1512 name_dir = lambda i: 'PROC_SA_CPP_%s_%s' % \
1513 (self._curr_model['name'], i)
1514 auto_path = lambda i: pjoin(self.writing_dir,
1515 name_dir(i))
1516 elif self._export_format == 'pythia8':
1517 if self.options['pythia8_path']:
1518 self._export_dir = self.options['pythia8_path']
1519 else:
1520 self._export_dir = '.'
1521 return
1522 else:
1523 self._export_dir = '.'
1524 return
1525 for i in range(500):
1526 if os.path.isdir(auto_path(i)):
1527 continue
1528 else:
1529 self._export_dir = auto_path(i)
1530 break
1531 if not self._export_dir:
1532 raise self.InvalidCmd('Can\'t use auto path,' + \
1533 'more than 500 dirs already')
1534
1540 """ Check the validity of input line for web entry
1541 (no explicit path authorized)"""
1542
1544 """class for WebRestriction"""
1545
1547 """check the validity of line
1548 syntax: draw FILEPATH [option=value]
1549 """
1550 raise self.WebRestriction('direct call to draw is forbidden on the web')
1551
1559
1561 """ Not authorize for the Web"""
1562
1563 raise self.WebRestriction('Check call is forbidden on the web')
1564
1565 - def check_history(self, args):
1566 """check the validity of line
1567 No Path authorize for the Web"""
1568
1569 CheckValidForCmd.check_history(self, args)
1570
1571 if len(args) == 2 and args[1] not in ['.', 'clean']:
1572 raise self.WebRestriction('Path can\'t be specify on the web.')
1573
1574
1590
1592 """ No possibility to install new software on the web """
1593 if args == ['update','--mode=mg5_start']:
1594 return
1595
1596 raise self.WebRestriction('Impossible to install program on the cluster')
1597
1599 """ check the validity of the line
1600 No Path authorize for the Web"""
1601
1602 CheckValidForCmd.check_load(self, args)
1603
1604 if len(args) == 2:
1605 if args[0] != 'model':
1606 raise self.WebRestriction('only model can be loaded online')
1607 if 'model.pkl' not in args[1]:
1608 raise self.WebRestriction('not valid pkl file: wrong name')
1609 if not os.path.realpath(args[1]).startswith(pjoin(MG4DIR, \
1610 'Models')):
1611 raise self.WebRestriction('Wrong path to load model')
1612
1614 """ not authorize on web"""
1615 raise self.WebRestriction('\"save\" command not authorize online')
1616
1618 """ not authorize on web"""
1619 raise self.WebRestriction('\"open\" command not authorize online')
1620
1622 """ check the validity of the line"""
1623
1624
1625 CheckValidForCmd.check_output(self, args)
1626 args[:] = ['.', '-f']
1627
1628 self._export_dir = os.path.realpath(os.getcwd())
1629
1630 if 'madevent' != self._export_format:
1631 raise self.WebRestriction, 'only available output format is madevent (at current stage)'
1632
1637 """ The Series of help routine for the MadGraphCmd"""
1638
1640 """ complete the nlo settings within square brackets. It uses the
1641 allowed_loop_mode for the proposed mode if specified, otherwise, it
1642 uses self._nlo_modes_for_completion"""
1643
1644
1645
1646
1647 nlo_modes = allowed_loop_mode if not allowed_loop_mode is None else \
1648 self._nlo_modes_for_completion
1649 if isinstance(self._curr_model,loop_base_objects.LoopModel):
1650 pert_couplings_allowed = self._curr_model['perturbation_couplings']
1651 else:
1652 pert_couplings_allowed = []
1653 if self._curr_model.get('name').startswith('sm'):
1654 pert_couplings_allowed = pert_couplings_allowed + ['QCD']
1655
1656 loop_specs = line[line.index('[')+1:]
1657 try:
1658 loop_orders = loop_specs[loop_specs.index('=')+1:]
1659 except ValueError:
1660 loop_orders = loop_specs
1661 possibilities = []
1662 possible_orders = [order for order in pert_couplings_allowed if \
1663 order not in loop_orders]
1664
1665
1666 single_completion = ''
1667 if len(nlo_modes)==1:
1668 single_completion = '%s= '%nlo_modes[0]
1669 if len(possible_orders)==1:
1670 single_completion = single_completion + possible_orders[0] + ' ] '
1671
1672 if text.endswith('['):
1673 if single_completion != '':
1674 return self.list_completion(text, ['[ '+single_completion])
1675 else:
1676 return self.list_completion(text,['[ '])
1677
1678 if text.endswith('='):
1679 return self.list_completion(text,[' '])
1680
1681 if args[-1]=='[':
1682 possibilities = possibilities + ['%s= '%mode for mode in nlo_modes]
1683 if single_completion != '':
1684 return self.list_completion(text, [single_completion])
1685 else:
1686 if len(possible_orders)==1:
1687 return self.list_completion(text, [poss+' %s ] '%\
1688 possible_orders[0] for poss in possibilities])
1689 return self.list_completion(text, possibilities)
1690
1691 if len(possible_orders)==1:
1692 possibilities.append(possible_orders[0]+' ] ')
1693 else:
1694 possibilities.extend(possible_orders)
1695 if any([(order in loop_orders) for order in pert_couplings_allowed]):
1696 possibilities.append(']')
1697 return self.list_completion(text, possibilities)
1698
1699 - def model_completion(self, text, process, line, categories = True, \
1700 allowed_loop_mode = None):
1701 """ complete the line with model information. If categories is True,
1702 it will use completion with categories. If allowed_loop_mode is
1703 specified, it will only complete with these loop modes."""
1704
1705
1706
1707 args = self.split_arg(process)
1708 if len(args) > 2 and '>' in line and '[' in line and not ']' in line:
1709 return self.nlo_completion(args,text,line, allowed_loop_mode = \
1710 allowed_loop_mode)
1711
1712 while ',' in process:
1713 process = process[process.index(',')+1:]
1714 args = self.split_arg(process)
1715 couplings = []
1716
1717
1718 if len(args) > 1 and args[-1]=='@':
1719 return
1720
1721
1722
1723 if isinstance(self._curr_model,loop_base_objects.LoopModel):
1724 pert_couplings_allowed = self._curr_model['perturbation_couplings']
1725 else:
1726 pert_couplings_allowed = []
1727 if self._curr_model.get('name').startswith('sm'):
1728 pert_couplings_allowed = pert_couplings_allowed + ['QCD']
1729
1730
1731 particles = list(set(self._particle_names + self._multiparticles.keys()))
1732 n_part_entered = len([1 for a in args if a in particles])
1733
1734
1735 if n_part_entered == 2 and args[-1] != '>':
1736 return self.list_completion(text, '>')
1737
1738
1739 syntax = []
1740 couplings = []
1741 if len(args) > 0 and args[-1] != '>' and n_part_entered > 0:
1742 syntax.append('>')
1743 if '>' in args and args.index('>') < len(args) - 1:
1744 couplings.extend(sum([[c+"=",c+'^2'] for c in \
1745 self._couplings+['WEIGHTED']],[]))
1746 syntax.extend(['@','$','/','>',','])
1747 if '[' not in line and ',' not in line and len(pert_couplings_allowed)>0:
1748 syntax.append('[')
1749
1750
1751
1752 if '[' in line:
1753 syntax = []
1754 particles = []
1755
1756 couplings.append('@')
1757
1758 if not categories:
1759
1760
1761
1762
1763
1764 return self.list_completion(text, particles+syntax+couplings)
1765 else:
1766
1767 poss_particles = self.list_completion(text, particles)
1768 poss_syntax = self.list_completion(text, syntax)
1769 poss_couplings = self.list_completion(text, couplings)
1770 possibilities = {}
1771 if poss_particles != []: possibilities['Particles']=poss_particles
1772 if poss_syntax != []: possibilities['Syntax']=poss_syntax
1773 if poss_couplings != []: possibilities['Coupling orders']=poss_couplings
1774 if len(possibilities.keys())==1:
1775 return self.list_completion(text, possibilities.values()[0])
1776 else:
1777 return self.deal_multiple_categories(possibilities)
1778
1780 "Complete the generate command"
1781
1782
1783
1784 args = self.split_arg(line[0:begidx])
1785
1786 valid_sqso_operators=['==','<=','>']
1787 if any(line.endswith('^2 %s '%op) for op in valid_sqso_operators):
1788 return
1789 if args[-1].endswith('^2'):
1790 return self.list_completion(text,valid_sqso_operators)
1791 match_op = [o for o in valid_sqso_operators if o.startswith(args[-1])]
1792 if args[-2].endswith('^2') and len(match_op)>0:
1793 if args[-1] in valid_sqso_operators:
1794 return self.list_completion(text,' ')
1795 if len(match_op)==1:
1796 return self.list_completion(text,[match_op[0][len(args[-1]):]])
1797 else:
1798 return self.list_completion(text,match_op)
1799
1800 if len(args) > 2 and args[-1] == '@' or ( args[-1].endswith('=') and \
1801 (not '[' in line or ('[' in line and ']' in line))):
1802 return
1803
1804 try:
1805 return self.model_completion(text, ' '.join(args[1:]),line)
1806 except Exception as error:
1807 print error
1808
1809
1810
1811
1812
1813
1814
1815
1816
1818 "Complete the compute_widths command"
1819
1820 args = self.split_arg(line[0:begidx])
1821
1822 if args[-1] in ['--path=', '--output=']:
1823 completion = {'path': self.path_completion(text)}
1824 elif line[begidx-1] == os.path.sep:
1825 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)])
1826 if current_dir.startswith('--path='):
1827 current_dir = current_dir[7:]
1828 if current_dir.startswith('--output='):
1829 current_dir = current_dir[9:]
1830 completion = {'path': self.path_completion(text, current_dir)}
1831 else:
1832 completion = {}
1833 completion['options'] = self.list_completion(text,
1834 ['--path=', '--output=', '--min_br=0.\$',
1835 '--precision_channel=0.\$', '--body_decay='])
1836 completion['particles'] = self.model_completion(text, '', line)
1837
1838 return self.deal_multiple_categories(completion)
1839
1840 complete_decay_diagram = complete_compute_widths
1841
1843 "Complete the add command"
1844
1845 args = self.split_arg(line[0:begidx])
1846
1847
1848 if len(args) == 1:
1849 return self.list_completion(text, self._add_opts)
1850
1851 if args[1] == 'process':
1852 return self.complete_generate(text, " ".join(args[1:]), begidx, endidx)
1853
1854 elif args[1] == 'model':
1855 completion_categories = self.complete_import(text, line, begidx, endidx,
1856 allow_restrict=False, treat_completion=False)
1857 completion_categories['options'] = self.list_completion(text,['--modelname=','--recreate'])
1858 return self.deal_multiple_categories(completion_categories)
1859
1861 "Complete the customize_model command"
1862
1863 args = self.split_arg(line[0:begidx])
1864
1865
1866 if len(args) == 1:
1867 return self.list_completion(text, ['--save='])
1868
1869
1871 "Complete the check command"
1872
1873 out = {}
1874 args = self.split_arg(line[0:begidx])
1875
1876
1877 if len(args) == 1:
1878 return self.list_completion(text, self._check_opts)
1879
1880
1881 if args[-1].endswith(os.path.sep):
1882 return self.path_completion(text, pjoin(*[a for a in args \
1883 if a.endswith(os.path.sep)]))
1884
1885 model_comp = self.model_completion(text, ' '.join(args[2:]),line,
1886 categories = True, allowed_loop_mode=['virt'])
1887
1888 model_comp_and_path = self.deal_multiple_categories(\
1889 {'Process completion': self.model_completion(text, ' '.join(args[2:]),
1890 line, categories = False, allowed_loop_mode=['virt']),
1891 'Param_card.dat path completion:':self.path_completion(text),
1892 'options': self.list_completion(text, ['--energy='])})
1893
1894 if len(args) == 2:
1895 return model_comp_and_path
1896 elif len(args) == 3:
1897 try:
1898 int(args[2])
1899 except ValueError:
1900 return model_comp
1901 else:
1902 return model_comp_and_path
1903 elif len(args) > 3:
1904 return model_comp
1905
1906
1913
1915 """Complete particle information"""
1916 return self.model_completion(text, line[6:],line)
1917
1931
1933 "Complete the draw command"
1934
1935 args = self.split_arg(line[0:begidx])
1936
1937
1938 if args[-1].endswith(os.path.sep):
1939 return self.path_completion(text,
1940 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
1941 only_dirs = True)
1942
1943 if len(args) == 1:
1944 return self.path_completion(text, '.', only_dirs = True)
1945
1946
1947
1948 if len(args) >= 2:
1949 opt = ['horizontal', 'external=', 'max_size=', 'add_gap=',
1950 'non_propagating', '--']
1951 return self.list_completion(text, opt)
1952
1954 """ complete the launch command"""
1955 args = self.split_arg(line[0:begidx])
1956
1957
1958 if args[-1].endswith(os.path.sep):
1959 return self.path_completion(text,
1960 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
1961 only_dirs = True)
1962
1963 if len(args) == 1:
1964 out = {'Path from ./': self.path_completion(text, '.', only_dirs = True)}
1965 if MG5DIR != os.path.realpath('.'):
1966 out['Path from %s' % MG5DIR] = self.path_completion(text,
1967 MG5DIR, only_dirs = True, relative=False)
1968 if MG4DIR and MG4DIR != os.path.realpath('.') and MG4DIR != MG5DIR:
1969 out['Path from %s' % MG4DIR] = self.path_completion(text,
1970 MG4DIR, only_dirs = True, relative=False)
1971
1972
1973
1974 if len(args) >= 2:
1975 out={}
1976
1977 if line[0:begidx].endswith('--laststep='):
1978 opt = ['parton', 'pythia', 'pgs','delphes','auto']
1979 out['Options'] = self.list_completion(text, opt, line)
1980 else:
1981 opt = ['--cluster', '--multicore', '-i', '--name=', '-f','-m', '-n',
1982 '-p','--parton','--interactive', '--laststep=parton', '--laststep=pythia',
1983 '--laststep=pgs', '--laststep=delphes','--laststep=auto']
1984 out['Options'] = self.list_completion(text, opt, line)
1985
1986
1987 return self.deal_multiple_categories(out)
1988
2007
2026
2027 @cmd.debug()
2029 """ complete the open command """
2030
2031 args = self.split_arg(line[0:begidx])
2032
2033
2034 if os.path.sep in args[-1] + text:
2035 return self.path_completion(text,
2036 pjoin(*[a for a in args if \
2037 a.endswith(os.path.sep)]))
2038
2039 possibility = []
2040 if self._done_export:
2041 path = self._done_export[0]
2042 possibility = ['index.html']
2043 if os.path.isfile(pjoin(path,'README')):
2044 possibility.append('README')
2045 if os.path.isdir(pjoin(path,'Cards')):
2046 possibility += [f for f in os.listdir(pjoin(path,'Cards'))
2047 if f.endswith('.dat')]
2048 if os.path.isdir(pjoin(path,'HTML')):
2049 possibility += [f for f in os.listdir(pjoin(path,'HTML'))
2050 if f.endswith('.html') and 'default' not in f]
2051 else:
2052 possibility.extend(['./','../'])
2053 if os.path.exists('MG5_debug'):
2054 possibility.append('MG5_debug')
2055 if os.path.exists('ME5_debug'):
2056 possibility.append('ME5_debug')
2057
2058 return self.list_completion(text, possibility)
2059
2060 @cmd.debug()
2061 - def complete_output(self, text, line, begidx, endidx,
2062 possible_options = ['f', 'noclean', 'nojpeg'],
2063 possible_options_full = ['-f', '-noclean', '-nojpeg']):
2064 "Complete the output command"
2065
2066 possible_format = self._export_formats
2067
2068 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2069 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2070 'mg5', 'DECAY', 'EventConverter', 'Models',
2071 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha']
2072
2073
2074 args = self.split_arg(line[0:begidx])
2075 if len(args) >= 1:
2076 if len(args) > 1 and args[1] == 'aloha':
2077 try:
2078 return self.aloha_complete_output(text, line, begidx, endidx)
2079 except Exception, error:
2080 print error
2081
2082 if args[-1].endswith(os.path.sep):
2083 return [name for name in self.path_completion(text,
2084 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2085 only_dirs = True) if name not in forbidden_names]
2086
2087 if args[-1][0] == '-' or len(args) > 1 and args[-2] == '-':
2088 return self.list_completion(text, possible_options)
2089 if len(args) > 2:
2090 return self.list_completion(text, possible_options_full)
2091
2092 if len(args) == 1:
2093 format = possible_format + ['.' + os.path.sep, '..' + os.path.sep, 'auto']
2094 return self.list_completion(text, format)
2095
2096
2097 content = [name for name in self.path_completion(text, '.', only_dirs = True) \
2098 if name not in forbidden_names]
2099 content += ['auto']
2100 return self.list_completion(text, content)
2101
2103 "Complete the output aloha command"
2104 args = self.split_arg(line[0:begidx])
2105 completion_categories = {}
2106
2107 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2108 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2109 'mg5', 'DECAY', 'EventConverter', 'Models',
2110 'ExRootAnalysis', 'Transfer_Fct', 'aloha',
2111 'apidoc','vendor']
2112
2113
2114
2115 options = ['--format=Fortran', '--format=Python','--format=gpu','--format=CPP','--output=']
2116 options = self.list_completion(text, options)
2117 if options:
2118 completion_categories['options'] = options
2119
2120 if args[-1] == '--output=' or args[-1].endswith(os.path.sep):
2121
2122 completion_categories['path'] = [name for name in self.path_completion(text,
2123 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2124 only_dirs = True) if name not in forbidden_names]
2125
2126 else:
2127 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
2128 wf_opt = []
2129 amp_opt = []
2130 opt_conjg = []
2131 for lor in ufomodel.all_lorentz:
2132 amp_opt.append('%s_0' % lor.name)
2133 for i in range(len(lor.spins)):
2134 wf_opt.append('%s_%i' % (lor.name,i+1))
2135 if i % 2 == 0 and lor.spins[i] == 2:
2136 opt_conjg.append('%sC%i_%i' % (lor.name,i //2 +1,i+1))
2137 completion_categories['amplitude routines'] = self.list_completion(text, amp_opt)
2138 completion_categories['Wavefunctions routines'] = self.list_completion(text, wf_opt)
2139 completion_categories['conjugate_routines'] = self.list_completion(text, opt_conjg)
2140
2141 return self.deal_multiple_categories(completion_categories)
2142
2144 "Complete the set command"
2145 args = self.split_arg(line[0:begidx])
2146
2147
2148 if len(args) == 1:
2149 opts = self.options.keys()
2150 return self.list_completion(text, opts)
2151
2152 if len(args) == 2:
2153 if args[1] in ['group_subprocesses', 'complex_mass_scheme',\
2154 'loop_optimized_output']:
2155 return self.list_completion(text, ['False', 'True', 'default'])
2156 elif args[1] in ['ignore_six_quark_processes']:
2157 return self.list_completion(text, self._multiparticles.keys())
2158 elif args[1] == 'gauge':
2159 return self.list_completion(text, ['unitary', 'Feynman','default'])
2160 elif args[1] == 'OLP':
2161 return self.list_completion(text, MadGraphCmd._OLP_supported)
2162 elif args[1] == 'output_dependencies':
2163 return self.list_completion(text,
2164 MadGraphCmd._output_dependencies_supported)
2165 elif args[1] == 'stdout_level':
2166 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR',
2167 'CRITICAL','default'])
2168 elif args[1] == 'fortran_compiler':
2169 return self.list_completion(text, ['f77','g77','gfortran','default'])
2170 elif args[1] == 'cpp_compiler':
2171 return self.list_completion(text, ['g++', 'c++', 'clang', 'default'])
2172 elif args[1] == 'nb_core':
2173 return self.list_completion(text, [str(i) for i in range(100)] + ['default'] )
2174 elif args[1] == 'run_mode':
2175 return self.list_completion(text, [str(i) for i in range(3)] + ['default'])
2176 elif args[1] == 'cluster_type':
2177 return self.list_completion(text, cluster.from_name.keys() + ['default'])
2178 elif args[1] == 'cluster_queue':
2179 return []
2180 elif args[1] == 'automatic_html_opening':
2181 return self.list_completion(text, ['False', 'True', 'default'])
2182 else:
2183
2184 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)]
2185 return self.list_completion(text, second_set + ['default'])
2186 elif len(args) >2 and args[-1].endswith(os.path.sep):
2187 return self.path_completion(text,
2188 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2189 only_dirs = True)
2190
2191 - def complete_import(self, text, line, begidx, endidx, allow_restrict=True,
2192 treat_completion=True):
2193 "Complete the import command"
2194
2195 args=self.split_arg(line[0:begidx])
2196
2197
2198 if len(args) == 1:
2199 opt = self.list_completion(text, self._import_formats)
2200 if opt:
2201 return opt
2202 mode = 'all'
2203 elif args[1] in self._import_formats:
2204 mode = args[1]
2205 else:
2206 args.insert(1, 'all')
2207 mode = 'all'
2208
2209
2210 completion_categories = {}
2211
2212 if mode in ['model', 'all'] and '-' in text:
2213
2214 path = '-'.join([part for part in text.split('-')[:-1]])
2215
2216
2217 all_name = self.find_restrict_card(path, no_restrict=False)
2218 all_name += self.find_restrict_card(path, no_restrict=False,
2219 base_dir=pjoin(MG5DIR,'models'))
2220
2221
2222 all_name = [name+' ' for name in all_name if name.startswith(text)
2223 and name.strip() != text]
2224
2225
2226 if all_name:
2227 completion_categories['Restricted model'] = all_name
2228
2229
2230 if os.path.sep in args[-1]:
2231 if mode.startswith('model') or mode == 'all':
2232
2233 try:
2234 cur_path = pjoin(*[a for a in args \
2235 if a.endswith(os.path.sep)])
2236 except Exception:
2237 pass
2238 else:
2239 all_dir = self.path_completion(text, cur_path, only_dirs = True)
2240 if mode in ['model_v4','all']:
2241 completion_categories['Path Completion'] = all_dir
2242
2243 new = []
2244 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2245 for name in all_dir]
2246 if data:
2247 completion_categories['Path Completion'] = all_dir + new
2248 else:
2249 try:
2250 cur_path = pjoin(*[a for a in args \
2251 if a.endswith(os.path.sep)])
2252 except Exception:
2253 pass
2254 else:
2255 all_path = self.path_completion(text, cur_path)
2256 if mode == 'all':
2257 new = []
2258 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2259 for name in all_path]
2260 if data:
2261 completion_categories['Path Completion'] = data[0]
2262 else:
2263 completion_categories['Path Completion'] = all_path
2264
2265
2266 if (len(args) == 2):
2267 is_model = True
2268 if mode == 'model':
2269 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py'))
2270 mod_name = lambda name: name
2271 elif mode == 'model_v4':
2272 file_cond = lambda p : (os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat'))
2273 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat')))
2274 mod_name = lambda name :(name[-3:] != '_v4' and name or name[:-3])
2275 elif mode == 'all':
2276 mod_name = lambda name: name
2277 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py')) \
2278 or os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat')) \
2279 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat'))
2280 else:
2281 cur_path = pjoin(*[a for a in args \
2282 if a.endswith(os.path.sep)])
2283 all_path = self.path_completion(text, cur_path)
2284 completion_categories['model name'] = all_path
2285 is_model = False
2286
2287 if is_model:
2288 model_list = [mod_name(name) for name in \
2289 self.path_completion(text,
2290 pjoin(MG5DIR,'models'),
2291 only_dirs = True) \
2292 if file_cond(name)]
2293
2294 if mode == 'model_v4':
2295 completion_categories['model name'] = model_list
2296 elif allow_restrict:
2297
2298 all_name = []
2299 for model_name in model_list:
2300 all_name += self.find_restrict_card(model_name,
2301 base_dir=pjoin(MG5DIR,'models'))
2302 else:
2303 all_name = model_list
2304
2305 if mode == 'all':
2306 cur_path = pjoin(*[a for a in args \
2307 if a.endswith(os.path.sep)])
2308 all_path = self.path_completion(text, cur_path)
2309 completion_categories['model name'] = all_path + all_name
2310 elif mode == 'model':
2311 completion_categories['model name'] = all_name
2312
2313
2314 if mode == 'all' and len(args)>1:
2315 mode = self.find_import_type(args[2])
2316
2317 if len(args) >= 3 and mode.startswith('model') and not '-modelname' in line:
2318 if not text and not completion_categories:
2319 return ['--modelname']
2320 elif not (os.path.sep in args[-1] and line[-1] != ' '):
2321 completion_categories['options'] = self.list_completion(text, ['--modelname','-modelname','--noprefix'])
2322 if len(args) >= 3 and mode.startswith('banner') and not '--no_launch' in line:
2323 completion_categories['options'] = self.list_completion(text, ['--no_launch'])
2324
2325 if treat_completion:
2326 return self.deal_multiple_categories(completion_categories)
2327 else:
2328
2329 return completion_categories
2330
2331
2333 """find the restriction file associate to a given model"""
2334
2335
2336 if no_restrict:
2337 output = [model_name]
2338 else:
2339 output = []
2340
2341
2342 if not os.path.exists(pjoin(base_dir, model_name, 'couplings.py')):
2343
2344 return output
2345
2346 if model_name.endswith(os.path.sep):
2347 model_name = model_name[:-1]
2348
2349
2350 if os.path.exists(pjoin(base_dir, model_name, 'restrict_default.dat')):
2351 output.append('%s-full' % model_name)
2352
2353
2354 for name in os.listdir(pjoin(base_dir, model_name)):
2355 if name.startswith('restrict_') and not name.endswith('default.dat') \
2356 and name.endswith('.dat'):
2357 tag = name[9:-4]
2358 while model_name.endswith(os.path.sep):
2359 model_name = model_name[:-1]
2360 output.append('%s-%s' % (model_name, tag))
2361
2362
2363 return output
2364
2375
2376
2377
2378
2379 -class MadGraphCmd(HelpToCmd, CheckValidForCmd, CompleteForCmd, CmdExtended):
2380 """The command line processor of MadGraph"""
2381
2382 writing_dir = '.'
2383
2384
2385 _display_opts = ['particles', 'interactions', 'processes', 'diagrams',
2386 'diagrams_text', 'multiparticles', 'couplings', 'lorentz',
2387 'checks', 'parameters', 'options', 'coupling_order','variable']
2388 _add_opts = ['process', 'model']
2389 _save_opts = ['model', 'processes', 'options']
2390 _tutorial_opts = ['aMCatNLO', 'stop', 'MadLoop', 'MadGraph5']
2391 _switch_opts = ['mg5','aMC@NLO','ML5']
2392 _check_opts = ['full', 'timing', 'stability', 'profile', 'permutation',
2393 'gauge','lorentz', 'brs']
2394 _import_formats = ['model_v4', 'model', 'proc_v4', 'command', 'banner']
2395 _install_opts = ['pythia-pgs', 'Delphes', 'MadAnalysis', 'ExRootAnalysis',
2396 'update', 'Delphes2', 'SysCalc', 'Golem95']
2397 _v4_export_formats = ['madevent', 'standalone', 'standalone_msP','standalone_msF',
2398 'matrix', 'standalone_rw', 'madweight']
2399 _export_formats = _v4_export_formats + ['standalone_cpp', 'pythia8', 'aloha']
2400 _set_options = ['group_subprocesses',
2401 'ignore_six_quark_processes',
2402 'stdout_level',
2403 'fortran_compiler',
2404 'cpp_compiler',
2405 'loop_optimized_output',
2406 'complex_mass_scheme',
2407 'gauge']
2408 _valid_nlo_modes = ['all','real','virt','sqrvirt','tree']
2409 _valid_sqso_types = ['==','<=','=','>']
2410 _valid_amp_so_types = ['=','<=']
2411 _OLP_supported = ['MadLoop', 'GoSam']
2412 _output_dependencies_supported = ['external', 'internal','environment_paths']
2413
2414
2415
2416 options_configuration = {'pythia8_path': './pythia8',
2417 'hwpp_path': './herwigPP',
2418 'thepeg_path': './thepeg',
2419 'hepmc_path': './hepmc',
2420 'madanalysis_path': './MadAnalysis',
2421 'pythia-pgs_path':'./pythia-pgs',
2422 'td_path':'./td',
2423 'delphes_path':'./Delphes',
2424 'exrootanalysis_path':'./ExRootAnalysis',
2425 'syscalc_path': './SysCalc',
2426 'timeout': 60,
2427 'web_browser':None,
2428 'eps_viewer':None,
2429 'text_editor':None,
2430 'fortran_compiler':None,
2431 'cpp_compiler':None,
2432 'auto_update':7,
2433 'cluster_type': 'condor',
2434 'cluster_temp_path': None,
2435 'cluster_queue': None,
2436 'cluster_status_update': (600, 30),
2437 'fastjet':'fastjet-config',
2438 'pjfry':'auto',
2439 'golem':'auto',
2440 'lhapdf':'lhapdf-config',
2441 'applgrid':'applgrid-config',
2442 'amcfast':'amcfast-config',
2443 'cluster_temp_path':None,
2444 'OLP': 'MadLoop',
2445 'cluster_nb_retry':1,
2446 'cluster_retry_wait':300,
2447 'output_dependencies':'external'
2448 }
2449
2450 options_madgraph= {'group_subprocesses': 'Auto',
2451 'ignore_six_quark_processes': False,
2452 'complex_mass_scheme': False,
2453 'gauge':'unitary',
2454 'stdout_level':None,
2455 'loop_optimized_output':True
2456 }
2457
2458 options_madevent = {'automatic_html_opening':True,
2459 'run_mode':2,
2460 'nb_core': None
2461 }
2462
2463
2464
2465 _curr_model = None
2466 _curr_amps = diagram_generation.AmplitudeList()
2467 _curr_matrix_elements = helas_objects.HelasMultiProcess()
2468 _curr_fortran_model = None
2469 _curr_cpp_model = None
2470 _curr_exporter = None
2471 _done_export = False
2472 _curr_decaymodel = None
2473
2474 helporder = ['Main commands', 'Documented commands']
2475
2476
2490
2491
2492 - def __init__(self, mgme_dir = '', *completekey, **stdin):
2493 """ add a tracker of the history """
2494
2495 CmdExtended.__init__(self, *completekey, **stdin)
2496
2497
2498 if mgme_dir:
2499 if os.path.isdir(pjoin(mgme_dir, 'Template')):
2500 self._mgme_dir = mgme_dir
2501 logger.info('Setting MG/ME directory to %s' % mgme_dir)
2502 else:
2503 logger.warning('Warning: Directory %s not valid MG/ME directory' % \
2504 mgme_dir)
2505 self._mgme_dir = MG4DIR
2506
2507
2508 self._multiparticles = {}
2509 self.options = {}
2510 self._generate_info = ""
2511 self._model_v4_path = None
2512 self._export_dir = None
2513 self._export_format = 'madevent'
2514 self._mgme_dir = MG4DIR
2515 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
2516 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
2517 self._comparisons = None
2518 self._nlo_modes_for_completion = ['all','virt','real']
2519
2520
2521 self.set_configuration()
2522
2541
2555
2556
2557
2559 """Generate an amplitude for a given process and add to
2560 existing amplitudes
2561 or merge two model
2562 """
2563
2564 args = self.split_arg(line)
2565
2566
2567 warning_duplicate = True
2568 if '--no_warning=duplicate' in args:
2569 warning_duplicate = False
2570 args.remove('--no_warning=duplicate')
2571
2572
2573 self.check_add(args)
2574
2575 if args[0] == 'model':
2576 return self.add_model(args[1:])
2577
2578
2579
2580 if args[-1].startswith('--optimize'):
2581 optimize = True
2582 args.pop()
2583 else:
2584 optimize = False
2585
2586 if args[0] == 'process':
2587
2588 line = ' '.join(args[1:])
2589
2590
2591 if not self._generate_info:
2592 self._generate_info = line
2593
2594
2595 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2596
2597
2598 if ',' in line:
2599 if ']' in line or '[' in line:
2600 error_msg=\
2601 """The '[' and ']' syntax cannot be used in cunjunction with decay chains.
2602 This implies that with decay chains:
2603 > Squared coupling order limitations are not available.
2604 > Loop corrections cannot be considered."""
2605 raise MadGraph5Error(error_msg)
2606 else:
2607 myprocdef, line = self.extract_decay_chain_process(line)
2608
2609
2610
2611 if myprocdef.are_decays_perturbed():
2612 raise MadGraph5Error("Decay processes cannot be perturbed.")
2613
2614
2615
2616 if myprocdef.decays_have_squared_orders() or \
2617 myprocdef['squared_orders']!={}:
2618 raise MadGraph5Error("Decay processes cannot specify "+\
2619 "squared orders constraints.")
2620 if myprocdef.are_negative_orders_present():
2621 raise MadGraph5Error("Decay processes cannot include negative"+\
2622 " coupling orders constraints.")
2623 else:
2624 myprocdef = self.extract_process(line)
2625
2626
2627 if not myprocdef:
2628 raise self.InvalidCmd("Empty or wrong format process, please try again.")
2629
2630
2631 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
2632 myprocdef.get_ninitial():
2633 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
2634
2635
2636
2637 if len([1 for val in myprocdef.get('orders').values()+\
2638 myprocdef.get('squared_orders').values() if val<0])>1:
2639 raise MadGraph5Error("Negative coupling order constraints"+\
2640 " can only be given on one type of coupling and either on"+\
2641 " squared orders or amplitude orders, not both.")
2642
2643 cpu_time1 = time.time()
2644
2645
2646 if self.options['group_subprocesses'] == 'Auto':
2647 collect_mirror_procs = True
2648 else:
2649 collect_mirror_procs = self.options['group_subprocesses']
2650 ignore_six_quark_processes = \
2651 self.options['ignore_six_quark_processes'] if \
2652 "ignore_six_quark_processes" in self.options \
2653 else []
2654
2655
2656 multiprocessclass=None
2657 if myprocdef['perturbation_couplings']!=[]:
2658 multiprocessclass=loop_diagram_generation.LoopMultiProcess
2659 else:
2660 multiprocessclass=diagram_generation.MultiProcess
2661
2662 myproc = diagram_generation.MultiProcess(myprocdef,
2663 collect_mirror_procs = collect_mirror_procs,
2664 ignore_six_quark_processes = ignore_six_quark_processes,
2665 optimize=optimize)
2666
2667
2668 for amp in myproc.get('amplitudes'):
2669 if amp not in self._curr_amps:
2670 self._curr_amps.append(amp)
2671 elif warning_duplicate:
2672 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
2673 amp.nice_string_processes()
2674
2675
2676
2677 self._done_export = False
2678
2679 cpu_time2 = time.time()
2680
2681 nprocs = len(myproc.get('amplitudes'))
2682 ndiags = sum([amp.get_number_of_diagrams() for \
2683 amp in myproc.get('amplitudes')])
2684 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
2685 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
2686 ndiags = sum([amp.get_number_of_diagrams() for \
2687 amp in self._curr_amps])
2688 logger.info("Total: %i processes with %i diagrams" % \
2689 (len(self._curr_amps), ndiags))
2690
2692 """merge two model"""
2693
2694 model_path = args[0]
2695 recreate = ('--recreate' in args)
2696 output_dir = [a.split('=',1)[1] for a in args if a.startswith('--output')]
2697 if output_dir:
2698 output_dir = output_dir[0]
2699 recreate = True
2700 restrict_name = ''
2701 else:
2702 name = os.path.basename(self._curr_model.get('modelpath'))
2703 restrict_name = self._curr_model.get('restrict_name')
2704 output_dir = pjoin(MG5DIR, 'models', '%s__%s' % (name,
2705 os.path.basename(model_path)))
2706
2707 if os.path.exists(output_dir):
2708 if recreate:
2709 shutil.rmtree(output_dir)
2710 else:
2711 logger.info('Model already created! Loading it from %s' % output_dir)
2712 oldmodel = self._curr_model.get('modelpath')
2713 new_model_name = output_dir
2714 if restrict_name:
2715 new_model_name = '%s-%s' % (output_dir, restrict_name)
2716 try:
2717 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
2718 printcmd=False, precmd=True, postcmd=True)
2719 except Exception, error:
2720 logger.debug('fail to load model %s with error:\n %s' % (output_dir, error))
2721 logger.warning('Fail to load the model. Restore previous model')
2722 self.exec_cmd('import model %s' % oldmodel, errorhandling=False,
2723 printcmd=False, precmd=True, postcmd=True)
2724 raise Exception('Invalid Model! Please retry with the option \'--recreate\'.')
2725 else:
2726 return
2727
2728
2729 import models.usermod as usermod
2730 base_model = usermod.UFOModel(self._curr_model.get('modelpath'))
2731
2732 identify = dict(tuple(a.split('=')) for a in args if '=' in a)
2733 base_model.add_model(path=model_path, identify_particles=identify)
2734 base_model.write(output_dir)
2735
2736 new_model_name = output_dir
2737 if restrict_name:
2738 new_model_name = '%s-%s' % (output_dir, restrict_name)
2739 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
2740 printcmd=False, precmd=True, postcmd=True)
2741
2742
2743
2780
2781
2783 """Display current internal status"""
2784
2785 args = self.split_arg(line)
2786
2787 self.check_display(args)
2788
2789 if args[0] == 'diagrams':
2790 self.draw(' '.join(args[1:]))
2791
2792 if args[0] == 'particles' and len(args) == 1:
2793 propagating_particle = []
2794 nb_unpropagating = 0
2795 for particle in self._curr_model['particles']:
2796 if particle.get('propagating'):
2797 propagating_particle.append(particle)
2798 else:
2799 nb_unpropagating += 1
2800
2801 print "Current model contains %i particles:" % \
2802 len(propagating_particle)
2803 part_antipart = [part for part in propagating_particle \
2804 if not part['self_antipart']]
2805 part_self = [part for part in propagating_particle \
2806 if part['self_antipart']]
2807 for part in part_antipart:
2808 print part['name'] + '/' + part['antiname'],
2809 print ''
2810 for part in part_self:
2811 print part['name'],
2812 print ''
2813 if nb_unpropagating:
2814 print 'In addition of %s un-physical particle mediating new interactions.' \
2815 % nb_unpropagating
2816
2817 elif args[0] == 'particles':
2818 for arg in args[1:]:
2819 if arg.isdigit() or (arg[0] == '-' and arg[1:].isdigit()):
2820 particle = self._curr_model.get_particle(abs(int(arg)))
2821 else:
2822 particle = self._curr_model['particles'].find_name(arg)
2823 if not particle:
2824 raise self.InvalidCmd, 'no particle %s in current model' % arg
2825
2826 print "Particle %s has the following properties:" % particle.get_name()
2827 print str(particle)
2828
2829 elif args[0] == 'interactions' and len(args) == 1:
2830 text = "Current model contains %i interactions\n" % \
2831 len(self._curr_model['interactions'])
2832 for i, inter in enumerate(self._curr_model['interactions']):
2833 text += str(i+1) + ':'
2834 for part in inter['particles']:
2835 if part['is_part']:
2836 text += part['name']
2837 else:
2838 text += part['antiname']
2839 text += " "
2840 text += " ".join(order + '=' + str(inter['orders'][order]) \
2841 for order in inter['orders'])
2842 text += '\n'
2843 pydoc.pager(text)
2844
2845 elif args[0] == 'interactions' and len(args)==2 and args[1].isdigit():
2846 for arg in args[1:]:
2847 if int(arg) > len(self._curr_model['interactions']):
2848 raise self.InvalidCmd, 'no interaction %s in current model' % arg
2849 if int(arg) == 0:
2850 print 'Special interactions which identify two particles'
2851 else:
2852 print "Interactions %s has the following property:" % arg
2853 print self._curr_model['interactions'][int(arg)-1]
2854
2855 elif args[0] == 'interactions':
2856 request_part = args[1:]
2857 text = ''
2858 for i, inter in enumerate(self._curr_model['interactions']):
2859 present_part = [part['is_part'] and part['name'] or part['antiname']
2860 for part in inter['particles']
2861 if (part['is_part'] and part['name'] in request_part) or
2862 (not part['is_part'] and part['antiname'] in request_part)]
2863 if len(present_part) < len(request_part):
2864 continue
2865
2866 if set(present_part) != set(request_part):
2867 continue
2868
2869 if len(request_part) > len(set(request_part)):
2870 for p in request_part:
2871 if request_part.count(p) > present_part.count(p):
2872 continue
2873
2874 name = str(i+1) + ' : '
2875 for part in inter['particles']:
2876 if part['is_part']:
2877 name += part['name']
2878 else:
2879 name += part['antiname']
2880 name += " "
2881 text += "\nInteractions %s has the following property:\n" % name
2882 text += str(self._curr_model['interactions'][i])
2883
2884 text += '\n'
2885 print name
2886 if text =='':
2887 text += 'No matching for any interactions'
2888 pydoc.pager(text)
2889
2890
2891 elif args[0] == 'parameters' and len(args) == 1:
2892 text = "Current model contains %i parameters\n" % \
2893 sum([len(part) for part in
2894 self._curr_model['parameters'].values()])
2895 keys = self._curr_model['parameters'].keys()
2896 def key_sort(x, y):
2897 if ('external',) == x:
2898 return -1
2899 elif ('external',) == y:
2900 return +1
2901 elif len(x) < len(y):
2902 return -1
2903 else:
2904 return 1
2905 keys.sort(key_sort)
2906 for key in keys:
2907 item = self._curr_model['parameters'][key]
2908 text += '\nparameter type: %s\n' % str(key)
2909 for value in item:
2910 if hasattr(value, 'expr'):
2911 if value.value is not None:
2912 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
2913 else:
2914 text+= ' %s = %s\n' % (value.name, value.expr)
2915 else:
2916 if value.value is not None:
2917 text+= ' %s = %s\n' % (value.name, value.value)
2918 else:
2919 text+= ' %s \n' % (value.name)
2920 pydoc.pager(text)
2921
2922 elif args[0] == 'processes':
2923 for amp in self._curr_amps:
2924 print amp.nice_string_processes()
2925
2926 elif args[0] == 'diagrams_text':
2927 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
2928 pydoc.pager(text)
2929
2930 elif args[0] == 'multiparticles':
2931 print 'Multiparticle labels:'
2932 for key in self._multiparticles:
2933 print self.multiparticle_string(key)
2934
2935 elif args[0] == 'coupling_order':
2936 hierarchy = self._curr_model['order_hierarchy'].items()
2937
2938 def order(first, second):
2939 if first[1] < second[1]:
2940 return -1
2941 else:
2942 return 1
2943 hierarchy.sort(order)
2944 for order in hierarchy:
2945 print ' %s : weight = %s' % order
2946
2947 elif args[0] == 'couplings' and len(args) == 1:
2948 if self._model_v4_path:
2949 print 'No couplings information available in V4 model'
2950 return
2951 text = ''
2952 text = "Current model contains %i couplings\n" % \
2953 sum([len(part) for part in
2954 self._curr_model['couplings'].values()])
2955 keys = self._curr_model['couplings'].keys()
2956 def key_sort(x, y):
2957 if ('external',) == x:
2958 return -1
2959 elif ('external',) == y:
2960 return +1
2961 elif len(x) < len(y):
2962 return -1
2963 else:
2964 return 1
2965 keys.sort(key_sort)
2966 for key in keys:
2967 item = self._curr_model['couplings'][key]
2968 text += '\ncouplings type: %s\n' % str(key)
2969 for value in item:
2970 if value.value is not None:
2971 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
2972 else:
2973 text+= ' %s = %s\n' % (value.name, value.expr)
2974
2975 pydoc.pager(text)
2976
2977 elif args[0] == 'couplings':
2978 if self._model_v4_path:
2979 print 'No couplings information available in V4 model'
2980 return
2981
2982 try:
2983 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
2984 print 'Note that this is the UFO informations.'
2985 print ' "display couplings" present the actual definition'
2986 print 'prints the current states of mode'
2987 print eval('ufomodel.couplings.%s.nice_string()'%args[1])
2988 except Exception:
2989 raise self.InvalidCmd, 'no couplings %s in current model' % args[1]
2990
2991 elif args[0] == 'lorentz':
2992 if self._model_v4_path:
2993 print 'No lorentz information available in V4 model'
2994 return
2995 elif len(args) == 1:
2996 raise self.InvalidCmd,\
2997 'display lorentz require an argument: the name of the lorentz structure.'
2998 return
2999 try:
3000 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3001 print eval('ufomodel.lorentz.%s.nice_string()'%args[1])
3002 except Exception:
3003 raise self.InvalidCmd, 'no lorentz %s in current model' % args[1]
3004
3005 elif args[0] == 'checks':
3006 comparisons = self._comparisons[0]
3007 if len(args) > 1 and args[1] == 'failed':
3008 comparisons = [c for c in comparisons if not c['passed']]
3009 outstr = "Process check results:"
3010 for comp in comparisons:
3011 outstr += "\n%s:" % comp['process'].nice_string()
3012 outstr += "\n Phase space point: (px py pz E)"
3013 for i, p in enumerate(comp['momenta']):
3014 outstr += "\n%2s %+.9e %+.9e %+.9e %+.9e" % tuple([i] + p)
3015 outstr += "\n Permutation values:"
3016 outstr += "\n " + str(comp['values'])
3017 if comp['passed']:
3018 outstr += "\n Process passed (rel. difference %.9e)" % \
3019 comp['difference']
3020 else:
3021 outstr += "\n Process failed (rel. difference %.9e)" % \
3022 comp['difference']
3023
3024 used_aloha = sorted(self._comparisons[1])
3025 outstr += "\nChecked ALOHA routines:"
3026 for aloha in used_aloha:
3027 aloha_str = aloha[0]
3028 if aloha[1]:
3029 aloha_str += 'C' + 'C'.join([str(ia) for ia in aloha[1]])
3030 aloha_str += "_%d" % aloha[2]
3031 outstr += "\n" + aloha_str
3032
3033 pydoc.pager(outstr)
3034
3035 elif args[0] == 'options':
3036 outstr = " MadGraph5_aMC@NLO Options \n"
3037 outstr += " ---------------- \n"
3038 for key, default in self.options_madgraph.items():
3039 value = self.options[key]
3040 if value == default:
3041 outstr += " %25s \t:\t%s\n" % (key,value)
3042 else:
3043 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3044 outstr += "\n"
3045 outstr += " MadEvent Options \n"
3046 outstr += " ---------------- \n"
3047 for key, default in self.options_madevent.items():
3048 value = self.options[key]
3049 if value == default:
3050 outstr += " %25s \t:\t%s\n" % (key,value)
3051 else:
3052 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3053 outstr += "\n"
3054 outstr += " Configuration Options \n"
3055 outstr += " --------------------- \n"
3056 for key, default in self.options_configuration.items():
3057 value = self.options[key]
3058 if value == default:
3059 outstr += " %25s \t:\t%s\n" % (key,value)
3060 else:
3061 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3062
3063 output.write(outstr)
3064 elif args[0] in ["variable"]:
3065 super(MadGraphCmd, self).do_display(line, output)
3066
3067
3068 - def multiparticle_string(self, key):
3069 """Returns a nicely formatted string for the multiparticle"""
3070
3071 if self._multiparticles[key] and \
3072 isinstance(self._multiparticles[key][0], list):
3073 return "%s = %s" % (key, "|".join([" ".join([self._curr_model.\
3074 get('particle_dict')[part_id].get_name() \
3075 for part_id in id_list]) \
3076 for id_list in self._multiparticles[key]]))
3077 else:
3078 return "%s = %s" % (key, " ".join([self._curr_model.\
3079 get('particle_dict')[part_id].get_name() \
3080 for part_id in self._multiparticles[key]]))
3081
3107
3108
3109
3110 - def draw(self, line,selection='all',type=''):
3166
3167
3169 """Check a given process or set of processes"""
3170
3171 args = self.split_arg(line)
3172
3173 param_card = self.check_check(args)
3174 options= {'events':None}
3175 if param_card and 'banner' == madevent_interface.MadEventCmd.detect_card_type(param_card):
3176 logger.info("Will use the param_card contained in the banner and the events associated")
3177 import madgraph.various.banner as banner
3178 options['events'] = param_card
3179 mybanner = banner.Banner(param_card)
3180 param_card = mybanner.charge_card('param_card')
3181
3182 aloha_lib.KERNEL.clean()
3183
3184 gauge = str(self.options['gauge'])
3185 options['reuse'] = args[1]=="-reuse"
3186 args = args[:1]+args[2:]
3187
3188
3189 if args[0] in ['stability', 'profile']:
3190 options['npoints'] = int(args[1])
3191 args = args[:1]+args[2:]
3192
3193 MLoptions={}
3194 i=-1
3195 while args[i].startswith('--'):
3196 option = args[i].split('=')
3197 if option[0] =='--energy':
3198 options['energy']=float(option[1])
3199 elif option[0]=='--split_orders':
3200 options['split_orders']=int(option[1])
3201 elif option[0]=='--reduction':
3202 MLoptions['MLReductionLib']=[int(ir) for ir in option[1].split('|')]
3203 i=i-1
3204 args = args[:i+1]
3205
3206 proc_line = " ".join(args[1:])
3207 myprocdef = self.extract_process(proc_line)
3208
3209
3210
3211 output_path = os.getcwd()
3212
3213
3214 if not myprocdef:
3215 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3216
3217 if args[0] in ['timing','stability', 'profile'] and not \
3218 myprocdef.get('perturbation_couplings'):
3219 raise self.InvalidCmd("Only loop processes can have their "+
3220 " timings or stability checked.")
3221
3222 if args[0]=='gauge' and \
3223 not myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3224 raise self.InvalidCmd(
3225 """Feynman vs unitary gauge comparisons can only be done if there are no loop
3226 propagators affected by this gauge. Typically, either processes at tree level
3227 or including only QCD perturbations can be considered here.""")
3228
3229 if args[0]=='gauge' and len(self._curr_model.get('gauge')) < 2:
3230 raise self.InvalidCmd("The current model does not allow for both "+\
3231 "Feynman and unitary gauge.")
3232
3233
3234 loggers = [logging.getLogger('madgraph.diagram_generation'),
3235 logging.getLogger('madgraph.loop_diagram_generation'),
3236 logging.getLogger('ALOHA'),
3237 logging.getLogger('madgraph.helas_objects'),
3238 logging.getLogger('madgraph.loop_exporter'),
3239 logging.getLogger('madgraph.export_v4'),
3240 logging.getLogger('cmdprint'),
3241 logging.getLogger('madgraph.model'),
3242 logging.getLogger('madgraph.base_objects')]
3243 old_levels = [log.level for log in loggers]
3244 for log in loggers:
3245 log.setLevel(logging.WARNING)
3246
3247
3248 cpu_time1 = time.time()
3249
3250
3251
3252
3253
3254
3255
3256 if myprocdef.get('perturbation_couplings')==[]:
3257 aloha.loop_mode = False
3258
3259 comparisons = []
3260 gauge_result = []
3261 gauge_result_no_brs = []
3262 lorentz_result =[]
3263 nb_processes = 0
3264 timings = []
3265 stability = []
3266 profile_time = []
3267 profile_stab = []
3268
3269 if "_cuttools_dir" in dir(self):
3270 CT_dir = self._cuttools_dir
3271 else:
3272 CT_dir =""
3273 if "MLReductionLib" in MLoptions:
3274 if 1 in MLoptions["MLReductionLib"]:
3275 MLoptions["MLReductionLib"].remove(1)
3276
3277 TIR_dir={}
3278 if "_iregi_dir" in dir(self):
3279 TIR_dir['iregi_dir']=self._iregi_dir
3280 else:
3281 if "MLReductionLib" in MLoptions:
3282 if 3 in MLoptions["MLReductionLib"]:
3283 logger.warning('IREGI not available on your system; it will be skipped.')
3284 MLoptions["MLReductionLib"].remove(3)
3285
3286 if 'pjfry' in self.options and isinstance(self.options['pjfry'],str):
3287 TIR_dir['pjfry_dir']=self.options['pjfry']
3288 else:
3289 if "MLReductionLib" in MLoptions:
3290 if 2 in MLoptions["MLReductionLib"]:
3291 logger.warning('PJFRY not available on your system; it will be skipped.')
3292 MLoptions["MLReductionLib"].remove(2)
3293
3294 if 'golem' in self.options and isinstance(self.options['golem'],str):
3295 TIR_dir['golem_dir']=self.options['golem']
3296 else:
3297 if "MLReductionLib" in MLoptions:
3298 if 4 in MLoptions["MLReductionLib"]:
3299 logger.warning('GOLEM not available on your system; it will be skipped.')
3300 MLoptions["MLReductionLib"].remove(4)
3301
3302 if args[0] in ['timing']:
3303 timings = process_checks.check_timing(myprocdef,
3304 param_card = param_card,
3305 cuttools=CT_dir,
3306 tir=TIR_dir,
3307 options = options,
3308 cmd = self,
3309 output_path = output_path,
3310 MLOptions = MLoptions
3311 )
3312
3313 if args[0] in ['stability']:
3314 stability=process_checks.check_stability(myprocdef,
3315 param_card = param_card,
3316 cuttools=CT_dir,
3317 tir=TIR_dir,
3318 options = options,
3319 output_path = output_path,
3320 cmd = self,
3321 MLOptions = MLoptions)
3322
3323 if args[0] in ['profile']:
3324
3325
3326 profile_time, profile_stab = process_checks.check_profile(myprocdef,
3327 param_card = param_card,
3328 cuttools=CT_dir,
3329 tir=TIR_dir,
3330 options = options,
3331 MLOptions = MLoptions,
3332 output_path = output_path,
3333 cmd = self)
3334
3335 if args[0] in ['gauge', 'full'] and \
3336 len(self._curr_model.get('gauge')) == 2 and\
3337 myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3338
3339 line = " ".join(args[1:])
3340 myprocdef = self.extract_process(line)
3341 if gauge == 'unitary':
3342 myprocdef_unit = myprocdef
3343 self.do_set('gauge Feynman', log=False)
3344 myprocdef_feyn = self.extract_process(line)
3345 else:
3346 myprocdef_feyn = myprocdef
3347 self.do_set('gauge unitary', log=False)
3348 myprocdef_unit = self.extract_process(line)
3349
3350 nb_part_unit = len(myprocdef_unit.get('model').get('particles'))
3351 nb_part_feyn = len(myprocdef_feyn.get('model').get('particles'))
3352 if nb_part_feyn == nb_part_unit:
3353 logger.error('No Goldstone present for this check!!')
3354 gauge_result_no_brs = process_checks.check_unitary_feynman(
3355 myprocdef_unit, myprocdef_feyn,
3356 param_card = param_card,
3357 options=options,
3358 cuttools=CT_dir,
3359 tir=TIR_dir,
3360 reuse = options['reuse'],
3361 output_path = output_path,
3362 cmd = self)
3363
3364
3365 self.do_set('gauge %s' % gauge, log=False)
3366 nb_processes += len(gauge_result_no_brs)
3367
3368 if args[0] in ['permutation', 'full']:
3369 comparisons = process_checks.check_processes(myprocdef,
3370 param_card = param_card,
3371 quick = True,
3372 cuttools=CT_dir,
3373 tir=TIR_dir,
3374 reuse = options['reuse'],
3375 cmd = self,
3376 output_path = output_path,
3377 options=options)
3378 nb_processes += len(comparisons[0])
3379
3380 if args[0] in ['lorentz', 'full']:
3381 myprocdeff = copy.copy(myprocdef)
3382 lorentz_result = process_checks.check_lorentz(myprocdeff,
3383 param_card = param_card,
3384 cuttools=CT_dir,
3385 tir=TIR_dir,
3386 reuse = options['reuse'],
3387 cmd = self,
3388 output_path = output_path,
3389 options=options)
3390 nb_processes += len(lorentz_result)
3391
3392 if args[0] in ['brs', 'full']:
3393 gauge_result = process_checks.check_gauge(myprocdef,
3394 param_card = param_card,
3395 cuttools=CT_dir,
3396 tir=TIR_dir,
3397 reuse = options['reuse'],
3398 cmd = self,
3399 output_path = output_path,
3400 options=options)
3401 nb_processes += len(gauge_result)
3402
3403 cpu_time2 = time.time()
3404 logger.info("%i checked performed in %0.3f s" \
3405 % (nb_processes,
3406 (cpu_time2 - cpu_time1)))
3407
3408 if args[0] not in ['timing','stability', 'profile']:
3409 if self.options['complex_mass_scheme']:
3410 text = "Note that Complex mass scheme gives gauge/lorentz invariant\n"
3411 text+= "results only for stable particles in final states.\n\n"
3412 elif not myprocdef.get('perturbation_couplings'):
3413 text = "Note That all width have been set to zero for those checks\n\n"
3414 else:
3415 text = "\n"
3416 else:
3417 text ="\n"
3418
3419 if timings:
3420 text += 'Timing result for the '+('optimized' if \
3421 self.options['loop_optimized_output'] else 'default')+' output:\n'
3422
3423 text += process_checks.output_timings(myprocdef, timings)
3424 if stability:
3425 text += 'Stability result for the '+('optimized' if \
3426 self.options['loop_optimized_output'] else 'default')+' output:\n'
3427 text += process_checks.output_stability(stability,output_path)
3428
3429 if profile_time and profile_stab:
3430 text += 'Timing result '+('optimized' if \
3431 self.options['loop_optimized_output'] else 'default')+':\n'
3432 text += process_checks.output_profile(myprocdef, profile_stab,
3433 profile_time, output_path, options['reuse']) + '\n'
3434 if lorentz_result:
3435 text += 'Lorentz invariance results:\n'
3436 text += process_checks.output_lorentz_inv(lorentz_result) + '\n'
3437 if gauge_result:
3438 text += 'Gauge results:\n'
3439 text += process_checks.output_gauge(gauge_result) + '\n'
3440 if gauge_result_no_brs:
3441 text += 'Gauge results (switching between Unitary/Feynman):\n'
3442 text += process_checks.output_unitary_feynman(gauge_result_no_brs) + '\n'
3443
3444 if comparisons and len(comparisons[0])>0:
3445 text += 'Process permutation results:\n'
3446 text += process_checks.output_comparisons(comparisons[0]) + '\n'
3447 self._comparisons = comparisons
3448
3449
3450 if len(text.split('\n'))>20 and not '-reuse' in line and text!='':
3451 if 'test_manager' not in sys.argv[0]:
3452 pydoc.pager(text)
3453
3454
3455 for i, log in enumerate(loggers):
3456 log.setLevel(old_levels[i])
3457
3458
3459
3460 if len(text.split('\n'))<=20 or options['reuse']:
3461
3462 logging.getLogger('madgraph.check_cmd').info(text)
3463 else:
3464 logging.getLogger('madgraph.check_cmd').debug(text)
3465
3466
3467 process_checks.clean_added_globals(process_checks.ADDED_GLOBAL)
3468 if not options['reuse']:
3469 process_checks.clean_up(self._mgme_dir)
3470
3471
3491
3493 """Extract a process definition from a string. Returns
3494 a ProcessDefinition."""
3495
3496
3497 if not line.count('>') in [1,2]:
3498 self.do_help('generate')
3499 raise self.InvalidCmd('Wrong use of \">\" special character.')
3500
3501
3502
3503
3504 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
3505 line = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
3506
3507
3508
3509
3510
3511
3512 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
3513 proc_number_re = proc_number_pattern.match(line)
3514 if proc_number_re:
3515 proc_number = int(proc_number_re.group(2))
3516 line = proc_number_re.group(1) + \
3517 proc_number_re.group(3)
3518
3519
3520
3521
3522 squared_order_pattern = re.compile(\
3523 "^(?P<before>.+>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
3524 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*$")
3525 squared_order_re = squared_order_pattern.match(line)
3526 squared_orders = {}
3527
3528
3529
3530
3531 split_orders = []
3532 while squared_order_re:
3533 type = squared_order_re.group('type')
3534 if type not in self._valid_sqso_types:
3535 raise self.InvalidCmd, "Type of squared order constraint '%s'"\
3536 %type+" is not supported."
3537 squared_orders[squared_order_re.group('name')] = \
3538 (int(squared_order_re.group('value')),type)
3539 line = squared_order_re.group('before')
3540 squared_order_re = squared_order_pattern.match(line)
3541
3542
3543 perturbation_couplings_pattern = \
3544 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*"+\
3545 "(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
3546 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
3547 perturbation_couplings = ""
3548 LoopOption= 'tree'
3549 HasBorn= True
3550 if perturbation_couplings_re:
3551 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
3552 option=perturbation_couplings_re.group("option")
3553 if option:
3554 if option in self._valid_nlo_modes:
3555 if option=='sqrvirt':
3556 LoopOption='virt'
3557 HasBorn=False
3558 else:
3559 LoopOption=option
3560 else:
3561 raise self.InvalidCmd, "NLO mode %s is not valid. "%option+\
3562 "Valid modes are %s. "%str(self._valid_nlo_modes)
3563 else:
3564 LoopOption='all'
3565
3566 line = perturbation_couplings_re.group("proc")+\
3567 perturbation_couplings_re.group("rest")
3568
3569
3570
3571
3572 orders = {}
3573 if not perturbation_couplings_re:
3574 new_squared_orders = {}
3575 for order in squared_orders.keys():
3576 if order.endswith('^2'):
3577 new_squared_orders[order[:-2]]=squared_orders[order]
3578 else:
3579 if squared_orders[order][1] not in self._valid_amp_so_types:
3580 raise self.InvalidCmd, \
3581 "Amplitude order constraints can only be of type %s"%\
3582 (', '.join(self._valid_amp_so_types))+\
3583 ", not '%s'."%squared_orders[order][1]
3584 orders[order]=squared_orders[order][0]
3585 squared_orders=new_squared_orders
3586 else:
3587
3588
3589 new_squared_orders = {}
3590 for order in squared_orders.keys():
3591 new_squared_orders[order[:-2] if order.endswith('^2') else order]=\
3592 squared_orders[order]
3593 squared_orders=new_squared_orders
3594
3595
3596
3597 order_pattern = re.compile(\
3598 "^(?P<before>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
3599 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*$")
3600 order_re = order_pattern.match(line)
3601 while order_re:
3602 type = order_re.group('type')
3603 if order_re.group('name').endswith('^2'):
3604 if type not in self._valid_sqso_types:
3605 raise self.InvalidCmd, "Type of squared order "+\
3606 "constraint '%s'"%type+" is not supported."
3607 squared_orders[order_re.group('name')[:-2]] = \
3608 (int(order_re.group('value')),type)
3609 else:
3610 if type not in self._valid_amp_so_types:
3611 raise self.InvalidCmd, \
3612 "Amplitude order constraints can only be of type %s"%\
3613 (', '.join(self._valid_amp_so_types))+", not '%s'."%type
3614
3615 orders[order_re.group('name')] = \
3616 int(order_re.group('value'))
3617 line = order_re.group('before')
3618 order_re = order_pattern.match(line)
3619
3620
3621
3622
3623
3624
3625 if orders=={} and squared_orders!={}:
3626 for order in squared_orders.keys():
3627 if squared_orders[order][0]>=0 and squared_orders[order][1]!='>':
3628 orders[order]=squared_orders[order][0]
3629 else:
3630 orders[order]=99
3631
3632 if not self._curr_model['case_sensitive']:
3633
3634 line = line.lower()
3635
3636
3637 slash = line.find("/")
3638 dollar = line.find("$")
3639 forbidden_particles = ""
3640 if slash > 0:
3641 if dollar > slash:
3642 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
3643 else:
3644 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
3645 if forbidden_particles_re:
3646 forbidden_particles = forbidden_particles_re.group(2)
3647 line = forbidden_particles_re.group(1)
3648 if len(forbidden_particles_re.groups()) > 2:
3649 line = line + forbidden_particles_re.group(3)
3650
3651
3652 forbidden_schannels_re = re.match("^(.+)\s*\$\s*\$\s*(.+)\s*$", line)
3653 forbidden_schannels = ""
3654 if forbidden_schannels_re:
3655 forbidden_schannels = forbidden_schannels_re.group(2)
3656 line = forbidden_schannels_re.group(1)
3657
3658
3659 forbidden_onsh_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
3660 forbidden_onsh_schannels = ""
3661 if forbidden_onsh_schannels_re:
3662 forbidden_onsh_schannels = forbidden_onsh_schannels_re.group(2)
3663 line = forbidden_onsh_schannels_re.group(1)
3664
3665
3666 required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
3667 required_schannels = ""
3668 if required_schannels_re:
3669 required_schannels = required_schannels_re.group(2)
3670 line = required_schannels_re.group(1) + ">" + \
3671 required_schannels_re.group(3)
3672
3673 args = self.split_arg(line)
3674
3675 myleglist = base_objects.MultiLegList()
3676 state = False
3677
3678
3679 for part_name in args:
3680 if part_name == '>':
3681 if not myleglist:
3682 raise self.InvalidCmd, "No final state particles"
3683 state = True
3684 continue
3685
3686 mylegids = []
3687 if part_name in self._multiparticles:
3688 if isinstance(self._multiparticles[part_name][0], list):
3689 raise self.InvalidCmd,\
3690 "Multiparticle %s is or-multiparticle" % part_name + \
3691 " which can be used only for required s-channels"
3692 mylegids.extend(self._multiparticles[part_name])
3693 else:
3694 mypart = self._curr_model['particles'].get_copy(part_name)
3695 if mypart:
3696 mylegids.append(mypart.get_pdg_code())
3697
3698 if mylegids:
3699 myleglist.append(base_objects.MultiLeg({'ids':mylegids,
3700 'state':state}))
3701 else:
3702 raise self.InvalidCmd, \
3703 "No particle %s in model" % part_name
3704
3705 if filter(lambda leg: leg.get('state') == True, myleglist):
3706
3707
3708 perturbation_couplings_list = perturbation_couplings.split()
3709 if perturbation_couplings_list==['']:
3710 perturbation_couplings_list=[]
3711
3712
3713 split_orders=list(set(perturbation_couplings_list+squared_orders.keys()))
3714 try:
3715 split_orders.sort(key=lambda elem: 0 if elem=='WEIGHTED' else
3716 self._curr_model['order_hierarchy'][elem])
3717 except KeyError:
3718 raise self.InvalidCmd, "The loaded model does not defined a "+\
3719 " coupling order hierarchy for these couplings: %s"%\
3720 str([so for so in split_orders if so!='WEIGHTED' and so not
3721 in self._curr_model['order_hierarchy'].keys()])
3722
3723
3724
3725
3726 if LoopOption=='tree':
3727 perturbation_couplings_list = []
3728 if perturbation_couplings_list and LoopOption!='real':
3729 if not isinstance(self._curr_model,loop_base_objects.LoopModel):
3730 raise self.InvalidCmd(\
3731 "The current model does not allow for loop computations.")
3732 else:
3733 for pert_order in perturbation_couplings_list:
3734 if pert_order not in self._curr_model['perturbation_couplings']:
3735 raise self.InvalidCmd(\
3736 "Perturbation order %s is not among" % pert_order + \
3737 " the perturbation orders allowed for by the loop model.")
3738
3739 if not self.options['loop_optimized_output'] and \
3740 LoopOption not in ['tree','real'] and split_orders!=[]:
3741 logger.info('The default output mode (loop_optimized_output'+\
3742 ' = False) does not support evaluations for given powers of'+\
3743 ' coupling orders. MadLoop output will therefore not be'+\
3744 ' able to provide such quantities.')
3745 split_orders = []
3746
3747
3748 forbidden_particle_ids = \
3749 self.extract_particle_ids(forbidden_particles)
3750 if forbidden_particle_ids and \
3751 isinstance(forbidden_particle_ids[0], list):
3752 raise self.InvalidCmd(\
3753 "Multiparticle %s is or-multiparticle" % part_name + \
3754 " which can be used only for required s-channels")
3755 forbidden_onsh_schannel_ids = \
3756 self.extract_particle_ids(forbidden_onsh_schannels)
3757 forbidden_schannel_ids = \
3758 self.extract_particle_ids(forbidden_schannels)
3759 if forbidden_onsh_schannel_ids and \
3760 isinstance(forbidden_onsh_schannel_ids[0], list):
3761 raise self.InvalidCmd,\
3762 "Multiparticle %s is or-multiparticle" % part_name + \
3763 " which can be used only for required s-channels"
3764 if forbidden_schannel_ids and \
3765 isinstance(forbidden_schannel_ids[0], list):
3766 raise self.InvalidCmd,\
3767 "Multiparticle %s is or-multiparticle" % part_name + \
3768 " which can be used only for required s-channels"
3769 required_schannel_ids = \
3770 self.extract_particle_ids(required_schannels)
3771 if required_schannel_ids and not \
3772 isinstance(required_schannel_ids[0], list):
3773 required_schannel_ids = [required_schannel_ids]
3774
3775 sqorders_values = dict([(k,v[0]) for k, v in squared_orders.items()])
3776 if len([1 for sqo_v in sqorders_values.values() if sqo_v<0])>1:
3777 raise self.InvalidCmd(
3778 "At most one negative squared order constraint can be specified.")
3779
3780 sqorders_types = dict([(k,v[1]) for k, v in squared_orders.items()])
3781
3782
3783 return \
3784 base_objects.ProcessDefinition({'legs': myleglist,
3785 'model': self._curr_model,
3786 'id': proc_number,
3787 'orders': orders,
3788 'squared_orders':sqorders_values,
3789 'sqorders_types':sqorders_types,
3790 'forbidden_particles': forbidden_particle_ids,
3791 'forbidden_onsh_s_channels': forbidden_onsh_schannel_ids,
3792 'forbidden_s_channels': forbidden_schannel_ids,
3793 'required_s_channels': required_schannel_ids,
3794 'overall_orders': overall_orders,
3795 'perturbation_couplings': perturbation_couplings_list,
3796 'has_born':HasBorn,
3797 'NLO_mode':LoopOption,
3798 'split_orders':split_orders
3799 })
3800
3801
3802
3803 @staticmethod
3805 """Takes a valid process and return
3806 a tuple (core_process, options). This removes
3807 - any NLO specifications.
3808 - any options
3809 [Used by MadSpin]
3810 """
3811
3812
3813
3814 line=procline
3815 pos1=line.find("[")
3816 if pos1>0:
3817 pos2=line.find("]")
3818 if pos2 >pos1:
3819 line=line[:pos1]+line[pos2+1:]
3820
3821
3822
3823
3824 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
3825 proc_number_re = proc_number_pattern.match(line)
3826 if proc_number_re:
3827 line = proc_number_re.group(1) + proc_number_re.group(3)
3828
3829
3830 pos=1000
3831
3832 order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
3833 order_re = order_pattern.match(line)
3834 if (order_re):
3835 pos_order=line.find(order_re.group(2))
3836 if pos_order>0 and pos_order < pos : pos=pos_order
3837
3838
3839 slash = line.find("/")
3840 if slash > 0 and slash < pos: pos=slash
3841 dollar = line.find("$")
3842 if dollar > 0 and dollar < pos: pos=dollar
3843
3844 if pos<1000:
3845 proc_option=line[pos:]
3846 line=line[:pos]
3847 else:
3848 proc_option=""
3849
3850 return line, proc_option
3851
3853 """Takes a valid process and return
3854 a set of id of final states particles. [Used by MadSpin]
3855 """
3856
3857 if not self._curr_model['case_sensitive']:
3858 procline = procline.lower()
3859 pids = self._curr_model.get('name2pdg')
3860
3861
3862
3863
3864
3865
3866
3867 if ',' in procline:
3868 core, decay = procline.split(',', 1)
3869 core_final = self.get_final_part(core)
3870
3871
3872 all_decays = decay.split(',')
3873 nb_level, tmp_decay = 0, ''
3874 decays = []
3875
3876 for one_decay in all_decays:
3877 if '(' in one_decay:
3878 nb_level += 1
3879 if ')' in one_decay:
3880 nb_level -= 1
3881
3882 if nb_level:
3883 if tmp_decay:
3884 tmp_decay += ', %s' % one_decay
3885 else:
3886 tmp_decay = one_decay
3887 elif tmp_decay:
3888 final = '%s,%s' % (tmp_decay, one_decay)
3889 final = final.strip()
3890 assert final[0] == '(' and final[-1] == ')'
3891 final = final[1:-1]
3892 decays.append(final)
3893 tmp_decay = ''
3894 else:
3895 decays.append(one_decay)
3896
3897 for one_decay in decays:
3898 first = one_decay.split('>',1)[0].strip()
3899 if first in pids:
3900 pid = set([pids[first]])
3901 elif first in self._multiparticles:
3902 pid = set(self._multiparticles[first])
3903 else:
3904 raise Exception, 'invalid particle name: %s. ' % first
3905 core_final.difference_update(pid)
3906 core_final.update(self.get_final_part(one_decay))
3907
3908 return core_final
3909
3910
3911 final = set()
3912 final_states = re.search(r'> ([^\/\$\=\@>]*)(\[|\s\S+\=|\$|\/|\@|$)', procline)
3913 particles = final_states.groups()[0]
3914 for particle in particles.split():
3915 if particle in pids:
3916 final.add(pids[particle])
3917 elif particle in self._multiparticles:
3918 final.update(set(self._multiparticles[particle]))
3919 return final
3920
3921 - def extract_particle_ids(self, args):
3922 """Extract particle ids from a list of particle names. If
3923 there are | in the list, this corresponds to an or-list, which
3924 is represented as a list of id lists. An or-list is used to
3925 allow multiple required s-channel propagators to be specified
3926 (e.g. Z/gamma)."""
3927
3928 if isinstance(args, basestring):
3929 args.replace("|", " | ")
3930 args = self.split_arg(args)
3931 all_ids = []
3932 ids=[]
3933 for part_name in args:
3934 mypart = self._curr_model['particles'].get_copy(part_name)
3935 if mypart:
3936 ids.append([mypart.get_pdg_code()])
3937 elif part_name in self._multiparticles:
3938 ids.append(self._multiparticles[part_name])
3939 elif part_name == "|":
3940
3941 if ids:
3942 all_ids.append(ids)
3943 ids = []
3944 elif part_name.isdigit() or (part_name.startswith('-') and part_name[1:].isdigit()):
3945 ids.append([int(part_name)])
3946 else:
3947 raise self.InvalidCmd("No particle %s in model" % part_name)
3948 all_ids.append(ids)
3949
3950
3951 res_lists = []
3952 for i, id_list in enumerate(all_ids):
3953 res_lists.extend(diagram_generation.expand_list_list(id_list))
3954
3955 for ilist, idlist in enumerate(res_lists):
3956 set_dict = {}
3957 res_lists[ilist] = [set_dict.setdefault(i,i) for i in idlist \
3958 if i not in set_dict]
3959
3960 if len(res_lists) == 1:
3961 res_lists = res_lists[0]
3962
3963 return res_lists
3964
3966 """Optimize the order of particles in a pdg list, so that
3967 similar particles are next to each other. Sort according to:
3968 1. pdg > 0, 2. spin, 3. color, 4. mass > 0"""
3969
3970 if not pdg_list:
3971 return
3972 if not isinstance(pdg_list[0], int):
3973 return
3974
3975 model = self._curr_model
3976 pdg_list.sort(key = lambda i: i < 0)
3977 pdg_list.sort(key = lambda i: model.get_particle(i).is_fermion())
3978 pdg_list.sort(key = lambda i: model.get_particle(i).get('color'),
3979 reverse = True)
3980 pdg_list.sort(key = lambda i: \
3981 model.get_particle(i).get('mass').lower() != 'zero')
3982
3984 """Recursively extract a decay chain process definition from a
3985 string. Returns a ProcessDefinition."""
3986
3987
3988 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*((\w+\s*=\s*\d+\s*)*)$")
3989 proc_number_re = proc_number_pattern.match(line)
3990 proc_number = 0
3991 overall_orders = {}
3992 if proc_number_re:
3993 proc_number = int(proc_number_re.group(2))
3994 line = proc_number_re.group(1)
3995 if proc_number_re.group(3):
3996 order_pattern = re.compile("^(.*?)\s*(\w+)\s*=\s*(\d+)\s*$")
3997 order_line = proc_number_re.group(3)
3998 order_re = order_pattern.match(order_line)
3999 while order_re:
4000 overall_orders[order_re.group(2)] = int(order_re.group(3))
4001 order_line = order_re.group(1)
4002 order_re = order_pattern.match(order_line)
4003 logger.info(line)
4004
4005 index_comma = line.find(",")
4006 index_par = line.find(")")
4007 min_index = index_comma
4008 if index_par > -1 and (index_par < min_index or min_index == -1):
4009 min_index = index_par
4010
4011 if min_index > -1:
4012 core_process = self.extract_process(line[:min_index], proc_number,
4013 overall_orders)
4014 else:
4015 core_process = self.extract_process(line, proc_number,
4016 overall_orders)
4017
4018
4019
4020 while index_comma > -1:
4021 line = line[index_comma + 1:]
4022 if not line.strip():
4023 break
4024 index_par = line.find(')')
4025
4026 if line.lstrip()[0] == '(' and index_par !=-1 and \
4027 not ',' in line[:index_par]:
4028 par_start = line.find('(')
4029 line = '%s %s' % (line[par_start+1:index_par], line[index_par+1:])
4030 index_par = line.find(')')
4031 if line.lstrip()[0] == '(':
4032
4033
4034 line = line.lstrip()[1:]
4035
4036 decay_process, line = \
4037 self.extract_decay_chain_process(line,
4038 level_down=True)
4039 index_comma = line.find(",")
4040 index_par = line.find(')')
4041 else:
4042 index_comma = line.find(",")
4043 min_index = index_comma
4044 if index_par > -1 and \
4045 (index_par < min_index or min_index == -1):
4046 min_index = index_par
4047 if min_index > -1:
4048 decay_process = self.extract_process(line[:min_index])
4049 else:
4050 decay_process = self.extract_process(line)
4051
4052 core_process.get('decay_chains').append(decay_process)
4053
4054 if level_down:
4055 if index_par == -1:
4056 raise self.InvalidCmd, \
4057 "Missing ending parenthesis for decay process"
4058
4059 if index_par < index_comma:
4060 line = line[index_par + 1:]
4061 level_down = False
4062 break
4063
4064 if level_down:
4065 index_par = line.find(')')
4066 if index_par == -1:
4067 raise self.InvalidCmd, \
4068 "Missing ending parenthesis for decay process"
4069 line = line[index_par + 1:]
4070
4071
4072
4073 return core_process, line
4074
4075
4076
4078 """Main commands: Import files with external formats"""
4079
4080 args = self.split_arg(line)
4081
4082 self.check_import(args)
4083 if args[0].startswith('model'):
4084 self._model_v4_path = None
4085
4086 self._curr_amps = diagram_generation.AmplitudeList()
4087 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
4088
4089 if args[0].endswith('_v4'):
4090 self._curr_model, self._model_v4_path = \
4091 import_v4.import_model(args[1], self._mgme_dir)
4092 self._curr_fortran_model = \
4093 helas_call_writers.FortranHelasCallWriter(\
4094 self._curr_model)
4095 else:
4096
4097 if (args[1].startswith('loop_qcd_qed_sm') or\
4098 args[1].split('/')[-1].startswith('loop_qcd_qed_sm')) and\
4099 self.options['gauge']!='Feynman':
4100 logger.info('Switching to Feynman gauge because '+\
4101 'it is the only one supported by the model loop_qcd_qed_sm.')
4102 self._curr_model = None
4103 self.do_set('gauge Feynman',log=False)
4104 prefix = not '--noprefix' in args
4105 if prefix:
4106 aloha.aloha_prefix='mdl_'
4107 else:
4108 aloha.aloha_prefix=''
4109
4110 try:
4111 self._curr_model = import_ufo.import_model(args[1], prefix=prefix)
4112 except import_ufo.UFOImportError, error:
4113 if 'not a valid UFO model' in str(error):
4114 logger_stderr.warning('WARNING: %s' % error)
4115 logger_stderr.warning('Try to recover by running '+\
4116 'automatically `import model_v4 %s` instead.'% args[1])
4117 self.exec_cmd('import model_v4 %s ' % args[1], precmd=True)
4118 return
4119 if self.options['complex_mass_scheme']:
4120 self._curr_model.change_mass_to_complex_scheme()
4121 if hasattr(self._curr_model, 'set_parameters_and_couplings'):
4122 self._curr_model.set_parameters_and_couplings()
4123 if self.options['gauge']=='unitary':
4124 if not force and isinstance(self._curr_model,\
4125 loop_base_objects.LoopModel) and \
4126 self._curr_model.get('perturbation_couplings') not in \
4127 [[],['QCD']]:
4128 if 1 not in self._curr_model.get('gauge') :
4129 logger_stderr.warning('This model does not allow Feynman '+\
4130 'gauge. You will only be able to do tree level '+\
4131 'QCD loop cmputations with it.')
4132 else:
4133 logger.info('Change to the gauge to Feynman because '+\
4134 'this loop model allows for more than just tree level'+\
4135 ' and QCD perturbations.')
4136 self.do_set('gauge Feynman', log=False)
4137 return
4138 if 0 not in self._curr_model.get('gauge') :
4139 logger_stderr.warning('Change the gauge to Feynman since '+\
4140 'the model does not allow unitary gauge')
4141 self.do_set('gauge Feynman', log=False)
4142 return
4143 else:
4144 if 1 not in self._curr_model.get('gauge') :
4145 logger_stderr.warning('Change the gauge to unitary since the'+\
4146 ' model does not allow Feynman gauge.'+\
4147 ' Please re-import the model')
4148 self._curr_model = None
4149 self.do_set('gauge unitary', log= False)
4150 return
4151
4152 self._curr_fortran_model = \
4153 helas_call_writers.FortranUFOHelasCallWriter(\
4154 self._curr_model)
4155 self._curr_cpp_model = \
4156 helas_call_writers.CPPUFOHelasCallWriter(\
4157 self._curr_model)
4158
4159 if '-modelname' not in args:
4160 self._curr_model.pass_particles_name_in_mg_default()
4161
4162
4163 self.process_model()
4164
4165 self._curr_amps = diagram_generation.AmplitudeList()
4166 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
4167 process_checks.store_aloha = []
4168
4169 elif args[0] == 'command':
4170
4171 if not os.path.isfile(args[1]):
4172 raise self.InvalidCmd("Path %s is not a valid pathname" % args[1])
4173 else:
4174
4175
4176 self.check_for_export_dir(args[1])
4177
4178 self.import_command_file(args[1])
4179
4180 elif args[0] == 'banner':
4181 type = madevent_interface.MadEventCmd.detect_card_type(args[1])
4182 if type != 'banner':
4183 raise self.InvalidCmd, 'The File should be a valid banner'
4184 ban = banner_module.Banner(args[1])
4185
4186 if 'mg5proccard' in ban:
4187 for line in ban['mg5proccard'].split('\n'):
4188 if line.startswith('#') or line.startswith('<'):
4189 continue
4190 self.exec_cmd(line)
4191 else:
4192 raise self.InvalidCmd, 'Only MG5 banner are supported'
4193
4194 if not self._done_export:
4195 self.exec_cmd('output . -f')
4196
4197 ban.split(self._done_export[0])
4198 logger.info('All Cards from the banner have been place in directory %s' % pjoin(self._done_export[0], 'Cards'))
4199 if '--no_launch' not in args:
4200 self.exec_cmd('launch')
4201
4202 elif args[0] == 'proc_v4':
4203
4204 if len(args) == 1 and self._export_dir:
4205 proc_card = pjoin(self._export_dir, 'Cards', \
4206 'proc_card.dat')
4207 elif len(args) == 2:
4208 proc_card = args[1]
4209
4210
4211 self.check_for_export_dir(os.path.realpath(proc_card))
4212 else:
4213 raise MadGraph5Error('No default directory in output')
4214
4215
4216
4217 self.import_mg4_proc_card(proc_card)
4218
4220 """ For simple decay chain: remove diagram that are not in the BR.
4221 param_card should be a ParamCard instance."""
4222
4223 assert isinstance(param_card, check_param_card.ParamCard)
4224
4225
4226 amplitudes = diagram_generation.AmplitudeList()
4227 for amp in self._curr_amps:
4228 amplitudes.extend(amp.get_amplitudes())
4229
4230 to_remove = []
4231 for amp in amplitudes:
4232 mother = [l.get('id') for l in amp['process'].get('legs') \
4233 if not l.get('state')]
4234 if 1 == len(mother):
4235 decay_table = param_card['decay'].decay_table[abs(mother[0])]
4236
4237 child = [l.get('id') for l in amp['process'].get('legs') \
4238 if l.get('state')]
4239 if not mother[0] > 0:
4240 child = [x if self._curr_model.get_particle(x)['self_antipart']
4241 else -x for x in child]
4242 child.sort()
4243 child.insert(0, len(child))
4244
4245 if tuple(child) not in decay_table.keys():
4246 to_remove.append(amp)
4247
4248 def remove_amp(amps):
4249 for amp in amps[:]:
4250 if amp in to_remove:
4251 amps.remove(amp)
4252 if isinstance(amp, diagram_generation.DecayChainAmplitude):
4253 remove_amp(amp.get('decay_chains'))
4254 for decay in amp.get('decay_chains'):
4255 remove_amp(decay.get('amplitudes'))
4256 remove_amp(self._curr_amps)
4257
4258
4267
4269 """Set variables _particle_names and _couplings for tab
4270 completion, define multiparticles"""
4271
4272
4273 self._particle_names = [p.get('name') for p in self._curr_model.get('particles')\
4274 if p.get('propagating')] + \
4275 [p.get('antiname') for p in self._curr_model.get('particles') \
4276 if p.get('propagating')]
4277
4278 self._couplings = list(set(sum([i.get('orders').keys() for i in \
4279 self._curr_model.get('interactions')], [])))
4280
4281 self.add_default_multiparticles()
4282
4283
4285 """ read a V4 proc card, convert it and run it in mg5"""
4286
4287
4288 if self.history and self.history[-1].startswith('import proc_v4'):
4289 self.history[-1] = '#%s' % self.history[-1]
4290
4291
4292 reader = files.read_from_file(filepath, import_v4.read_proc_card_v4)
4293 if not reader:
4294 raise self.InvalidCmd('\"%s\" is not a valid path' % filepath)
4295
4296 if self._mgme_dir:
4297
4298 self.exec_cmd("# Import the model %s" % reader.model, precmd=True)
4299 line = self.exec_cmd('import model_v4 %s -modelname' % \
4300 (reader.model), precmd=True)
4301 else:
4302 logging.error('No MG_ME installation detected')
4303 return
4304
4305
4306
4307 lines = reader.extract_command_lines(self._curr_model)
4308 for line in lines:
4309 self.exec_cmd(line, precmd=True)
4310
4311 return
4312
4314 """ add default particle from file interface.multiparticles_default.txt
4315 """
4316
4317 defined_multiparticles = self._multiparticles.keys()
4318 removed_multiparticles = []
4319
4320
4321 for key in self._multiparticles.keys():
4322 try:
4323 for part in self._multiparticles[key]:
4324 self._curr_model.get('particle_dict')[part]
4325 except Exception:
4326 del self._multiparticles[key]
4327 defined_multiparticles.remove(key)
4328 removed_multiparticles.append(key)
4329
4330
4331 for line in open(pjoin(MG5DIR, 'input', \
4332 'multiparticles_default.txt')):
4333 if line.startswith('#'):
4334 continue
4335 try:
4336 if not self._curr_model['case_sensitive']:
4337 multipart_name = line.lower().split()[0]
4338 else:
4339 multipart_name = line.split()[0]
4340 if multipart_name not in self._multiparticles:
4341
4342 self.exec_cmd('define %s' % line, printcmd=False, precmd=True)
4343 except self.InvalidCmd, why:
4344 logger_stderr.warning('impossible to set default multiparticles %s because %s' %
4345 (line.split()[0],why))
4346 if defined_multiparticles:
4347 if 'all' in defined_multiparticles:
4348 defined_multiparticles.remove('all')
4349 logger.info("Kept definitions of multiparticles %s unchanged" % \
4350 " / ".join(defined_multiparticles))
4351
4352 for removed_part in removed_multiparticles:
4353 if removed_part in self._multiparticles:
4354 removed_multiparticles.remove(removed_part)
4355
4356 if removed_multiparticles:
4357 logger.info("Removed obsolete multiparticles %s" % \
4358 " / ".join(removed_multiparticles))
4359
4360
4361 line = []
4362 for part in self._curr_model.get('particles'):
4363 line.append('%s %s' % (part.get('name'), part.get('antiname')))
4364 line = 'all =' + ' '.join(line)
4365 self.do_define(line)
4366
4368 """Install optional package from the MG suite."""
4369
4370 args = self.split_arg(line)
4371
4372 self.check_install(args)
4373
4374 if sys.platform == "darwin":
4375 program = "curl"
4376 else:
4377 program = "wget"
4378
4379
4380 if args[0] == 'update':
4381 self.install_update(args, wget=program)
4382 return
4383
4384
4385 import urllib
4386 path = {}
4387
4388 data_path = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
4389 'http://madgraph.hep.uiuc.edu/package_info.dat']
4390 r = random.randint(0,1)
4391 r = [r, (1-r)]
4392 for index in r:
4393 cluster_path = data_path[index]
4394 try:
4395 data = urllib.urlopen(cluster_path)
4396 except Exception:
4397 continue
4398 break
4399 else:
4400 raise MadGraph5Error, '''Impossible to connect any of us servers.
4401 Please check your internet connection or retry later'''
4402
4403 for line in data:
4404 split = line.split()
4405 path[split[0]] = split[1]
4406
4407
4408 if args[0] == 'Delphes':
4409 args[0] = 'Delphes3'
4410
4411 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
4412 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
4413 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'MadAnalysis',
4414 'SysCalc':'SysCalc', 'Golem95': 'golem95'}
4415 name = name[args[0]]
4416
4417
4418 try:
4419 os.system('rm -rf %s' % pjoin(MG5DIR, name))
4420 except Exception:
4421 pass
4422
4423
4424 logger.info('Downloading %s' % path[args[0]])
4425 if sys.platform == "darwin":
4426 misc.call(['curl', path[args[0]], '-o%s.tgz' % name], cwd=MG5DIR)
4427 else:
4428 misc.call(['wget', path[args[0]], '--output-document=%s.tgz'% name], cwd=MG5DIR)
4429
4430
4431 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
4432 stdout=open(os.devnull, 'w'))
4433
4434 if returncode:
4435 raise MadGraph5Error, 'Fail to download correctly the File. Stop'
4436
4437
4438
4439 if not os.path.exists(pjoin(MG5DIR, name)):
4440 created_name = [n for n in os.listdir(MG5DIR) if n.startswith(name)
4441 and not n.endswith('gz')]
4442 if not created_name:
4443 raise MadGraph5Error, 'The file was not loaded correctly. Stop'
4444 else:
4445 created_name = created_name[0]
4446 files.mv(pjoin(MG5DIR, created_name), pjoin(MG5DIR, name))
4447
4448
4449 logger.info('compile %s. This might takes a while.' % name)
4450
4451
4452 if args[0] == "pythia-pgs" and sys.maxsize > 2**32:
4453 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
4454 text = open(path).read()
4455 text = text.replace('MBITS=32','MBITS=64')
4456 open(path, 'w').writelines(text)
4457 if not os.path.exists(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib')):
4458 os.mkdir(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib'))
4459
4460
4461
4462 if 'FC' not in os.environ or not os.environ['FC']:
4463 if self.options['fortran_compiler'] and self.options['fortran_compiler'] != 'None':
4464 compiler = self.options['fortran_compiler']
4465 elif misc.which('gfortran'):
4466 compiler = 'gfortran'
4467 elif misc.which('g77'):
4468 compiler = 'g77'
4469 else:
4470 raise self.InvalidCmd('Require g77 or Gfortran compiler')
4471
4472 path = None
4473 base_compiler= ['FC=g77','FC=gfortran']
4474 if args[0] == "pythia-pgs":
4475 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
4476 elif args[0] == 'MadAnalysis':
4477 path = os.path.join(MG5DIR, 'MadAnalysis', 'makefile')
4478 if path:
4479 text = open(path).read()
4480 for base in base_compiler:
4481 text = text.replace(base,'FC=%s' % compiler)
4482 open(path, 'w').writelines(text)
4483 os.environ['FC'] = compiler
4484
4485
4486 if name == 'golem95':
4487
4488 ld_path = misc.Popen(['./configure',
4489 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC']],
4490 cwd=pjoin(MG5DIR,'golem95'),stdout=subprocess.PIPE).communicate()[0]
4491
4492
4493 if name == 'SysCalc':
4494 if self.options['lhapdf']:
4495 ld_path = misc.Popen([self.options['lhapdf'], '--libdir'],
4496 stdout=subprocess.PIPE).communicate()[0]
4497 ld_path = ld_path.replace('\n','')
4498 if 'LD_LIBRARY_PATH' not in os.environ:
4499 os.environ['LD_LIBRARY_PATH'] = ld_path
4500 elif not os.environ['LD_LIBRARY_PATH']:
4501 os.environ['LD_LIBRARY_PATH'] = ld_path
4502 elif ld_path not in os.environ['LD_LIBRARY_PATH']:
4503 os.environ['LD_LIBRARY_PATH'] += ';%s' % ld_path
4504 else:
4505 raise self.InvalidCmd('lhapdf is required to compile/use SysCalc')
4506
4507 if logger.level <= logging.INFO:
4508 devnull = open(os.devnull,'w')
4509 try:
4510 misc.call(['make', 'clean'], stdout=devnull, stderr=-2)
4511 except Exception:
4512 pass
4513 if name == 'pythia-pgs':
4514
4515 status = misc.call(['make'], cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
4516 if name == 'golem95':
4517 status = misc.call(['make','install'],
4518 cwd = os.path.join(MG5DIR, name))
4519 else:
4520 status = misc.call(['make'], cwd = os.path.join(MG5DIR, name))
4521 else:
4522 try:
4523 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
4524 except Exception:
4525 pass
4526 if name == 'pythia-pgs':
4527
4528 status = self.compile(mode='', cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
4529 if name == 'golem95':
4530 status = misc.compile(['install'], mode='',
4531 cwd = os.path.join(MG5DIR, name))
4532 else:
4533 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
4534
4535 if not status:
4536 logger.info('Compilation succeeded')
4537 else:
4538
4539 if name == 'pythia-pgs':
4540 to_comment = ['libraries/PGS4/src/stdhep-dir/mcfio/arch_mcfio',
4541 'libraries/PGS4/src/stdhep-dir/src/stdhep_Arch']
4542 for f in to_comment:
4543 f = pjoin(MG5DIR, name, *f.split('/'))
4544 text = "".join(l for l in open(f) if 'fno-second-underscore' not in l)
4545 fsock = open(f,'w').write(text)
4546 try:
4547 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
4548 except Exception:
4549 pass
4550 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
4551 if not status:
4552 logger.info('Compilation succeeded')
4553 else:
4554 logger.warning('Error detected during the compilation. Please check the compilation error and run make manually.')
4555
4556
4557
4558 if args[0] == 'MadAnalysis':
4559 try:
4560 os.system('rm -rf td')
4561 os.mkdir(pjoin(MG5DIR, 'td'))
4562 except Exception, error:
4563 print error
4564 pass
4565
4566 if sys.platform == "darwin":
4567 logger.info('Downloading TD for Mac')
4568 target = 'http://theory.fnal.gov/people/parke/TD/td_mac_intel.tar.gz'
4569 misc.call(['curl', target, '-otd.tgz'],
4570 cwd=pjoin(MG5DIR,'td'))
4571 misc.call(['tar', '-xzpvf', 'td.tgz'],
4572 cwd=pjoin(MG5DIR,'td'))
4573 files.mv(MG5DIR + '/td/td_mac_intel',MG5DIR+'/td/td')
4574 else:
4575 logger.info('Downloading TD for Linux 32 bit')
4576 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td'
4577 misc.call(['wget', target], cwd=pjoin(MG5DIR,'td'))
4578 os.chmod(pjoin(MG5DIR,'td','td'), 0775)
4579 if sys.maxsize > 2**32:
4580 logger.warning('''td program (needed by MadAnalysis) is not compile for 64 bit computer.
4581 In 99% of the case, this is perfectly fine. If you do not have plot, please follow
4582 instruction in https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/TopDrawer .''')
4583 self.options['td_path'] = pjoin(MG5DIR,'td')
4584
4585 if not misc.which('gs'):
4586 logger.warning('''gosthscript not install on your system. This is not required to run MA.
4587 but this prevent to create jpg files and therefore to have the plots in the html output.''')
4588 if sys.platform == "darwin":
4589 logger.warning('''You can download this program at the following link:
4590 http://www.macupdate.com/app/mac/9980/gpl-ghostscript''')
4591
4592 if args[0] == 'Delphes2':
4593 data = open(pjoin(MG5DIR, 'Delphes','data','DetectorCard.dat')).read()
4594 data = data.replace('data/', 'DELPHESDIR/data/')
4595 out = open(pjoin(MG5DIR, 'Template','Common', 'Cards', 'delphes_card_default.dat'), 'w')
4596 out.write(data)
4597 if args[0] == 'Delphes3':
4598 files.cp(pjoin(MG5DIR, 'Delphes','examples','delphes_card_CMS_PileUp.tcl'),
4599 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_default.dat'))
4600 files.cp(pjoin(MG5DIR, 'Delphes','examples','delphes_card_CMS.tcl'),
4601 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_CMS.dat'))
4602 files.cp(pjoin(MG5DIR, 'Delphes','examples','delphes_card_ATLAS.tcl'),
4603 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_ATLAS.dat'))
4604
4605
4606
4607 options_name = {'Delphes': 'delphes_path',
4608 'Delphes2': 'delphes_path',
4609 'Delphes3': 'delphes_path',
4610 'ExRootAnalysis': 'exrootanalysis_path',
4611 'MadAnalysis': 'madanalysis_path',
4612 'SysCalc': 'syscalc_path',
4613 'pythia-pgs':'pythia-pgs_path',
4614 'Golem95': 'golem'}
4615
4616 if args[0] in options_name:
4617 opt = options_name[args[0]]
4618 if opt=='golem':
4619 self.options[opt] = pjoin(MG5DIR,name,'lib')
4620 self.exec_cmd('save options')
4621 elif self.options[opt] != self.options_configuration[opt]:
4622 self.options[opt] = self.options_configuration[opt]
4623 self.exec_cmd('save options')
4624
4625
4626
4628 """ check if the current version of mg5 is up-to-date.
4629 and allow user to install the latest version of MG5 """
4630
4631 def apply_patch(filetext):
4632 """function to apply the patch"""
4633 text = filetext.read()
4634 pattern = re.compile(r'''=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
4635
4636 for orig, new in pattern.findall(text):
4637 shutil.copytree(pjoin(MG5DIR, orig), pjoin(MG5DIR, 'UPDATE_TMP'))
4638 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
4639 for i, name in enumerate(full_path):
4640 path = os.path.sep.join(full_path[:i+1])
4641 if path and not os.path.isdir(path):
4642 os.mkdir(path)
4643 shutil.copytree(pjoin(MG5DIR, 'UPDATE_TMP'), pjoin(MG5DIR, new))
4644 shutil.rmtree(pjoin(MG5DIR, 'UPDATE_TMP'))
4645
4646 pattern = re.compile(r'''=== renamed file \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
4647
4648 for orig, new in pattern.findall(text):
4649 print 'move %s to %s' % (orig, new)
4650 try:
4651 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
4652 except IOError:
4653 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
4654 for i, name in enumerate(full_path):
4655 path = os.path.sep.join(full_path[:i+1])
4656 if path and not os.path.isdir(path):
4657 os.mkdir(path)
4658 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
4659
4660 pattern = re.compile(r'''^=== added file \'(?P<new>[^\']*)\'''',re.M)
4661 all_add = pattern.findall(text)
4662
4663
4664 pattern=re.compile(r'''=== removed file \'(?P<new>[^\']*)\'(?=.*=== added file \'(?P=new)\')''',re.S)
4665 print 'this step can take a few minuts. please be patient'
4666 all_rm_add = pattern.findall(text)
4667
4668 for new in all_add:
4669 if new in all_rm_add:
4670 continue
4671 if os.path.isfile(pjoin(MG5DIR, new)):
4672 os.remove(pjoin(MG5DIR, new))
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684 p= subprocess.Popen(['patch', '-p1'], stdin=subprocess.PIPE,
4685 cwd=MG5DIR)
4686 p.communicate(text)
4687
4688
4689
4690
4691
4692 pattern=re.compile('''=== modified file \'(?P<new>[^\']*)\'[^\n]*\n\-\-\- old/(?P<old>\S*)[^\n]*\n\+\+\+ new/(?P=new)''',re.S)
4693 for match in pattern.findall(text):
4694 new = pjoin(MG5DIR, match[0])
4695 old = pjoin(MG5DIR, match[1])
4696 if new == old:
4697 continue
4698 elif os.path.exists(old):
4699 if not os.path.exists(os.path.dirname(new)):
4700 split = new.split('/')
4701 for i in range(1,len(split)):
4702 path = '/'.join(split[:i])
4703 if not os.path.exists(path):
4704 print 'mkdir', path
4705 os.mkdir(path)
4706 files.cp(old,new)
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727 for path in glob.glob(pjoin(MG5DIR, 'bin','*')):
4728 misc.call(['chmod', '+x', path])
4729 for path in glob.glob(pjoin(MG5DIR, 'Template','*','bin','*')):
4730 misc.call(['chmod', '+x', path])
4731 for path in glob.glob(pjoin(MG5DIR, 'Template','*','bin','internal','*')):
4732 misc.call(['chmod', '+x', path])
4733 for path in glob.glob(pjoin(MG5DIR, 'Template','*','*', '*.py')):
4734 misc.call(['chmod', '+x', path])
4735 for path in glob.glob(pjoin(MG5DIR, 'Template','*','*','*.sh')):
4736 misc.call(['chmod', '+x', path])
4737
4738
4739 pattern=re.compile('''^=== touch (file|directory) \'(?P<new>[^\']*)\'''',re.M)
4740 for match in pattern.findall(text):
4741 if match[0] == 'file':
4742 new = os.path.dirname(pjoin(MG5DIR, match[1]))
4743 else:
4744 new = pjoin(MG5DIR, match[1])
4745 if not os.path.exists(new):
4746 split = new.split('/')
4747 for i in range(1,len(split)+1):
4748 path = '/'.join(split[:i])
4749 if path and not os.path.exists(path):
4750 print 'mkdir', path
4751 os.mkdir(path)
4752 if match[0] == 'file':
4753 print 'touch ', pjoin(MG5DIR, match[1])
4754 misc.call(['touch', pjoin(MG5DIR, match[1])])
4755
4756 pattern=re.compile('''^=== link file \'(?P<new>[^\']*)\' \'(?P<old>[^\']*)\'''', re.M)
4757 for new, old in pattern.findall(text):
4758 if not os.path.exists(pjoin(MG5DIR, new)):
4759 files.ln(old, os.path.dirname(new), os.path.basename(new))
4760
4761
4762 if os.path.isfile(pjoin(MG5DIR,'vendor','CutTools','includects','libcts.a')):
4763 misc.compile(cwd=pjoin(MG5DIR,'vendor','CutTools'))
4764 if os.path.isfile(pjoin(MG5DIR,'vendor','IREGI','src','libiregi.a')):
4765 misc.compile(cwd=pjoin(MG5DIR,'vendor','IREGI','src'))
4766
4767
4768 pattern = re.compile("""^Binary files old/(\S*).*and new/(\S*).*$""", re.M)
4769 if pattern.search(text):
4770 return True
4771 else:
4772 return False
4773
4774
4775 mode = [arg.split('=',1)[1] for arg in args if arg.startswith('--mode=')]
4776 if mode:
4777 mode = mode[-1]
4778 else:
4779 mode = "userrequest"
4780 force = any([arg=='-f' for arg in args])
4781 timeout = [arg.split('=',1)[1] for arg in args if arg.startswith('--timeout=')]
4782 if timeout:
4783 try:
4784 timeout = int(timeout[-1])
4785 except ValueError:
4786 raise self.InvalidCmd('%s: invalid argument for timeout (integer expected)'%timeout[-1])
4787 else:
4788 timeout = self.options['timeout']
4789 input_path = [arg.split('=',1)[1] for arg in args if arg.startswith('--input=')]
4790
4791 if input_path:
4792 fsock = open(input_path[0])
4793 need_binary = apply_patch(fsock)
4794 logger.info('manual patch apply. Please test your version.')
4795 if need_binary:
4796 logger.warning('Note that some files need to be loaded separately!')
4797 sys.exit(0)
4798
4799 options = ['y','n','on_exit']
4800 if mode == 'mg5_start':
4801 timeout = 2
4802 default = 'n'
4803 update_delay = self.options['auto_update'] * 24 * 3600
4804 if update_delay == 0:
4805 return
4806 elif mode == 'mg5_end':
4807 timeout = 5
4808 default = 'n'
4809 update_delay = self.options['auto_update'] * 24 * 3600
4810 if update_delay == 0:
4811 return
4812 options.remove('on_exit')
4813 elif mode == "userrequest":
4814 default = 'y'
4815 update_delay = 0
4816 else:
4817 raise self.InvalidCmd('Unknown mode for command install update')
4818
4819 if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')) or \
4820 os.path.exists(os.path.join(MG5DIR,'.bzr')):
4821 error_text = """This version of MG5 doesn\'t support auto-update. Common reasons are:
4822 1) This version was loaded via bazaar (use bzr pull to update instead).
4823 2) This version is a beta release of MG5."""
4824 if mode == 'userrequest':
4825 raise self.ConfigurationError(error_text)
4826 return
4827
4828 if not misc.which('patch'):
4829 error_text = """Not able to find program \'patch\'. Please reload a clean version
4830 or install that program and retry."""
4831 if mode == 'userrequest':
4832 raise self.ConfigurationError(error_text)
4833 return
4834
4835
4836
4837 data = {}
4838 for line in open(os.path.join(MG5DIR,'input','.autoupdate')):
4839 if not line.strip():
4840 continue
4841 sline = line.split()
4842 data[sline[0]] = int(sline[1])
4843
4844
4845 if 'version_nb' not in data:
4846 if mode == 'userrequest':
4847 error_text = 'This version of MG5 doesn\'t support auto-update. (Invalid information)'
4848 raise self.ConfigurationError(error_text)
4849 return
4850 elif 'last_check' not in data:
4851 data['last_check'] = time.time()
4852
4853
4854 if time.time() - data['last_check'] < update_delay:
4855 return
4856
4857 logger.info('Checking if MG5 is up-to-date... (takes up to %ss)' % timeout)
4858 class TimeOutError(Exception): pass
4859
4860 def handle_alarm(signum, frame):
4861 raise TimeOutError
4862
4863 signal.signal(signal.SIGALRM, handle_alarm)
4864 signal.alarm(timeout)
4865 to_update = 0
4866 try:
4867 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/mg5amc_build_nb')
4868 signal.alarm(0)
4869 web_version = int(filetext.read().strip())
4870 except (TimeOutError, ValueError, IOError):
4871 signal.alarm(0)
4872 print 'failed to connect server'
4873 if mode == 'mg5_end':
4874
4875 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
4876 fsock.write("version_nb %s\n" % data['version_nb'])
4877 fsock.write("last_check %s\n" % \
4878 int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1))
4879 fsock.close()
4880 return
4881
4882 if web_version == data['version_nb']:
4883 logger.info('No new version of MG5 available')
4884
4885 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
4886 fsock.write("version_nb %s\n" % data['version_nb'])
4887 fsock.write("last_check %s\n" % int(time.time()))
4888 fsock.close()
4889 return
4890 elif data['version_nb'] > web_version:
4891 logger_stderr.info('impossible to update: local %s web %s' % (data['version_nb'], web_version))
4892 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
4893 fsock.write("version_nb %s\n" % data['version_nb'])
4894 fsock.write("last_check %s\n" % int(time.time()))
4895 fsock.close()
4896 return
4897 else:
4898 if not force:
4899 answer = self.ask('New Version of MG5 available! Do you want to update your current version?',
4900 default, options)
4901 else:
4902 answer = default
4903
4904
4905 if answer == 'y':
4906 logger.info('start updating code')
4907 fail = 0
4908 for i in range(data['version_nb'], web_version):
4909 try:
4910 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/patch/build%s.patch' %(i+1))
4911
4912 except Exception:
4913 print 'fail to load patch to build #%s' % (i+1)
4914 fail = i
4915 break
4916 need_binary = apply_patch(filetext)
4917 if need_binary:
4918 path = "http://madgraph.phys.ucl.ac.be/binary/binary_file%s.tgz" %(i+1)
4919 name = "extra_file%i" % (i+1)
4920 if sys.platform == "darwin":
4921 misc.call(['curl', path, '-o%s.tgz' % name], cwd=MG5DIR)
4922 else:
4923 misc.call(['wget', path, '--output-document=%s.tgz'% name], cwd=MG5DIR)
4924
4925 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
4926 stdout=open(os.devnull, 'w'))
4927
4928 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
4929 if not fail:
4930 fsock.write("version_nb %s\n" % web_version)
4931 else:
4932 fsock.write("version_nb %s\n" % fail)
4933 fsock.write("last_check %s\n" % int(time.time()))
4934 fsock.close()
4935 logger.info('Checking current version. (type ctrl-c to bypass the check)')
4936 subprocess.call([os.path.join('tests','test_manager.py')],
4937 cwd=MG5DIR)
4938
4939 print 'new version installed, please relaunch mg5'
4940 sys.exit(0)
4941 elif answer == 'n':
4942
4943 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
4944 fsock.write("version_nb %s\n" % data['version_nb'])
4945 fsock.write("last_check %s\n" % int(time.time()))
4946 fsock.close()
4947 logger.info('Update bypassed.')
4948 logger.info('The next check for a new version will be performed in %s days' \
4949 % abs(self.options['auto_update']))
4950 logger.info('In order to change this delay. Enter the command:')
4951 logger.info('set auto_update X')
4952 logger.info('Putting X to zero will prevent this check at anytime.')
4953 logger.info('You can upgrade your version at any time by typing:')
4954 logger.info('install update')
4955 else:
4956
4957
4958 self.options['auto_update'] = -1 * self.options['auto_update']
4959
4960
4961
4963 """ assign all configuration variable from file
4964 ./input/mg5_configuration.txt. assign to default if not define """
4965
4966 if not self.options:
4967 self.options = dict(self.options_configuration)
4968 self.options.update(self.options_madgraph)
4969 self.options.update(self.options_madevent)
4970
4971 if not config_path:
4972 if os.environ.has_key('MADGRAPH_BASE'):
4973 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
4974 self.set_configuration(config_path, final)
4975 return
4976 if 'HOME' in os.environ:
4977 config_path = pjoin(os.environ['HOME'],'.mg5',
4978 'mg5_configuration.txt')
4979 if os.path.exists(config_path):
4980 self.set_configuration(config_path, final=False)
4981 config_path = os.path.relpath(pjoin(MG5DIR,'input',
4982 'mg5_configuration.txt'))
4983 return self.set_configuration(config_path, final)
4984
4985 if not os.path.exists(config_path):
4986 files.cp(pjoin(MG5DIR,'input','.mg5_configuration_default.txt'), config_path)
4987 config_file = open(config_path)
4988
4989
4990 logger.info('load MG5 configuration from %s ' % config_file.name)
4991 for line in config_file:
4992 if '#' in line:
4993 line = line.split('#',1)[0]
4994 line = line.replace('\n','').replace('\r\n','')
4995 try:
4996 name, value = line.split('=')
4997 except ValueError:
4998 pass
4999 else:
5000 name = name.strip()
5001 value = value.strip()
5002 if name != 'mg5_path':
5003 self.options[name] = value
5004 if value.lower() == "none" or value=="":
5005 self.options[name] = None
5006
5007 self.options['stdout_level'] = logging.getLogger('madgraph').level
5008 if not final:
5009 return self.options
5010
5011
5012
5013
5014 for key in self.options:
5015 if key in ['pythia8_path', 'hwpp_path', 'thepeg_path', 'hepmc_path']:
5016 if self.options[key] in ['None', None]:
5017 self.options[key] = None
5018 continue
5019 path = self.options[key]
5020
5021 if key == 'pythia8_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Pythia.h')):
5022 if not os.path.isfile(pjoin(path, 'include', 'Pythia.h')):
5023 self.options['pythia8_path'] = None
5024 else:
5025 continue
5026
5027 elif key == 'hwpp_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
5028 if not os.path.isfile(pjoin(path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
5029 self.options['hwpp_path'] = None
5030 else:
5031 continue
5032
5033 elif key == 'thepeg_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
5034 if not os.path.isfile(pjoin(path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
5035 self.options['thepeg_path'] = None
5036 else:
5037 continue
5038
5039 elif key == 'hepmc_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'HEPEVT_Wrapper.h')):
5040 if not os.path.isfile(pjoin(path, 'include', 'HEPEVT_Wrapper.h')):
5041 self.options['hepmc_path'] = None
5042 else:
5043 continue
5044
5045 elif key in ['pjfry','golem']:
5046 if isinstance(self.options[key],str) and self.options[key].lower() == 'auto':
5047
5048 program = misc.which_lib('lib%s.a'%key)
5049 if program != None:
5050 fpath, fname = os.path.split(program)
5051 logger.info('Using %s library in %s'%(key,fpath))
5052 self.options[key]=fpath
5053 else:
5054
5055 local_install = {'pjfry':'PJFRY', 'golem':'golem95'}
5056 if os.path.isdir(pjoin(MG5DIR,local_install[key])):
5057 self.options[key]=pjoin(MG5DIR,local_install[key],'lib')
5058 else:
5059 self.options[key]=None
5060
5061 elif key.endswith('path'):
5062 pass
5063 elif key in ['run_mode', 'auto_update']:
5064 self.options[key] = int(self.options[key])
5065 elif key in ['cluster_type','automatic_html_opening']:
5066 pass
5067 elif key not in ['text_editor','eps_viewer','web_browser', 'stdout_level']:
5068
5069 try:
5070 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
5071 except MadGraph5Error, error:
5072 print error
5073 logger.warning("Option %s from config file not understood" \
5074 % key)
5075 else:
5076 if key in self.options_madgraph:
5077 self.history.append('set %s %s' % (key, self.options[key]))
5078
5079 launch_ext.open_file.configure(self.options)
5080
5081 return self.options
5082
5084 """Check if the files is in a valid export directory and assign it to
5085 export path if if is"""
5086
5087
5088 if self._export_dir:
5089 return
5090
5091 if os.path.exists(pjoin(os.getcwd(), 'Cards')):
5092 self._export_dir = os.getcwd()
5093 return
5094
5095 path_split = filepath.split(os.path.sep)
5096 if len(path_split) > 2 and path_split[-2] == 'Cards':
5097 self._export_dir = os.path.sep.join(path_split[:-2])
5098 return
5099
5101 """Main commands: Ask for editing the parameter and then
5102 Execute the code (madevent/standalone/...)
5103 """
5104
5105
5106 current_options = dict([(name, self.options[name]) for name in self.options_madgraph])
5107 start_cwd = os.getcwd()
5108
5109 args = self.split_arg(line)
5110
5111 (options, args) = _launch_parser.parse_args(args)
5112 self.check_launch(args, options)
5113 options = options.__dict__
5114
5115
5116 if args[0].startswith('standalone'):
5117 if os.path.isfile(os.path.join(os.getcwd(),args[1],'Cards',\
5118 'MadLoopParams.dat')) and not os.path.isfile(os.path.join(\
5119 os.getcwd(),args[1],'SubProcesses','check_poles.f')):
5120 ext_program = launch_ext.MadLoopLauncher(self, args[1], \
5121 options=self.options, **options)
5122 else:
5123 ext_program = launch_ext.SALauncher(self, args[1], \
5124 options=self.options, **options)
5125 elif args[0] == 'madevent':
5126 if options['interactive']:
5127 if hasattr(self, 'do_shell'):
5128 ME = madevent_interface.MadEventCmdShell(me_dir=args[1], options=self.options)
5129 else:
5130 ME = madevent_interface.MadEventCmd(me_dir=args[1],options=self.options)
5131 ME.pass_in_web_mode()
5132 stop = self.define_child_cmd_interface(ME)
5133 return stop
5134
5135
5136 if not self._generate_info:
5137
5138
5139 info = open(pjoin(args[1],'SubProcesses','procdef_mg5.dat')).read()
5140 generate_info = info.split('# Begin PROCESS',1)[1].split('\n')[1]
5141 generate_info = generate_info.split('#')[0]
5142 else:
5143 generate_info = self._generate_info
5144
5145 if len(generate_info.split('>')[0].strip().split())>1:
5146 ext_program = launch_ext.MELauncher(args[1], self,
5147 shell = hasattr(self, 'do_shell'),
5148 options=self.options,**options)
5149 else:
5150
5151 ext_program = launch_ext.MELauncher(args[1], self, unit='GeV',
5152 shell = hasattr(self, 'do_shell'),
5153 options=self.options,**options)
5154
5155 elif args[0] == 'pythia8':
5156 ext_program = launch_ext.Pythia8Launcher( args[1], self, **options)
5157
5158 elif args[0] == 'aMC@NLO':
5159 if options['interactive']:
5160 if hasattr(self, 'do_shell'):
5161 ME = amcatnlo_run.aMCatNLOCmdShell(me_dir=args[1], options=self.options)
5162 else:
5163 ME = amcatnlo_run.aMCatNLOCmd(me_dir=args[1],options=self.options)
5164 ME.pass_in_web_mode()
5165
5166 config_line = [l for l in self.history if l.strip().startswith('set')]
5167 for line in config_line:
5168 ME.exec_cmd(line)
5169 stop = self.define_child_cmd_interface(ME)
5170 return stop
5171 ext_program = launch_ext.aMCatNLOLauncher( args[1], self, **options)
5172 elif args[0] == 'madweight':
5173 import madgraph.interface.madweight_interface as madweight_interface
5174 if options['interactive']:
5175 if hasattr(self, 'do_shell'):
5176 MW = madweight_interface.MadWeightCmdShell(me_dir=args[1], options=self.options)
5177 else:
5178 MW = madweight_interface.MadWeightCmd(me_dir=args[1],options=self.options)
5179
5180 config_line = [l for l in self.history if l.strip().startswith('set')]
5181 for line in config_line:
5182 MW.exec_cmd(line)
5183 stop = self.define_child_cmd_interface(MW)
5184 return stop
5185 ext_program = launch_ext.MWLauncher( self, args[1],
5186 shell = hasattr(self, 'do_shell'),
5187 options=self.options,**options)
5188 else:
5189 os.chdir(start_cwd)
5190 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
5191
5192
5193 ext_program.run()
5194 os.chdir(start_cwd)
5195
5196 for key, value in current_options.items():
5197 self.options[key] = value
5198
5264
5265
5267 """create a restriction card in a interactive way"""
5268
5269 args = self.split_arg(line)
5270 self.check_customize_model(args)
5271
5272 model_path = self._curr_model.get('modelpath')
5273 if not os.path.exists(pjoin(model_path,'build_restrict.py')):
5274 raise self.InvalidCmd('''Model not compatible with this option.''')
5275
5276
5277 self._curr_model = import_ufo.import_model(model_path, restrict=False)
5278
5279
5280 out_path = StringIO.StringIO()
5281 param_writer.ParamCardWriter(self._curr_model, out_path)
5282
5283 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
5284
5285
5286 all_categories = self.ask('','0',[], ask_class=AskforCustomize)
5287
5288 for block in param_card:
5289 value_dict = {}
5290 for param in param_card[block]:
5291 value = param.value
5292 if value == 0:
5293 param.value = 0.000001e-99
5294 elif value == 1:
5295 param.value = 9.999999e-1
5296 elif abs(value) in value_dict:
5297 param.value += value_dict[abs(value)] * 1e-4 * param.value
5298 value_dict[abs(value)] += 1
5299 else:
5300 value_dict[abs(value)] = 1
5301
5302 for category in all_categories:
5303 for options in category:
5304 if not options.status:
5305 continue
5306 param = param_card[options.lhablock].get(options.lhaid)
5307 param.value = options.value
5308
5309 logger.info('Loading the resulting model')
5310
5311 self._curr_model = import_ufo.RestrictModel(self._curr_model)
5312 model_name = self._curr_model.get('name')
5313 if model_name == 'mssm':
5314 keep_external=True
5315 else:
5316 keep_external=False
5317 self._curr_model.restrict_model(param_card,keep_external=keep_external)
5318
5319 if args:
5320 name = args[0].split('=',1)[1]
5321 path = pjoin(model_path,'restrict_%s.dat' % name)
5322 logger.info('Save restriction file as %s' % path)
5323 param_card.write(path)
5324 self._curr_model['name'] += '-%s' % name
5325
5326
5327
5328 - def do_save(self, line, check=True, to_keep={}, log=True):
5329 """Not in help: Save information to file"""
5330
5331 args = self.split_arg(line)
5332
5333 if check:
5334 self.check_save(args)
5335
5336 if args[0] == 'model':
5337 if self._curr_model:
5338
5339 if save_load_object.save_to_file(args[1], self._curr_model):
5340 logger.info('Saved model to file %s' % args[1])
5341 else:
5342 raise self.InvalidCmd('No model to save!')
5343 elif args[0] == 'processes':
5344 if self._curr_amps:
5345 if save_load_object.save_to_file(args[1], self._curr_amps):
5346 logger.info('Saved processes to file %s' % args[1])
5347 else:
5348 raise self.InvalidCmd('No processes to save!')
5349
5350 elif args[0] == 'options':
5351
5352 to_define = {}
5353 for key, default in self.options_configuration.items():
5354 if self.options_configuration[key] != self.options[key] != None:
5355 to_define[key] = self.options[key]
5356
5357 if not '--auto' in args:
5358 for key, default in self.options_madevent.items():
5359 if self.options_madevent[key] != self.options[key] != None:
5360 if '_path' in key and os.path.basename(self.options[key]) == 'None':
5361 continue
5362 to_define[key] = self.options[key]
5363 elif key == 'cluster_queue' and self.options[key] is None:
5364 to_define[key] = self.options[key]
5365
5366 if '--all' in args:
5367 for key, default in self.options_madgraph.items():
5368 if self.options_madgraph[key] != self.options[key] != None and \
5369 key != 'stdout_level':
5370 to_define[key] = self.options[key]
5371 elif not '--auto' in args:
5372 for key, default in self.options_madgraph.items():
5373 if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level':
5374 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
5375 % (key,self.options_madgraph[key]) )
5376 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
5377 if len(args) >1 and not args[1].startswith('--'):
5378 filepath = args[1]
5379 else:
5380 filepath = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
5381 basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt')
5382 basedir = MG5DIR
5383
5384 if to_keep:
5385 to_define = to_keep
5386 self.write_configuration(filepath, basefile, basedir, to_define)
5387
5388
5389 - def do_set(self, line, log=True):
5390 """Set an option, which will be default for coming generations/outputs
5391 """
5392
5393
5394 args = self.split_arg(line)
5395
5396
5397 self.check_set(args)
5398
5399 if args[0] == 'ignore_six_quark_processes':
5400 if args[1] == 'False':
5401 self.options[args[0]] = False
5402 return
5403 self.options[args[0]] = list(set([abs(p) for p in \
5404 self._multiparticles[args[1]]\
5405 if self._curr_model.get_particle(p).\
5406 is_fermion() and \
5407 self._curr_model.get_particle(abs(p)).\
5408 get('color') == 3]))
5409 if log:
5410 logger.info('Ignore processes with >= 6 quarks (%s)' % \
5411 ",".join([\
5412 self._curr_model.get_particle(q).get('name') \
5413 for q in self.options[args[0]]]))
5414
5415 elif args[0] == 'group_subprocesses':
5416 if args[1] not in ['Auto', 'NLO']:
5417 self.options[args[0]] = eval(args[1])
5418 else:
5419 self.options[args[0]] = args[1]
5420 if log:
5421 logger.info('Set group_subprocesses to %s' % \
5422 str(self.options[args[0]]))
5423 logger.info('Note that you need to regenerate all processes')
5424 self._curr_amps = diagram_generation.AmplitudeList()
5425 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5426
5427 elif args[0] == "stdout_level":
5428 if args[1].isdigit():
5429 level = int(args[1])
5430 else:
5431 level = eval('logging.' + args[1])
5432 logging.root.setLevel(level)
5433 logging.getLogger('madgraph').setLevel(level)
5434 logging.getLogger('madevent').setLevel(level)
5435 if log:
5436 logger.info('set output information to level: %s' % level)
5437
5438 elif args[0] == "complex_mass_scheme":
5439 old = self.options[args[0]]
5440 self.options[args[0]] = eval(args[1])
5441 aloha.complex_mass = eval(args[1])
5442 aloha_lib.KERNEL.clean()
5443 if not self._curr_model:
5444 pass
5445 elif self.options[args[0]]:
5446 if old:
5447 if log:
5448 logger.info('Complex mass already activated.')
5449 return
5450 if log:
5451 logger.info('Activate complex mass scheme.')
5452 self._curr_model.change_mass_to_complex_scheme()
5453 if hasattr(self._curr_model, 'set_parameters_and_couplings'):
5454 self._curr_model.set_parameters_and_couplings()
5455 else:
5456 if not old:
5457 if log:
5458 logger.info('Complex mass already desactivated.')
5459 return
5460 if log:
5461 logger.info('Desactivate complex mass scheme.')
5462 self.exec_cmd('import model %s' % self._curr_model.get('name'))
5463
5464 elif args[0] == "gauge":
5465
5466 if not self._curr_model:
5467 if args[1] == 'unitary':
5468 aloha.unitary_gauge = True
5469 else:
5470 aloha.unitary_gauge = False
5471 aloha_lib.KERNEL.clean()
5472 self.options[args[0]] = args[1]
5473 if log: logger.info('Passing to gauge %s.' % args[1])
5474 return
5475
5476
5477 able_to_mod = True
5478 if args[1] == 'unitary':
5479 if 0 in self._curr_model.get('gauge'):
5480 aloha.unitary_gauge = True
5481 else:
5482 able_to_mod = False
5483 if log: logger.warning('Note that unitary gauge is not allowed for your current model %s' \
5484 % self._curr_model.get('name'))
5485 else:
5486 if 1 in self._curr_model.get('gauge'):
5487 aloha.unitary_gauge = False
5488 else:
5489 able_to_mod = False
5490 if log: logger.warning('Note that Feynman gauge is not allowed for your current model %s' \
5491 % self._curr_model.get('name'))
5492 self.options[args[0]] = args[1]
5493
5494 if able_to_mod and log and args[0] == 'gauge' and \
5495 args[1] == 'unitary' and not self.options['gauge']=='unitary' and \
5496 isinstance(self._curr_model,loop_base_objects.LoopModel) and \
5497 not self._curr_model['perturbation_couplings'] in [[],['QCD']]:
5498 logger.warning('You will only be able to do tree level'+\
5499 ' and QCD corrections in the unitary gauge.')
5500
5501
5502 model_name = self._curr_model.get('modelpath+restriction')
5503 self._curr_model = None
5504 self._curr_amps = diagram_generation.AmplitudeList()
5505 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5506 self._curr_fortran_model = None
5507 self._curr_cpp_model = None
5508 self._curr_exporter = None
5509 self._done_export = False
5510 import_ufo._import_once = []
5511 logger.info('Passing to gauge %s.' % args[1])
5512
5513 if able_to_mod:
5514
5515
5516
5517 MadGraphCmd.do_import(self,'model %s' %model_name, force=True)
5518 elif log:
5519 logger.info('Note that you have to reload the model')
5520
5521 elif args[0] == 'fortran_compiler':
5522 if args[1] != 'None':
5523 if log:
5524 logger.info('set fortran compiler to %s' % args[1])
5525 self.options['fortran_compiler'] = args[1]
5526 else:
5527 self.options['fortran_compiler'] = None
5528 elif args[0] == 'loop_optimized_output':
5529 if log:
5530 logger.info('set loop optimized output to %s' % args[1])
5531 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5532 self.options[args[0]] = eval(args[1])
5533
5534 elif args[0] == 'fastjet':
5535 try:
5536 p = subprocess.Popen([args[1], '--version'], stdout=subprocess.PIPE,
5537 stderr=subprocess.PIPE)
5538 output, error = p.communicate()
5539 res = 0
5540 except Exception:
5541 res = 1
5542
5543 if res != 0 or error:
5544 logger.info('%s does not seem to correspond to a valid fastjet-config ' % args[1] + \
5545 'executable (v3+). We will use fjcore instead.\n Please set the \'fastjet\'' + \
5546 'variable to the full (absolute) /PATH/TO/fastjet-config (including fastjet-config).' +
5547 '\n MG5_aMC> set fastjet /PATH/TO/fastjet-config\n')
5548 self.options[args[0]] = None
5549 self.history.pop()
5550 elif int(output.split('.')[0]) < 3:
5551 logger.warning('%s is not ' % args[1] + \
5552 'v3 or greater. Please install FastJet v3+.')
5553 self.options[args[0]] = None
5554 self.history.pop()
5555 else:
5556 logger.info('set fastjet to %s' % args[1])
5557 self.options[args[0]] = args[1]
5558
5559 elif args[0] in ["pjfry","golem"]:
5560 program = misc.which_lib(os.path.join(args[1],"lib%s.a"%args[0]))
5561 if program!=None:
5562 res = 0
5563 logger.info('set %s to %s' % (args[0],args[1]))
5564 self.options[args[0]] = args[1]
5565 else:
5566 res = 1
5567
5568 if res != 0 :
5569 logger.warning('%s does not seem to correspond to a valid %s lib ' % (args[1],args[0]) + \
5570 '. Please enter the full PATH/TO/%s/lib .\n'%args[0] + \
5571 'You will NOT be able to run %s otherwise.\n'%args[0])
5572
5573 elif args[0] == 'lhapdf':
5574 try:
5575 res = misc.call([args[1], '--version'], stdout=subprocess.PIPE,
5576 stderr=subprocess.PIPE)
5577 logger.info('set lhapdf to %s' % args[1])
5578 self.options[args[0]] = args[1]
5579 except Exception:
5580 res = 1
5581 if res != 0:
5582 logger.info('%s does not seem to correspond to a valid lhapdf-config ' % args[1] + \
5583 'executable. \nPlease set the \'lhapdf\' variable to the (absolute) ' + \
5584 '/PATH/TO/lhapdf-config (including lhapdf-config).\n' + \
5585 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n' + \
5586 ' MG5_aMC> set lhapdf /PATH/TO/lhapdf-config\n')
5587
5588 elif args[0] in ['timeout', 'auto_update', 'cluster_nb_retry',
5589 'cluster_retry_wait']:
5590 self.options[args[0]] = int(args[1])
5591
5592 elif args[0] == 'cluster_status_update':
5593 if '(' in args[1]:
5594 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
5595 data = data.replace('(','').replace(')','').replace(',',' ').split()
5596 first, second = data[:2]
5597 else:
5598 first, second = args[1:3]
5599
5600 self.options[args[0]] = (int(first), int(second))
5601
5602 elif args[0] == 'OLP':
5603
5604
5605 self._curr_amps = diagram_generation.AmplitudeList()
5606 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5607 self._curr_exporter = None
5608 self.options[args[0]] = args[1]
5609
5610 elif args[0] =='output_dependencies':
5611 self.options[args[0]] = args[1]
5612
5613 elif args[0] in self.options:
5614 if args[1] in ['None','True','False']:
5615 self.options[args[0]] = eval(args[1])
5616 else:
5617 self.options[args[0]] = args[1]
5618
5619 - def post_set(self, stop, line):
5620 """Check if we need to save this in the option file"""
5621
5622 args = self.split_arg(line)
5623
5624 try:
5625 self.check_set(args, log=False)
5626 except Exception:
5627 return stop
5628
5629 if args[0] in self.options_configuration and '--no_save' not in args:
5630 self.exec_cmd('save options --auto', log=False)
5631 elif args[0] in self.options_madevent:
5632 if not '--no_save' in line:
5633 logger.info('This option will be the default in any output that you are going to create in this session.')
5634 logger.info('In order to keep this changes permanent please run \'save options\'')
5635 else:
5636
5637 if not self.history or self.history[-1].split() != line.split():
5638 self.history.append('set %s' % line)
5639 self.avoid_history_duplicate('set %s' % args[0], ['define', 'set'])
5640 return stop
5641
5651
5653 """Main commands: Initialize a new Template or reinitialize one"""
5654
5655 args = self.split_arg(line)
5656
5657 self.check_output(args)
5658
5659
5660 noclean = '-noclean' in args
5661 force = '-f' in args
5662 nojpeg = '-nojpeg' in args
5663 main_file_name = ""
5664 try:
5665 main_file_name = args[args.index('-name') + 1]
5666 except Exception:
5667 pass
5668
5669
5670
5671
5672 if self._export_format == 'aloha':
5673
5674 format = [d[9:] for d in args if d.startswith('--format=')]
5675 if not format:
5676 format = 'Fortran'
5677 else:
5678 format = format[-1]
5679
5680 output = [d for d in args if d.startswith('--output=')]
5681 if not output:
5682 output = import_ufo.find_ufo_path(self._curr_model['name'])
5683 output = pjoin(output, format)
5684 if not os.path.isdir(output):
5685 os.mkdir(output)
5686 else:
5687 output = output[-1]
5688 if not os.path.isdir(output):
5689 raise self.InvalidCmd('%s is not a valid directory' % output)
5690 logger.info('creating routines in directory %s ' % output)
5691
5692 names = [d for d in args if not d.startswith('-')]
5693 wanted_lorentz = aloha_fct.guess_routine_from_name(names)
5694
5695 aloha_model = create_aloha.AbstractALOHAModel(self._curr_model.get('name'))
5696 aloha_model.add_Lorentz_object(self._curr_model.get('lorentz'))
5697 if wanted_lorentz:
5698 aloha_model.compute_subset(wanted_lorentz)
5699 else:
5700 aloha_model.compute_all(save=False)
5701 aloha_model.write(output, format)
5702 return
5703
5704
5705
5706
5707
5708
5709
5710
5711 config = {}
5712 config['madevent'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
5713 config['matrix'] = {'check': False, 'exporter': 'v4', 'output':'dir'}
5714 config['standalone'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
5715 config['standalone_msF'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
5716 config['standalone_msP'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
5717 config['standalone_rw'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
5718 config['standalone_cpp'] = {'check': False, 'exporter': 'cpp', 'output': 'Template'}
5719 config['pythia8'] = {'check': False, 'exporter': 'cpp', 'output':'dir'}
5720 config['madweight'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
5721
5722 options = config[self._export_format]
5723
5724 if os.path.realpath(self._export_dir) == os.getcwd():
5725 if len(args) == 0:
5726 i=0
5727 while 1:
5728 if os.path.exists('Pythia8_proc_%i' %i):
5729 i+=1
5730 else:
5731 break
5732 os.mkdir('Pythia8_proc_%i' %i)
5733 self._export_dir = pjoin(self._export_dir, 'Pythia8_proc_%i' %i)
5734 logger.info('Create output in %s' % self._export_dir)
5735 elif not args[0] in ['.', '-f']:
5736 raise self.InvalidCmd, 'Wrong path directory to create in local directory use \'.\''
5737 elif not noclean and os.path.isdir(self._export_dir) and options['check']:
5738 if not force:
5739
5740 logger.info('INFO: directory %s already exists.' % self._export_dir)
5741 logger.info('If you continue this directory will be deleted and replaced.')
5742 answer = self.ask('Do you want to continue?', 'y', ['y','n'])
5743 else:
5744 answer = 'y'
5745 if answer != 'y':
5746 raise self.InvalidCmd('Stopped by user request')
5747 else:
5748 shutil.rmtree(self._export_dir)
5749
5750
5751 if options['exporter'] == 'v4':
5752 self._curr_exporter = export_v4.ExportV4Factory(self, noclean)
5753 if options['output'] == 'Template':
5754 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name'))
5755 if options['exporter'] == 'cpp' and options['output'] == 'Template':
5756 export_cpp.setup_cpp_standalone_dir(self._export_dir, self._curr_model)
5757
5758 if options['output'] == 'dir' and not os.path.isdir(self._export_dir):
5759 os.makedirs(self._export_dir)
5760
5761
5762 self._done_export = False
5763
5764
5765 self.export(nojpeg, main_file_name, args)
5766
5767
5768 self.finalize(nojpeg)
5769
5770
5771 self._done_export = (self._export_dir, self._export_format)
5772
5773
5774 self._export_dir = None
5775
5776
5777 - def export(self, nojpeg = False, main_file_name = "", args=[]):
5778 """Export a generated amplitude to file"""
5779
5780 def generate_matrix_elements(self):
5781 """Helper function to generate the matrix elements before
5782 exporting"""
5783
5784 if self._export_format in ['standalone_msP', 'standalone_msF', 'standalone_mw']:
5785 to_distinguish = []
5786 for part in self._curr_model.get('particles'):
5787 if part.get('name') in args and part.get('antiname') in args and\
5788 part.get('name') != part.get('antiname'):
5789 to_distinguish.append(abs(part.get('pdg_code')))
5790
5791
5792 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \
5793 a1.get_number_of_diagrams())
5794
5795
5796 group = True
5797 if self.options['group_subprocesses'] is False:
5798 group = False
5799 elif self.options['group_subprocesses'] == 'Auto' and \
5800 self._curr_amps[0].get_ninitial() == 1:
5801 group = False
5802
5803
5804
5805 cpu_time1 = time.time()
5806 ndiags = 0
5807 if not self._curr_matrix_elements.get_matrix_elements():
5808 if group:
5809 cpu_time1 = time.time()
5810 dc_amps = diagram_generation.DecayChainAmplitudeList(\
5811 [amp for amp in self._curr_amps if isinstance(amp, \
5812 diagram_generation.DecayChainAmplitude)])
5813 non_dc_amps = diagram_generation.AmplitudeList(\
5814 [amp for amp in self._curr_amps if not \
5815 isinstance(amp, \
5816 diagram_generation.DecayChainAmplitude)])
5817 subproc_groups = group_subprocs.SubProcessGroupList()
5818 if non_dc_amps:
5819 subproc_groups.extend(\
5820 group_subprocs.SubProcessGroup.group_amplitudes(\
5821 non_dc_amps, self._export_format))
5822
5823 if dc_amps:
5824 dc_subproc_group = \
5825 group_subprocs.DecayChainSubProcessGroup.\
5826 group_amplitudes(dc_amps, self._export_format)
5827 subproc_groups.extend(dc_subproc_group.\
5828 generate_helas_decay_chain_subproc_groups())
5829
5830 ndiags = sum([len(m.get('diagrams')) for m in \
5831 subproc_groups.get_matrix_elements()])
5832 self._curr_matrix_elements = subproc_groups
5833
5834 uid = 0
5835 for group in subproc_groups:
5836 uid += 1
5837 for me in group.get('matrix_elements'):
5838 me.get('processes')[0].set('uid', uid)
5839 else:
5840 mode = {}
5841 if self._export_format in [ 'standalone_msP' , 'standalone_msF', 'standalone_rw']:
5842 mode['mode'] = 'MadSpin'
5843 self._curr_matrix_elements = \
5844 helas_objects.HelasMultiProcess(self._curr_amps, matrix_element_opts=mode)
5845 ndiags = sum([len(me.get('diagrams')) for \
5846 me in self._curr_matrix_elements.\
5847 get_matrix_elements()])
5848
5849 uid = 0
5850 for me in self._curr_matrix_elements.get_matrix_elements()[:]:
5851 uid += 1
5852 me.get('processes')[0].set('uid', uid)
5853
5854 cpu_time2 = time.time()
5855
5856
5857 return ndiags, cpu_time2 - cpu_time1
5858
5859
5860
5861 ndiags, cpu_time = generate_matrix_elements(self)
5862
5863 calls = 0
5864
5865 path = self._export_dir
5866 if self._export_format in ['standalone_cpp', 'madevent', 'standalone',
5867 'standalone_msP', 'standalone_msF',
5868 'standalone_rw', 'madweight']:
5869 path = pjoin(path, 'SubProcesses')
5870
5871 cpu_time1 = time.time()
5872
5873
5874
5875
5876
5877 if self._export_format == 'madevent':
5878 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
5879 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
5880 calls = calls + \
5881 self._curr_exporter.generate_subprocess_directory_v4(\
5882 me_group, self._curr_fortran_model,
5883 group_number)
5884 else:
5885 for me_number, me in \
5886 enumerate(self._curr_matrix_elements.get_matrix_elements()):
5887 calls = calls + \
5888 self._curr_exporter.generate_subprocess_directory_v4(\
5889 me, self._curr_fortran_model, me_number)
5890
5891
5892
5893 card_path = pjoin(path, os.path.pardir, 'SubProcesses', \
5894 'procdef_mg5.dat')
5895 if self._generate_info:
5896 self._curr_exporter.write_procdef_mg5(card_path,
5897 self._curr_model['name'],
5898 self._generate_info)
5899 try:
5900 cmd.Cmd.onecmd(self, 'history .')
5901 except Exception:
5902 misc.sprint('command history fails.', 10)
5903 pass
5904
5905
5906 if self._export_format == 'pythia8':
5907
5908 process_names = []
5909 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
5910 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
5911 exporter = export_cpp.generate_process_files_pythia8(\
5912 me_group.get('matrix_elements'), self._curr_cpp_model,
5913 process_string = me_group.get('name'),
5914 process_number = group_number, path = path)
5915 process_names.append(exporter.process_name)
5916 else:
5917 exporter = export_cpp.generate_process_files_pythia8(\
5918 self._curr_matrix_elements, self._curr_cpp_model,
5919 process_string = self._generate_info, path = path)
5920 process_names.append(exporter.process_file_name)
5921
5922
5923 model_name, model_path = export_cpp.convert_model_to_pythia8(\
5924 self._curr_model, self._export_dir)
5925
5926
5927 filename, make_filename = \
5928 export_cpp.generate_example_file_pythia8(path,
5929 model_path,
5930 process_names,
5931 exporter,
5932 main_file_name)
5933
5934
5935 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
5936
5937
5938 if self._export_format == 'madweight':
5939
5940 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
5941
5942 self._curr_matrix_elements = self._curr_matrix_elements.split_lepton_grouping()
5943
5944 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
5945 calls = calls + \
5946 self._curr_exporter.generate_subprocess_directory_v4(\
5947 me_group, self._curr_fortran_model,
5948 group_number)
5949 else:
5950 for me_number, me in \
5951 enumerate(self._curr_matrix_elements.get_matrix_elements()):
5952 calls = calls + \
5953 self._curr_exporter.generate_subprocess_directory_v4(\
5954 me, self._curr_fortran_model, me_number)
5955
5956
5957 if self._export_format in ['standalone', 'standalone_msP', 'standalone_msF', 'standalone_rw']:
5958 for me in matrix_elements[:]:
5959 new_calls = self._curr_exporter.generate_subprocess_directory_v4(\
5960 me, self._curr_fortran_model)
5961 if not new_calls:
5962 matrix_elements.remove(me)
5963 calls = calls + new_calls
5964
5965
5966 if self._export_format == 'matrix':
5967 for me in matrix_elements:
5968 filename = pjoin(path, 'matrix_' + \
5969 me.get('processes')[0].shell_string() + ".f")
5970 if os.path.isfile(filename):
5971 logger.warning("Overwriting existing file %s" % filename)
5972 else:
5973 logger.info("Creating new file %s" % filename)
5974 calls = calls + self._curr_exporter.write_matrix_element_v4(\
5975 writers.FortranWriter(filename),\
5976 me, self._curr_fortran_model)
5977
5978
5979 if self._export_format == 'standalone_cpp':
5980 for me in matrix_elements:
5981 export_cpp.generate_subprocess_directory_standalone_cpp(\
5982 me, self._curr_cpp_model,
5983 path = path)
5984
5985 cpu_time2 = time.time() - cpu_time1
5986
5987 logger.info(("Generated helas calls for %d subprocesses " + \
5988 "(%d diagrams) in %0.3f s") % \
5989 (len(matrix_elements),
5990 ndiags, cpu_time))
5991
5992 if calls:
5993 if "cpu_time2" in locals():
5994 logger.info("Wrote files for %d helas calls in %0.3f s" % \
5995 (calls, cpu_time2))
5996 else:
5997 logger.info("Wrote files for %d helas calls" % \
5998 (calls))
5999
6000 if self._export_format == 'pythia8':
6001 logger.info("- All necessary files for Pythia 8 generated.")
6002 logger.info("- Run \"launch\" and select %s.cc," % filename)
6003 logger.info(" or go to %s/examples and run" % path)
6004 logger.info(" make -f %s" % make_filename)
6005 logger.info(" (with process_name replaced by process name).")
6006 logger.info(" You can then run ./%s to produce events for the process" % \
6007 filename)
6008
6009
6010
6011
6012 self._curr_amps = diagram_generation.AmplitudeList(\
6013 [me.get('base_amplitude') for me in \
6014 matrix_elements])
6015
6016 - def finalize(self, nojpeg, online = False):
6017 """Make the html output, write proc_card_mg5.dat and create
6018 madevent.tar.gz for a MadEvent directory"""
6019 if self._export_format in ['madevent', 'standalone', 'standalone_msP',
6020 'standalone_msF', 'standalone_rw', 'NLO', 'madweight']:
6021
6022
6023 if self._model_v4_path:
6024 logger.info('Copy %s model files to directory %s' % \
6025 (os.path.basename(self._model_v4_path), self._export_dir))
6026 self._curr_exporter.export_model_files(self._model_v4_path)
6027 self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS'))
6028 else:
6029 logger.info('Export UFO model to MG4 format')
6030
6031
6032
6033 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
6034 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
6035 self._curr_exporter.convert_model_to_mg4(self._curr_model,
6036 wanted_lorentz,
6037 wanted_couplings)
6038
6039 if self._export_format == 'standalone_cpp':
6040 logger.info('Export UFO model to C++ format')
6041
6042
6043
6044 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
6045 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
6046 export_cpp.convert_model_to_cpp(self._curr_model,
6047 pjoin(self._export_dir),
6048 wanted_lorentz,
6049 wanted_couplings)
6050 export_cpp.make_model_cpp(self._export_dir)
6051
6052
6053 elif self._export_format in ['NLO']:
6054
6055 devnull = os.open(os.devnull, os.O_RDWR)
6056 try:
6057 res = misc.call([self.options['lhapdf'], '--version'], \
6058 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
6059 except Exception:
6060 res = 1
6061 if res != 0:
6062 logger.info('The value for lhapdf in the current configuration does not ' + \
6063 'correspond to a valid executable.\nPlease set it correctly either in ' + \
6064 'input/mg5_configuration or with "set lhapdf /path/to/lhapdf-config" ' + \
6065 'and regenrate the process. \nTo avoid regeneration, manually edit the ' + \
6066 ('%s/Source/fj_lhapdf_opts file.\n' % self._export_dir ) + \
6067 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n')
6068
6069 compiler_dict = {'fortran': self.options['fortran_compiler'],
6070 'cpp': self.options['cpp_compiler']}
6071
6072 self._curr_exporter.finalize_fks_directory( \
6073 self._curr_matrix_elements,
6074 self.history,
6075 not nojpeg,
6076 online,
6077 compiler_dict,
6078 output_dependencies = self.options['output_dependencies'],
6079 MG5DIR = MG5DIR)
6080
6081
6082 filename = os.path.join(self._export_dir, 'Cards', 'amcatnlo_configuration.txt')
6083 opts_to_keep = ['lhapdf', 'fastjet', 'pythia8_path', 'hwpp_path', 'thepeg_path',
6084 'hepmc_path']
6085 to_keep = {}
6086 for opt in opts_to_keep:
6087 if self.options[opt]:
6088 to_keep[opt] = self.options[opt]
6089 self.do_save('options %s' % filename.replace(' ', '\ '), check=False, \
6090 to_keep = to_keep)
6091
6092 elif self._export_format in ['madevent', 'madweight']:
6093
6094 filename = os.path.join(self._export_dir, 'Cards', 'me5_configuration.txt')
6095 self.do_save('options %s' % filename.replace(' ', '\ '), check=False,
6096 to_keep={'mg5_path':MG5DIR})
6097
6098 if self._export_format in ['madevent', 'standalone', 'standalone_msP', 'standalone_msF',
6099 'standalone_rw', 'madweight']:
6100
6101 self._curr_exporter.finalize_v4_directory( \
6102 self._curr_matrix_elements,
6103 self.history,
6104 not nojpeg,
6105 online,
6106 self.options['fortran_compiler'])
6107
6108 if self._export_format in ['madevent', 'standalone', 'standalone_cpp','madweight']:
6109 logger.info('Output to directory ' + self._export_dir + ' done.')
6110
6111 if self._export_format in ['madevent', 'NLO']:
6112 logger.info('Type \"launch\" to generate events from this process, or see')
6113 logger.info(self._export_dir + '/README')
6114 logger.info('Run \"open index.html\" to see more information about this process.')
6115
6117 """ propose some usefull possible action """
6118
6119 super(MadGraphCmd,self).do_help(line)
6120
6121 if line:
6122 return
6123
6124 if len(self.history) == 0:
6125 last_action_2 = 'mg5_start'
6126 last_action = 'mg5_start'
6127 else:
6128 args = self.history[-1].split()
6129 last_action = args[0]
6130 if len(args)>1:
6131 last_action_2 = '%s %s' % (last_action, args[1])
6132 else:
6133 last_action_2 = 'none'
6134
6135
6136
6137
6139 """Documented commands:Generate amplitudes for decay width calculation, with fixed
6140 number of final particles (called level)
6141 syntax; compute_widths particle [other particles] [--options=]
6142
6143 - particle/other particles can also be multiparticle name (can also be
6144 pid of the particle)
6145
6146 --body_decay=X [default=4.0025] allow to choose the precision.
6147 if X is an integer: compute all X body decay
6148 if X is a float <1: compute up to the time that total error < X
6149 if X is a float >1: stops at the first condition.
6150
6151 --path=X. Use a given file for the param_card. (default UFO built-in)
6152
6153 special argument:
6154 - skip_2body: allow to not consider those decay (use FR)
6155 - model: use the model pass in argument.
6156
6157 """
6158
6159 warning_text = """Be carefull automatic computation of the width is
6160 ONLY valid in Narrow-Width Approximation and at Tree-Level."""
6161 logger.warning(warning_text)
6162 self.change_principal_cmd('MadGraph')
6163 if not model:
6164 modelname = self._curr_model['name']
6165 with misc.MuteLogger(['madgraph'], ['INFO']):
6166 model = import_ufo.import_model(modelname, decay=True)
6167 else:
6168 self._curr_model = model
6169 self._curr_fortran_model = \
6170 helas_call_writers.FortranUFOHelasCallWriter(\
6171 self._curr_model)
6172 if not isinstance(model, model_reader.ModelReader):
6173 model = model_reader.ModelReader(model)
6174
6175
6176
6177 particles, opts = self.check_compute_widths(self.split_arg(line))
6178
6179 if opts['path']:
6180 correct = True
6181 param_card = check_param_card.ParamCard(opts['path'])
6182 for param in param_card['decay']:
6183 if param.value == "auto":
6184 param.value = 1
6185 param.format = 'float'
6186 correct = False
6187 if not correct:
6188 if opts['output']:
6189 param_card.write(opts['output'])
6190 opts['path'] = opts['output']
6191 else:
6192 param_card.write(opts['path'])
6193
6194 data = model.set_parameters_and_couplings(opts['path'])
6195
6196
6197 if do2body:
6198 skip_2body = True
6199 decay_info = {}
6200 for pid in particles:
6201 particle = model.get_particle(pid)
6202 if not hasattr(particle, 'partial_widths'):
6203 skip_2body = False
6204 break
6205 elif not decay_info:
6206 logger_mg.info('Get two body decay from FeynRules formula')
6207 decay_info[pid] = []
6208 mass = abs(eval(str(particle.get('mass')), data).real)
6209 data = model.set_parameters_and_couplings(opts['path'], scale= mass)
6210 total = 0
6211
6212 for mode, expr in particle.partial_widths.items():
6213 tmp_mass = mass
6214 for p in mode:
6215 try:
6216 tmp_mass -= abs(eval(str(p.mass), data))
6217 except Exception:
6218 tmp_mass -= abs(eval("mdl_"+str(p.mass), data))
6219 if tmp_mass <=0:
6220 continue
6221
6222 decay_to = [p.get('pdg_code') for p in mode]
6223 value = eval(expr,{'cmath':cmath},data).real
6224 if -1e-10 < value < 0:
6225 value = 0
6226 if -1e-5 < value < 0:
6227 logger.warning('Partial width for %s > %s negative: %s automatically set to zero' %
6228 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value))
6229 value = 0
6230 elif value < 0:
6231 raise Exception, 'Partial width for %s > %s negative: %s' % \
6232 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value)
6233 decay_info[particle.get('pdg_code')].append([decay_to, value])
6234 total += value
6235 else:
6236 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
6237 opts['path'], opts['output'])
6238 if float(opts['body_decay']) == 2:
6239 return
6240 else:
6241 skip_2body = True
6242
6243
6244
6245
6246 self.do_decay_diagram('%s %s' % (' '.join([`id` for id in particles]),
6247 ' '.join('--%s=%s' % (key,value)
6248 for key,value in opts.items()
6249 if key not in ['precision_channel'])
6250 ), skip_2body=skip_2body)
6251
6252 if self._curr_amps:
6253 logger.info('Pass to numerical integration for computing the widths:')
6254 else:
6255 logger.info('No need for N body-decay (N>2). Results are in %s' % opts['output'])
6256 return
6257
6258
6259 with misc.TMP_directory(dir=os.getcwd()) as path:
6260 decay_dir = pjoin(path,'temp_decay')
6261 logger_mg.info('More info in temporary files:\n %s/index.html' % (decay_dir))
6262 with misc.MuteLogger(['madgraph','ALOHA','cmdprint','madevent'], [40,40,40,40]):
6263 self.exec_cmd('output %s -f' % decay_dir)
6264
6265 files.cp(opts['output'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
6266 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
6267 check_param_card.convert_to_slha1(pjoin(decay_dir, 'Cards', 'param_card.dat'))
6268
6269 me_cmd = madevent_interface.MadEventCmd(decay_dir)
6270
6271 me_cmd.model_name = self._curr_model['name']
6272 me_cmd.options['automatic_html_opening'] = False
6273
6274 me_opts=[('accuracy', opts['precision_channel']),
6275 ('points', 1000),
6276 ('iterations',9)]
6277 me_cmd.exec_cmd('survey decay -f %s' % (
6278 " ".join(['--%s=%s' % val for val in me_opts])),
6279 postcmd=False)
6280 me_cmd.exec_cmd('combine_events', postcmd=False)
6281
6282 me_cmd.collect_decay_widths()
6283 me_cmd.do_quit('')
6284
6285 del me_cmd
6286
6287 param = check_param_card.ParamCard(pjoin(decay_dir, 'Events', 'decay','param_card.dat'))
6288
6289 for pid in particles:
6290 width = param['decay'].get((pid,)).value
6291 if not pid in param['decay'].decay_table:
6292 continue
6293 if pid not in decay_info:
6294 decay_info[pid] = []
6295 for BR in param['decay'].decay_table[pid]:
6296 if len(BR.lhacode) == 3 and skip_2body:
6297 continue
6298 decay_info[pid].append([BR.lhacode[1:], BR.value * width])
6299
6300 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
6301 opts['path'], opts['output'])
6302
6303 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
6304 check_param_card.convert_to_slha1(opts['output'])
6305 return
6306
6307
6308
6309
6311 """Not in help: Generate amplitudes for decay width calculation, with fixed
6312 number of final particles (called level)
6313 syntax; decay_diagram part_name level param_path
6314 args; part_name level param_path
6315 part_name = name of the particle you want to calculate width
6316 level = a.) when level is int,
6317 it means the max number of decay products
6318 b.) when level is float,
6319 it means the required precision for width.
6320 param_path = path for param_card
6321 (this is necessary to determine whether a channel is onshell or not)
6322 e.g. calculate width for higgs up to 2-body decays.
6323 calculate_width h 2 [path]
6324 N.B. param_card must be given so that the program knows which channel
6325 is on shell and which is not.
6326
6327 special argument:
6328 - skip_2body: allow to not consider those decay (use FR)
6329 - model: use the model pass in argument.
6330 """
6331
6332 if model:
6333 self._curr_model = model
6334
6335 args = self.split_arg(line)
6336
6337 particles, args = self.check_decay_diagram(args)
6338
6339 pids = particles
6340 level = float(args['body_decay'])
6341 param_card_path = args['path']
6342 min_br = float(args['min_br'])
6343
6344
6345 self._curr_amps = diagram_generation.AmplitudeList()
6346
6347 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6348
6349 self._done_export = False
6350
6351 self._export_format = None
6352
6353
6354
6355 if not model:
6356 self._curr_decaymodel = decay_objects.DecayModel(self._curr_model,
6357 True)
6358 self._curr_decaymodel.read_param_card(param_card_path)
6359 else:
6360 self._curr_decaymodel = model
6361 model = self._curr_decaymodel
6362
6363 if isinstance(pids, int):
6364 pids = [pids]
6365
6366 first =True
6367 for part_nb,pid in enumerate(pids):
6368 part = self._curr_decaymodel.get_particle(pid)
6369 if part.get('width').lower() == 'zero':
6370 continue
6371 logger_mg.info('get decay diagram for %s' % part['name'])
6372
6373 if level // 1 == level and level >1:
6374 level = int(level)
6375 self._curr_decaymodel.find_channels(part, level, min_br)
6376 if not skip_2body:
6377 amp = part.get_amplitudes(2)
6378 if amp:
6379 self._curr_amps.extend(amp)
6380
6381 for l in range(3, level+1):
6382 amp = part.get_amplitudes(l)
6383 if amp:
6384 self._curr_amps.extend(amp)
6385 else:
6386 max_level = level // 1
6387 if max_level < 2:
6388 max_level = 999
6389 precision = level % 1
6390 if first:
6391 model.find_all_channels(2,generate_abstract=False)
6392 first = False
6393 if not skip_2body:
6394 amp = part.get_amplitudes(2)
6395 if amp:
6396 self._curr_amps.extend(amp)
6397 clevel = 2
6398 while part.get('apx_decaywidth_err').real > precision:
6399 clevel += 1
6400 if clevel > max_level:
6401 logger_mg.info(' stop to %s body-decay. approximate error: %s' %
6402 (max_level, part.get('apx_decaywidth_err')) )
6403 break
6404 if clevel > 3:
6405 logger_mg.info(' current estimated error: %s go to %s-body decay:' %\
6406 (part.get('apx_decaywidth_err'), clevel))
6407 part.find_channels_nextlevel(model, min_br)
6408
6409 amp = part.get_amplitudes(clevel)
6410 if amp:
6411 self._curr_amps.extend(amp)
6412 part.update_decay_attributes(False, True, True, model)
6413
6414
6415
6416 if len(self._curr_amps) > 0:
6417 process = self._curr_amps[0]['process'].nice_string()
6418
6419 self._generate_info = process[9:]
6420
6421 else:
6422 print "No decay is found"
6423
6425 """Temporary parser"""
6426
6427
6428
6429
6430
6431 _draw_usage = "draw FILEPATH [options]\n" + \
6432 "-- draw the diagrams in eps format\n" + \
6433 " Files will be FILEPATH/diagrams_\"process_string\".eps \n" + \
6434 " Example: draw plot_dir . \n"
6435 _draw_parser = misc.OptionParser(usage=_draw_usage)
6436 _draw_parser.add_option("", "--horizontal", default=False,
6437 action='store_true', help="force S-channel to be horizontal")
6438 _draw_parser.add_option("", "--external", default=0, type='float',
6439 help="authorizes external particles to end at top or " + \
6440 "bottom of diagram. If bigger than zero this tune the " + \
6441 "length of those line.")
6442 _draw_parser.add_option("", "--max_size", default=1.5, type='float',
6443 help="this forbids external line bigger than max_size")
6444 _draw_parser.add_option("", "--non_propagating", default=True, \
6445 dest="contract_non_propagating", action='store_false',
6446 help="avoid contractions of non propagating lines")
6447 _draw_parser.add_option("", "--add_gap", default=0, type='float', \
6448 help="set the x-distance between external particles")
6449
6450
6451 _launch_usage = "launch [DIRPATH] [options]\n" + \
6452 "-- execute the madevent/standalone/standalone_cpp/pythia8/NLO output present in DIRPATH\n" + \
6453 " By default DIRPATH is the latest created directory \n" + \
6454 " (for pythia8, it should be the Pythia 8 main directory) \n" + \
6455 " Example: launch PROC_sm_1 --name=run2 \n" + \
6456 " Example: launch ../pythia8 \n"
6457 _launch_parser = misc.OptionParser(usage=_launch_usage)
6458 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
6459 help="Use the card present in the directory in order to launch the different program")
6460 _launch_parser.add_option("-n", "--name", default='', type='str',
6461 help="Provide a name to the run (for madevent run)")
6462 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
6463 help="submit the job on the cluster")
6464 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
6465 help="submit the job on multicore core")
6466
6467 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
6468 help="Use Interactive Console [if available]")
6469 _launch_parser.add_option("-s", "--laststep", default='',
6470 help="last program run in MadEvent run. [auto|parton|pythia|pgs|delphes]")
6476 """A class for asking a question where in addition you can have the
6477 set command define and modifying the param_card/run_card correctly"""
6478
6479 - def __init__(self, question, allow_arg=[], default=None,
6480 mother_interface=None, *arg, **opt):
6481
6482 model_path = mother_interface._curr_model.get('modelpath')
6483
6484 ufo_model = ufomodels.load_model(model_path)
6485 self.all_categories = ufo_model.build_restrict.all_categories
6486
6487 question = self.get_question()
6488
6489
6490 allow_arg = ['0']
6491 self.name2options = {}
6492 for category in self.all_categories:
6493 for options in category:
6494 if not options.first:
6495 continue
6496 self.name2options[str(len(allow_arg))] = options
6497 self.name2options[options.name.replace(' ','')] = options
6498 allow_arg.append(len(allow_arg))
6499 allow_arg.append('done')
6500
6501 cmd.SmartQuestion.__init__(self, question, allow_arg, default, mother_interface)
6502
6503
6504
6506 """Default action if line is not recognized"""
6507
6508 line = line.strip()
6509 args = line.split()
6510 if line == '' and self.default_value is not None:
6511 self.value = self.default_value
6512
6513 elif hasattr(self, 'do_%s' % args[0]):
6514 self.do_set(' '.join(args[1:]))
6515 elif line.strip() != '0' and line.strip() != 'done' and \
6516 str(line) != 'EOF' and line.strip() in self.allow_arg:
6517 option = self.name2options[line.strip()]
6518 option.status = not option.status
6519 self.value = 'repeat'
6520 else:
6521 self.value = line
6522
6523 return self.all_categories
6524
6525 - def reask(self, reprint_opt=True):
6530
6532 """ """
6533 self.value = 'repeat'
6534
6535 args = line.split()
6536 if args[0] not in self.name2options:
6537 logger.warning('Invalid set command. %s not recognize options. Valid options are: \n %s' %
6538 (args[0], ', '.join(self.name2options.keys()) ))
6539 return
6540 elif len(args) != 2:
6541 logger.warning('Invalid set command. Not correct number of argument')
6542 return
6543
6544
6545 if args[1] in ['True','1','.true.','T',1,True,'true','TRUE']:
6546 self.name2options[args[0]].status = True
6547 elif args[1] in ['False','0','.false.','F',0,False,'false','FALSE']:
6548 self.name2options[args[0]].status = False
6549 else:
6550 logger.warning('%s is not True/False. Didn\'t do anything.' % args[1])
6551
6552
6553
6555 """define the current question."""
6556 question = ''
6557 i=0
6558 for category in self.all_categories:
6559 question += category.name + ':\n'
6560 for options in category:
6561 if not options.first:
6562 continue
6563 i+=1
6564 question += ' %s: %s [%s]\n' % (i, options.name,
6565 options.display(options.status))
6566 question += 'Enter a number to change it\'s status or press enter to validate.\n'
6567 question += 'For scripting this function, please type: \'help\''
6568 return question
6569
6570
6572 """ Complete the set command"""
6573 signal.alarm(0)
6574 args = self.split_arg(line[0:begidx])
6575
6576 if len(args) == 1:
6577 possibilities = [x for x in self.name2options if not x.isdigit()]
6578 return self.list_completion(text, possibilities, line)
6579 else:
6580 return self.list_completion(text,['True', 'False'], line)
6581
6582
6584 '''help message'''
6585
6586 print 'This allows you to optimize your model to your needs.'
6587 print 'Enter the number associate to the possible restriction/add-on'
6588 print ' to change the status of this restriction/add-on.'
6589 print ''
6590 print 'In order to allow scripting of this function you can use the '
6591 print 'function \'set\'. This function takes two argument:'
6592 print 'set NAME VALUE'
6593 print ' NAME is the description of the option where you remove all spaces'
6594 print ' VALUE is either True or False'
6595 print ' Example: For the question'
6596 print ''' sm customization:
6597 1: diagonal ckm [True]
6598 2: c mass = 0 [True]
6599 3: b mass = 0 [False]
6600 4: tau mass = 0 [False]
6601 5: muon mass = 0 [True]
6602 6: electron mass = 0 [True]
6603 Enter a number to change it's status or press enter to validate.'''
6604 print ''' you can answer by'''
6605 print ' set diagonalckm False'
6606 print ' set taumass=0 True'
6607
6611
6612
6613
6614
6615
6616
6617
6618 if __name__ == '__main__':
6619
6620 run_option = sys.argv
6621 if len(run_option) > 1:
6622
6623 input_file = open(run_option[1], 'rU')
6624 cmd_line = MadGraphCmd(stdin=input_file)
6625 cmd_line.use_rawinput = False
6626 cmd_line.cmdloop()
6627 else:
6628
6629 MadGraphCmd().cmdloop()
6630