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