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 import random
41
42
43
44 pjoin = os.path.join
45
46 try:
47 import readline
48 GNU_SPLITTING = ('GNU' in readline.__doc__)
49 except:
50 GNU_SPLITTING = True
51
52 import aloha
53 import madgraph
54 from madgraph import MG4DIR, MG5DIR, MadGraph5Error
55
56
57 import madgraph.core.base_objects as base_objects
58 import madgraph.core.diagram_generation as diagram_generation
59 import madgraph.loop.loop_diagram_generation as loop_diagram_generation
60 import madgraph.loop.loop_base_objects as loop_base_objects
61 import madgraph.core.drawing as draw_lib
62 import madgraph.core.helas_objects as helas_objects
63
64
65
66 import madgraph.iolibs.drawing_eps as draw
67 import madgraph.iolibs.export_cpp as export_cpp
68 import madgraph.iolibs.export_v4 as export_v4
69 import madgraph.iolibs.helas_call_writers as helas_call_writers
70 import madgraph.iolibs.file_writers as writers
71 import madgraph.iolibs.files as files
72 import madgraph.iolibs.group_subprocs as group_subprocs
73 import madgraph.iolibs.import_v4 as import_v4
74 import madgraph.iolibs.save_load_object as save_load_object
75
76 import madgraph.interface.extended_cmd as cmd
77 import madgraph.interface.tutorial_text as tutorial_text
78 import madgraph.interface.tutorial_text_nlo as tutorial_text_nlo
79 import madgraph.interface.tutorial_text_madloop as tutorial_text_madloop
80 import madgraph.interface.launch_ext_program as launch_ext
81 import madgraph.interface.madevent_interface as madevent_interface
82 import madgraph.interface.amcatnlo_run_interface as amcatnlo_run
83
84 import madgraph.loop.loop_exporters as loop_exporters
85 import madgraph.loop.loop_helas_objects as loop_helas_objects
86
87 import madgraph.various.process_checks as process_checks
88 import madgraph.various.banner as banner_module
89 import madgraph.various.misc as misc
90 import madgraph.various.cluster as cluster
91
92 import models as ufomodels
93 import models.import_ufo as import_ufo
94 import models.write_param_card as param_writer
95 import models.check_param_card as check_param_card
96 import models.model_reader as model_reader
97
98 import aloha.aloha_fct as aloha_fct
99 import aloha.create_aloha as create_aloha
100 import aloha.aloha_lib as aloha_lib
101
102 import mg5decay.decay_objects as decay_objects
103
104
105
106 logger = logging.getLogger('cmdprint')
107 logger_check = logging.getLogger('check')
108 logger_mg = logging.getLogger('madgraph.interface')
109 logger_stderr = logging.getLogger('fatalerror')
110 logger_tuto = logging.getLogger('tutorial')
111
112 logger_tuto_nlo = logging.getLogger('tutorial_aMCatNLO')
113
114
115 logger_tuto_madloop = logging.getLogger('tutorial_MadLoop')
121 """Particularisation of the cmd command for MG5"""
122
123
124 next_possibility = {
125 'start': ['import model ModelName', 'import command PATH',
126 'import proc_v4 PATH', 'tutorial'],
127 'import model' : ['generate PROCESS','define MULTIPART PART1 PART2 ...',
128 'display particles', 'display interactions'],
129 'define': ['define MULTIPART PART1 PART2 ...', 'generate PROCESS',
130 'display multiparticles'],
131 'generate': ['add process PROCESS','output [OUTPUT_TYPE] [PATH]','display diagrams'],
132 'add process':['output [OUTPUT_TYPE] [PATH]', 'display processes'],
133 'output':['launch','open index.html','history PATH', 'exit'],
134 'display': ['generate PROCESS', 'add process PROCESS', 'output [OUTPUT_TYPE] [PATH]'],
135 'import proc_v4' : ['launch','exit'],
136 'launch': ['open index.html','exit'],
137 'tutorial': ['generate PROCESS', 'import model MODEL', 'help TOPIC']
138 }
139
140 debug_output = 'MG5_debug'
141 error_debug = 'Please report this bug on https://bugs.launchpad.net/mg5amcnlo\n'
142 error_debug += 'More information is found in \'%(debug)s\'.\n'
143 error_debug += 'Please attach this file to your report.'
144
145 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/mg5amcnlo\n'
146
147 keyboard_stop_msg = """stopping all operation
148 in order to quit mg5 please enter exit"""
149
150
151 InvalidCmd = madgraph.InvalidCmd
152 ConfigurationError = MadGraph5Error
153
154 intro_banner = "************************************************************\n" + \
155 "* *\n" + \
156 "* W E L C O M E to *\n" + \
157 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
158 "* *\n" + \
159 "* *\n" + \
160 "* * * *\n" + \
161 "* * * * * *\n" + \
162 "* * * * * 5 * * * * *\n" + \
163 "* * * * * *\n" + \
164 "* * * *\n" + \
165 "* *\n" + \
166 "%s" + \
167 "* *\n" + \
168 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
169 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
170 "* and *\n" + \
171 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \
172 "* *\n" + \
173 "* Type 'help' for in-line help. *\n" + \
174 "* Type 'tutorial' to learn how MG5 works *\n" + \
175 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \
176 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \
177 "* *\n" + \
178 "************************************************************"
179
180
182 """Init history and line continuation"""
183
184
185
186 info = misc.get_pkg_info()
187 info_line = ""
188
189 if info.has_key('version') and info.has_key('date'):
190 len_version = len(info['version'])
191 len_date = len(info['date'])
192 if len_version + len_date < 30:
193 info_line = "#* VERSION %s %s %s *\n" % \
194 (info['version'],
195 (30 - len_version - len_date) * ' ',
196 info['date'])
197
198 if os.path.exists(pjoin(MG5DIR, '.bzr')):
199 proc = subprocess.Popen(['bzr', 'nick'], stdout=subprocess.PIPE,cwd=MG5DIR)
200 bzrname,_ = proc.communicate()
201 proc = subprocess.Popen(['bzr', 'revno'], stdout=subprocess.PIPE,cwd=MG5DIR)
202 bzrversion,_ = proc.communicate()
203 bzrname, bzrversion = bzrname.strip(), bzrversion.strip()
204 len_name = len(bzrname)
205 len_version = len(bzrversion)
206 info_line += "#* BZR %s %s %s *\n" % \
207 (bzrname,
208 (34 - len_name - len_version) * ' ',
209 bzrversion)
210
211
212
213 self.history_header = banner_module.ProcCard.history_header % {'info_line': info_line}
214 banner_module.ProcCard.history_header = self.history_header
215
216 if info_line:
217 info_line = info_line.replace("#*","*")
218
219
220
221 logger.info(self.intro_banner % info_line)
222
223 cmd.Cmd.__init__(self, *arg, **opt)
224
225 self.history = banner_module.ProcCard()
226
227
229 """Default action if line is not recognized"""
230
231
232 log=True
233 if line.startswith('p') or line.startswith('e'):
234 logger.warning("Command %s not recognized. Did you mean \'generate %s\'?. Please try again" %
235 (line.split()[0], line))
236 log=False
237 return super(CmdExtended,self).default(line, log=log)
238
239 - def postcmd(self,stop, line):
240 """ finishing a command
241 This looks if the command add a special post part.
242 This looks if we have to write an additional text for the tutorial."""
243
244 stop = super(CmdExtended, self).postcmd(stop, line)
245
246 if stop == False:
247 return False
248
249 args=line.split()
250
251 if len(args)==0:
252 return stop
253
254
255
256
257 if len(args)==1:
258 command=args[0]
259 else:
260 command = args[0]+'_'+args[1].split('.')[0]
261
262 try:
263 logger_tuto.info(getattr(tutorial_text, command).replace('\n','\n\t'))
264 except Exception:
265 try:
266 logger_tuto.info(getattr(tutorial_text, args[0]).replace('\n','\n\t'))
267 except Exception:
268 pass
269
270 try:
271 logger_tuto_nlo.info(getattr(tutorial_text_nlo, command).replace('\n','\n\t'))
272 except Exception:
273 try:
274 logger_tuto_nlo.info(getattr(tutorial_text_nlo, args[0]).replace('\n','\n\t'))
275 except Exception:
276 pass
277
278 try:
279 logger_tuto_madloop.info(getattr(tutorial_text_madloop, command).replace('\n','\n\t'))
280 except Exception:
281 try:
282 logger_tuto_madloop.info(getattr(tutorial_text_madloop, args[0]).replace('\n','\n\t'))
283 except Exception:
284 pass
285
286 return stop
287
288
290 """return the history header"""
291 return self.history_header % misc.get_time_info()
292
297 """ The Series of help routine for the MadGraphCmd"""
298
300 logger.info("syntax: save %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
301 logger.info("-- save information as file FILENAME",'$MG:color:BLACK')
302 logger.info(" FILENAME is optional for saving 'options'.")
303 logger.info(' By default it uses ./input/mg5_configuration.txt')
304 logger.info(' If you put "global" for FILENAME it will use ~/.mg5/mg5_configuration.txt')
305 logger.info(' If this files exists, it is uses by all MG5 on the system but continues')
306 logger.info(' to read the local options files.')
307
309 logger.info("syntax: load %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
310 logger.info("-- load information from file FILENAME",'$MG:color:BLACK')
311
313 logger.info("syntax: import " + "|".join(self._import_formats) + \
314 " FILENAME",'$MG:color:BLUE')
315 logger.info("-- imports file(s) in various formats",'$MG:color:GREEN')
316 logger.info("")
317 logger.info(" import model MODEL[-RESTRICTION] [OPTIONS]:",'$MG:color:BLACK')
318 logger.info(" Import a UFO model.")
319 logger.info(" MODEL should be a valid UFO model name")
320 logger.info(" Model restrictions are specified by MODEL-RESTRICTION")
321 logger.info(" with the file restrict_RESTRICTION.dat in the model dir.")
322 logger.info(" By default, restrict_default.dat is used.")
323 logger.info(" Specify model_name-full to get unrestricted model.")
324 logger.info(" '--modelname' keeps the original particle names for the model")
325 logger.info("")
326 logger.info(" import model_v4 MODEL [--modelname] :",'$MG:color:BLACK')
327 logger.info(" Import an MG4 model.")
328 logger.info(" Model should be the name of the model")
329 logger.info(" or the path to theMG4 model directory")
330 logger.info(" '--modelname' keeps the original particle names for the model")
331 logger.info("")
332 logger.info(" import proc_v4 [PATH] :",'$MG:color:BLACK')
333 logger.info(" Execute MG5 based on a proc_card.dat in MG4 format.")
334 logger.info(" Path to the proc_card is optional if you are in a")
335 logger.info(" madevent directory")
336 logger.info("")
337 logger.info(" import command PATH :",'$MG:color:BLACK')
338 logger.info(" Execute the list of command in the file at PATH")
339 logger.info("")
340 logger.info(" import banner PATH [--no_launch]:",'$MG:color:BLACK')
341 logger.info(" Rerun the exact same run define in the valid banner.")
342
344 logger.info("syntax: install " + "|".join(self._install_opts),'$MG:color:BLUE')
345 logger.info("-- Download the last version of the program and install it")
346 logger.info(" locally in the current MadGraph5_aMC@NLO version. In order to have")
347 logger.info(" a successful installation, you will need to have an up-to-date")
348 logger.info(" F77 and/or C and Root compiler.")
349 logger.info(" ")
350 logger.info(" When installing any of the following programs:")
351 logger.info(" %s"%(', '.join(self._advanced_install_opts)))
352 logger.info(" The following options are available:")
353 logger.info(" --force Overwrite without asking any existing installation.")
354 logger.info(" --keep_source Keep a local copy of the sources of the tools MG5_aMC installed from.")
355 logger.info(" ")
356 logger.info(" \"install update\"",'$MG:color:BLACK')
357 logger.info(" check if your MG5 installation is the latest one.")
358 logger.info(" If not it load the difference between your current version and the latest one,")
359 logger.info(" and apply it to the code. Two options are available for this command:")
360 logger.info(" -f: didn't ask for confirmation if it founds an update.")
361 logger.info(" --timeout=: Change the maximum time allowed to reach the server.")
362
364 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLUE')
365 logger.info("-- display a the status of various internal state variables")
366 logger.info(" for particles/interactions you can specify the name or id of the")
367 logger.info(" particles/interactions to receive more details information.")
368 logger.info(" Example: display particles e+.",'$MG:color:GREEN')
369 logger.info(" > For \"checks\", can specify only to see failed checks.")
370 logger.info(" > For \"diagrams\", you can specify where the file will be written.")
371 logger.info(" Example: display diagrams ./",'$MG:color:GREEN')
372
373
375 """help for launch command"""
376
377
378
379 logger.info("syntax: launch <dir_path> <options>",'$MG:color:BLUE')
380 logger.info("-- execute the aMC@NLO/madevent/standalone/pythia8 output present in dir_path",'$MG:color:BLACK')
381 logger.info("By default, dir_path points to the last created directory.")
382 logger.info("(for pythia8, it should be the Pythia 8 main directory)")
383 logger.info("")
384 logger.info("Launch on madevent/pythia8/standalone outputs:",'$MG:color:BLACK')
385 logger.info(" o Example: launch PROC_sm_1 --name=run2",'$MG:color:GREEN')
386 logger.info(" o Example: launch ../pythia8",'$MG:color:GREEN')
387 logger.info(" > Options:")
388 logger.info(" -h, --help show this help message and exit")
389 logger.info(" -f, --force Use the card present in the directory in order")
390 logger.info(" to launch the different program")
391 logger.info(" -n NAME, --name=NAME Provide a name to the run (for madevent run)")
392 logger.info(" -c, --cluster submit the job on the cluster")
393 logger.info(" -m, --multicore submit the job on multicore core")
394 logger.info(" -i, --interactive Use Interactive Console [if available]")
395 logger.info(" -s LASTSTEP, --laststep=LASTSTEP")
396 logger.info(" last program run in MadEvent run.")
397 logger.info(" [auto|parton|pythia|pgs|delphes]")
398 logger.info("")
399 logger.info("Launch on MadLoop standalone output:",'$MG:color:BLACK')
400 logger.info(" o Example: launch PROC_loop_sm_1 -f",'$MG:color:GREEN')
401 logger.info(" > Simple check of a single Phase-space points.")
402 logger.info(" > You will be asked whether you want to edit the MadLoop ")
403 logger.info(" and model param card as well as the PS point, unless ")
404 logger.info(" the -f option is specified. All other options are ")
405 logger.info(" irrelevant for this kind of launch.")
406 logger.info("")
407 logger.info("Launch on aMC@NLO output:",'$MG:color:BLACK')
408 logger.info(" > launch <dir_path> <mode> <options>",'$MG:color:BLUE')
409 logger.info(" o Example: launch MyProc aMC@NLO -f -p",'$MG:color:GREEN')
410
412 logger.info("syntax: tutorial [" + "|".join(self._tutorial_opts) + "]",'$MG:color:BLUE')
413 logger.info("-- start/stop the MG5 tutorial mode (or stop any other mode)")
414 logger.info("-- aMCatNLO: start aMC@NLO tutorial mode")
415 logger.info("-- MadLoop: start MadLoop tutorial mode")
416
418 logger.info("syntax: open FILE ",'$MG:color:BLUE')
419 logger.info("-- open a file with the appropriate editor.",'$MG:color:BLACK')
420 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
421 logger.info(' the path to the last created/used directory is used')
422 logger.info(' The program used to open those files can be chosen in the')
423 logger.info(' configuration file ./input/mg5_configuration.txt')
424
426 logger.info("syntax: customize_model --save=NAME",'$MG:color:BLUE')
427 logger.info("-- Open an invite where you options to tweak the model.",'$MG:color:BLACK')
428 logger.info(" If you specify the option --save=NAME, this tweak will be")
429 logger.info(" available for future import with the command 'import model XXXX-NAME'")
430
432 logger.info("syntax: output [" + "|".join(self._export_formats) + \
433 "] [path|.|auto] [options]",'$MG:color:BLUE')
434 logger.info("-- Output any generated process(es) to file.",'$MG:color:BLACK')
435 logger.info(" Default mode is madevent. Default path is \'.\' or auto.")
436 logger.info(" mode:",'$MG:color:BLACK')
437 logger.info(" - For MadLoop and aMC@NLO runs, there is only one mode and")
438 logger.info(" it is set by default.")
439 logger.info(" - If mode is madevent, create a MadEvent process directory.")
440 logger.info(" - If mode is standalone, create a Standalone directory")
441 logger.info(" - If mode is matrix, output the matrix.f files for all")
442 logger.info(" generated processes in directory \"path\".")
443 logger.info(" - If mode is standalone_cpp, create a standalone C++")
444 logger.info(" directory in \"path\".")
445 logger.info(" - If mode is pythia8, output all files needed to generate")
446 logger.info(" the processes using Pythia 8. The files are written in")
447 logger.info(" the Pythia 8 directory (default).")
448 logger.info(" NOTE: The Pythia 8 directory is set in the ./input/mg5_configuration.txt")
449 logger.info(" - If mode is aloha: Special syntax output:")
450 logger.info(" syntax: aloha [ROUTINE] [--options]" )
451 logger.info(" valid options for aloha output are:")
452 logger.info(" --format=Fortran|Python|Cpp : defining the output language")
453 logger.info(" --output= : defining output directory")
454 logger.info(" path: The path of the process directory.",'$MG:color:BLACK')
455 logger.info(" If you put '.' as path, your pwd will be used.")
456 logger.info(" If you put 'auto', an automatic directory PROC_XX_n will be created.")
457 logger.info(" options:",'$MG:color:BLACK')
458 logger.info(" -f: force cleaning of the directory if it already exists")
459 logger.info(" -d: specify other MG/ME directory")
460 logger.info(" -noclean: no cleaning performed in \"path\".")
461 logger.info(" -nojpeg: no jpeg diagrams will be generated.")
462 logger.info(" -name: the postfix of the main file in pythia8 mode.")
463 logger.info(" Examples:",'$MG:color:GREEN')
464 logger.info(" output",'$MG:color:GREEN')
465 logger.info(" output standalone MYRUN -f",'$MG:color:GREEN')
466 logger.info(" output pythia8 ../pythia8/ -name qcdprocs",'$MG:color:GREEN')
467
469 logger.info("syntax: check [" + "|".join(self._check_opts) + "] [param_card] process_definition [--energy=] [--split_orders=] [--reduction=]",'$MG:color:BLUE')
470 logger.info("-- check a process or set of processes.",'$MG:color:BLACK')
471 logger.info("General options:",'$MG:color:BLACK')
472 logger.info("o full:",'$MG:color:GREEN')
473 logger.info(" Perform all four checks described below:")
474 logger.info(" permutation, brs, gauge and lorentz_invariance.")
475 logger.info("o permutation:",'$MG:color:GREEN')
476 logger.info(" Check that the model and MG5 are working properly")
477 logger.info(" by generating permutations of the process and checking")
478 logger.info(" that the resulting matrix elements give the same value.")
479 logger.info("o gauge:",'$MG:color:GREEN')
480 logger.info(" Check that processes are gauge invariant by ")
481 logger.info(" comparing Feynman and unitary gauges.")
482 logger.info(" This check is, for now, not available for loop processes.")
483 logger.info("o brs:",'$MG:color:GREEN')
484 logger.info(" Check that the Ward identities are satisfied if the ")
485 logger.info(" process has at least one massless gauge boson as an")
486 logger.info(" external particle.")
487 logger.info("o lorentz_invariance:",'$MG:color:GREEN')
488 logger.info(" Check that the amplitude is lorentz invariant by")
489 logger.info(" comparing the amplitiude in different frames")
490 logger.info("o cms:",'$MG:color:GREEN')
491 logger.info(" Check the complex mass scheme consistency by comparing")
492 logger.info(" it to the narrow width approximation in the off-shell")
493 logger.info(" region of detected resonances and by progressively")
494 logger.info(" decreasing the width. Additional options for this check are:")
495 logger.info(" --offshellness=f : f is a positive or negative float specifying ")
496 logger.info(" the distance from the pole as f*particle_mass. Default is 10.0")
497 logger.info(" --seed=i : to force a specific RNG integer seed i (default is fixed to 0)")
498 logger.info(" --cms=order1&order2;...,p1->f(p,lambdaCMS)&p2->f2(p,lambdaCMS);...")
499 logger.info(" 'order_i' specifies the expansion orders considered for the test.")
500 logger.info(" The substitution lists specifies how internal parameter must be modified")
501 logger.info(" with the width scaling 'lambdaCMS'. The default value for this option is:")
502 logger.info(" --cms=QED&QCD,aewm1->10.0/lambdaCMS&as->0.1*lambdaCMS ")
503 logger.info(" The number of order and parameters don't have to be the same.")
504 logger.info(" The scaling must be specified so that one occurrence of the coupling order.")
505 logger.info(" brings in exactly one power of lambdaCMS.")
506 logger.info(" --recompute_width= never|first_time|always|auto")
507 logger.info(" Decides when to use MadWidth to automatically recompute the width")
508 logger.info(" 'auto' (default) let MG5 chose the most appropriate behavior.")
509 logger.info(" 'never' uses the default width value for lambdaCMS=1.0.")
510 logger.info(" 'first_time' uses MadWidth to compute the width for lambdaCMS=1.0.")
511 logger.info(" 'first_time' and 'never' assume linear scaling of the widths with lambdaCMS")
512 logger.info(" 'always' uses MadWidth to compute the widths for all values of lambdaCMS")
513 logger.info(" the test relies on linear scaling of the width, so 'always' is ")
514 logger.info(" only for double-checks")
515 logger.info(" --lambdaCMS = <python_list> : specifies the list of lambdaCMS values to ")
516 logger.info(" use for the test. For example: '[(1/2.0)**exp\ for\ exp\ in\ range(0,20)]'")
517 logger.info(" In the list expression, you must escape spaces. Also, this option")
518 logger.info(" *must* appear last in the otpion list. Finally, the default value is '1.0e-6'")
519 logger.info(" for which an optimal list of progressive values is picked up to 1.0e-6")
520 logger.info(" --show_plot = True or False: Whether to show plot during analysis (default is True)")
521 logger.info(" --report = concise or full: Whether return a concise or full report.")
522 logger.info("Comments",'$MG:color:GREEN')
523 logger.info(" > If param_card is given, that param_card is used ")
524 logger.info(" instead of the default values for the model.")
525 logger.info(" If that file is an (LHE) event file. The param_card of the banner")
526 logger.info(" is used and the first event compatible with the requested process")
527 logger.info(" is used for the computation of the square matrix elements")
528 logger.info(" > \"--energy=\" allows to change the default value of sqrt(S).")
529 logger.info(" > Except for the 'gauge' test, all checks above are also")
530 logger.info(" available for loop processes with ML5 ('virt=' mode)")
531 logger.info("Example: check full p p > j j",'$MG:color:GREEN')
532 logger.info("Options for loop processes only:",'$MG:color:BLACK')
533 logger.info("o timing:",'$MG:color:GREEN')
534 logger.info(" Generate and output a process and returns detailed")
535 logger.info(" information about the code and a timing benchmark.")
536 logger.info("o stability:",'$MG:color:GREEN')
537 logger.info(" Generate and output a process and returns detailed")
538 logger.info(" statistics about the numerical stability of the code.")
539 logger.info("o profile:",'$MG:color:GREEN')
540 logger.info(" Performs both the timing and stability analysis at once")
541 logger.info(" and outputs the result in a log file without prompting")
542 logger.info(" it to the user.")
543 logger.info("Comments",'$MG:color:GREEN')
544 logger.info(" > These checks are only available for ML5 ('virt=' mode)")
545 logger.info(" > For the 'profile' and 'stability' checks, you can chose")
546 logger.info(" how many PS points should be used for the statistic by")
547 logger.info(" specifying it as an integer just before the [param_card]")
548 logger.info(" optional argument.")
549 logger.info(" > Notice multiparticle labels cannot be used with these checks.")
550 logger.info(" > \"--reduction=\" allows to change what reduction methods should be used.")
551 logger.info(" > \"--split_orders=\" allows to change what specific combination of coupling orders to consider.")
552 logger.info(" > For process syntax, please see help generate.")
553 logger.info(" > In order to save the directory generated or the reuse an existing one")
554 logger.info(" previously generated with the check command, one can add the '-reuse' ")
555 logger.info(" keyword just after the specification of the type of check desired.")
556 logger.info("Example: check profile g g > t t~ [virt=QCD]",'$MG:color:GREEN')
557
558
560
561 logger.info("-- generate diagrams for a given process",'$MG:color:BLUE')
562 logger.info("General leading-order syntax:",'$MG:color:BLACK')
563 logger.info(" o generate INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2^2=ORDER2 @N")
564 logger.info(" o Example: generate l+ vl > w+ > l+ vl a $ z / a h QED<=3 QCD=0 @1",'$MG:color:GREEN')
565 logger.info(" > Alternative required s-channels can be separated by \"|\":")
566 logger.info(" b b~ > W+ W- | H+ H- > ta+ vt ta- vt~")
567 logger.info(" > If no coupling orders are given, MG5 will try to determine")
568 logger.info(" orders to ensure maximum number of QCD vertices.")
569 logger.info(" > Desired coupling orders combination can be specified directly for")
570 logger.info(" the squared matrix element by appending '^2' to the coupling name.")
571 logger.info(" For example, 'p p > j j QED^2==2 QCD^==2' selects the QED-QCD")
572 logger.info(" interference terms only. The other two operators '<=' and '>' are")
573 logger.info(" supported. Finally, a negative value COUP^2==-I refers to the")
574 logger.info(" N^(-I+1)LO term in the expansion of the COUP order.")
575 logger.info(" > allowed coupling operator are: \"==\", \"=\", \"<=\" and \">\".")
576 logger.info(" \"==\" request exactly that number of coupling while \"=\" is interpreted as \"<=\".")
577 logger.info(" > To generate a second process use the \"add process\" command")
578 logger.info("Decay chain syntax:",'$MG:color:BLACK')
579 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
580 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')
581 logger.info(" > Note that identical particles will all be decayed.")
582 logger.info("Loop processes syntax:",'$MG:color:BLACK')
583 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
584 logger.info(" o Example: generate p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
585 logger.info(" > Notice that in this format, decay chains are not allowed.")
586 logger.info(" > The LoopOrder(s) defined specify the kind of loops to consider (only QCD for now).")
587 logger.info(" > The coupling restrictions before '[' restrict the orders of born *amplitudes*.")
588 logger.info(" So that in the example above QCD=2 restricts the born amplitude to have at")
589 logger.info(" most QCD=2 and loop amplitudes at most QCD=2+2 (because QCD loops are considered)")
590 logger.info(" > The coupling restrictions after ']' restrict the orders of the matrix element, ")
591 logger.info(" namely the squared amplitudes. In the example above QCD=6 correspond to born")
592 logger.info(" amplitudes with QCD=2 squared against loop amplitudes with QCD=4, adding up to 6.")
593 logger.info(" > The optional <NLO_mode=> can be any of the following ('all=' by default if absent):")
594 logger.info(" all= : Generate all the real-emission and loop diagrams, ready for aMC@NLO runs.")
595 logger.info(" virt= : Generate only the loop diagrams, read for MadLoop standalone checks/runs.")
596 logger.info(" real= : Generate only the real-emission diagrams, for use with alternative OLP. ")
597 logger.info(" > For processes without born amplitudes (i.e. loop-induced like g g > z), please use ")
598 logger.info(" the 'virt=' NLO mode. aMC@NLO cannot integrate these processes, but standalone MadLoop5")
599 logger.info(" can still handle these.")
600
602 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
603 logger.info(" OR merge two model",'$MG:color:BLUE')
604 logger.info('')
605 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
606 logger.info("General leading-order syntax:",'$MG:color:BLACK')
607 logger.info(" o add process INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2 @N")
608 logger.info(" o Example: add process l+ vl > w+ > l+ vl a $ z / a h QED=3 QCD=0 @1",'$MG:color:GREEN')
609 logger.info(" > Alternative required s-channels can be separated by \"|\":")
610 logger.info(" b b~ > W+ W- | H+ H- > ta+ vt ta- vt~")
611 logger.info(" > If no coupling orders are given, MG5 will try to determine")
612 logger.info(" orders to ensure maximum number of QCD vertices.")
613 logger.info(" > Note that if there are more than one non-QCD coupling type,")
614 logger.info(" coupling orders need to be specified by hand.")
615 logger.info("Decay chain syntax:",'$MG:color:BLACK')
616 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
617 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')
618 logger.info(" > Note that identical particles will all be decayed.")
619 logger.info("Loop processes syntax:",'$MG:color:BLACK')
620 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
621 logger.info(" o Example: add process p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
622 logger.info(" > Notice that in this format, decay chains are not allowed.")
623 logger.info(" > The LoopOrder(s) defined specify the kind of loops to consider (only QCD for now).")
624 logger.info(" > The coupling restrictions before '[' restrict the orders of born *amplitudes*.")
625 logger.info(" So that in the example above QCD=2 restricts the born amplitude to have at")
626 logger.info(" most QCD=2 and loop amplitudes at most QCD=2+2 (because QCD loops are considered)")
627 logger.info(" > The coupling restrictions after ']' restrict the orders of the matrix element, ")
628 logger.info(" namely the squared amplitudes. In the example above QCD=6 correspond to born")
629 logger.info(" amplitudes with QCD=2 squared against loop amplitudes with QCD=4, adding up to 6.")
630 logger.info(" > The optional <NLO_mode=> can be any of the following ('all=' by default if absent):")
631 logger.info(" all= : Generate all the real-emission and loop diagrams, ready for aMC@NLO runs.")
632 logger.info(" virt= : Generate only the loop diagrams, read for MadLoop standalone checks/runs.")
633 logger.info(" real= : Generate only the real-emission diagrams, for use with alternative OLP. ")
634 logger.info(" > For processes without born amplitudes (i.e. loop-induced like g g > z), please use ")
635 logger.info(" the 'virt=' NLO mode. aMC@NLO cannot integrate these processes, but standalone MadLoop5")
636 logger.info(" can still handle these.")
637
638 logger.info("-- merge two model to create a new one", '$MG:color:BLUE')
639 logger.info("syntax:",'$MG:color:BLACK')
640 logger.info(" o add model MODELNAME [OPTIONS]")
641 logger.info(" o Example: add model taudecay",'$MG:color:GREEN')
642 logger.info(" > Merge the two model in a single one. If that same merge was done before.")
643 logger.info(" > Just reload the previous merge. (WARNING: This doesn't check if those model are modified)")
644 logger.info(" > Options:")
645 logger.info(" --output= : Specify the name of the directory where the merge is done.")
646 logger.info(" This allow to do \"import NAME\" to load that merge.")
647 logger.info(" --recreate : Force to recreated the merge model even if the merge model directory already exists.")
648
650 logger.info("syntax: calculate_width PART [other particles] [OPTIONS]")
651 logger.info(" Computes the width and partial width for a set of particles")
652 logger.info(" Returns a valid param_card with this information.")
653 logger.info(" ")
654 logger.info(" PART: name of the particle you want to calculate width")
655 logger.info(" you can enter either the name or pdg code.\n")
656 logger.info(" Various options:\n")
657 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
658 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
659 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
660 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
661 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
662 logger.info(" default: 4.0025")
663 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
664 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
665 logger.info(" --precision_channel=X: requested numerical precision for each channel")
666 logger.info(" default: 0.01")
667 logger.info(" --path=X: path for param_card")
668 logger.info(" default: take value from the model")
669 logger.info(" --output=X: path where to write the resulting card. ")
670 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
671 logger.info(" --nlo: Compute NLO width [if the model support it]")
672 logger.info("")
673 logger.info(" example: calculate_width h --body_decay=2 --output=./param_card")
674
676 logger.info("syntax: decay_diagram PART [other particles] [OPTIONS]")
677 logger.info(" Returns the amplitude required for the computation of the widths")
678 logger.info(" ")
679 logger.info(" PART: name of the particle you want to calculate width")
680 logger.info(" you can enter either the name or pdg code.\n")
681 logger.info(" Various options:\n")
682 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
683 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
684 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
685 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
686 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
687 logger.info(" default: 4.0025")
688 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
689 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
690 logger.info(" --precision_channel=X: requested numerical precision for each channel")
691 logger.info(" default: 0.01")
692 logger.info(" --path=X: path for param_card")
693 logger.info(" default: take value from the model")
694 logger.info(" --output=X: path where to write the resulting card. ")
695 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
696 logger.info("")
697 logger.info(" example: calculate_width h --body_decay=2 --output=./param_card")
698
700 logger.info("-- define a multiparticle",'$MG:color:BLUE')
701 logger.info("Syntax: define multipart_name [=] part_name_list")
702 logger.info("Example: define p = g u u~ c c~ d d~ s s~ b b~",'$MG:color:GREEN')
703 logger.info("Special syntax: Use | for OR (used for required s-channels)")
704 logger.info("Special syntax: Use / to remove particles. Example: define q = p / g")
705
707 logger.info("-- set options for generation or output.",'$MG:color:BLUE')
708 logger.info("syntax: set <option_name> <option_value>",'$MG:color:BLACK')
709 logger.info("Possible options are: ")
710 for opts in [self._set_options[i*3:(i+1)*3] for i in \
711 range((len(self._set_options)//4)+1)]:
712 logger.info("%s"%(','.join(opts)),'$MG:color:GREEN')
713 logger.info("Details of each option:")
714 logger.info("group_subprocesses True/False/Auto: ",'$MG:color:GREEN')
715 logger.info(" > (default Auto) Smart grouping of subprocesses into ")
716 logger.info(" directories, mirroring of initial states, and ")
717 logger.info(" combination of integration channels.")
718 logger.info(" > Example: p p > j j j w+ gives 5 directories and 184 channels",'$MG:color:BLACK')
719 logger.info(" (cf. 65 directories and 1048 channels for regular output)",'$MG:color:BLACK')
720 logger.info(" > Auto means False for decay computation and True for collisions.")
721 logger.info("ignore_six_quark_processes multi_part_label",'$MG:color:GREEN')
722 logger.info(" > (default none) ignore processes with at least 6 of any")
723 logger.info(" of the quarks given in multi_part_label.")
724 logger.info(" > These processes give negligible contribution to the")
725 logger.info(" cross section but have subprocesses/channels.")
726 logger.info("stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL",'$MG:color:GREEN')
727 logger.info(" > change the default level for printed information")
728 logger.info("fortran_compiler NAME",'$MG:color:GREEN')
729 logger.info(" > (default None) Force a specific fortran compiler.")
730 logger.info(" If None, it tries first g77 and if not present gfortran")
731 logger.info(" but loop output use gfortran.")
732 logger.info("loop_optimized_output True|False",'$MG:color:GREEN')
733 logger.info(" > Exploits the open loop thechnique for considerable")
734 logger.info(" improvement.")
735 logger.info(" > CP relations among helicites are detected and the helicity")
736 logger.info(" filter has more potential.")
737 logger.info("loop_color_flows True|False",'$MG:color:GREEN')
738 logger.info(" > Only relevant for the loop optimized output.")
739 logger.info(" > Reduces the loop diagrams at the amplitude level")
740 logger.info(" rendering possible the computation of the loop amplitude")
741 logger.info(" for a fixed color flow or color configuration.")
742 logger.info(" > This option can considerably slow down the loop ME")
743 logger.info(" computation time, especially when summing over all color")
744 logger.info(" and helicity configuration, hence turned off by default.")
745 logger.info("gauge unitary|Feynman",'$MG:color:GREEN')
746 logger.info(" > (default unitary) choose the gauge of the non QCD part.")
747 logger.info(" > For loop processes, only Feynman gauge is employable.")
748 logger.info("complex_mass_scheme True|False",'$MG:color:GREEN')
749 logger.info(" > (default False) Set complex mass scheme.")
750 logger.info(" > Complex mass scheme is not yet supported for loop processes.")
751 logger.info("timeout VALUE",'$MG:color:GREEN')
752 logger.info(" > (default 20) Seconds allowed to answer questions.")
753 logger.info(" > Note that pressing tab always stops the timer.")
754 logger.info("cluster_temp_path PATH",'$MG:color:GREEN')
755 logger.info(" > (default None) [Used in Madevent Output]")
756 logger.info(" > Allow to perform the run in PATH directory")
757 logger.info(" > This allow to not run on the central disk. ")
758 logger.info(" > This is not used by condor cluster (since condor has")
759 logger.info(" its own way to prevent it).")
760 logger.info("mg5amc_py8_interface_path PATH",'$MG:color:GREEN')
761 logger.info(" > Necessary when showering events with Pythia8 from Madevent.")
762 logger.info("OLP ProgramName",'$MG:color:GREEN')
763 logger.info(" > (default 'MadLoop') [Used for virtual generation]")
764 logger.info(" > Chooses what One-Loop Program to use for the virtual")
765 logger.info(" > matrix element generation via the BLAH accord.")
766 logger.info("output_dependencies <mode>",'$MG:color:GREEN')
767 logger.info(" > (default 'external') [Use for NLO outputs]")
768 logger.info(" > Choses how the external dependences (such as CutTools)")
769 logger.info(" > of NLO outputs are handled. Possible values are:")
770 logger.info(" o external: Some of the libraries the output depends")
771 logger.info(" on are links to their installation in MG5 root dir.")
772 logger.info(" o internal: All libraries the output depends on are")
773 logger.info(" copied and compiled locally in the output directory.")
774 logger.info(" o environment_paths: The location of all libraries the ")
775 logger.info(" output depends on should be found in your env. paths.")
776
788 """ The Series of help routine for the MadGraphCmd"""
789
791 """a class for read/write errors"""
792
794 """check the validity of line
795 syntax: add process PROCESS | add model MODELNAME
796 """
797
798 if len(args) < 2:
799 self.help_add()
800 raise self.InvalidCmd('\"add\" requires at least two arguments')
801
802 if args[0] not in ['model', 'process']:
803 raise self.InvalidCmd('\"add\" requires the argument \"process\" or \"model\"')
804
805 if args[0] == 'process':
806 return self.check_generate(args)
807
808 if args[0] == 'model':
809 pass
810
811
813 """check the validity of line
814 syntax: define multipart_name [ part_name_list ]
815 """
816
817 if len(args) < 2:
818 self.help_define()
819 raise self.InvalidCmd('\"define\" command requires at least two arguments')
820
821 if args[1] == '=':
822 del args[1]
823 if len(args) < 2:
824 self.help_define()
825 raise self.InvalidCmd('\"define\" command requires at least one particles name after \"=\"')
826
827 if '=' in args:
828 self.help_define()
829 raise self.InvalidCmd('\"define\" command requires symbols \"=\" at the second position')
830
831 if not self._curr_model:
832 logger.info('No model currently active. Try with the Standard Model')
833 self.do_import('model sm')
834
835 if self._curr_model['particles'].find_name(args[0]):
836 raise self.InvalidCmd("label %s is a particle name in this model\n\
837 Please retry with another name." % args[0])
838
840 """check the validity of line
841 syntax: display XXXXX
842 """
843
844 if len(args) < 1:
845 self.help_display()
846 raise self.InvalidCmd, 'display requires an argument specifying what to display'
847 if args[0] not in self._display_opts:
848 self.help_display()
849 raise self.InvalidCmd, 'Invalid arguments for display command: %s' % args[0]
850
851 if not self._curr_model:
852 raise self.InvalidCmd("No model currently active, please import a model!")
853
854
855 if (args[0] in ['processes', 'diagrams'] and not self._curr_amps and not self._fks_multi_proc):
856 raise self.InvalidCmd("No process generated, please generate a process!")
857 if args[0] == 'checks' and not self._comparisons and not self._cms_checks:
858 raise self.InvalidCmd("No check results to display.")
859
860 if args[0] == 'variable' and len(args) !=2:
861 raise self.InvalidCmd('variable need a variable name')
862
863
865 """check the validity of line
866 syntax: draw DIRPATH [option=value]
867 """
868
869 if len(args) < 1:
870 args.append('/tmp')
871
872 if not self._curr_amps:
873 raise self.InvalidCmd("No process generated, please generate a process!")
874
875 if not os.path.isdir(args[0]):
876 raise self.InvalidCmd( "%s is not a valid directory for export file" % args[0])
877
879 """check the validity of args"""
880
881 if not self._curr_model:
882 raise self.InvalidCmd("No model currently active, please import a model!")
883
884 if self._model_v4_path:
885 raise self.InvalidCmd(\
886 "\"check\" not possible for v4 models")
887
888 if len(args) < 2 and not args[0].lower().endswith('options'):
889 self.help_check()
890 raise self.InvalidCmd("\"check\" requires a process.")
891
892 if args[0] not in self._check_opts and \
893 not args[0].lower().endswith('options'):
894 args.insert(0, 'full')
895
896 param_card = None
897 if args[0] not in ['stability','profile','timing'] and \
898 len(args)>1 and os.path.isfile(args[1]):
899 param_card = args.pop(1)
900
901 if len(args)>1:
902 if args[1] != "-reuse":
903 args.insert(1, '-no_reuse')
904 else:
905 args.append('-no_reuse')
906
907 if args[0] in ['timing'] and len(args)>2 and os.path.isfile(args[2]):
908 param_card = args.pop(2)
909 if args[0] in ['stability', 'profile'] and len(args)>1:
910
911
912
913 try:
914 int(args[2])
915 except ValueError:
916 args.insert(2, '100')
917
918 if args[0] in ['stability', 'profile'] and os.path.isfile(args[3]):
919 param_card = args.pop(3)
920 if any([',' in elem for elem in args if not elem.startswith('--')]):
921 raise self.InvalidCmd('Decay chains not allowed in check')
922
923 user_options = {'--energy':'1000','--split_orders':'-1',
924 '--reduction':'1|2|3|4|5|6','--CTModeRun':'-1',
925 '--helicity':'-1','--seed':'-1','--collier_cache':'-1',
926 '--collier_req_acc':'auto',
927 '--collier_internal_stability_test':'False',
928 '--collier_mode':'1'}
929
930 if args[0] in ['cms'] or args[0].lower()=='cmsoptions':
931
932 user_options['--energy']='5000'
933
934
935
936
937 parameters = ['aewm1->10.0/lambdaCMS','as->0.1*lambdaCMS']
938 user_options['--cms']='QED&QCD,'+'&'.join(parameters)
939
940
941 user_options['--recompute_width']='auto'
942
943 user_options['--offshellness']='10.0'
944
945
946
947
948
949
950 user_options['--lambdaCMS']='(1.0e-6,5)'
951
952 user_options['--seed']=666
953
954 user_options['--analyze']='None'
955
956 user_options['--show_plot']='True'
957
958 user_options['--report']='concise'
959
960
961
962
963 user_options['--diff_lambda_power']='1'
964
965 user_options['--lambda_plot_range']='[-1.0,-1.0]'
966
967
968 user_options['--loop_filter']='None'
969
970
971
972 user_options['--tweak']='default()'
973
974 user_options['--name']='auto'
975
976 user_options['--resonances']='1'
977
978 for arg in args[:]:
979 if arg.startswith('--') and '=' in arg:
980 parsed = arg.split('=')
981 key, value = parsed[0],'='.join(parsed[1:])
982 if key not in user_options:
983 raise self.InvalidCmd, "unknown option %s" % key
984 user_options[key] = value
985 args.remove(arg)
986
987
988
989 if not (args[0]=='cms' and '--analyze' in user_options and \
990 user_options['--analyze']!='None') and not \
991 args[0].lower().endswith('options'):
992
993 self.check_process_format(" ".join(args[1:]))
994
995 for option, value in user_options.items():
996 args.append('%s=%s'%(option,value))
997
998 return param_card
999
1024
1025
1064
1065
1078
1079
1080
1126
1127
1128
1130 """check that the install command is valid"""
1131
1132
1133 install_options = {'options_for_HEPToolsInstaller':[],
1134 'update_options':[]}
1135 hidden_prog = ['Delphes2', 'pythia-pgs']
1136
1137 if len(args) < 1:
1138 self.help_install()
1139 raise self.InvalidCmd('install command require at least one argument')
1140
1141 if len(args) > 1:
1142 for arg in args[1:]:
1143 try:
1144 option, value = arg.split('=')
1145 except ValueError:
1146 option = arg
1147 value = None
1148
1149 if args[0]=='update':
1150 if value is None:
1151 install_options['update_options'].append(option)
1152 else:
1153 install_options['update_options'].append('='.join([option,value]))
1154 else:
1155
1156
1157 install_options['options_for_HEPToolsInstaller'].append(arg)
1158
1159
1160 args = args[:1]
1161
1162 if args[0] not in self._install_opts + hidden_prog:
1163 if not args[0].startswith('td'):
1164 self.help_install()
1165 raise self.InvalidCmd('Not recognize program %s ' % args[0])
1166
1167 if args[0] in ["ExRootAnalysis", "Delphes", "Delphes2"]:
1168 if not misc.which('root'):
1169 raise self.InvalidCmd(
1170 '''In order to install ExRootAnalysis, you need to install Root on your computer first.
1171 please follow information on http://root.cern.ch/drupal/content/downloading-root''')
1172 if 'ROOTSYS' not in os.environ:
1173 raise self.InvalidCmd(
1174 '''The environment variable ROOTSYS is not configured.
1175 You can set it by adding the following lines in your .bashrc [.bash_profile for mac]:
1176 export ROOTSYS=%s
1177 export PATH=$PATH:$ROOTSYS/bin
1178 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib
1179 export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$ROOTSYS/lib
1180 This will take effect only in a NEW terminal
1181 ''' % os.path.realpath(pjoin(misc.which('root'), \
1182 os.path.pardir, os.path.pardir)))
1183
1184 return install_options
1185
1187 """check the validity of the line"""
1188
1189
1190 if not( 0 <= int(options.cluster) <= 2):
1191 return self.InvalidCmd, 'cluster mode should be between 0 and 2'
1192
1193 if not args:
1194 if self._done_export:
1195 mode = self.find_output_type(self._done_export[0])
1196 if (self._done_export[1] == 'plugin' and mode not in self._export_formats):
1197 args.append(mode)
1198 args.append(self._done_export[0])
1199 elif self._done_export[1].startswith(mode):
1200 args.append(self._done_export[1])
1201 args.append(self._done_export[0])
1202 else:
1203 raise self.InvalidCmd, \
1204 '%s not valid directory for launch' % self._done_export[0]
1205 return
1206 else:
1207 logger.warning('output command missing, run it automatically (with default argument)')
1208 self.do_output('')
1209 logger.warning('output done: running launch')
1210 return self.check_launch(args, options)
1211
1212 if len(args) != 1:
1213 self.help_launch()
1214 return self.InvalidCmd, 'Invalid Syntax: Too many argument'
1215
1216
1217 if os.path.isdir(args[0]):
1218 path = os.path.realpath(args[0])
1219 elif os.path.isdir(pjoin(MG5DIR,args[0])):
1220 path = pjoin(MG5DIR,args[0])
1221 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
1222 path = pjoin(MG4DIR,args[0])
1223 else:
1224 raise self.InvalidCmd, '%s is not a valid directory' % args[0]
1225
1226 mode = self.find_output_type(path)
1227
1228 args[0] = mode
1229 args.append(path)
1230
1231 self._done_export = [path, mode]
1232
1233
1235 """ identify the import type of a given path
1236 valid output: model/model_v4/proc_v4/command"""
1237
1238 possibility = [pjoin(MG5DIR,'models',path), \
1239 pjoin(MG5DIR,'models',path+'_v4'), path]
1240 if '-' in path:
1241 name = path.rsplit('-',1)[0]
1242 possibility = [pjoin(MG5DIR,'models',name), name] + possibility
1243
1244 for name in possibility:
1245 if os.path.isdir(name):
1246 if os.path.exists(pjoin(name,'particles.py')):
1247 return 'model'
1248 elif os.path.exists(pjoin(name,'particles.dat')):
1249 return 'model_v4'
1250
1251
1252 if os.path.isfile(path):
1253 text = open(path).read()
1254 pat = re.compile('(Begin process|<MGVERSION>)', re.I)
1255 matches = pat.findall(text)
1256 if not matches:
1257 return 'command'
1258 elif len(matches) > 1:
1259 return 'banner'
1260 elif matches[0].lower() == 'begin process':
1261 return 'proc_v4'
1262 else:
1263 return 'banner'
1264 else:
1265 return 'proc_v4'
1266
1267
1268
1269
1271 """ identify the type of output of a given directory:
1272 valid output: madevent/standalone/standalone_cpp"""
1273
1274 card_path = pjoin(path,'Cards')
1275 bin_path = pjoin(path,'bin')
1276 src_path = pjoin(path,'src')
1277 include_path = pjoin(path,'include')
1278 subproc_path = pjoin(path,'SubProcesses')
1279 mw_path = pjoin(path,'Source','MadWeight')
1280
1281 if os.path.isfile(pjoin(include_path, 'Pythia.h')) or \
1282 os.path.isfile(pjoin(include_path, 'Pythia8', 'Pythia.h')):
1283 return 'pythia8'
1284 elif not os.path.isdir(os.path.join(path, 'SubProcesses')):
1285 raise self.InvalidCmd, '%s : Not a valid directory' % path
1286
1287 if os.path.isdir(src_path):
1288 return 'standalone_cpp'
1289 elif os.path.isdir(mw_path):
1290 return 'madweight'
1291 elif os.path.isfile(pjoin(bin_path,'madevent')):
1292 return 'madevent'
1293 elif os.path.isfile(pjoin(bin_path,'aMCatNLO')):
1294 return 'aMC@NLO'
1295 elif os.path.isdir(card_path):
1296 return 'standalone'
1297
1298 raise self.InvalidCmd, '%s : Not a valid directory' % path
1299
1306
1308 """check the validity of the line"""
1309
1310
1311 if len(args) >1 :
1312 self.help_customize_model()
1313 raise self.InvalidCmd('No argument expected for this command')
1314
1315 if len(args):
1316 if not args[0].startswith('--save='):
1317 self.help_customize_model()
1318 raise self.InvalidCmd('Wrong argument for this command')
1319 if '-' in args[0][6:]:
1320 raise self.InvalidCmd('The name given in save options can\'t contain \'-\' symbol.')
1321
1322 if self._model_v4_path:
1323 raise self.InvalidCmd('Restriction of Model is not supported by v4 model.')
1324
1325
1327 """ check the validity of the line"""
1328
1329 if len(args) == 0:
1330 args.append('options')
1331
1332 if args[0] not in self._save_opts and args[0] != 'global':
1333 self.help_save()
1334 raise self.InvalidCmd('wrong \"save\" format')
1335 elif args[0] == 'global':
1336 args.insert(0, 'options')
1337
1338 if args[0] != 'options' and len(args) != 2:
1339 self.help_save()
1340 raise self.InvalidCmd('wrong \"save\" format')
1341 elif args[0] != 'options' and len(args) == 2:
1342 basename = os.path.dirname(args[1])
1343 if not os.path.exists(basename):
1344 raise self.InvalidCmd('%s is not a valid path, please retry' % \
1345 args[1])
1346
1347 if args[0] == 'options':
1348 has_path = None
1349 for arg in args[1:]:
1350 if arg in ['--auto', '--all'] or arg in self.options:
1351 continue
1352 elif arg.startswith('--'):
1353 raise self.InvalidCmd('unknow command for \'save options\'')
1354 elif arg == 'global':
1355 if os.environ.has_key('HOME'):
1356 args.remove('global')
1357 args.insert(1,pjoin(os.environ['HOME'],'.mg5','mg5_configuration.txt'))
1358 has_path = True
1359 else:
1360 basename = os.path.dirname(arg)
1361 if not os.path.exists(basename):
1362 raise self.InvalidCmd('%s is not a valid path, please retry' % \
1363 arg)
1364 elif has_path:
1365 raise self.InvalidCmd('only one path is allowed')
1366 else:
1367 args.remove(arg)
1368 args.insert(1, arg)
1369 has_path = True
1370 if not has_path:
1371 args.insert(1, pjoin(MG5DIR,'input','mg5_configuration.txt'))
1372
1373
1375 """ check the validity of the line"""
1376
1377 if len(args) == 1 and args[0] in ['complex_mass_scheme',\
1378 'loop_optimized_output',\
1379 'loop_color_flows',\
1380 'low_mem_multicore_nlo_generation']:
1381 args.append('True')
1382
1383 if len(args) > 2 and '=' == args[1]:
1384 args.pop(1)
1385
1386 if len(args) < 2:
1387 self.help_set()
1388 raise self.InvalidCmd('set needs an option and an argument')
1389
1390 if args[1] == 'default':
1391 if args[0] in self.options_configuration:
1392 default = self.options_configuration[args[0]]
1393 elif args[0] in self.options_madgraph:
1394 default = self.options_madgraph[args[0]]
1395 elif args[0] in self.options_madevent:
1396 default = self.options_madevent[args[0]]
1397 else:
1398 raise self.InvalidCmd('%s doesn\'t have a valid default value' % args[0])
1399 if log:
1400 logger.info('Pass parameter %s to it\'s default value: %s' %
1401 (args[0], default))
1402 args[1] = str(default)
1403
1404 if args[0] not in self._set_options:
1405 if not args[0] in self.options and not args[0] in self.options:
1406 self.help_set()
1407 raise self.InvalidCmd('Possible options for set are %s' % \
1408 self._set_options)
1409
1410 if args[0] in ['group_subprocesses']:
1411 if args[1] not in ['False', 'True', 'Auto']:
1412 raise self.InvalidCmd('%s needs argument False, True or Auto' % \
1413 args[0])
1414 if args[0] in ['ignore_six_quark_processes']:
1415 if args[1] not in self._multiparticles.keys() and args[1] != 'False':
1416 raise self.InvalidCmd('ignore_six_quark_processes needs ' + \
1417 'a multiparticle name as argument')
1418
1419 if args[0] in ['stdout_level']:
1420 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] and \
1421 not args[1].isdigit():
1422 raise self.InvalidCmd('output_level needs ' + \
1423 'a valid level')
1424
1425 if args[0] in ['timeout', 'max_npoint_for_channel']:
1426 if not args[1].isdigit():
1427 raise self.InvalidCmd('%s values should be a integer' % args[0])
1428
1429 if args[0] in ['loop_optimized_output', 'loop_color_flows', 'low_mem_multicore_nlo_generation']:
1430 try:
1431 args[1] = banner_module.ConfigFile.format_variable(args[1], bool, args[0])
1432 except Exception:
1433 raise self.InvalidCmd('%s needs argument True or False'%args[0])
1434
1435 if args[0] in ['gauge']:
1436 if args[1] not in ['unitary','Feynman']:
1437 raise self.InvalidCmd('gauge needs argument unitary or Feynman.')
1438
1439 if args[0] in ['timeout']:
1440 if not args[1].isdigit():
1441 raise self.InvalidCmd('timeout values should be a integer')
1442
1443 if args[0] in ['OLP']:
1444 if args[1] not in MadGraphCmd._OLP_supported:
1445 raise self.InvalidCmd('OLP value should be one of %s'\
1446 %str(MadGraphCmd._OLP_supported))
1447
1448 if args[0].lower() in ['ewscheme']:
1449 if not self._curr_model:
1450 raise self.InvalidCmd("ewscheme acts on the current model please load one first.")
1451 if args[1] not in ['external']:
1452 raise self.InvalidCmd('Only valid ewscheme is "external". To restore default, please re-import the model.')
1453
1454 if args[0] in ['output_dependencies']:
1455 if args[1] not in MadGraphCmd._output_dependencies_supported:
1456 raise self.InvalidCmd('output_dependencies value should be one of %s'\
1457 %str(MadGraphCmd._output_dependencies_supported))
1458
1460 """ check the validity of the line """
1461
1462 if len(args) != 1:
1463 self.help_open()
1464 raise self.InvalidCmd('OPEN command requires exactly one argument')
1465
1466 if args[0].startswith('./'):
1467 if not os.path.isfile(args[0]):
1468 raise self.InvalidCmd('%s: not such file' % args[0])
1469 return True
1470
1471
1472 if not self._done_export:
1473 if not os.path.isfile(args[0]):
1474 self.help_open()
1475 raise self.InvalidCmd('No command \"output\" or \"launch\" used. Impossible to associate this name to a file')
1476 else:
1477 return True
1478
1479 path = self._done_export[0]
1480 if os.path.isfile(pjoin(path,args[0])):
1481 args[0] = pjoin(path,args[0])
1482 elif os.path.isfile(pjoin(path,'Cards',args[0])):
1483 args[0] = pjoin(path,'Cards',args[0])
1484 elif os.path.isfile(pjoin(path,'HTML',args[0])):
1485 args[0] = pjoin(path,'HTML',args[0])
1486
1487 elif '_card.dat' in args[0]:
1488 name = args[0].replace('_card.dat','_card_default.dat')
1489 if os.path.isfile(pjoin(path,'Cards', name)):
1490 files.cp(path + '/Cards/' + name, path + '/Cards/'+ args[0])
1491 args[0] = pjoin(path,'Cards', args[0])
1492 else:
1493 raise self.InvalidCmd('No default path for this file')
1494 elif not os.path.isfile(args[0]):
1495 raise self.InvalidCmd('No default path for this file')
1496
1497
1499 """ check the validity of the line"""
1500
1501
1502 if args and args[0] in self._export_formats:
1503 self._export_format = args.pop(0)
1504 elif args:
1505
1506 for plugpath in self.plugin_path:
1507 plugindirname = os.path.basename(plugpath)
1508 for plug in os.listdir(plugpath):
1509 if os.path.exists(pjoin(plugpath, plug, '__init__.py')):
1510 try:
1511 __import__('%s.%s' % (plugindirname,plug))
1512 except Exception, error:
1513 logger.warning("error detected in plugin: %s.", plug)
1514 logger.warning("%s", error)
1515 continue
1516 plugin = sys.modules['%s.%s' % (plugindirname,plug)]
1517 if hasattr(plugin, 'new_output'):
1518 if not misc.is_plugin_supported(plugin):
1519 continue
1520 if args[0] in plugin.new_output:
1521 self._export_format = 'plugin'
1522 self._export_plugin = plugin.new_output[args[0]]
1523 logger.info('Output will be done with PLUGIN: %s' % plug ,'$MG:color:BLACK')
1524 args.pop(0)
1525 break
1526 else:
1527 continue
1528 break
1529 else:
1530 self._export_format = default
1531 else:
1532 self._export_format = default
1533
1534 if not self._curr_model:
1535 text = 'No model found. Please import a model first and then retry.'
1536 raise self.InvalidCmd(text)
1537
1538 if self._model_v4_path and \
1539 (self._export_format not in self._v4_export_formats):
1540 text = " The Model imported (MG4 format) does not contain enough\n "
1541 text += " information for this type of output. In order to create\n"
1542 text += " output for " + args[0] + ", you have to use a UFO model.\n"
1543 text += " Those model can be imported with MG5> import model NAME."
1544 logger.warning(text)
1545 raise self.InvalidCmd('')
1546
1547 if self._export_format == 'aloha':
1548 return
1549
1550
1551 if not self._curr_amps:
1552 text = 'No processes generated. Please generate a process first.'
1553 raise self.InvalidCmd(text)
1554
1555 if args and args[0][0] != '-':
1556
1557 path = args.pop(0)
1558 forbiden_chars = ['>','<',';','&']
1559 for char in forbiden_chars:
1560 if char in path:
1561 raise self.InvalidCmd('%s is not allowed in the output path' % char)
1562
1563 if path == 'auto' and self._export_format in \
1564 ['madevent', 'standalone', 'standalone_cpp', 'matchbox_cpp', 'madweight',
1565 'matchbox', 'plugin']:
1566 self.get_default_path()
1567 if '-noclean' not in args and os.path.exists(self._export_dir):
1568 args.append('-noclean')
1569 elif path != 'auto':
1570 if path in ['HELAS', 'tests', 'MadSpin', 'madgraph', 'mg5decay', 'vendor']:
1571 if os.getcwd() == MG5DIR:
1572 raise self.InvalidCmd, "This name correspond to a buildin MG5 directory. Please choose another name"
1573 self._export_dir = path
1574 elif path == 'auto':
1575 if self.options['pythia8_path']:
1576 self._export_dir = self.options['pythia8_path']
1577 else:
1578 self._export_dir = '.'
1579 else:
1580 if self._export_format != 'pythia8':
1581
1582 self.get_default_path()
1583 if '-noclean' not in args and os.path.exists(self._export_dir):
1584 args.append('-noclean')
1585
1586 else:
1587 if self.options['pythia8_path']:
1588 self._export_dir = self.options['pythia8_path']
1589 else:
1590 self._export_dir = '.'
1591
1592 self._export_dir = os.path.realpath(self._export_dir)
1593
1594
1596 """ check and format calculate decay width:
1597 Expected format: NAME [other names] [--options]
1598 # fill the options if not present.
1599 # NAME can be either (anti-)particle name, multiparticle, pid
1600 """
1601
1602 if len(args)<1:
1603 self.help_compute_widths()
1604 raise self.InvalidCmd('''compute_widths requires at least the name of one particle.
1605 If you want to compute the width of all particles, type \'compute_widths all\'''')
1606
1607 particles = set()
1608 options = {'path':None, 'output':None,
1609 'min_br':None, 'body_decay':4.0025, 'precision_channel':0.01,
1610 'nlo':False}
1611
1612
1613 for i,arg in enumerate(args):
1614 if arg.startswith('--'):
1615 if arg.startswith('--nlo'):
1616 options['nlo'] =True
1617 continue
1618 elif not '=' in arg:
1619 raise self.InvalidCmd('Options required an equal (and then the value)')
1620 arg, value = arg.split('=')
1621 if arg[2:] not in options:
1622 raise self.InvalidCmd('%s not valid options' % arg)
1623 options[arg[2:]] = value
1624 continue
1625
1626 if arg.isdigit():
1627 p = self._curr_model.get_particle(int(arg))
1628 if not p:
1629 raise self.InvalidCmd('Model doesn\'t have pid %s for any particle' % arg)
1630 particles.add(abs(int(arg)))
1631 elif arg in self._multiparticles:
1632 particles.update([abs(id) for id in self._multiparticles[args[0]]])
1633 else:
1634 if not self._curr_model['case_sensitive']:
1635 arg = arg.lower()
1636 for p in self._curr_model['particles']:
1637 if p['name'] == arg or p['antiname'] == arg:
1638 particles.add(abs(p.get_pdg_code()))
1639 break
1640 else:
1641 if arg == 'all':
1642
1643 particles.update([abs(p.get_pdg_code())
1644 for p in self._curr_model['particles']])
1645 else:
1646 raise self.InvalidCmd('%s invalid particle name' % arg)
1647
1648 if options['path'] and not os.path.isfile(options['path']):
1649
1650 if os.path.exists(pjoin(MG5DIR, options['path'])):
1651 options['path'] = pjoin(MG5DIR, options['path'])
1652 elif self._model_v4_path and os.path.exists(pjoin(self._model_v4_path, options['path'])):
1653 options['path'] = pjoin(self._curr_model_v4_path, options['path'])
1654 elif os.path.exists(pjoin(self._curr_model.path, options['path'])):
1655 options['path'] = pjoin(self._curr_model.path, options['path'])
1656
1657 if os.path.isdir(options['path']) and os.path.isfile(pjoin(options['path'], 'param_card.dat')):
1658 options['path'] = pjoin(options['path'], 'param_card.dat')
1659 elif not os.path.isfile(options['path']):
1660 raise self.InvalidCmd('%s is not a valid path' % args[2])
1661
1662 if madevent_interface.MadEventCmd.detect_card_type(options['path']) != 'param_card.dat':
1663 raise self.InvalidCmd('%s should be a path to a param_card' % options['path'])
1664
1665 if not options['path']:
1666 param_card_text = self._curr_model.write_param_card()
1667 if not options['output']:
1668 dirpath = self._curr_model.get('modelpath')
1669 options['path'] = pjoin(dirpath, 'param_card.dat')
1670 else:
1671 options['path'] = options['output']
1672 ff = open(options['path'],'w')
1673 ff.write(param_card_text)
1674 ff.close()
1675 if not options['output']:
1676 options['output'] = options['path']
1677
1678 if not options['min_br']:
1679 options['min_br'] = (float(options['body_decay']) % 1) / 5
1680 return particles, options
1681
1682
1683 check_decay_diagram = check_compute_widths
1684
1686 """Set self._export_dir to the default (\'auto\') path"""
1687
1688 if self._export_format in ['madevent', 'standalone']:
1689
1690
1691 if 'TemplateVersion.txt' in os.listdir('.'):
1692
1693 self._export_dir = os.path.realpath('.')
1694 return
1695 elif 'TemplateVersion.txt' in os.listdir('..'):
1696
1697 self._export_dir = os.path.realpath('..')
1698 return
1699 elif self.stdin != sys.stdin:
1700
1701 input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
1702 print "Not standard stdin, use input path"
1703 if input_path[-2] == 'Cards':
1704 self._export_dir = os.path.sep.join(input_path[:-2])
1705 if 'TemplateVersion.txt' in self._export_dir:
1706 return
1707
1708
1709 if self._export_format == 'NLO':
1710 name_dir = lambda i: 'PROCNLO_%s_%s' % \
1711 (self._curr_model['name'], i)
1712 auto_path = lambda i: pjoin(self.writing_dir,
1713 name_dir(i))
1714 elif self._export_format.startswith('madevent'):
1715 name_dir = lambda i: 'PROC_%s_%s' % \
1716 (self._curr_model['name'], i)
1717 auto_path = lambda i: pjoin(self.writing_dir,
1718 name_dir(i))
1719 elif self._export_format.startswith('standalone'):
1720 name_dir = lambda i: 'PROC_SA_%s_%s' % \
1721 (self._curr_model['name'], i)
1722 auto_path = lambda i: pjoin(self.writing_dir,
1723 name_dir(i))
1724 elif self._export_format == 'madweight':
1725 name_dir = lambda i: 'PROC_MW_%s_%s' % \
1726 (self._curr_model['name'], i)
1727 auto_path = lambda i: pjoin(self.writing_dir,
1728 name_dir(i))
1729 elif self._export_format == 'standalone_cpp':
1730 name_dir = lambda i: 'PROC_SA_CPP_%s_%s' % \
1731 (self._curr_model['name'], i)
1732 auto_path = lambda i: pjoin(self.writing_dir,
1733 name_dir(i))
1734 elif self._export_format in ['matchbox_cpp', 'matchbox']:
1735 name_dir = lambda i: 'PROC_MATCHBOX_%s_%s' % \
1736 (self._curr_model['name'], i)
1737 auto_path = lambda i: pjoin(self.writing_dir,
1738 name_dir(i))
1739 elif self._export_format in ['plugin']:
1740 name_dir = lambda i: 'PROC_PLUGIN_%s_%s' % \
1741 (self._curr_model['name'], i)
1742 auto_path = lambda i: pjoin(self.writing_dir,
1743 name_dir(i))
1744 elif self._export_format == 'pythia8':
1745 if self.options['pythia8_path']:
1746 self._export_dir = self.options['pythia8_path']
1747 else:
1748 self._export_dir = '.'
1749 return
1750 else:
1751 self._export_dir = '.'
1752 return
1753 for i in range(500):
1754 if os.path.isdir(auto_path(i)):
1755 continue
1756 else:
1757 self._export_dir = auto_path(i)
1758 break
1759 if not self._export_dir:
1760 raise self.InvalidCmd('Can\'t use auto path,' + \
1761 'more than 500 dirs already')
1762
1768 """ Check the validity of input line for web entry
1769 (no explicit path authorized)"""
1770
1772 """class for WebRestriction"""
1773
1775 """check the validity of line
1776 syntax: draw FILEPATH [option=value]
1777 """
1778 raise self.WebRestriction('direct call to draw is forbidden on the web')
1779
1787
1789 """ Not authorize for the Web"""
1790
1791 raise self.WebRestriction('Check call is forbidden on the web')
1792
1793 - def check_history(self, args):
1794 """check the validity of line
1795 No Path authorize for the Web"""
1796
1797 CheckValidForCmd.check_history(self, args)
1798
1799 if len(args) == 2 and args[1] not in ['.', 'clean']:
1800 raise self.WebRestriction('Path can\'t be specify on the web.')
1801
1802
1818
1820 """ No possibility to install new software on the web """
1821 if args == ['update','--mode=mg5_start']:
1822 return
1823
1824 raise self.WebRestriction('Impossible to install program on the cluster')
1825
1827 """ check the validity of the line
1828 No Path authorize for the Web"""
1829
1830 CheckValidForCmd.check_load(self, args)
1831
1832 if len(args) == 2:
1833 if args[0] != 'model':
1834 raise self.WebRestriction('only model can be loaded online')
1835 if 'model.pkl' not in args[1]:
1836 raise self.WebRestriction('not valid pkl file: wrong name')
1837 if not os.path.realpath(args[1]).startswith(pjoin(MG4DIR, \
1838 'Models')):
1839 raise self.WebRestriction('Wrong path to load model')
1840
1842 """ not authorize on web"""
1843 raise self.WebRestriction('\"save\" command not authorize online')
1844
1846 """ not authorize on web"""
1847 raise self.WebRestriction('\"open\" command not authorize online')
1848
1850 """ check the validity of the line"""
1851
1852
1853 CheckValidForCmd.check_output(self, args, default=default)
1854 args[:] = ['.', '-f']
1855
1856 self._export_dir = os.path.realpath(os.getcwd())
1857
1858 if 'madevent' != self._export_format:
1859 raise self.WebRestriction, 'only available output format is madevent (at current stage)'
1860
1865 """ The Series of help routine for the MadGraphCmd"""
1866
1868 """ complete the nlo settings within square brackets. It uses the
1869 allowed_loop_mode for the proposed mode if specified, otherwise, it
1870 uses self._nlo_modes_for_completion"""
1871
1872
1873
1874
1875 nlo_modes = allowed_loop_mode if not allowed_loop_mode is None else \
1876 self._nlo_modes_for_completion
1877 if isinstance(self._curr_model,loop_base_objects.LoopModel):
1878 pert_couplings_allowed = ['all']+self._curr_model['perturbation_couplings']
1879 else:
1880 pert_couplings_allowed = []
1881 if self._curr_model.get('name').startswith('sm'):
1882 pert_couplings_allowed = pert_couplings_allowed + ['QCD']
1883
1884 loop_specs = line[line.index('[')+1:]
1885 try:
1886 loop_orders = loop_specs[loop_specs.index('=')+1:]
1887 except ValueError:
1888 loop_orders = loop_specs
1889 possibilities = []
1890 possible_orders = [order for order in pert_couplings_allowed if \
1891 order not in loop_orders]
1892
1893
1894 single_completion = ''
1895 if len(nlo_modes)==1:
1896 single_completion = '%s= '%nlo_modes[0]
1897 if len(possible_orders)==1:
1898 single_completion = single_completion + possible_orders[0] + ' ] '
1899
1900 if text.endswith('['):
1901 if single_completion != '':
1902 return self.list_completion(text, ['[ '+single_completion])
1903 else:
1904 return self.list_completion(text,['[ '])
1905
1906 if text.endswith('='):
1907 return self.list_completion(text,[' '])
1908
1909 if args[-1]=='[':
1910 possibilities = possibilities + ['%s= '%mode for mode in nlo_modes]
1911 if single_completion != '':
1912 return self.list_completion(text, [single_completion])
1913 else:
1914 if len(possible_orders)==1:
1915 return self.list_completion(text, [poss+' %s ] '%\
1916 possible_orders[0] for poss in possibilities])
1917 return self.list_completion(text, possibilities)
1918
1919 if len(possible_orders)==1:
1920 possibilities.append(possible_orders[0]+' ] ')
1921 else:
1922 possibilities.extend(possible_orders)
1923 if any([(order in loop_orders) for order in pert_couplings_allowed]):
1924 possibilities.append(']')
1925 return self.list_completion(text, possibilities)
1926
1927 - def model_completion(self, text, process, line, categories = True, \
1928 allowed_loop_mode = None,
1929 formatting=True):
1930 """ complete the line with model information. If categories is True,
1931 it will use completion with categories. If allowed_loop_mode is
1932 specified, it will only complete with these loop modes."""
1933
1934
1935
1936 args = self.split_arg(process)
1937 if len(args) > 2 and '>' in line and '[' in line and not ']' in line:
1938 return self.nlo_completion(args,text,line, allowed_loop_mode = \
1939 allowed_loop_mode)
1940
1941 while ',' in process:
1942 process = process[process.index(',')+1:]
1943 args = self.split_arg(process)
1944 couplings = []
1945
1946
1947 if len(args) > 1 and args[-1]=='@':
1948 return
1949
1950
1951
1952 if isinstance(self._curr_model,loop_base_objects.LoopModel):
1953 pert_couplings_allowed = ['all'] + self._curr_model['perturbation_couplings']
1954 else:
1955 pert_couplings_allowed = []
1956 if self._curr_model.get('name').startswith('sm'):
1957 pert_couplings_allowed = pert_couplings_allowed + ['QCD']
1958
1959
1960 particles = list(set(self._particle_names + self._multiparticles.keys()))
1961 n_part_entered = len([1 for a in args if a in particles])
1962
1963
1964 if n_part_entered == 2 and args[-1] != '>':
1965 return self.list_completion(text, '>')
1966
1967
1968 syntax = []
1969 couplings = []
1970 if len(args) > 0 and args[-1] != '>' and n_part_entered > 0:
1971 syntax.append('>')
1972 if '>' in args and args.index('>') < len(args) - 1:
1973 couplings.extend(sum([[c+"<=", c+"==", c+">",c+'^2<=',c+'^2==',c+'^2>' ] for c in \
1974 self._couplings+['WEIGHTED']],[]))
1975 syntax.extend(['@','$','/','>',','])
1976 if '[' not in line and ',' not in line and len(pert_couplings_allowed)>0:
1977 syntax.append('[')
1978
1979
1980
1981 if '[' in line:
1982 syntax = []
1983 particles = []
1984
1985 couplings.append('@')
1986
1987 if not categories:
1988
1989
1990
1991
1992
1993 return self.list_completion(text, particles+syntax+couplings)
1994 else:
1995
1996 poss_particles = self.list_completion(text, particles)
1997 poss_syntax = self.list_completion(text, syntax)
1998 poss_couplings = self.list_completion(text, couplings)
1999 possibilities = {}
2000 if poss_particles != []: possibilities['Particles']=poss_particles
2001 if poss_syntax != []: possibilities['Syntax']=poss_syntax
2002 if poss_couplings != []: possibilities['Coupling orders']=poss_couplings
2003 if len(possibilities.keys())==1:
2004 return self.list_completion(text, possibilities.values()[0])
2005 else:
2006 return self.deal_multiple_categories(possibilities, formatting)
2007
2009 "Complete the generate command"
2010
2011
2012
2013 args = self.split_arg(line[0:begidx])
2014
2015 valid_sqso_operators=['==','<=','>']
2016
2017 if any(line.endswith('^2 %s '%op) for op in valid_sqso_operators):
2018 return
2019 if args[-1].endswith('^2'):
2020 return self.list_completion(text,valid_sqso_operators)
2021 match_op = [o for o in valid_sqso_operators if o.startswith(args[-1])]
2022 if len(args)>2 and args[-2].endswith('^2') and len(match_op)>0:
2023 if args[-1] in valid_sqso_operators:
2024 return self.list_completion(text,' ')
2025 if len(match_op)==1:
2026 return self.list_completion(text,[match_op[0][len(args[-1]):]])
2027 else:
2028 return self.list_completion(text,match_op)
2029 if len(args) > 2 and args[-1] == '@' or ( args[-1].endswith('=') and \
2030 (not '[' in line or ('[' in line and ']' in line))):
2031 return
2032
2033 try:
2034 return self.model_completion(text, ' '.join(args[1:]),line, formatting)
2035 except Exception as error:
2036 print error
2037
2038
2039
2040
2041
2042
2043
2044
2045
2047 "Complete the compute_widths command"
2048
2049 args = self.split_arg(line[0:begidx])
2050
2051 if args[-1] in ['--path=', '--output=']:
2052 completion = {'path': self.path_completion(text)}
2053 elif line[begidx-1] == os.path.sep:
2054 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)])
2055 if current_dir.startswith('--path='):
2056 current_dir = current_dir[7:]
2057 if current_dir.startswith('--output='):
2058 current_dir = current_dir[9:]
2059 completion = {'path': self.path_completion(text, current_dir)}
2060 else:
2061 completion = {}
2062 completion['options'] = self.list_completion(text,
2063 ['--path=', '--output=', '--min_br=0.\$',
2064 '--precision_channel=0.\$', '--body_decay=', '--nlo'])
2065 completion['particles'] = self.model_completion(text, '', line)
2066
2067 return self.deal_multiple_categories(completion,formatting)
2068
2069 complete_decay_diagram = complete_compute_widths
2070
2071 - def complete_add(self, text, line, begidx, endidx, formatting):
2072 "Complete the add command"
2073
2074 args = self.split_arg(line[0:begidx])
2075
2076
2077 if len(args) == 1:
2078 return self.list_completion(text, self._add_opts)
2079
2080 if args[1] == 'process':
2081 return self.complete_generate(text, " ".join(args[1:]), begidx, endidx)
2082
2083 elif args[1] == 'model':
2084 completion_categories = self.complete_import(text, line, begidx, endidx,
2085 allow_restrict=False, formatting=False)
2086 completion_categories['options'] = self.list_completion(text,['--modelname=','--recreate'])
2087 return self.deal_multiple_categories(completion_categories, formatting)
2088
2090 "Complete the customize_model command"
2091
2092 args = self.split_arg(line[0:begidx])
2093
2094
2095 if len(args) == 1:
2096 return self.list_completion(text, ['--save='])
2097
2098
2099 - def complete_check(self, text, line, begidx, endidx, formatting=True):
2100 "Complete the check command"
2101
2102 out = {}
2103 args = self.split_arg(line[0:begidx])
2104
2105
2106 if len(args) == 1:
2107 return self.list_completion(text, self._check_opts)
2108
2109
2110 cms_check_mode = len(args) >= 2 and args[1]=='cms'
2111
2112 cms_options = ['--name=','--tweak=','--seed=','--offshellness=',
2113 '--lambdaCMS=','--show_plot=','--report=','--lambda_plot_range=','--recompute_width=',
2114 '--CTModeRun=','--helicity=','--reduction=','--cms=','--diff_lambda_power=',
2115 '--loop_filter=','--resonances=']
2116
2117 options = ['--energy=']
2118 if cms_options:
2119 options.extend(cms_options)
2120
2121
2122 if args[-1].endswith(os.path.sep):
2123 return self.path_completion(text, pjoin(*[a for a in args \
2124 if a.endswith(os.path.sep)]))
2125
2126 model_comp = self.model_completion(text, ' '.join(args[2:]),line,
2127 categories = True, allowed_loop_mode=['virt'])
2128
2129 model_comp_and_path = self.deal_multiple_categories(\
2130 {'Process completion': self.model_completion(text, ' '.join(args[2:]),
2131 line, categories = False, allowed_loop_mode=['virt']),
2132 'Param_card.dat path completion:':self.path_completion(text),
2133 'options': self.list_completion(text,options)}, formatting)
2134
2135
2136 if cms_check_mode:
2137
2138 if line[-1]!=' ' and line[-2]!='\\' and not '--' in line[begidx:endidx] \
2139 and args[-1].startswith('--') and '=' in args[-1]:
2140 examples = {
2141 '--tweak=':
2142 ['default','alltweaks',"['default','allwidths->1.1*all_withds&seed333(Increased_widths_and_seed_333)','logp->logm&logm->logp(inverted_logs)']"],
2143 '--lambdaCMS=':
2144 ['(1.0e-2,5)',"[float('1.0e-%d'%exp)\\ for\\ exp\\ in\\ range(8)]","[1.0,0.5,0.001]"],
2145 '--lambda_plot_range=':
2146 [' [1e-05,1e-02]','[0.01,1.0]'],
2147 '--reduction=':
2148 ['1','1|2|3|4','1|2','3'],
2149 '--cms=':
2150 ['QED&QCD,aewm1->10.0/lambdaCMS&as->0.1*lambdaCMS',
2151 'NP&QED&QCD,aewm1->10.0/lambdaCMS&as->0.1*lambdaCMS&newExpansionParameter->newExpansionParameter*lambdaCMS'],
2152 '--loop_filter=':
2153 ['None','n>3','n<4 and 6 in loop_pdgs and 3<=id<=7'],
2154 '--resonances=':
2155 ['1','all','(24,(3,4))','[(24,(3,4)),(24,(4,5))]'],
2156 '--analyze=':
2157 ['my_default_run.pkl',
2158 'default_run.pkl,increased_widths.pkl(Increased_widths),logs_modified.pkl(Inverted_logs),seed_668.pkl(Different_seed)']
2159 }
2160 for name, example in examples.items():
2161 if args[-1].startswith(name):
2162 return self.deal_multiple_categories(
2163 {"Examples of completion for option '%s'"%args[-1].split('=')[0]:
2164
2165 ['%s'%ex for i, ex in enumerate(example)]},formatting,
2166 forceCategory=True)
2167 if args[-1]=='--recompute_width=':
2168 return self.list_completion(text,
2169 ['never','first_time','always','auto'])
2170 elif args[-1]=='--show_plot=':
2171 return self.list_completion(text,['True','False'])
2172 elif args[-1]=='--report=':
2173 return self.list_completion(text,['concise','full'])
2174 elif args[-1]=='--CTModeRun=':
2175 return self.list_completion(text,['-1','1','2','3','4'])
2176 else:
2177 return text
2178 if len(args)==2 or len(args)==3 and args[-1]=='-reuse':
2179 return self.deal_multiple_categories(
2180 {'Process completion': self.model_completion(text, ' '.join(args[2:]),
2181 line, categories = False, allowed_loop_mode=['virt']),
2182 'Param_card.dat path completion:': self.path_completion(text),
2183 'reanalyze result on disk / save output:':self.list_completion(
2184 text,['-reuse','--analyze='])},
2185 formatting)
2186 elif not any(arg.startswith('--') for arg in args):
2187 if '>' in args:
2188 return self.deal_multiple_categories({'Process completion':
2189 self.model_completion(text, ' '.join(args[2:]),
2190 line, categories = False, allowed_loop_mode=['virt']),
2191 'options': self.list_completion(text,options)},
2192 formatting)
2193 else:
2194 return self.deal_multiple_categories({'Process completion':
2195 self.model_completion(text, ' '.join(args[2:]),
2196 line, categories = False, allowed_loop_mode=['virt'])},
2197 formatting)
2198 else:
2199 return self.list_completion(text,options)
2200
2201 if len(args) == 2:
2202 return model_comp_and_path
2203 elif len(args) == 3:
2204 try:
2205 int(args[2])
2206 except ValueError:
2207 return model_comp
2208 else:
2209 return model_comp_and_path
2210 elif len(args) > 3:
2211 return model_comp
2212
2213
2220
2222 """Complete particle information"""
2223 return self.model_completion(text, line[6:],line)
2224
2238
2240 "Complete the draw command"
2241
2242 args = self.split_arg(line[0:begidx])
2243
2244
2245 if args[-1].endswith(os.path.sep):
2246 return self.path_completion(text,
2247 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2248 only_dirs = True)
2249
2250 if len(args) == 1:
2251 return self.path_completion(text, '.', only_dirs = True)
2252
2253
2254
2255 if len(args) >= 2:
2256 opt = ['horizontal', 'external=', 'max_size=', 'add_gap=',
2257 'non_propagating', '--']
2258 return self.list_completion(text, opt)
2259
2261 """ complete the launch command"""
2262 args = self.split_arg(line[0:begidx])
2263
2264
2265 if args[-1].endswith(os.path.sep):
2266 return self.path_completion(text,
2267 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2268 only_dirs = True)
2269
2270 if len(args) == 1:
2271 out = {'Path from ./': self.path_completion(text, '.', only_dirs = True)}
2272 if MG5DIR != os.path.realpath('.'):
2273 out['Path from %s' % MG5DIR] = self.path_completion(text,
2274 MG5DIR, only_dirs = True, relative=False)
2275 if MG4DIR and MG4DIR != os.path.realpath('.') and MG4DIR != MG5DIR:
2276 out['Path from %s' % MG4DIR] = self.path_completion(text,
2277 MG4DIR, only_dirs = True, relative=False)
2278
2279
2280
2281 if len(args) >= 2:
2282 out={}
2283
2284 if line[0:begidx].endswith('--laststep='):
2285 opt = ['parton', 'pythia', 'pgs','delphes','auto']
2286 out['Options'] = self.list_completion(text, opt, line)
2287 else:
2288 opt = ['--cluster', '--multicore', '-i', '--name=', '-f','-m', '-n',
2289 '-p','--parton','--interactive', '--laststep=parton', '--laststep=pythia',
2290 '--laststep=pgs', '--laststep=delphes','--laststep=auto']
2291 out['Options'] = self.list_completion(text, opt, line)
2292
2293
2294 return self.deal_multiple_categories(out,formatting)
2295
2314
2333
2334 @cmd.debug()
2336 """ complete the open command """
2337
2338 args = self.split_arg(line[0:begidx])
2339
2340
2341 if os.path.sep in args[-1] + text:
2342 return self.path_completion(text,
2343 pjoin(*[a for a in args if \
2344 a.endswith(os.path.sep)]))
2345
2346 possibility = []
2347 if self._done_export:
2348 path = self._done_export[0]
2349 possibility = ['index.html']
2350 if os.path.isfile(pjoin(path,'README')):
2351 possibility.append('README')
2352 if os.path.isdir(pjoin(path,'Cards')):
2353 possibility += [f for f in os.listdir(pjoin(path,'Cards'))
2354 if f.endswith('.dat')]
2355 if os.path.isdir(pjoin(path,'HTML')):
2356 possibility += [f for f in os.listdir(pjoin(path,'HTML'))
2357 if f.endswith('.html') and 'default' not in f]
2358 else:
2359 possibility.extend(['./','../'])
2360 if os.path.exists('MG5_debug'):
2361 possibility.append('MG5_debug')
2362 if os.path.exists('ME5_debug'):
2363 possibility.append('ME5_debug')
2364
2365 return self.list_completion(text, possibility)
2366
2367 @cmd.debug()
2368 - def complete_output(self, text, line, begidx, endidx,
2369 possible_options = ['f', 'noclean', 'nojpeg'],
2370 possible_options_full = ['-f', '-noclean', '-nojpeg']):
2371 "Complete the output command"
2372
2373 possible_format = self._export_formats
2374
2375 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2376 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2377 'mg5', 'DECAY', 'EventConverter', 'Models',
2378 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha',
2379 'matchbox', 'matchbox_cpp', 'tests']
2380
2381
2382 args = self.split_arg(line[0:begidx])
2383 if len(args) >= 1:
2384
2385 if len(args) > 1 and args[1] == 'pythia8':
2386 possible_options_full = list(possible_options_full) + ['--version=8.1','--version=8.2']
2387
2388 if len(args) > 1 and args[1] == 'aloha':
2389 try:
2390 return self.aloha_complete_output(text, line, begidx, endidx)
2391 except Exception, error:
2392 print error
2393
2394 if args[-1].endswith(os.path.sep):
2395 return [name for name in self.path_completion(text,
2396 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2397 only_dirs = True) if name not in forbidden_names]
2398
2399 if args[-1][0] == '-' or len(args) > 1 and args[-2] == '-':
2400 return self.list_completion(text, possible_options)
2401
2402 if len(args) > 2:
2403 return self.list_completion(text, possible_options_full)
2404
2405 if len(args) == 1:
2406 format = possible_format + ['.' + os.path.sep, '..' + os.path.sep, 'auto']
2407 return self.list_completion(text, format)
2408
2409
2410 content = [name for name in self.path_completion(text, '.', only_dirs = True) \
2411 if name not in forbidden_names]
2412 content += ['auto']
2413 content += possible_options_full
2414 return self.list_completion(text, content)
2415
2417 "Complete the output aloha command"
2418 args = self.split_arg(line[0:begidx])
2419 completion_categories = {}
2420
2421 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2422 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2423 'mg5', 'DECAY', 'EventConverter', 'Models',
2424 'ExRootAnalysis', 'Transfer_Fct', 'aloha',
2425 'apidoc','vendor']
2426
2427
2428
2429 options = ['--format=Fortran', '--format=Python','--format=gpu','--format=CPP','--output=']
2430 options = self.list_completion(text, options)
2431 if options:
2432 completion_categories['options'] = options
2433
2434 if args[-1] == '--output=' or args[-1].endswith(os.path.sep):
2435
2436 completion_categories['path'] = [name for name in self.path_completion(text,
2437 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2438 only_dirs = True) if name not in forbidden_names]
2439
2440 else:
2441 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
2442 wf_opt = []
2443 amp_opt = []
2444 opt_conjg = []
2445 for lor in ufomodel.all_lorentz:
2446 amp_opt.append('%s_0' % lor.name)
2447 for i in range(len(lor.spins)):
2448 wf_opt.append('%s_%i' % (lor.name,i+1))
2449 if i % 2 == 0 and lor.spins[i] == 2:
2450 opt_conjg.append('%sC%i_%i' % (lor.name,i //2 +1,i+1))
2451 completion_categories['amplitude routines'] = self.list_completion(text, amp_opt)
2452 completion_categories['Wavefunctions routines'] = self.list_completion(text, wf_opt)
2453 completion_categories['conjugate_routines'] = self.list_completion(text, opt_conjg)
2454
2455 return self.deal_multiple_categories(completion_categories,formatting)
2456
2458 "Complete the set command"
2459
2460 args = self.split_arg(line[0:begidx])
2461
2462
2463 if len(args) == 1:
2464 opts = list(set(self.options.keys() + self._set_options))
2465 return self.list_completion(text, opts)
2466
2467 if len(args) == 2:
2468 if args[1] in ['group_subprocesses', 'complex_mass_scheme',\
2469 'loop_optimized_output', 'loop_color_flows',\
2470 'low_mem_multicore_nlo_generation']:
2471 return self.list_completion(text, ['False', 'True', 'default'])
2472 elif args[1] in ['ignore_six_quark_processes']:
2473 return self.list_completion(text, self._multiparticles.keys())
2474 elif args[1].lower() == 'ewscheme':
2475 return self.list_completion(text, ["external"])
2476 elif args[1] == 'gauge':
2477 return self.list_completion(text, ['unitary', 'Feynman','default'])
2478 elif args[1] == 'OLP':
2479 return self.list_completion(text, MadGraphCmd._OLP_supported)
2480 elif args[1] == 'output_dependencies':
2481 return self.list_completion(text,
2482 MadGraphCmd._output_dependencies_supported)
2483 elif args[1] == 'stdout_level':
2484 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR',
2485 'CRITICAL','default'])
2486 elif args[1] == 'fortran_compiler':
2487 return self.list_completion(text, ['f77','g77','gfortran','default'])
2488 elif args[1] == 'cpp_compiler':
2489 return self.list_completion(text, ['g++', 'c++', 'clang', 'default'])
2490 elif args[1] == 'nb_core':
2491 return self.list_completion(text, [str(i) for i in range(100)] + ['default'] )
2492 elif args[1] == 'run_mode':
2493 return self.list_completion(text, [str(i) for i in range(3)] + ['default'])
2494 elif args[1] == 'cluster_type':
2495 return self.list_completion(text, cluster.from_name.keys() + ['default'])
2496 elif args[1] == 'cluster_queue':
2497 return []
2498 elif args[1] == 'automatic_html_opening':
2499 return self.list_completion(text, ['False', 'True', 'default'])
2500 else:
2501
2502 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)]
2503 return self.list_completion(text, second_set + ['default'])
2504 elif len(args) >2 and args[-1].endswith(os.path.sep):
2505 return self.path_completion(text,
2506 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2507 only_dirs = True)
2508
2509 - def complete_import(self, text, line, begidx, endidx, allow_restrict=True,
2510 formatting=True):
2511 "Complete the import command"
2512
2513 args=self.split_arg(line[0:begidx])
2514
2515
2516 if len(args) == 1:
2517 opt = self.list_completion(text, self._import_formats)
2518 if opt:
2519 return opt
2520 mode = 'all'
2521 elif args[1] in self._import_formats:
2522 mode = args[1]
2523 else:
2524 args.insert(1, 'all')
2525 mode = 'all'
2526
2527
2528 completion_categories = {}
2529
2530 if mode in ['model', 'all'] and '-' in text:
2531
2532 path = '-'.join([part for part in text.split('-')[:-1]])
2533
2534
2535 all_name = self.find_restrict_card(path, no_restrict=False)
2536 all_name += self.find_restrict_card(path, no_restrict=False,
2537 base_dir=pjoin(MG5DIR,'models'))
2538 if os.environ['PYTHONPATH']:
2539 for modeldir in os.environ['PYTHONPATH'].split(':'):
2540 if not modeldir:
2541 continue
2542 all_name += self.find_restrict_card(path, no_restrict=False,
2543 base_dir=modeldir)
2544
2545 all_name = [name+' ' for name in all_name if name.startswith(text)
2546 and name.strip() != text]
2547
2548
2549 if all_name:
2550 completion_categories['Restricted model'] = all_name
2551
2552
2553 if os.path.sep in args[-1]:
2554 if mode.startswith('model') or mode == 'all':
2555
2556 try:
2557 cur_path = pjoin(*[a for a in args \
2558 if a.endswith(os.path.sep)])
2559 except Exception:
2560 pass
2561 else:
2562 all_dir = self.path_completion(text, cur_path, only_dirs = True)
2563 if mode in ['model_v4','all']:
2564 completion_categories['Path Completion'] = all_dir
2565
2566 new = []
2567 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2568 for name in all_dir]
2569 if data:
2570 completion_categories['Path Completion'] = all_dir + new
2571 else:
2572 try:
2573 cur_path = pjoin(*[a for a in args \
2574 if a.endswith(os.path.sep)])
2575 except Exception:
2576 pass
2577 else:
2578 all_path = self.path_completion(text, cur_path)
2579 if mode == 'all':
2580 new = []
2581 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2582 for name in all_path]
2583 if data:
2584 completion_categories['Path Completion'] = data[0]
2585 else:
2586 completion_categories['Path Completion'] = all_path
2587
2588
2589 if (len(args) == 2):
2590 is_model = True
2591 if mode == 'model':
2592 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py'))
2593 mod_name = lambda name: name
2594 elif mode == 'model_v4':
2595 file_cond = lambda p : (os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat'))
2596 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat')))
2597 mod_name = lambda name :(name[-3:] != '_v4' and name or name[:-3])
2598 elif mode == 'all':
2599 mod_name = lambda name: name
2600 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py')) \
2601 or os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat')) \
2602 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat'))
2603 else:
2604 cur_path = pjoin(*[a for a in args \
2605 if a.endswith(os.path.sep)])
2606 all_path = self.path_completion(text, cur_path)
2607 completion_categories['model name'] = all_path
2608 is_model = False
2609
2610 if is_model:
2611 model_list = [mod_name(name) for name in \
2612 self.path_completion(text,
2613 pjoin(MG5DIR,'models'),
2614 only_dirs = True) \
2615 if file_cond(name)]
2616 if mode == 'model' and 'PYTHONPATH' in os.environ:
2617 for modeldir in os.environ['PYTHONPATH'].split(':'):
2618 if not modeldir:
2619 continue
2620 model_list += [name for name in self.path_completion(text,
2621 modeldir, only_dirs=True)
2622 if os.path.exists(pjoin(modeldir,name, 'particles.py'))]
2623
2624
2625
2626 if mode == 'model_v4':
2627 completion_categories['model name'] = model_list
2628 elif allow_restrict:
2629
2630 all_name = []
2631 for model_name in model_list:
2632 all_name += self.find_restrict_card(model_name,
2633 base_dir=pjoin(MG5DIR,'models'))
2634 else:
2635 all_name = model_list
2636
2637 if mode == 'all':
2638 cur_path = pjoin(*[a for a in args \
2639 if a.endswith(os.path.sep)])
2640 all_path = self.path_completion(text, cur_path)
2641 completion_categories['model name'] = all_path + all_name
2642 elif mode == 'model':
2643 completion_categories['model name'] = all_name
2644
2645
2646 if mode == 'all' and len(args)>1:
2647 mode = self.find_import_type(args[2])
2648
2649 if len(args) >= 3 and mode.startswith('model') and not '-modelname' in line:
2650 if not text and not completion_categories:
2651 return ['--modelname']
2652 elif not (os.path.sep in args[-1] and line[-1] != ' '):
2653 completion_categories['options'] = self.list_completion(text, ['--modelname','-modelname','--noprefix'])
2654 if len(args) >= 3 and mode.startswith('banner') and not '--no_launch' in line:
2655 completion_categories['options'] = self.list_completion(text, ['--no_launch'])
2656
2657 return self.deal_multiple_categories(completion_categories,formatting)
2658
2660 """find the restriction file associate to a given model"""
2661
2662
2663 if no_restrict:
2664 output = [model_name]
2665 else:
2666 output = []
2667
2668
2669 if not os.path.exists(pjoin(base_dir, model_name, 'couplings.py')):
2670
2671 return output
2672
2673 if model_name.endswith(os.path.sep):
2674 model_name = model_name[:-1]
2675
2676
2677 if os.path.exists(pjoin(base_dir, model_name, 'restrict_default.dat')):
2678 output.append('%s-full' % model_name)
2679
2680
2681 for name in os.listdir(pjoin(base_dir, model_name)):
2682 if name.startswith('restrict_') and not name.endswith('default.dat') \
2683 and name.endswith('.dat'):
2684 tag = name[9:-4]
2685 while model_name.endswith(os.path.sep):
2686 model_name = model_name[:-1]
2687 output.append('%s-%s' % (model_name, tag))
2688
2689
2690 return output
2691
2693 "Complete the import command"
2694
2695 args = self.split_arg(line[0:begidx])
2696
2697 if len(args) == 1:
2698 return self.list_completion(text, self._install_opts)
2699 elif len(args) and args[0] == 'update':
2700 return self.list_completion(text, ['-f','--timeout='])
2701 elif len(args)>=2 and args[1] in self._advanced_install_opts:
2702 options = ['--keep_source','--logging=']
2703 if args[1]=='pythia8':
2704 options.append('--pythia8_tarball=')
2705 elif args[1]=='mg5amc_py8_interface':
2706 options.append('--mg5amc_py8_interface_tarball=')
2707 elif args[1] in ['MadAnalysis5','MadAnalysis']:
2708
2709 options.append('--no_root_in_MA5')
2710 options.append('--update')
2711 options.append('--madanalysis5_tarball=')
2712 for prefix in ['--with', '--veto']:
2713 for prog in ['fastjet', 'delphes', 'delphesMA5tune']:
2714 options.append('%s_%s' % (prefix, prog))
2715
2716 for opt in options[:]:
2717 if any(a.startswith(opt) for a in args):
2718 options.remove(opt)
2719 return self.list_completion(text, options)
2720 else:
2721 return self.list_completion(text, [])
2722
2723
2724
2725
2726 -class MadGraphCmd(HelpToCmd, CheckValidForCmd, CompleteForCmd, CmdExtended):
2727 """The command line processor of MadGraph"""
2728
2729 writing_dir = '.'
2730
2731
2732 _display_opts = ['particles', 'interactions', 'processes', 'diagrams',
2733 'diagrams_text', 'multiparticles', 'couplings', 'lorentz',
2734 'checks', 'parameters', 'options', 'coupling_order','variable']
2735 _add_opts = ['process', 'model']
2736 _save_opts = ['model', 'processes', 'options']
2737 _tutorial_opts = ['aMCatNLO', 'stop', 'MadLoop', 'MadGraph5']
2738 _switch_opts = ['mg5','aMC@NLO','ML5']
2739 _check_opts = ['full', 'timing', 'stability', 'profile', 'permutation',
2740 'gauge','lorentz', 'brs', 'cms']
2741 _import_formats = ['model_v4', 'model', 'proc_v4', 'command', 'banner']
2742 _install_opts = ['Delphes', 'MadAnalysis4', 'ExRootAnalysis',
2743 'update', 'SysCalc', 'Golem95', 'PJFry', 'QCDLoop', 'maddm']
2744
2745
2746 _advanced_install_opts = ['pythia8','zlib','boost','lhapdf6','lhapdf5','collier',
2747 'hepmc','mg5amc_py8_interface','ninja','oneloop','MadAnalysis5','MadAnalysis']
2748
2749 _install_opts.extend(_advanced_install_opts)
2750
2751 _v4_export_formats = ['madevent', 'standalone', 'standalone_msP','standalone_msF',
2752 'matrix', 'standalone_rw', 'madweight']
2753 _export_formats = _v4_export_formats + ['standalone_cpp', 'pythia8', 'aloha',
2754 'matchbox_cpp', 'matchbox']
2755 _set_options = ['group_subprocesses',
2756 'ignore_six_quark_processes',
2757 'stdout_level',
2758 'fortran_compiler',
2759 'cpp_compiler',
2760 'loop_optimized_output',
2761 'complex_mass_scheme',
2762 'gauge',
2763 'EWscheme',
2764 'max_npoint_for_channel']
2765 _valid_nlo_modes = ['all','real','virt','sqrvirt','tree','noborn','LOonly']
2766 _valid_sqso_types = ['==','<=','=','>']
2767 _valid_amp_so_types = ['=','<=', '==', '>']
2768 _OLP_supported = ['MadLoop', 'GoSam']
2769 _output_dependencies_supported = ['external', 'internal','environment_paths']
2770
2771
2772
2773 options_configuration = {'pythia8_path': './HEPTools/pythia8',
2774 'hwpp_path': './herwigPP',
2775 'thepeg_path': './thepeg',
2776 'hepmc_path': './hepmc',
2777 'madanalysis_path': './MadAnalysis',
2778 'madanalysis5_path':'./HEPTools/madanalysis5/madanalysis5',
2779 'pythia-pgs_path':'./pythia-pgs',
2780 'td_path':'./td',
2781 'delphes_path':'./Delphes',
2782 'exrootanalysis_path':'./ExRootAnalysis',
2783 'syscalc_path': './SysCalc',
2784 'timeout': 60,
2785 'web_browser':None,
2786 'eps_viewer':None,
2787 'text_editor':None,
2788 'fortran_compiler':None,
2789 'f2py_compiler':None,
2790 'cpp_compiler':None,
2791 'auto_update':7,
2792 'cluster_type': 'condor',
2793 'cluster_queue': None,
2794 'cluster_status_update': (600, 30),
2795 'fastjet':'fastjet-config',
2796 'pjfry':'auto',
2797 'golem':'auto',
2798 'samurai':None,
2799 'ninja':'./HEPTools/lib',
2800 'collier':'./HEPTools/lib',
2801 'lhapdf':'lhapdf-config',
2802 'applgrid':'applgrid-config',
2803 'amcfast':'amcfast-config',
2804 'cluster_temp_path':None,
2805 'mg5amc_py8_interface_path': './HEPTools/MG5aMC_PY8_interface',
2806 'cluster_local_path': None,
2807 'OLP': 'MadLoop',
2808 'cluster_nb_retry':1,
2809 'cluster_retry_wait':300,
2810 'cluster_size':100,
2811 'output_dependencies':'external',
2812 'crash_on_error':False
2813 }
2814
2815 options_madgraph= {'group_subprocesses': 'Auto',
2816 'ignore_six_quark_processes': False,
2817 'low_mem_multicore_nlo_generation': False,
2818 'complex_mass_scheme': False,
2819 'gauge':'unitary',
2820 'stdout_level':None,
2821 'loop_optimized_output':True,
2822 'loop_color_flows':False,
2823 'max_npoint_for_channel': 0
2824 }
2825
2826 options_madevent = {'automatic_html_opening':True,
2827 'run_mode':2,
2828 'nb_core': None,
2829 'notification_center': True
2830 }
2831
2832
2833
2834 _curr_model = None
2835 _curr_amps = diagram_generation.AmplitudeList()
2836 _curr_proc_defs = base_objects.ProcessDefinitionList()
2837 _curr_matrix_elements = helas_objects.HelasMultiProcess()
2838 _curr_helas_model = None
2839 _curr_exporter = None
2840 _done_export = False
2841 _curr_decaymodel = None
2842
2843 helporder = ['Main commands', 'Documented commands']
2844
2845
2859
2860
2861 - def __init__(self, mgme_dir = '', *completekey, **stdin):
2862 """ add a tracker of the history """
2863
2864 CmdExtended.__init__(self, *completekey, **stdin)
2865
2866
2867 if mgme_dir:
2868 if os.path.isdir(pjoin(mgme_dir, 'Template')):
2869 self._mgme_dir = mgme_dir
2870 logger.info('Setting MG/ME directory to %s' % mgme_dir)
2871 else:
2872 logger.warning('Warning: Directory %s not valid MG/ME directory' % \
2873 mgme_dir)
2874 self._mgme_dir = MG4DIR
2875
2876
2877 make_opts = pjoin(MG5DIR, 'Template','LO','Source','make_opts')
2878 make_opts_source = pjoin(MG5DIR, 'Template','LO','Source','.make_opts')
2879 if not os.path.exists(make_opts):
2880 shutil.copy(make_opts_source, make_opts)
2881 elif os.path.getmtime(make_opts) < os.path.getmtime(make_opts_source):
2882 shutil.copy(make_opts_source, make_opts)
2883
2884
2885 self._multiparticles = {}
2886 self.options = {}
2887 self._generate_info = ""
2888 self._model_v4_path = None
2889 self._export_dir = None
2890 self._export_format = 'madevent'
2891 self._mgme_dir = MG4DIR
2892 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
2893 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
2894 self._comparisons = None
2895 self._cms_checks = []
2896 self._nlo_modes_for_completion = ['all','virt','real','LOonly']
2897
2898
2899 self.set_configuration()
2900
2920
2937
2938
2939
2941 """Generate an amplitude for a given process and add to
2942 existing amplitudes
2943 or merge two model
2944 """
2945
2946 args = self.split_arg(line)
2947
2948
2949 warning_duplicate = True
2950 if '--no_warning=duplicate' in args:
2951 warning_duplicate = False
2952 args.remove('--no_warning=duplicate')
2953
2954 diagram_filter = False
2955 if '--diagram_filter' in args:
2956 diagram_filter = True
2957 args.remove('--diagram_filter')
2958
2959 standalone_only = False
2960 if '--standalone' in args:
2961 standalone_only = True
2962 args.remove('--standalone')
2963
2964
2965 self.check_add(args)
2966
2967 if args[0] == 'model':
2968 return self.add_model(args[1:])
2969
2970
2971
2972 if args[-1].startswith('--optimize'):
2973 optimize = True
2974 args.pop()
2975 else:
2976 optimize = False
2977
2978 if args[0] == 'process':
2979
2980 line = ' '.join(args[1:])
2981
2982
2983 if not self._generate_info:
2984 self._generate_info = line
2985
2986
2987 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2988
2989
2990 if ',' in line:
2991 if ']' in line or '[' in line:
2992 error_msg=\
2993 """The '[' and ']' syntax cannot be used in cunjunction with decay chains.
2994 This implies that with decay chains:
2995 > Squared coupling order limitations are not available.
2996 > Loop corrections cannot be considered."""
2997 raise MadGraph5Error(error_msg)
2998 else:
2999 nb_proc = len([l for l in self.history if l.startswith(('generate','add process'))])
3000 myprocdef, line = self.extract_decay_chain_process(line, proc_number=nb_proc)
3001
3002
3003
3004 if myprocdef.are_decays_perturbed():
3005 raise MadGraph5Error("Decay processes cannot be perturbed.")
3006
3007
3008
3009 if myprocdef.decays_have_squared_orders() or \
3010 myprocdef['squared_orders']!={}:
3011 raise MadGraph5Error("Decay processes cannot specify "+\
3012 "squared orders constraints.")
3013 if myprocdef.are_negative_orders_present():
3014 raise MadGraph5Error("Decay processes cannot include negative"+\
3015 " coupling orders constraints.")
3016 else:
3017 nb_proc = len([l for l in self.history if l.startswith(('generate','add process'))])
3018 myprocdef = self.extract_process(line, proc_number=nb_proc)
3019
3020
3021
3022
3023 if not myprocdef:
3024 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3025
3026
3027 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
3028 myprocdef.get_ninitial() and not standalone_only:
3029 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
3030
3031 self._curr_proc_defs.append(myprocdef)
3032
3033
3034
3035 if len([1 for val in myprocdef.get('orders').values()+\
3036 myprocdef.get('squared_orders').values() if val<0])>1:
3037 raise MadGraph5Error("Negative coupling order constraints"+\
3038 " can only be given on one type of coupling and either on"+\
3039 " squared orders or amplitude orders, not both.")
3040
3041 cpu_time1 = time.time()
3042
3043
3044 if self.options['group_subprocesses'] == 'Auto':
3045 collect_mirror_procs = True
3046 else:
3047 collect_mirror_procs = self.options['group_subprocesses']
3048 ignore_six_quark_processes = \
3049 self.options['ignore_six_quark_processes'] if \
3050 "ignore_six_quark_processes" in self.options \
3051 else []
3052
3053 myproc = diagram_generation.MultiProcess(myprocdef,
3054 collect_mirror_procs = collect_mirror_procs,
3055 ignore_six_quark_processes = ignore_six_quark_processes,
3056 optimize=optimize, diagram_filter=diagram_filter)
3057
3058
3059 for amp in myproc.get('amplitudes'):
3060 if amp not in self._curr_amps:
3061 self._curr_amps.append(amp)
3062 elif warning_duplicate:
3063 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
3064 amp.nice_string_processes()
3065
3066
3067 self._done_export = False
3068
3069 cpu_time2 = time.time()
3070
3071 nprocs = len(myproc.get('amplitudes'))
3072 ndiags = sum([amp.get_number_of_diagrams() for \
3073 amp in myproc.get('amplitudes')])
3074
3075 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
3076 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
3077 ndiags = sum([amp.get_number_of_diagrams() for \
3078 amp in self._curr_amps])
3079 logger.info("Total: %i processes with %i diagrams" % \
3080 (len(self._curr_amps), ndiags))
3081
3083 """merge two model"""
3084
3085 model_path = args[0]
3086 recreate = ('--recreate' in args)
3087 keep_decay = ('--keep_decay' in args)
3088 output_dir = [a.split('=',1)[1] for a in args if a.startswith('--output')]
3089 if output_dir:
3090 output_dir = output_dir[0]
3091 recreate = True
3092 restrict_name = ''
3093 else:
3094 name = os.path.basename(self._curr_model.get('modelpath'))
3095 restrict_name = self._curr_model.get('restrict_name')
3096 output_dir = pjoin(MG5DIR, 'models', '%s__%s' % (name,
3097 os.path.basename(model_path)))
3098
3099 if os.path.exists(output_dir):
3100 if recreate:
3101 shutil.rmtree(output_dir)
3102 else:
3103 logger.info('Model already created! Loading it from %s' % output_dir)
3104 oldmodel = self._curr_model.get('modelpath')
3105 new_model_name = output_dir
3106 if restrict_name:
3107 new_model_name = '%s-%s' % (output_dir, restrict_name)
3108 try:
3109 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
3110 printcmd=False, precmd=True, postcmd=True)
3111 except Exception, error:
3112 logger.debug('fail to load model %s with error:\n %s' % (output_dir, error))
3113 logger.warning('Fail to load the model. Restore previous model')
3114 self.exec_cmd('import model %s' % oldmodel, errorhandling=False,
3115 printcmd=False, precmd=True, postcmd=True)
3116 raise Exception('Invalid Model! Please retry with the option \'--recreate\'.')
3117 else:
3118 return
3119
3120
3121 import models.usermod as usermod
3122 base_model = copy.deepcopy(usermod.UFOModel(self._curr_model.get('modelpath')))
3123
3124 identify = dict(tuple(a.split('=')) for a in args if '=' in a)
3125 base_model.add_model(path=model_path, identify_particles=identify)
3126 base_model.write(output_dir)
3127
3128 if keep_decay and os.path.exists(pjoin(self._curr_model.get('modelpath'), 'decays.py')):
3129 base_model.mod_file(pjoin(pjoin(self._curr_model.get('modelpath'), 'decays.py')),
3130 pjoin(pjoin(output_dir, 'decays.py')))
3131
3132 new_model_name = output_dir
3133 if restrict_name:
3134 new_model_name = '%s-%s' % (output_dir, restrict_name)
3135
3136 if 'modelname' in self.history.get('full_model_line'):
3137 opts = '--modelname'
3138 else:
3139 opts=''
3140 self.exec_cmd('import model %s %s' % (new_model_name, opts), errorhandling=False,
3141 printcmd=False, precmd=True, postcmd=True)
3142
3143
3144
3182
3183
3185 """Display current internal status"""
3186
3187 args = self.split_arg(line)
3188
3189 self.check_display(args)
3190
3191 if args[0] == 'diagrams':
3192 self.draw(' '.join(args[1:]))
3193
3194 if args[0] == 'particles' and len(args) == 1:
3195 propagating_particle = []
3196 nb_unpropagating = 0
3197 for particle in self._curr_model['particles']:
3198 if particle.get('propagating'):
3199 propagating_particle.append(particle)
3200 else:
3201 nb_unpropagating += 1
3202
3203 print "Current model contains %i particles:" % \
3204 len(propagating_particle)
3205 part_antipart = [part for part in propagating_particle \
3206 if not part['self_antipart']]
3207 part_self = [part for part in propagating_particle \
3208 if part['self_antipart']]
3209 for part in part_antipart:
3210 print part['name'] + '/' + part['antiname'],
3211 print ''
3212 for part in part_self:
3213 print part['name'],
3214 print ''
3215 if nb_unpropagating:
3216 print 'In addition of %s un-physical particle mediating new interactions.' \
3217 % nb_unpropagating
3218
3219 elif args[0] == 'particles':
3220 for arg in args[1:]:
3221 if arg.isdigit() or (arg[0] == '-' and arg[1:].isdigit()):
3222 particle = self._curr_model.get_particle(abs(int(arg)))
3223 else:
3224 particle = self._curr_model['particles'].find_name(arg)
3225 if not particle:
3226 raise self.InvalidCmd, 'no particle %s in current model' % arg
3227
3228 print "Particle %s has the following properties:" % particle.get_name()
3229 print str(particle)
3230
3231 elif args[0] == 'interactions' and len(args) == 1:
3232 text = "Current model contains %i interactions\n" % \
3233 len(self._curr_model['interactions'])
3234 for i, inter in enumerate(self._curr_model['interactions']):
3235 text += str(i+1) + ':'
3236 for part in inter['particles']:
3237 if part['is_part']:
3238 text += part['name']
3239 else:
3240 text += part['antiname']
3241 text += " "
3242 text += " ".join(order + '=' + str(inter['orders'][order]) \
3243 for order in inter['orders'])
3244 text += '\n'
3245 pydoc.pager(text)
3246
3247 elif args[0] == 'interactions' and len(args)==2 and args[1].isdigit():
3248 for arg in args[1:]:
3249 if int(arg) > len(self._curr_model['interactions']):
3250 raise self.InvalidCmd, 'no interaction %s in current model' % arg
3251 if int(arg) == 0:
3252 print 'Special interactions which identify two particles'
3253 else:
3254 print "Interactions %s has the following property:" % arg
3255 print self._curr_model['interactions'][int(arg)-1]
3256
3257 elif args[0] == 'interactions':
3258 request_part = args[1:]
3259 text = ''
3260 for i, inter in enumerate(self._curr_model['interactions']):
3261 present_part = [part['is_part'] and part['name'] or part['antiname']
3262 for part in inter['particles']
3263 if (part['is_part'] and part['name'] in request_part) or
3264 (not part['is_part'] and part['antiname'] in request_part)]
3265 if len(present_part) < len(request_part):
3266 continue
3267
3268 if set(present_part) != set(request_part):
3269 continue
3270
3271 if len(request_part) > len(set(request_part)):
3272 for p in request_part:
3273 if request_part.count(p) > present_part.count(p):
3274 continue
3275
3276 name = str(i+1) + ' : '
3277 for part in inter['particles']:
3278 if part['is_part']:
3279 name += part['name']
3280 else:
3281 name += part['antiname']
3282 name += " "
3283 text += "\nInteractions %s has the following property:\n" % name
3284 text += str(self._curr_model['interactions'][i])
3285
3286 text += '\n'
3287 print name
3288 if text =='':
3289 text += 'No matching for any interactions'
3290 pydoc.pager(text)
3291
3292
3293 elif args[0] == 'parameters' and len(args) == 1:
3294 text = "Current model contains %i parameters\n" % \
3295 sum([len(part) for part in
3296 self._curr_model['parameters'].values()])
3297 keys = self._curr_model['parameters'].keys()
3298 def key_sort(x, y):
3299 if ('external',) == x:
3300 return -1
3301 elif ('external',) == y:
3302 return +1
3303 elif len(x) < len(y):
3304 return -1
3305 else:
3306 return 1
3307 keys.sort(key_sort)
3308 for key in keys:
3309 item = self._curr_model['parameters'][key]
3310 text += '\nparameter type: %s\n' % str(key)
3311 for value in item:
3312 if hasattr(value, 'expr'):
3313 if value.value is not None:
3314 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3315 else:
3316 text+= ' %s = %s\n' % (value.name, value.expr)
3317 else:
3318 if value.value is not None:
3319 text+= ' %s = %s\n' % (value.name, value.value)
3320 else:
3321 text+= ' %s \n' % (value.name)
3322 pydoc.pager(text)
3323
3324 elif args[0] == 'processes':
3325 for amp in self._curr_amps:
3326 print amp.nice_string_processes()
3327
3328 elif args[0] == 'diagrams_text':
3329 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
3330 pydoc.pager(text)
3331
3332 elif args[0] == 'multiparticles':
3333 print 'Multiparticle labels:'
3334 for key in self._multiparticles:
3335 print self.multiparticle_string(key)
3336
3337 elif args[0] == 'coupling_order':
3338 hierarchy = self._curr_model['order_hierarchy'].items()
3339
3340 def order(first, second):
3341 if first[1] < second[1]:
3342 return -1
3343 else:
3344 return 1
3345 hierarchy.sort(order)
3346 for order in hierarchy:
3347 print ' %s : weight = %s' % order
3348
3349 elif args[0] == 'couplings' and len(args) == 1:
3350 if self._model_v4_path:
3351 print 'No couplings information available in V4 model'
3352 return
3353 text = ''
3354 text = "Current model contains %i couplings\n" % \
3355 sum([len(part) for part in
3356 self._curr_model['couplings'].values()])
3357 keys = self._curr_model['couplings'].keys()
3358 def key_sort(x, y):
3359 if ('external',) == x:
3360 return -1
3361 elif ('external',) == y:
3362 return +1
3363 elif len(x) < len(y):
3364 return -1
3365 else:
3366 return 1
3367 keys.sort(key_sort)
3368 for key in keys:
3369 item = self._curr_model['couplings'][key]
3370 text += '\ncouplings type: %s\n' % str(key)
3371 for value in item:
3372 if value.value is not None:
3373 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3374 else:
3375 text+= ' %s = %s\n' % (value.name, value.expr)
3376
3377 pydoc.pager(text)
3378
3379 elif args[0] == 'couplings':
3380 if self._model_v4_path:
3381 print 'No couplings information available in V4 model'
3382 return
3383
3384 try:
3385 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3386 print 'Note that this is the UFO informations.'
3387 print ' "display couplings" present the actual definition'
3388 print 'prints the current states of mode'
3389 print eval('ufomodel.couplings.%s.nice_string()'%args[1])
3390 except Exception:
3391 raise self.InvalidCmd, 'no couplings %s in current model' % args[1]
3392
3393 elif args[0] == 'lorentz':
3394 if self._model_v4_path:
3395 print 'No lorentz information available in V4 model'
3396 return
3397 elif len(args) == 1:
3398 raise self.InvalidCmd,\
3399 'display lorentz require an argument: the name of the lorentz structure.'
3400 return
3401 try:
3402 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3403 print eval('ufomodel.lorentz.%s.nice_string()'%args[1])
3404 except Exception:
3405 raise self.InvalidCmd, 'no lorentz %s in current model' % args[1]
3406
3407 elif args[0] == 'checks':
3408 outstr = ''
3409 if self._comparisons:
3410 comparisons = self._comparisons[0]
3411 if len(args) > 1 and args[1] == 'failed':
3412 comparisons = [c for c in comparisons if not c['passed']]
3413 outstr += "Process check results:"
3414 for comp in comparisons:
3415 outstr += "\n%s:" % comp['process'].nice_string()
3416 outstr += "\n Phase space point: (px py pz E)"
3417 for i, p in enumerate(comp['momenta']):
3418 outstr += "\n%2s %+.9e %+.9e %+.9e %+.9e" % tuple([i] + p)
3419 outstr += "\n Permutation values:"
3420 outstr += "\n " + str(comp['values'])
3421 if comp['passed']:
3422 outstr += "\n Process passed (rel. difference %.9e)" % \
3423 comp['difference']
3424 else:
3425 outstr += "\n Process failed (rel. difference %.9e)" % \
3426 comp['difference']
3427
3428 used_aloha = sorted(self._comparisons[1])
3429 if used_aloha:
3430 outstr += "\nChecked ALOHA routines:"
3431 for aloha in used_aloha:
3432 aloha_str = aloha[0]
3433 if aloha[1]:
3434 aloha_str += 'C' + 'C'.join([str(ia) for ia in aloha[1]])
3435 aloha_str += "_%d" % aloha[2]
3436 outstr += "\n" + aloha_str
3437
3438 outstr += '\n'
3439 for cms_check in self._cms_checks:
3440 outstr += '*'*102+'\n'
3441 outstr += 'Complex Mass Scheme check:\n'
3442 outstr += ' -> check %s\n'%cms_check['line']
3443 outstr += '*'*102+'\n'
3444 tmp_options = copy.copy(cms_check['options'])
3445 tmp_options['show_plot']=False
3446 outstr += process_checks.output_complex_mass_scheme(
3447 cms_check['cms_result'], cms_check['output_path'],
3448 tmp_options, self._curr_model) + '\n'
3449 outstr += '*'*102+'\n\n'
3450 pydoc.pager(outstr)
3451
3452 elif args[0] == 'options':
3453 if len(args) == 1:
3454 to_print = lambda name: True
3455 else:
3456 to_print = lambda name: any(poss in name for poss in args[1:])
3457
3458 outstr = " MadGraph5_aMC@NLO Options \n"
3459 outstr += " ---------------- \n"
3460 keys = self.options_madgraph.keys()
3461 keys.sort()
3462 for key in keys:
3463 if not to_print(key):
3464 continue
3465 default = self.options_madgraph[key]
3466 value = self.options[key]
3467 if value == default:
3468 outstr += " %25s \t:\t%s\n" % (key,value)
3469 else:
3470 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3471 outstr += "\n"
3472 outstr += " MadEvent Options \n"
3473 outstr += " ---------------- \n"
3474 keys = self.options_madevent.keys()
3475 keys.sort()
3476 for key in keys:
3477 if not to_print(key):
3478 continue
3479 default = self.options_madevent[key]
3480 value = self.options[key]
3481 if value == default:
3482 outstr += " %25s \t:\t%s\n" % (key,value)
3483 else:
3484 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3485 outstr += "\n"
3486 outstr += " Configuration Options \n"
3487 outstr += " --------------------- \n"
3488 keys = self.options_configuration.keys()
3489 keys.sort()
3490 for key in keys:
3491 if not to_print(key):
3492 continue
3493 default = self.options_configuration[key]
3494 value = self.options[key]
3495 if value == default:
3496 outstr += " %25s \t:\t%s\n" % (key,value)
3497 else:
3498 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3499
3500 output.write(outstr)
3501 elif args[0] in ["variable"]:
3502 super(MadGraphCmd, self).do_display(line, output)
3503
3504
3505 - def multiparticle_string(self, key):
3506 """Returns a nicely formatted string for the multiparticle"""
3507
3508 if self._multiparticles[key] and \
3509 isinstance(self._multiparticles[key][0], list):
3510 return "%s = %s" % (key, "|".join([" ".join([self._curr_model.\
3511 get('particle_dict')[part_id].get_name() \
3512 for part_id in id_list]) \
3513 for id_list in self._multiparticles[key]]))
3514 else:
3515 return "%s = %s" % (key, " ".join([self._curr_model.\
3516 get('particle_dict')[part_id].get_name() \
3517 for part_id in self._multiparticles[key]]))
3518
3544
3545
3546
3547 - def draw(self, line,selection='all',type=''):
3603
3604
3606 """Check a given process or set of processes"""
3607
3608 def create_lambda_values_list(lower_bound, N):
3609 """ Returns a list of values spanning the range [1.0, lower_bound] with
3610 lower_bound < 1.0 and with each interval [1e-i, 1e-(i+1)] covered
3611 by N values uniformly distributed. For example, lower_bound=1e-2
3612 and N=5 returns:
3613 [1, 0.8, 0.6, 0.4, 0.2, 0.1, 0.08, 0.06, 0.04, 0.02, 0.01]"""
3614
3615 lCMS_values = [1]
3616 exp = 0
3617 n = 0
3618 while lCMS_values[-1]>=lower_bound:
3619 n = (n+1)
3620 lCMS_values.append(float('1.0e-%d'%exp)*((N-n%N)/float(N)))
3621 if lCMS_values[-1]==lCMS_values[-2]:
3622 lCMS_values.pop()
3623 exp = (n+1)//N
3624
3625 lCMS_values = lCMS_values[:-1]
3626 if lCMS_values[-1]!=lower_bound:
3627 lCMS_values.append(lower_bound)
3628
3629 return lCMS_values
3630
3631
3632
3633 args = self.split_arg(line)
3634
3635 param_card = self.check_check(args)
3636
3637 options= {'events':None}
3638 if param_card and 'banner' == madevent_interface.MadEventCmd.detect_card_type(param_card):
3639 logger_check.info("Will use the param_card contained in the banner and the events associated")
3640 import madgraph.various.banner as banner
3641 options['events'] = param_card
3642 mybanner = banner.Banner(param_card)
3643 param_card = mybanner.charge_card('param_card')
3644
3645 aloha_lib.KERNEL.clean()
3646
3647 gauge = str(self.options['gauge'])
3648 options['reuse'] = args[1]=="-reuse"
3649 args = args[:1]+args[2:]
3650
3651
3652 if args[0] in ['stability', 'profile']:
3653 options['npoints'] = int(args[1])
3654 args = args[:1]+args[2:]
3655
3656 MLoptions={}
3657 i=-1
3658 CMS_options = {}
3659 while args[i].startswith('--'):
3660 option = args[i].split('=')
3661 if option[0] =='--energy':
3662 options['energy']=float(option[1])
3663 elif option[0]=='--split_orders':
3664 options['split_orders']=int(option[1])
3665 elif option[0]=='--helicity':
3666 try:
3667 options['helicity']=int(option[1])
3668 except ValueError:
3669 raise self.InvalidCmd("The value of the 'helicity' option"+\
3670 " must be an integer, not %s."%option[1])
3671 elif option[0]=='--reduction':
3672 MLoptions['MLReductionLib']=[int(ir) for ir in option[1].split('|')]
3673 elif option[0]=='--collier_mode':
3674 MLoptions['COLLIERMode']=int(option[1])
3675 elif option[0]=='--collier_cache':
3676 MLoptions['COLLIERGlobalCache']=int(option[1])
3677 elif option[0]=='--collier_req_acc':
3678 if option[1]!='auto':
3679 MLoptions['COLLIERRequiredAccuracy']=float(option[1])
3680 elif option[0]=='--collier_internal_stability_test':
3681 MLoptions['COLLIERUseInternalStabilityTest']=eval(option[1])
3682 elif option[0]=='--CTModeRun':
3683 try:
3684 MLoptions['CTModeRun']=int(option[1])
3685 except ValueError:
3686 raise self.InvalidCmd("The value of the 'CTModeRun' option"+\
3687 " must be an integer, not %s."%option[1])
3688 elif option[0]=='--offshellness':
3689 CMS_options['offshellness'] = float(option[1])
3690 if CMS_options['offshellness']<=-1.0:
3691 raise self.InvalidCmd('Offshellness must be number larger or'+
3692 ' equal to -1.0, not %f'%CMS_options['offshellness'])
3693 elif option[0]=='--analyze':
3694 options['analyze'] = option[1]
3695 elif option[0]=='--show_plot':
3696 options['show_plot'] = 'true' in option[1].lower()
3697 elif option[0]=='--report':
3698 options['report'] = option[1].lower()
3699 elif option[0]=='--seed':
3700 options['seed'] = int(option[1])
3701 elif option[0]=='--name':
3702 if '.' in option[1]:
3703 raise self.InvalidCmd("Do not specify the extension in the"+
3704 " name of the run")
3705 CMS_options['name'] = option[1]
3706 elif option[0]=='--resonances':
3707 if option[1]=='all':
3708 CMS_options['resonances'] = 'all'
3709 else:
3710 try:
3711 resonances=eval(option[1])
3712 except:
3713 raise self.InvalidCmd("Could not evaluate 'resonances'"+
3714 " option '%s'"%option[1])
3715 if isinstance(resonances,int) and resonances>0:
3716 CMS_options['resonances'] = resonances
3717 elif isinstance(resonances,list) and all(len(res)==2 and
3718 isinstance(res[0],int) and all(isinstance(i, int) for i in
3719 res[1]) for res in resonances):
3720 CMS_options['resonances'] = resonances
3721 else:
3722 raise self.InvalidCmd("The option 'resonances' can only be 'all'"+
3723 " or and integer or a list of tuples of the form "+
3724 "(resPDG,(res_mothers_ID)). You gave '%s'"%option[1])
3725 elif option[0]=='--tweak':
3726
3727 value = option[1]
3728
3729 if value=='alltweaks':
3730 value=str(['default','seed667(seed667)','seed668(seed668)',
3731 'allwidths->0.9*allwidths(widths_x_0.9)',
3732 'allwidths->0.99*allwidths(widths_x_0.99)',
3733 'allwidths->1.01*allwidths(widths_x_1.01)',
3734 'allwidths->1.1*allwidths(widths_x_1.1)',
3735 'logp->logm(logp2logm)','logm->logp(logm2logp)'])
3736 try:
3737 tweaks = eval(value)
3738 if isinstance(tweaks, str):
3739 tweaks = [value]
3740 elif not isinstance(tweaks,list):
3741 tweaks = [value]
3742 except:
3743 tweaks = [value]
3744 if not all(isinstance(t,str) for t in tweaks):
3745 raise self.InvalidCmd("Invalid specificaiton of tweaks: %s"%value)
3746 CMS_options['tweak'] = []
3747 for tweakID, tweakset in enumerate(tweaks):
3748 specs =re.match(r'^(?P<tweakset>.*)\((?P<name>.*)\)$', tweakset)
3749 if specs:
3750 tweakset = specs.group('tweakset')
3751 name = specs.group('name')
3752 else:
3753 if tweakset!='default':
3754 name = 'tweak_%d'%(tweakID+1)
3755 else:
3756 name = ''
3757 new_tweak_set = {'custom':[],'params':{},'name':name}
3758 for tweak in tweakset.split('&'):
3759 if tweak=='default':
3760 continue
3761 if tweak.startswith('seed'):
3762 new_tweak_set['custom'].append(tweak)
3763 continue
3764 try:
3765 param, replacement = tweak.split('->')
3766 except ValueError:
3767 raise self.InvalidCmd("Tweak specification '%s'"%\
3768 tweak+" is incorrect. It should be of"+\
3769 " the form a->_any_function_of_(a,lambdaCMS).")
3770 if param in ['logp','logm','log'] and \
3771 replacement in ['logp','logm','log']:
3772 new_tweak_set['custom'].append(tweak)
3773 continue
3774 try:
3775
3776
3777 orig_param, orig_replacement = param, replacement
3778 replacement = replacement.replace(param,
3779 '__tmpprefix__%s'%param)
3780 param = '__tmpprefix__%s'%param
3781 res = float(eval(replacement.lower(),
3782 {'lambdacms':1.0,param.lower():98.85}))
3783 except:
3784 raise self.InvalidCmd("The substitution expression "+
3785 "'%s' for the tweaked parameter"%orig_replacement+
3786 " '%s' could not be evaluated. It must be an "%orig_param+
3787 "expression of the parameter and 'lambdaCMS'.")
3788 new_tweak_set['params'][param.lower()] = replacement.lower()
3789 CMS_options['tweak'].append(new_tweak_set)
3790
3791 elif option[0]=='--recompute_width':
3792 if option[1].lower() not in ['never','always','first_time','auto']:
3793 raise self.InvalidCmd("The option 'recompute_width' can "+\
3794 "only be 'never','always', 'first_time' or 'auto' (default).")
3795 CMS_options['recompute_width'] = option[1]
3796 elif option[0]=='--loop_filter':
3797
3798
3799
3800 CMS_options['loop_filter'] = '='.join(option[1:])
3801 elif option[0]=='--diff_lambda_power':
3802
3803
3804
3805
3806 try:
3807 CMS_options['diff_lambda_power']=float(option[1])
3808 except ValueError:
3809 raise self.InvalidCmd("the '--diff_lambda_power' option"+\
3810 " must be an integer or float, not '%s'."%option[1])
3811 elif option[0]=='--lambda_plot_range':
3812 try:
3813 plot_range=eval(option[1])
3814 except Exception as e:
3815 raise self.InvalidCmd("The plot range specified %s"%option[1]+\
3816 " is not a valid syntax. Error:\n%s"%str(e))
3817 if not isinstance(plot_range,(list,tuple)) or \
3818 len(plot_range)!=2 or any(not isinstance(p,(float,int))
3819 for p in plot_range):
3820 raise self.InvalidCmd("The plot range specified %s"\
3821 %option[1]+" is invalid")
3822 CMS_options['lambda_plot_range']=list([float(p) for p in plot_range])
3823 elif option[0]=='--lambdaCMS':
3824 try:
3825 lambda_values = eval(option[1])
3826 except SyntaxError:
3827 raise self.InvalidCmd("'%s' is not a correct"%option[1]+
3828 " python expression for lambdaCMS values.")
3829 if isinstance(lambda_values,list):
3830 if lambda_values[0]!=1.0:
3831 raise self.InvalidCmd("The first value of the lambdaCMS values"+
3832 " specified must be 1.0, not %s"%str(lambda_values))
3833 for l in lambda_values:
3834 if not isinstance(l,float):
3835 raise self.InvalidCmd("All lambda CMS values must be"+
3836 " float, not '%s'"%str(l))
3837 elif isinstance(lambda_values,(tuple,float)):
3838
3839
3840
3841
3842 if isinstance(lambda_values, float):
3843
3844 lower_bound = lambda_values
3845 N = 10
3846 else:
3847 if isinstance(lambda_values[0],float) and \
3848 isinstance(lambda_values[1],int):
3849 lower_bound = lambda_values[0]
3850 N = lambda_values[1]
3851 else:
3852 raise self.InvalidCmd("'%s' must be a "%option[1]+
3853 "tuple with types (float, int).")
3854 lambda_values = create_lambda_values_list(lower_bound,N)
3855 else:
3856 raise self.InvalidCmd("'%s' must be an expression"%option[1]+
3857 " for either a float, tuple or list.")
3858 lower_bound = lambda_values[-1]
3859
3860
3861
3862
3863
3864
3865 CMS_options['lambdaCMS'] = lambda_values
3866 elif option[0]=='--cms':
3867 try:
3868 CMS_expansion_orders, CMS_expansion_parameters = \
3869 option[1].split(',')
3870 except ValueError:
3871 raise self.InvalidCmd("CMS expansion specification '%s'"%\
3872 args[i]+" is incorrect.")
3873 CMS_options['expansion_orders'] = [expansion_order for
3874 expansion_order in CMS_expansion_orders.split('&')]
3875 CMS_options['expansion_parameters'] = {}
3876 for expansion_parameter in CMS_expansion_parameters.split('&'):
3877 try:
3878 param, replacement = expansion_parameter.split('->')
3879 except ValueError:
3880 raise self.InvalidCmd("CMS expansion specification '%s'"%\
3881 expansion_parameter+" is incorrect. It should be of"+\
3882 " the form a->_any_function_of_(a,lambdaCMS).")
3883 try:
3884
3885
3886 orig_param, orig_replacement = param, replacement
3887 replacement = replacement.replace(param,
3888 '__tmpprefix__%s'%param)
3889 param = '__tmpprefix__%s'%param
3890 res = float(eval(replacement.lower(),
3891 {'lambdacms':1.0,param.lower():98.85}))
3892 except:
3893 raise self.InvalidCmd("The substitution expression "+
3894 "'%s' for CMS expansion parameter"%orig_replacement+
3895 " '%s' could not be evaluated. It must be an "%orig_param+
3896 "expression of the parameter and 'lambdaCMS'.")
3897
3898
3899 CMS_options['expansion_parameters'][param.lower()]=\
3900 replacement.lower()
3901 else:
3902 raise self.InvalidCmd("The option '%s' is not reckognized."%option[0])
3903
3904 i=i-1
3905 args = args[:i+1]
3906
3907 if args[0]=='options':
3908
3909 logger_check.info("Options for the command 'check' are:")
3910 logger_check.info("{:<20} {}".format(' name','default value'))
3911 logger_check.info("-"*40)
3912 for key, value in options.items():
3913 logger_check.info("{:<20} = {}".format('--%s'%key,str(value)))
3914 return
3915
3916 if args[0].lower()=='cmsoptions':
3917
3918 logger_check.info("Special options for the command 'check cms' are:")
3919 logger_check.info("{:<20} {}".format(' name','default value'))
3920 logger_check.info("-"*40)
3921 for key, value in CMS_options.items():
3922 logger_check.info("{:<20} = {}".format('--%s'%key,str(value)))
3923 return
3924
3925
3926 if args[0]!='cms' and options['seed']!=-1:
3927
3928
3929
3930 logger_check.info('Setting random seed to %d.'%options['seed'])
3931 random.seed(options['seed'])
3932
3933 proc_line = " ".join(args[1:])
3934
3935 if not (args[0]=='cms' and options['analyze']!='None'):
3936 myprocdef = self.extract_process(proc_line)
3937
3938
3939 if not myprocdef:
3940 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3941
3942 if myprocdef.get('NLO_mode')=='all':
3943 myprocdef.set('NLO_mode','virt')
3944 else:
3945 myprocdef = None
3946
3947
3948
3949 output_path = os.getcwd()
3950
3951 if args[0] in ['timing','stability', 'profile'] and not \
3952 myprocdef.get('perturbation_couplings'):
3953 raise self.InvalidCmd("Only loop processes can have their "+
3954 " timings or stability checked.")
3955
3956 if args[0]=='gauge' and \
3957 not myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3958 raise self.InvalidCmd(
3959 """Feynman vs unitary gauge comparisons can only be done if there are no loop
3960 propagators affected by this gauge. Typically, either processes at tree level
3961 or including only QCD perturbations can be considered here.""")
3962
3963 if args[0]=='gauge' and len(self._curr_model.get('gauge')) < 2:
3964 raise self.InvalidCmd("The current model does not allow for both "+\
3965 "Feynman and unitary gauge.")
3966
3967
3968 loggers = [logging.getLogger('madgraph.diagram_generation'),
3969 logging.getLogger('madgraph.loop_diagram_generation'),
3970 logging.getLogger('ALOHA'),
3971 logging.getLogger('madgraph.helas_objects'),
3972 logging.getLogger('madgraph.loop_exporter'),
3973 logging.getLogger('madgraph.export_v4'),
3974 logging.getLogger('cmdprint'),
3975 logging.getLogger('madgraph.model'),
3976 logging.getLogger('madgraph.base_objects')]
3977 old_levels = [log.level for log in loggers]
3978 for log in loggers:
3979 log.setLevel(logging.WARNING)
3980
3981
3982 cpu_time1 = time.time()
3983
3984
3985
3986
3987
3988
3989
3990 if myprocdef:
3991 if myprocdef.get('perturbation_couplings')==[]:
3992 aloha.loop_mode = False
3993
3994 comparisons = []
3995 gauge_result = []
3996 gauge_result_no_brs = []
3997 lorentz_result =[]
3998 nb_processes = 0
3999 timings = []
4000 stability = []
4001 profile_time = []
4002 profile_stab = []
4003 cms_results = []
4004
4005 if "_cuttools_dir" in dir(self):
4006 CT_dir = self._cuttools_dir
4007 else:
4008 CT_dir =""
4009 if "MLReductionLib" in MLoptions:
4010 if 1 in MLoptions["MLReductionLib"]:
4011 MLoptions["MLReductionLib"].remove(1)
4012
4013 TIR_dir={}
4014 if "_iregi_dir" in dir(self):
4015 TIR_dir['iregi_dir']=self._iregi_dir
4016 else:
4017 if "MLReductionLib" in MLoptions:
4018 if 3 in MLoptions["MLReductionLib"]:
4019 logger_check.warning('IREGI not available on your system; it will be skipped.')
4020 MLoptions["MLReductionLib"].remove(3)
4021
4022 if 'pjfry' in self.options and isinstance(self.options['pjfry'],str):
4023 TIR_dir['pjfry_dir']=self.options['pjfry']
4024 else:
4025 if "MLReductionLib" in MLoptions:
4026 if 2 in MLoptions["MLReductionLib"]:
4027 logger_check.warning('PJFRY not available on your system; it will be skipped.')
4028 MLoptions["MLReductionLib"].remove(2)
4029
4030 if 'golem' in self.options and isinstance(self.options['golem'],str):
4031 TIR_dir['golem_dir']=self.options['golem']
4032 else:
4033 if "MLReductionLib" in MLoptions:
4034 if 4 in MLoptions["MLReductionLib"]:
4035 logger_check.warning('GOLEM not available on your system; it will be skipped.')
4036 MLoptions["MLReductionLib"].remove(4)
4037
4038 if 'samurai' in self.options and isinstance(self.options['samurai'],str):
4039 TIR_dir['samurai_dir']=self.options['samurai']
4040 else:
4041 if "MLReductionLib" in MLoptions:
4042 if 5 in MLoptions["MLReductionLib"]:
4043 logger_check.warning('Samurai not available on your system; it will be skipped.')
4044 MLoptions["MLReductionLib"].remove(5)
4045
4046 if 'collier' in self.options and isinstance(self.options['collier'],str):
4047 TIR_dir['collier_dir']=self.options['collier']
4048 else:
4049 if "MLReductionLib" in MLoptions:
4050 if 7 in MLoptions["MLReductionLib"]:
4051 logger_check.warning('Collier not available on your system; it will be skipped.')
4052 MLoptions["MLReductionLib"].remove(7)
4053
4054 if 'ninja' in self.options and isinstance(self.options['ninja'],str):
4055 TIR_dir['ninja_dir']=self.options['ninja']
4056 else:
4057 if "MLReductionLib" in MLoptions:
4058 if 6 in MLoptions["MLReductionLib"]:
4059 logger_check.warning('Ninja not available on your system; it will be skipped.')
4060 MLoptions["MLReductionLib"].remove(6)
4061
4062 if args[0] in ['timing']:
4063 timings = process_checks.check_timing(myprocdef,
4064 param_card = param_card,
4065 cuttools=CT_dir,
4066 tir=TIR_dir,
4067 options = options,
4068 cmd = self,
4069 output_path = output_path,
4070 MLOptions = MLoptions
4071 )
4072
4073 if args[0] in ['stability']:
4074 stability=process_checks.check_stability(myprocdef,
4075 param_card = param_card,
4076 cuttools=CT_dir,
4077 tir=TIR_dir,
4078 options = options,
4079 output_path = output_path,
4080 cmd = self,
4081 MLOptions = MLoptions)
4082
4083 if args[0] in ['profile']:
4084
4085
4086 profile_time, profile_stab = process_checks.check_profile(myprocdef,
4087 param_card = param_card,
4088 cuttools=CT_dir,
4089 tir=TIR_dir,
4090 options = options,
4091 MLOptions = MLoptions,
4092 output_path = output_path,
4093 cmd = self)
4094
4095 if args[0] in ['gauge', 'full'] and \
4096 len(self._curr_model.get('gauge')) == 2 and\
4097 myprocdef.get('perturbation_couplings') in [[],['QCD']]:
4098
4099 line = " ".join(args[1:])
4100 myprocdef = self.extract_process(line)
4101 if gauge == 'unitary':
4102 myprocdef_unit = myprocdef
4103 self.do_set('gauge Feynman', log=False)
4104 myprocdef_feyn = self.extract_process(line)
4105 else:
4106 myprocdef_feyn = myprocdef
4107 self.do_set('gauge unitary', log=False)
4108 myprocdef_unit = self.extract_process(line)
4109
4110 nb_part_unit = len(myprocdef_unit.get('model').get('particles'))
4111 nb_part_feyn = len(myprocdef_feyn.get('model').get('particles'))
4112 if nb_part_feyn == nb_part_unit:
4113 logger_check.error('No Goldstone present for this check!!')
4114 gauge_result_no_brs = process_checks.check_unitary_feynman(
4115 myprocdef_unit, myprocdef_feyn,
4116 param_card = param_card,
4117 options=options,
4118 cuttools=CT_dir,
4119 tir=TIR_dir,
4120 reuse = options['reuse'],
4121 output_path = output_path,
4122 cmd = self)
4123
4124
4125 self.do_set('gauge %s' % gauge, log=False)
4126 nb_processes += len(gauge_result_no_brs)
4127
4128 if args[0] in ['permutation', 'full']:
4129 comparisons = process_checks.check_processes(myprocdef,
4130 param_card = param_card,
4131 quick = True,
4132 cuttools=CT_dir,
4133 tir=TIR_dir,
4134 reuse = options['reuse'],
4135 cmd = self,
4136 output_path = output_path,
4137 options=options)
4138 nb_processes += len(comparisons[0])
4139
4140 if args[0] in ['lorentz', 'full']:
4141 myprocdeff = copy.copy(myprocdef)
4142 lorentz_result = process_checks.check_lorentz(myprocdeff,
4143 param_card = param_card,
4144 cuttools=CT_dir,
4145 tir=TIR_dir,
4146 reuse = options['reuse'],
4147 cmd = self,
4148 output_path = output_path,
4149 options=options)
4150 nb_processes += len(lorentz_result)
4151
4152 if args[0] in ['brs', 'full']:
4153 gauge_result = process_checks.check_gauge(myprocdef,
4154 param_card = param_card,
4155 cuttools=CT_dir,
4156 tir=TIR_dir,
4157 reuse = options['reuse'],
4158 cmd = self,
4159 output_path = output_path,
4160 options=options)
4161 nb_processes += len(gauge_result)
4162
4163
4164
4165 if args[0] in ['cms']:
4166
4167 cms_original_setup = self.options['complex_mass_scheme']
4168 process_line = " ".join(args[1:])
4169
4170 for key, value in CMS_options.items():
4171 if key=='tweak':
4172 continue
4173 if key not in options:
4174 options[key] = value
4175 else:
4176 raise MadGraph5Error,"Option '%s' is both in the option"%key+\
4177 " and CMS_option dictionary."
4178
4179 if options['analyze']=='None':
4180 cms_results = []
4181 for tweak in CMS_options['tweak']:
4182 options['tweak']=tweak
4183
4184 guessed_proc = myprocdef.get_process(
4185 [leg.get('ids')[0] for leg in myprocdef.get('legs')
4186 if not leg.get('state')],
4187 [leg.get('ids')[0] for leg in myprocdef.get('legs')
4188 if leg.get('state')])
4189 save_path = process_checks.CMS_save_path('pkl',
4190 {'ordered_processes':[guessed_proc.base_string()],
4191 'perturbation_orders':guessed_proc.get('perturbation_couplings')},
4192 self._curr_model, options, output_path=output_path)
4193 if os.path.isfile(save_path) and options['reuse']:
4194 cms_result = save_load_object.load_from_file(save_path)
4195 logger_check.info("The cms check for tweak %s is recycled from file:\n %s"%
4196 (tweak['name'],save_path))
4197 if cms_result is None:
4198 raise self.InvalidCmd('The complex mass scheme check result'+
4199 " file below could not be read.\n %s"%save_path)
4200 else:
4201 cms_result = process_checks.check_complex_mass_scheme(
4202 process_line,
4203 param_card = param_card,
4204 cuttools=CT_dir,
4205 tir=TIR_dir,
4206 cmd = self,
4207 output_path = output_path,
4208 MLOptions = MLoptions,
4209 options=options)
4210
4211 save_path = process_checks.CMS_save_path('pkl', cms_result,
4212 self._curr_model, options, output_path=output_path)
4213 cms_results.append((cms_result,save_path,tweak['name']))
4214 else:
4215 cms_result = save_load_object.load_from_file(
4216 options['analyze'].split(',')[0])
4217 cms_results.append((cms_result,options['analyze'].split(',')[0],
4218 CMS_options['tweak'][0]['name']))
4219 if cms_result is None:
4220 raise self.InvalidCmd('The complex mass scheme check result'+
4221 " file below could not be read.\n %s"
4222 %options['analyze'].split(',')[0])
4223
4224
4225 self.do_set('complex_mass_scheme %s'%str(cms_original_setup),
4226 log=False)
4227
4228 nb_processes += len(cms_result['ordered_processes'])
4229
4230 cpu_time2 = time.time()
4231 logger_check.info("%i check performed in %s"% (nb_processes,
4232 misc.format_time(int(cpu_time2 - cpu_time1))))
4233
4234 if args[0] in ['cms']:
4235 text = "Note that the complex mass scheme test in principle only\n"
4236 text+= "works for stable particles in final states.\n\ns"
4237 if args[0] not in ['timing','stability', 'profile', 'cms']:
4238 if self.options['complex_mass_scheme']:
4239 text = "Note that Complex mass scheme gives gauge/lorentz invariant\n"
4240 text+= "results only for stable particles in final states.\n\ns"
4241 elif not myprocdef.get('perturbation_couplings'):
4242 text = "Note That all width have been set to zero for those checks\n\n"
4243 else:
4244 text = "\n"
4245 else:
4246 text ="\n"
4247
4248 if timings:
4249 text += 'Timing result for the '+('optimized' if \
4250 self.options['loop_optimized_output'] else 'default')+' output:\n'
4251
4252 text += process_checks.output_timings(myprocdef, timings)
4253 if stability:
4254 text += 'Stability result for the '+('optimized' if \
4255 self.options['loop_optimized_output'] else 'default')+' output:\n'
4256 text += process_checks.output_stability(stability,output_path)
4257
4258 if profile_time and profile_stab:
4259 text += 'Timing result '+('optimized' if \
4260 self.options['loop_optimized_output'] else 'default')+':\n'
4261 text += process_checks.output_profile(myprocdef, profile_stab,
4262 profile_time, output_path, options['reuse']) + '\n'
4263 if lorentz_result:
4264 text += 'Lorentz invariance results:\n'
4265 text += process_checks.output_lorentz_inv(lorentz_result) + '\n'
4266 if gauge_result:
4267 text += 'Gauge results:\n'
4268 text += process_checks.output_gauge(gauge_result) + '\n'
4269 if gauge_result_no_brs:
4270 text += 'Gauge results (switching between Unitary/Feynman):\n'
4271 text += process_checks.output_unitary_feynman(gauge_result_no_brs) + '\n'
4272 if cms_results:
4273 text += 'Complex mass scheme results (varying width in the off-shell regions):\n'
4274 cms_result = cms_results[0][0]
4275 if len(cms_results)>1:
4276 analyze = []
4277 for i, (cms_res, save_path, tweakname) in enumerate(cms_results):
4278 save_load_object.save_to_file(save_path, cms_res)
4279 logger_check.info("Pickle file for tweak '%s' saved to disk at:\n ->%s"%
4280 (tweakname,save_path))
4281 if i==0:
4282 analyze.append(save_path)
4283 else:
4284 analyze.append('%s(%s)'%(save_path,tweakname))
4285 options['analyze']=','.join(analyze)
4286 options['tweak'] = CMS_options['tweak'][0]
4287
4288 self._cms_checks.append({'line':line, 'cms_result':cms_result,
4289 'options':options, 'output_path':output_path})
4290 text += process_checks.output_complex_mass_scheme(cms_result,
4291 output_path, options, self._curr_model,
4292 output='concise_text' if options['report']=='concise' else 'text')+'\n'
4293
4294 if comparisons and len(comparisons[0])>0:
4295 text += 'Process permutation results:\n'
4296 text += process_checks.output_comparisons(comparisons[0]) + '\n'
4297 self._comparisons = comparisons
4298
4299
4300 if len(text.split('\n'))>20 and not '-reuse' in line and text!='':
4301 if 'test_manager' not in sys.argv[0]:
4302 pydoc.pager(text)
4303
4304
4305 for i, log in enumerate(loggers):
4306 log.setLevel(old_levels[i])
4307
4308
4309
4310 if len(text.split('\n'))<=20 or options['reuse']:
4311
4312 logging.getLogger('madgraph.check_cmd').info(text)
4313 else:
4314 logging.getLogger('madgraph.check_cmd').debug(text)
4315
4316
4317 process_checks.clean_added_globals(process_checks.ADDED_GLOBAL)
4318 if not options['reuse']:
4319 process_checks.clean_up(self._mgme_dir)
4320
4321
4343
4345 """Extract a process definition from a string. Returns
4346 a ProcessDefinition."""
4347
4348 orig_line = line
4349
4350 if not len(re.findall('>\D', line)) in [1,2]:
4351 self.do_help('generate')
4352 raise self.InvalidCmd('Wrong use of \">\" special character.')
4353
4354
4355
4356
4357 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
4358 line = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
4359
4360
4361
4362
4363
4364
4365 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
4366 proc_number_re = proc_number_pattern.match(line)
4367 if proc_number_re:
4368 proc_number = int(proc_number_re.group(2))
4369 line = proc_number_re.group(1)+ proc_number_re.group(3)
4370
4371
4372
4373 perturbation_couplings_pattern = \
4374 re.compile("^(?P<proc>.+>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*"+\
4375 "(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
4376 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
4377 perturbation_couplings = ""
4378 LoopOption= 'tree'
4379 HasBorn= True
4380 if perturbation_couplings_re:
4381 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
4382 option=perturbation_couplings_re.group("option")
4383 if option:
4384 if option in self._valid_nlo_modes:
4385 LoopOption=option
4386 if option=='sqrvirt':
4387 LoopOption='virt'
4388 HasBorn=False
4389 elif option=='noborn':
4390 HasBorn=False
4391 else:
4392 raise self.InvalidCmd, "NLO mode %s is not valid. "%option+\
4393 "Valid modes are %s. "%str(self._valid_nlo_modes)
4394 else:
4395 LoopOption='all'
4396
4397 line = perturbation_couplings_re.group("proc")+\
4398 perturbation_couplings_re.group("rest")
4399
4400
4401 order_pattern = re.compile(\
4402 "^(?P<before>.+>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
4403 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*")
4404 order_re = order_pattern.match(line)
4405 squared_orders = {}
4406 orders = {}
4407 constrained_orders = {}
4408
4409
4410
4411
4412 split_orders = []
4413 while order_re:
4414 type = order_re.group('type')
4415 if order_re.group('name').endswith('^2'):
4416 if type not in self._valid_sqso_types:
4417 raise self.InvalidCmd, "Type of squared order "+\
4418 "constraint '%s'"% type+" is not supported."
4419 if type == '=':
4420 name = order_re.group('name')
4421 value = order_re.group('value')
4422 logger.warning("Interpreting '%(n)s=%(v)s' as '%(n)s<=%(v)s'" %\
4423 {'n':name, 'v': value})
4424 type = "<="
4425 squared_orders[order_re.group('name')[:-2]] = \
4426 (int(order_re.group('value')),type)
4427 else:
4428 if type not in self._valid_amp_so_types:
4429 raise self.InvalidCmd, \
4430 "Amplitude order constraints can only be of type %s"%\
4431 (', '.join(self._valid_amp_so_types))+", not '%s'."%type
4432 name = order_re.group('name')
4433 value = int(order_re.group('value'))
4434 if type in ['=', '<=']:
4435 if type == '=' and value != 0:
4436 logger.warning("Interpreting '%(n)s=%(v)s' as '%(n)s<=%(v)s'" %\
4437 {'n':name, 'v': value})
4438 orders[name] = value
4439 elif type == "==":
4440 constrained_orders[name] = (value, type)
4441 if name not in squared_orders:
4442 squared_orders[name] = (2 * value,'==')
4443 if True:
4444 orders[name] = value
4445
4446 elif type == ">":
4447 constrained_orders[name] = (value, type)
4448 if name not in squared_orders:
4449 squared_orders[name] = (2 * value,'>')
4450
4451 line = order_re.group('before')
4452 order_re = order_pattern.match(line)
4453
4454
4455 if constrained_orders and LoopOption != 'tree':
4456 raise self.InvalidCmd, \
4457 "Amplitude order constraints (for not LO processes) can only be of type %s"%\
4458 (', '.join(['<=']))+", not '%s'."%type
4459
4460
4461
4462
4463
4464
4465 if orders=={} and squared_orders!={}:
4466 for order in squared_orders.keys():
4467 if squared_orders[order][0]>=0 and squared_orders[order][1]!='>':
4468 orders[order]=squared_orders[order][0]
4469 else:
4470 orders[order]=99
4471
4472 if not self._curr_model['case_sensitive']:
4473
4474 line = line.lower()
4475
4476
4477 slash = line.find("/")
4478 dollar = line.find("$")
4479 forbidden_particles = ""
4480 if slash > 0:
4481 if dollar > slash:
4482 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
4483 else:
4484 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
4485 if forbidden_particles_re:
4486 forbidden_particles = forbidden_particles_re.group(2)
4487 line = forbidden_particles_re.group(1)
4488 if len(forbidden_particles_re.groups()) > 2:
4489 line = line + forbidden_particles_re.group(3)
4490
4491
4492 forbidden_schannels_re = re.match("^(.+)\s*\$\s*\$\s*(.+)\s*$", line)
4493 forbidden_schannels = ""
4494 if forbidden_schannels_re:
4495 forbidden_schannels = forbidden_schannels_re.group(2)
4496 line = forbidden_schannels_re.group(1)
4497
4498
4499 forbidden_onsh_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
4500 forbidden_onsh_schannels = ""
4501 if forbidden_onsh_schannels_re:
4502 forbidden_onsh_schannels = forbidden_onsh_schannels_re.group(2)
4503 line = forbidden_onsh_schannels_re.group(1)
4504
4505
4506 required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
4507 required_schannels = ""
4508 if required_schannels_re:
4509 required_schannels = required_schannels_re.group(2)
4510 line = required_schannels_re.group(1) + ">" + \
4511 required_schannels_re.group(3)
4512
4513 args = self.split_arg(line)
4514
4515 myleglist = base_objects.MultiLegList()
4516 state = False
4517
4518
4519 for part_name in args:
4520 if part_name == '>':
4521 if not myleglist:
4522 raise self.InvalidCmd, "No final state particles"
4523 state = True
4524 continue
4525
4526 mylegids = []
4527 if part_name in self._multiparticles:
4528 if isinstance(self._multiparticles[part_name][0], list):
4529 raise self.InvalidCmd,\
4530 "Multiparticle %s is or-multiparticle" % part_name + \
4531 " which can be used only for required s-channels"
4532 mylegids.extend(self._multiparticles[part_name])
4533 elif part_name.isdigit() or part_name.startswith('-') and part_name[1:].isdigit():
4534 if int(part_name) in self._curr_model.get('particle_dict'):
4535 mylegids.append(int(part_name))
4536 else:
4537 raise self.InvalidCmd, \
4538 "No pdg_code %s in model" % part_name
4539 else:
4540 mypart = self._curr_model['particles'].get_copy(part_name)
4541 if mypart:
4542 mylegids.append(mypart.get_pdg_code())
4543
4544 if mylegids:
4545 myleglist.append(base_objects.MultiLeg({'ids':mylegids,
4546 'state':state}))
4547 else:
4548 raise self.InvalidCmd, "No particle %s in model" % part_name
4549
4550
4551 if perturbation_couplings.lower()=='all':
4552 perturbation_couplings=' '.join(self._curr_model['perturbation_couplings'])
4553
4554 if filter(lambda leg: leg.get('state') == True, myleglist):
4555
4556
4557 perturbation_couplings_list = perturbation_couplings.split()
4558 if perturbation_couplings_list==['']:
4559 perturbation_couplings_list=[]
4560
4561
4562 split_orders=list(set(perturbation_couplings_list+squared_orders.keys()))
4563 try:
4564 split_orders.sort(key=lambda elem: 0 if elem=='WEIGHTED' else
4565 self._curr_model['order_hierarchy']
4566 [elem if not elem.endswith('.sqrt') else elem[:-5]])
4567 except KeyError:
4568 raise self.InvalidCmd, "The loaded model does not defined a "+\
4569 " coupling order hierarchy for these couplings: %s"%\
4570 str([so for so in split_orders if so!='WEIGHTED' and so not
4571 in self._curr_model['order_hierarchy'].keys()])
4572
4573
4574
4575
4576 if LoopOption=='tree':
4577 perturbation_couplings_list = []
4578 if perturbation_couplings_list and LoopOption not in ['real', 'LOonly']:
4579 if not isinstance(self._curr_model,loop_base_objects.LoopModel):
4580 raise self.InvalidCmd(\
4581 "The current model does not allow for loop computations.")
4582 else:
4583 for pert_order in perturbation_couplings_list:
4584 if pert_order not in self._curr_model['perturbation_couplings']:
4585 raise self.InvalidCmd(\
4586 "Perturbation order %s is not among" % pert_order + \
4587 " the perturbation orders allowed for by the loop model.")
4588 if not self.options['loop_optimized_output'] and \
4589 LoopOption not in ['tree','real'] and split_orders!=[]:
4590 logger.warning('The default output mode (loop_optimized_output'+\
4591 ' = False) does not support evaluations for given powers of'+\
4592 ' coupling orders. MadLoop output will therefore not be'+\
4593 ' able to provide such quantities.')
4594 split_orders = []
4595
4596
4597 forbidden_particle_ids = \
4598 self.extract_particle_ids(forbidden_particles)
4599 if forbidden_particle_ids and \
4600 isinstance(forbidden_particle_ids[0], list):
4601 raise self.InvalidCmd(\
4602 "Multiparticle %s is or-multiparticle" % part_name + \
4603 " which can be used only for required s-channels")
4604 forbidden_onsh_schannel_ids = \
4605 self.extract_particle_ids(forbidden_onsh_schannels)
4606 forbidden_schannel_ids = \
4607 self.extract_particle_ids(forbidden_schannels)
4608 if forbidden_onsh_schannel_ids and \
4609 isinstance(forbidden_onsh_schannel_ids[0], list):
4610 raise self.InvalidCmd,\
4611 "Multiparticle %s is or-multiparticle" % part_name + \
4612 " which can be used only for required s-channels"
4613 if forbidden_schannel_ids and \
4614 isinstance(forbidden_schannel_ids[0], list):
4615 raise self.InvalidCmd,\
4616 "Multiparticle %s is or-multiparticle" % part_name + \
4617 " which can be used only for required s-channels"
4618 required_schannel_ids = \
4619 self.extract_particle_ids(required_schannels)
4620 if required_schannel_ids and not \
4621 isinstance(required_schannel_ids[0], list):
4622 required_schannel_ids = [required_schannel_ids]
4623
4624 sqorders_values = dict([(k,v[0]) for k, v in squared_orders.items()])
4625 if len([1 for sqo_v in sqorders_values.values() if sqo_v<0])>1:
4626 raise self.InvalidCmd(
4627 "At most one negative squared order constraint can be specified.")
4628
4629 sqorders_types = dict([(k,v[1]) for k, v in squared_orders.items()])
4630
4631
4632 out = base_objects.ProcessDefinition({'legs': myleglist,
4633 'model': self._curr_model,
4634 'id': proc_number,
4635 'orders': orders,
4636 'squared_orders':sqorders_values,
4637 'sqorders_types':sqorders_types,
4638 'constrained_orders': constrained_orders,
4639 'forbidden_particles': forbidden_particle_ids,
4640 'forbidden_onsh_s_channels': forbidden_onsh_schannel_ids,
4641 'forbidden_s_channels': forbidden_schannel_ids,
4642 'required_s_channels': required_schannel_ids,
4643 'overall_orders': overall_orders,
4644 'perturbation_couplings': perturbation_couplings_list,
4645 'has_born':HasBorn,
4646 'NLO_mode':LoopOption,
4647 'split_orders':split_orders
4648 })
4649 return out
4650
4651
4652
4654 """ Routine to create the MultiProcess for the loop-induced case"""
4655
4656 args = self.split_arg(line)
4657
4658 warning_duplicate = True
4659 if '--no_warning=duplicate' in args:
4660 warning_duplicate = False
4661 args.remove('--no_warning=duplicate')
4662
4663
4664 self.check_add(args)
4665 if args[0] == 'process':
4666 args = args[1:]
4667
4668
4669
4670 if args[-1].startswith('--optimize'):
4671 optimize = True
4672 args.pop()
4673 else:
4674 optimize = False
4675
4676
4677 if not myprocdef:
4678 myprocdef = self.extract_process(' '.join(args))
4679
4680 myprocdef.set('NLO_mode', 'noborn')
4681
4682
4683 if not self._generate_info:
4684 self._generate_info = line
4685
4686
4687
4688
4689
4690
4691
4692 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
4693 myprocdef.get_ninitial():
4694 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
4695
4696 if self._curr_amps and (not isinstance(self._curr_amps[0], loop_diagram_generation.LoopAmplitude) or \
4697 self._curr_amps[0]['has_born']):
4698 raise self.InvalidCmd("Can not mix loop induced process with not loop induced process")
4699
4700
4701
4702 if len([1 for val in myprocdef.get('orders').values()+\
4703 myprocdef.get('squared_orders').values() if val<0])>1:
4704 raise MadGraph5Error("Negative coupling order constraints"+\
4705 " can only be given on one type of coupling and either on"+\
4706 " squared orders or amplitude orders, not both.")
4707
4708 cpu_time1 = time.time()
4709
4710
4711 if self.options['group_subprocesses'] == 'Auto':
4712 collect_mirror_procs = True
4713 else:
4714 collect_mirror_procs = self.options['group_subprocesses']
4715 ignore_six_quark_processes = \
4716 self.options['ignore_six_quark_processes'] if \
4717 "ignore_six_quark_processes" in self.options \
4718 else []
4719
4720
4721
4722 myproc = loop_diagram_generation.LoopInducedMultiProcess(myprocdef,
4723 collect_mirror_procs = collect_mirror_procs,
4724 ignore_six_quark_processes = ignore_six_quark_processes,
4725 optimize=optimize)
4726
4727 for amp in myproc.get('amplitudes'):
4728 if amp not in self._curr_amps:
4729 self._curr_amps.append(amp)
4730 if amp['has_born']:
4731 raise Exception
4732 elif warning_duplicate:
4733 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
4734 amp.nice_string_processes()
4735
4736
4737 self._done_export = False
4738
4739 cpu_time2 = time.time()
4740
4741 nprocs = len(myproc.get('amplitudes'))
4742 ndiags = sum([amp.get_number_of_diagrams() for \
4743 amp in myproc.get('amplitudes')])
4744 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
4745 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
4746 ndiags = sum([amp.get_number_of_diagrams() for \
4747 amp in self._curr_amps])
4748 logger.info("Total: %i processes with %i diagrams" % \
4749 (len(self._curr_amps), ndiags))
4750
4751 @staticmethod
4753 """Takes a valid process and return
4754 a tuple (core_process, options). This removes
4755 - any NLO specifications.
4756 - any options
4757 [Used by MadSpin]
4758 """
4759
4760
4761
4762 line=procline
4763 pos1=line.find("[")
4764 if pos1>0:
4765 pos2=line.find("]")
4766 if pos2 >pos1:
4767 line=line[:pos1]+line[pos2+1:]
4768
4769
4770
4771
4772 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
4773 proc_number_re = proc_number_pattern.match(line)
4774 if proc_number_re:
4775 line = proc_number_re.group(1) + proc_number_re.group(3)
4776
4777
4778 pos=1000
4779
4780 order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
4781 order_re = order_pattern.match(line)
4782 if (order_re):
4783 pos_order=line.find(order_re.group(2))
4784 if pos_order>0 and pos_order < pos : pos=pos_order
4785
4786
4787 slash = line.find("/")
4788 if slash > 0 and slash < pos: pos=slash
4789 dollar = line.find("$")
4790 if dollar > 0 and dollar < pos: pos=dollar
4791
4792 if pos<1000:
4793 proc_option=line[pos:]
4794 line=line[:pos]
4795 else:
4796 proc_option=""
4797
4798 return line, proc_option
4799
4801 """Takes a valid process and return
4802 a set of id of final states particles. [Used by MadSpin]
4803 """
4804
4805 if not self._curr_model['case_sensitive']:
4806 procline = procline.lower()
4807 pids = self._curr_model.get('name2pdg')
4808
4809
4810
4811
4812
4813
4814
4815 if ',' in procline:
4816 core, decay = procline.split(',', 1)
4817 core_final = self.get_final_part(core)
4818
4819
4820 all_decays = decay.split(',')
4821 nb_level, tmp_decay = 0, ''
4822 decays = []
4823
4824 for one_decay in all_decays:
4825 if '(' in one_decay:
4826 nb_level += 1
4827 if ')' in one_decay:
4828 nb_level -= 1
4829
4830 if nb_level:
4831 if tmp_decay:
4832 tmp_decay += ', %s' % one_decay
4833 else:
4834 tmp_decay = one_decay
4835 elif tmp_decay:
4836 final = '%s,%s' % (tmp_decay, one_decay)
4837 final = final.strip()
4838 assert final[0] == '(' and final[-1] == ')'
4839 final = final[1:-1]
4840 decays.append(final)
4841 tmp_decay = ''
4842 else:
4843 decays.append(one_decay)
4844
4845 for one_decay in decays:
4846 first = one_decay.split('>',1)[0].strip()
4847 if first in pids:
4848 pid = set([pids[first]])
4849 elif first in self._multiparticles:
4850 pid = set(self._multiparticles[first])
4851 else:
4852 raise Exception, 'invalid particle name: %s. ' % first
4853 core_final.difference_update(pid)
4854 core_final.update(self.get_final_part(one_decay))
4855
4856 return core_final
4857
4858
4859 final = set()
4860 final_states = re.search(r'> ([^\/\$\=\@>]*)(\[|\s\S+\=|\$|\/|\@|$)', procline)
4861 particles = final_states.groups()[0]
4862 for particle in particles.split():
4863 if particle in pids:
4864 final.add(pids[particle])
4865 elif particle in self._multiparticles:
4866 final.update(set(self._multiparticles[particle]))
4867 return final
4868
4869 - def extract_particle_ids(self, args):
4870 """Extract particle ids from a list of particle names. If
4871 there are | in the list, this corresponds to an or-list, which
4872 is represented as a list of id lists. An or-list is used to
4873 allow multiple required s-channel propagators to be specified
4874 (e.g. Z/gamma)."""
4875
4876 if isinstance(args, basestring):
4877 args.replace("|", " | ")
4878 args = self.split_arg(args)
4879 all_ids = []
4880 ids=[]
4881 for part_name in args:
4882 mypart = self._curr_model['particles'].get_copy(part_name)
4883 if mypart:
4884 ids.append([mypart.get_pdg_code()])
4885 elif part_name in self._multiparticles:
4886 ids.append(self._multiparticles[part_name])
4887 elif part_name == "|":
4888
4889 if ids:
4890 all_ids.append(ids)
4891 ids = []
4892 elif part_name.isdigit() or (part_name.startswith('-') and part_name[1:].isdigit()):
4893 ids.append([int(part_name)])
4894 else:
4895 raise self.InvalidCmd("No particle %s in model" % part_name)
4896 all_ids.append(ids)
4897
4898
4899 res_lists = []
4900 for i, id_list in enumerate(all_ids):
4901 res_lists.extend(diagram_generation.expand_list_list(id_list))
4902
4903 for ilist, idlist in enumerate(res_lists):
4904 set_dict = {}
4905 res_lists[ilist] = [set_dict.setdefault(i,i) for i in idlist \
4906 if i not in set_dict]
4907
4908 if len(res_lists) == 1:
4909 res_lists = res_lists[0]
4910
4911 return res_lists
4912
4914 """Optimize the order of particles in a pdg list, so that
4915 similar particles are next to each other. Sort according to:
4916 1. pdg > 0, 2. spin, 3. color, 4. mass > 0"""
4917
4918 if not pdg_list:
4919 return
4920 if not isinstance(pdg_list[0], int):
4921 return
4922
4923 model = self._curr_model
4924 pdg_list.sort(key = lambda i: i < 0)
4925 pdg_list.sort(key = lambda i: model.get_particle(i).is_fermion())
4926 pdg_list.sort(key = lambda i: model.get_particle(i).get('color'),
4927 reverse = True)
4928 pdg_list.sort(key = lambda i: \
4929 model.get_particle(i).get('mass').lower() != 'zero')
4930
4932 """Recursively extract a decay chain process definition from a
4933 string. Returns a ProcessDefinition."""
4934
4935
4936 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*((\w+\s*=\s*\d+\s*)*)$")
4937 proc_number_re = proc_number_pattern.match(line)
4938 overall_orders = {}
4939 if proc_number_re:
4940 proc_number = int(proc_number_re.group(2))
4941 line = proc_number_re.group(1)
4942 if proc_number_re.group(3):
4943 order_pattern = re.compile("^(.*?)\s*(\w+)\s*=\s*(\d+)\s*$")
4944 order_line = proc_number_re.group(3)
4945 order_re = order_pattern.match(order_line)
4946 while order_re:
4947 overall_orders[order_re.group(2)] = int(order_re.group(3))
4948 order_line = order_re.group(1)
4949 order_re = order_pattern.match(order_line)
4950 logger.info(line)
4951
4952
4953 index_comma = line.find(",")
4954 index_par = line.find(")")
4955 min_index = index_comma
4956 if index_par > -1 and (index_par < min_index or min_index == -1):
4957 min_index = index_par
4958
4959 if min_index > -1:
4960 core_process = self.extract_process(line[:min_index], proc_number,
4961 overall_orders)
4962 else:
4963 core_process = self.extract_process(line, proc_number,
4964 overall_orders)
4965
4966
4967
4968 while index_comma > -1:
4969 line = line[index_comma + 1:]
4970 if not line.strip():
4971 break
4972 index_par = line.find(')')
4973
4974 if line.lstrip()[0] == '(' and index_par !=-1 and \
4975 not ',' in line[:index_par]:
4976 par_start = line.find('(')
4977 line = '%s %s' % (line[par_start+1:index_par], line[index_par+1:])
4978 index_par = line.find(')')
4979 if line.lstrip()[0] == '(':
4980
4981
4982 line = line.lstrip()[1:]
4983
4984 decay_process, line = \
4985 self.extract_decay_chain_process(line,
4986 level_down=True)
4987 index_comma = line.find(",")
4988 index_par = line.find(')')
4989 else:
4990 index_comma = line.find(",")
4991 min_index = index_comma
4992 if index_par > -1 and \
4993 (index_par < min_index or min_index == -1):
4994 min_index = index_par
4995 if min_index > -1:
4996 decay_process = self.extract_process(line[:min_index])
4997 else:
4998 decay_process = self.extract_process(line)
4999
5000 core_process.get('decay_chains').append(decay_process)
5001
5002 if level_down:
5003 if index_par == -1:
5004 raise self.InvalidCmd, \
5005 "Missing ending parenthesis for decay process"
5006
5007 if index_par < index_comma:
5008 line = line[index_par + 1:]
5009 level_down = False
5010 break
5011
5012 if level_down:
5013 index_par = line.find(')')
5014 if index_par == -1:
5015 raise self.InvalidCmd, \
5016 "Missing ending parenthesis for decay process"
5017 line = line[index_par + 1:]
5018
5019
5020
5021 return core_process, line
5022
5023
5024
5026 """Main commands: Import files with external formats"""
5027
5028 args = self.split_arg(line)
5029
5030 self.check_import(args)
5031 if args[0].startswith('model'):
5032 self._model_v4_path = None
5033
5034 self._curr_amps = diagram_generation.AmplitudeList()
5035
5036 self._curr_proc_defs = base_objects.ProcessDefinitionList()
5037 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5038
5039 if args[0].endswith('_v4'):
5040 self._curr_model, self._model_v4_path = \
5041 import_v4.import_model(args[1], self._mgme_dir)
5042 else:
5043
5044 if (args[1].startswith('loop_qcd_qed_sm') or\
5045 args[1].split('/')[-1].startswith('loop_qcd_qed_sm')) and\
5046 self.options['gauge']!='Feynman':
5047 logger.info('Switching to Feynman gauge because '+\
5048 'it is the only one supported by the model %s.'%args[1])
5049 self._curr_model = None
5050 self.do_set('gauge Feynman',log=False)
5051 prefix = not '--noprefix' in args
5052 if prefix:
5053 aloha.aloha_prefix='mdl_'
5054 else:
5055 aloha.aloha_prefix=''
5056
5057 try:
5058 self._curr_model = import_ufo.import_model(args[1], prefix=prefix,
5059 complex_mass_scheme=self.options['complex_mass_scheme'])
5060 except import_ufo.UFOImportError, error:
5061 if 'not a valid UFO model' in str(error):
5062 logger_stderr.warning('WARNING: %s' % error)
5063 logger_stderr.warning('Try to recover by running '+\
5064 'automatically `import model_v4 %s` instead.'% args[1])
5065 self.exec_cmd('import model_v4 %s ' % args[1], precmd=True)
5066 return
5067 if self.options['gauge']=='unitary':
5068 if not force and isinstance(self._curr_model,\
5069 loop_base_objects.LoopModel) and \
5070 self._curr_model.get('perturbation_couplings') not in \
5071 [[],['QCD']]:
5072 if 1 not in self._curr_model.get('gauge') :
5073 logger_stderr.warning('This model does not allow Feynman '+\
5074 'gauge. You will only be able to do tree level '+\
5075 'QCD loop cmputations with it.')
5076 else:
5077 logger.info('Change to the gauge to Feynman because '+\
5078 'this loop model allows for more than just tree level'+\
5079 ' and QCD perturbations.')
5080 self.do_set('gauge Feynman', log=False)
5081 return
5082 if 0 not in self._curr_model.get('gauge') :
5083 logger_stderr.warning('Change the gauge to Feynman since '+\
5084 'the model does not allow unitary gauge')
5085 self.do_set('gauge Feynman', log=False)
5086 return
5087 else:
5088 if 1 not in self._curr_model.get('gauge') :
5089 logger_stderr.warning('Change the gauge to unitary since the'+\
5090 ' model does not allow Feynman gauge.'+\
5091 ' Please re-import the model')
5092 self._curr_model = None
5093 self.do_set('gauge unitary', log= False)
5094 return
5095
5096 if '-modelname' not in args:
5097 self._curr_model.pass_particles_name_in_mg_default()
5098
5099
5100 self.process_model()
5101
5102 self._curr_amps = diagram_generation.AmplitudeList()
5103
5104 self._curr_proc_defs = base_objects.ProcessDefinitionList()
5105 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5106 process_checks.store_aloha = []
5107
5108 elif args[0] == 'command':
5109
5110 if not os.path.isfile(args[1]):
5111 raise self.InvalidCmd("Path %s is not a valid pathname" % args[1])
5112 else:
5113
5114
5115 self.check_for_export_dir(args[1])
5116
5117 self.import_command_file(args[1])
5118
5119 elif args[0] == 'banner':
5120 type = madevent_interface.MadEventCmd.detect_card_type(args[1])
5121 if type != 'banner':
5122 raise self.InvalidCmd, 'The File should be a valid banner'
5123 ban = banner_module.Banner(args[1])
5124
5125 if 'mg5proccard' in ban:
5126 for line in ban['mg5proccard'].split('\n'):
5127 if line.startswith('#') or line.startswith('<'):
5128 continue
5129 self.exec_cmd(line)
5130 else:
5131 raise self.InvalidCmd, 'Only MG5 banner are supported'
5132
5133 if not self._done_export:
5134 self.exec_cmd('output . -f')
5135
5136 ban.split(self._done_export[0])
5137 logger.info('All Cards from the banner have been place in directory %s' % pjoin(self._done_export[0], 'Cards'))
5138 if '--no_launch' not in args:
5139 self.exec_cmd('launch')
5140
5141 elif args[0] == 'proc_v4':
5142
5143 if len(args) == 1 and self._export_dir:
5144 proc_card = pjoin(self._export_dir, 'Cards', \
5145 'proc_card.dat')
5146 elif len(args) == 2:
5147 proc_card = args[1]
5148
5149
5150 self.check_for_export_dir(os.path.realpath(proc_card))
5151 else:
5152 raise MadGraph5Error('No default directory in output')
5153
5154
5155
5156 self.import_mg4_proc_card(proc_card)
5157
5159 """ For simple decay chain: remove diagram that are not in the BR.
5160 param_card should be a ParamCard instance."""
5161
5162 assert isinstance(param_card, check_param_card.ParamCard)
5163
5164
5165 amplitudes = diagram_generation.AmplitudeList()
5166 for amp in self._curr_amps:
5167 amplitudes.extend(amp.get_amplitudes())
5168
5169 decay_tables = param_card['decay'].decay_table
5170 to_remove = []
5171 for amp in amplitudes:
5172 mother = [l.get('id') for l in amp['process'].get('legs') \
5173 if not l.get('state')]
5174 if 1 == len(mother):
5175 try:
5176 decay_table = decay_tables[abs(mother[0])]
5177 except KeyError:
5178 logger.warning("No decay table for %s. decay of this particle with MadSpin should be discarded" % abs(mother[0]))
5179 continue
5180
5181 child = [l.get('id') for l in amp['process'].get('legs') \
5182 if l.get('state')]
5183 if not mother[0] > 0:
5184 child = [x if self._curr_model.get_particle(x)['self_antipart']
5185 else -x for x in child]
5186 child.sort()
5187 child.insert(0, len(child))
5188
5189 if tuple(child) not in decay_table.keys():
5190 to_remove.append(amp)
5191
5192 def remove_amp(amps):
5193 for amp in amps[:]:
5194 if amp in to_remove:
5195 amps.remove(amp)
5196 if isinstance(amp, diagram_generation.DecayChainAmplitude):
5197 remove_amp(amp.get('decay_chains'))
5198 for decay in amp.get('decay_chains'):
5199 remove_amp(decay.get('amplitudes'))
5200 remove_amp(self._curr_amps)
5201
5202
5207
5209 """Set variables _particle_names and _couplings for tab
5210 completion, define multiparticles"""
5211
5212
5213 self._particle_names = [p.get('name') for p in self._curr_model.get('particles')\
5214 if p.get('propagating')] + \
5215 [p.get('antiname') for p in self._curr_model.get('particles') \
5216 if p.get('propagating')]
5217
5218 self._couplings = list(set(sum([i.get('orders').keys() for i in \
5219 self._curr_model.get('interactions')], [])))
5220
5221 self.add_default_multiparticles()
5222
5223
5252
5254 """ add default particle from file interface.multiparticles_default.txt
5255 """
5256
5257 defined_multiparticles = self._multiparticles.keys()
5258 removed_multiparticles = []
5259
5260
5261
5262 for key in self._multiparticles.keys():
5263 try:
5264 for part in self._multiparticles[key]:
5265 self._curr_model.get('particle_dict')[part]
5266 except Exception:
5267 del self._multiparticles[key]
5268 defined_multiparticles.remove(key)
5269 removed_multiparticles.append(key)
5270
5271
5272 for line in open(pjoin(MG5DIR, 'input', \
5273 'multiparticles_default.txt')):
5274 if line.startswith('#'):
5275 continue
5276 try:
5277 if not self._curr_model['case_sensitive']:
5278 multipart_name = line.lower().split()[0]
5279 else:
5280 multipart_name = line.split()[0]
5281 if multipart_name not in self._multiparticles:
5282
5283 self.exec_cmd('define %s' % line, printcmd=False, precmd=True)
5284 except self.InvalidCmd, why:
5285 logger_stderr.warning('impossible to set default multiparticles %s because %s' %
5286 (line.split()[0],why))
5287 if self.history[-1] == 'define %s' % line.strip():
5288 self.history.pop(-1)
5289 else:
5290 misc.sprint([self.history[-1], 'define %s' % line.strip()])
5291
5292 scheme = "old"
5293 for qcd_container in ['p', 'j']:
5294 if qcd_container not in self._multiparticles:
5295 continue
5296 multi = self._multiparticles[qcd_container]
5297 b = self._curr_model.get_particle(5)
5298 if not b:
5299 break
5300
5301 if 5 in multi:
5302 if b['mass'] != 'ZERO':
5303 multi.remove(5)
5304 multi.remove(-5)
5305 scheme = 4
5306 elif b['mass'] == 'ZERO':
5307 multi.append(5)
5308 multi.append(-5)
5309 scheme = 5
5310
5311 if scheme in [4,5]:
5312 logger.warning("Pass the definition of \'j\' and \'p\' to %s flavour scheme." % scheme)
5313 for container in ['p', 'j']:
5314 if container in defined_multiparticles:
5315 defined_multiparticles.remove(container)
5316 self.history.append("define p = %s # pass to %s flavors" % \
5317 (' ' .join([`i` for i in self._multiparticles['p']]),
5318 scheme)
5319 )
5320 self.history.append("define j = p")
5321
5322
5323 if defined_multiparticles:
5324 if 'all' in defined_multiparticles:
5325 defined_multiparticles.remove('all')
5326 logger.info("Kept definitions of multiparticles %s unchanged" % \
5327 " / ".join(defined_multiparticles))
5328
5329 for removed_part in removed_multiparticles:
5330 if removed_part in self._multiparticles:
5331 removed_multiparticles.remove(removed_part)
5332
5333 if removed_multiparticles:
5334 logger.info("Removed obsolete multiparticles %s" % \
5335 " / ".join(removed_multiparticles))
5336
5337
5338 line = []
5339 for part in self._curr_model.get('particles'):
5340 line.append('%s %s' % (part.get('name'), part.get('antiname')))
5341 line = 'all =' + ' '.join(line)
5342 self.do_define(line)
5343
5344 - def advanced_install(self, tool_to_install,
5345 HepToolsInstaller_web_address=None,
5346 additional_options=[]):
5347 """ Uses the HEPToolsInstaller.py script maintened online to install
5348 HEP tools with more complicated dependences.
5349 Additional options will be added to the list when calling HEPInstaller"""
5350
5351
5352 add_options = list(additional_options)
5353
5354
5355 if not os.path.isdir(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers')):
5356 if HepToolsInstaller_web_address is None:
5357 raise MadGraph5Error, "The option 'HepToolsInstaller_web_address'"+\
5358 " must be specified in function advanced_install"+\
5359 " if the installers are not already downloaded."
5360 if not os.path.isdir(pjoin(MG5DIR,'HEPTools')):
5361 os.mkdir(pjoin(MG5DIR,'HEPTools'))
5362 elif not HepToolsInstaller_web_address is None:
5363 shutil.rmtree(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5364 if not HepToolsInstaller_web_address is None:
5365 logger.info('Downloading the HEPToolInstaller at:\n %s'%
5366 HepToolsInstaller_web_address)
5367
5368 if '//' in HepToolsInstaller_web_address:
5369 if sys.platform == "darwin":
5370 misc.call(['curl', HepToolsInstaller_web_address, '-o%s'
5371 %pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz')],
5372 stderr=open(os.devnull,'w'), stdout=open(os.devnull,'w'),
5373 cwd=MG5DIR)
5374 else:
5375 misc.call(['wget', HepToolsInstaller_web_address,
5376 '--output-document=%s'% pjoin(MG5DIR,'HEPTools',
5377 'HEPToolsInstallers.tar.gz')], stderr=open(os.devnull, 'w'),
5378 stdout=open(os.devnull, 'w'), cwd=MG5DIR)
5379 else:
5380
5381 shutil.copyfile(HepToolsInstaller_web_address,
5382 pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz'))
5383
5384
5385 returncode = misc.call(['tar', '-xzpf', 'HEPToolsInstallers.tar.gz'],
5386 cwd=pjoin(MG5DIR,'HEPTools'), stdout=open(os.devnull, 'w'))
5387
5388
5389 os.remove(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz'))
5390
5391
5392
5393 if '--local' in add_options:
5394 add_options.remove('--local')
5395 logger.warning('you are using a local installer. This is intended for debugging only!')
5396 shutil.rmtree(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5397 shutil.copytree(os.path.abspath(pjoin(MG5DIR,os.path.pardir,
5398 'HEPToolsInstallers')),pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5399
5400
5401 name_map = {}
5402 try:
5403 tool = name_map[tool_to_install]
5404 except:
5405 tool = tool_to_install
5406
5407
5408 compiler_options = []
5409 if self.options['cpp_compiler'] is not None:
5410 compiler_options.append('--cpp_compiler=%s'%
5411 self.options['cpp_compiler'])
5412 compiler_options.append('--cpp_standard_lib=%s'%
5413 misc.detect_cpp_std_lib_dependence(self.options['cpp_compiler']))
5414 elif misc.which('g++'):
5415 compiler_options.append('--cpp_standard_lib=%s'%
5416 misc.detect_cpp_std_lib_dependence('g++'))
5417 else:
5418 compiler_options.append('--cpp_standard_lib=%s'%
5419 misc.detect_cpp_std_lib_dependence(None))
5420
5421 if not self.options['fortran_compiler'] is None:
5422 compiler_options.append('--fortran_compiler=%s'%
5423 self.options['fortran_compiler'])
5424
5425 if 'heptools_install_dir' in self.options:
5426 prefix = self.options['heptools_install_dir']
5427 config_file = '~/.mg5/mg5_configuration.txt'
5428 else:
5429 prefix = pjoin(MG5DIR, 'HEPTools')
5430 config_file = ''
5431
5432
5433 if tool=='mg5amc_py8_interface':
5434 add_options.append('--mg5_path=%s'%MG5DIR)
5435
5436 if misc.which('gnuplot') is None:
5437 logger.warning("==========")
5438 logger.warning("The optional dependency 'gnuplot' for the tool"+\
5439 " 'mg5amc_py8_interface' was not found. We recommend that you"+\
5440 " install it so as to be able to view the plots related to "+\
5441 " merging with Pythia 8.")
5442 logger.warning("==========")
5443 if self.options['pythia8_path']:
5444 add_options.append(
5445 '--with_pythia8=%s'%self.options['pythia8_path'])
5446
5447
5448 if tool=='madanalysis5':
5449 add_options.append('--mg5_path=%s'%MG5DIR)
5450 if not any(opt.startswith(('--with_fastjet', '--veto_fastjet')) for opt in add_options):
5451 fastjet_config = misc.which(self.options['fastjet'])
5452 if fastjet_config:
5453 add_options.append('--with_fastjet=%s'%fastjet_config)
5454
5455 if self.options['delphes_path'] and os.path.isdir(
5456 os.path.normpath(pjoin(MG5DIR,self.options['delphes_path']))):
5457 add_options.append('--with_delphes3=%s'%\
5458 os.path.normpath(pjoin(MG5DIR,self.options['delphes_path'])))
5459
5460 if tool=='pythia8':
5461
5462 lhapdf_config = misc.which(self.options['lhapdf'])
5463 lhapdf_version = None
5464 if lhapdf_config is None:
5465 lhapdf_version = None
5466 else:
5467 try:
5468 version = misc.Popen(
5469 [lhapdf_config,'--version'], stdout=subprocess.PIPE)
5470 lhapdf_version = int(version.stdout.read()[0])
5471 if lhapdf_version not in [5,6]:
5472 raise
5473 except:
5474 raise self.InvalidCmd('Could not detect LHAPDF version. Make'+
5475 " sure '%s --version ' runs properly."%lhapdf_config)
5476
5477 if lhapdf_version is None:
5478 answer = self.ask(question=
5479 "\033[33;34mLHAPDF was not found. Do you want to install LHPADF6? "+
5480 "(recommended) \033[0m \033[33;32my\033[0m/\033[33;31mn\033[0m >",
5481 default='y',text_format='33;32')
5482 if not answer.lower() in ['y','']:
5483 lhapdf_path = None
5484 else:
5485 self.advanced_install('lhapdf6',
5486 additional_options=add_options)
5487 lhapdf_path = pjoin(MG5DIR,'HEPTools','lhapdf6')
5488 lhapdf_version = 6
5489 else:
5490 lhapdf_path = os.path.abspath(pjoin(os.path.dirname(\
5491 lhapdf_config),os.path.pardir))
5492 if lhapdf_version is None:
5493 logger.warning('You decided not to link the Pythia8 installation'+
5494 ' to LHAPDF. Beware that only built-in PDF sets can be used then.')
5495 else:
5496 logger.info('Pythia8 will be linked to LHAPDF v%d.'%lhapdf_version)
5497 logger.info('Now installing Pythia8. Be patient...','$MG:color:GREEN')
5498 lhapdf_option = []
5499 if lhapdf_version is None:
5500 lhapdf_option.append('--with_lhapdf6=OFF')
5501 lhapdf_option.append('--with_lhapdf5=OFF')
5502 elif lhapdf_version==5:
5503 lhapdf_option.append('--with_lhapdf5=%s'%lhapdf_path)
5504 lhapdf_option.append('--with_lhapdf6=OFF')
5505 elif lhapdf_version==6:
5506 lhapdf_option.append('--with_lhapdf5=OFF')
5507 lhapdf_option.append('--with_lhapdf6=%s'%lhapdf_path)
5508
5509 add_options = list(set(add_options))
5510
5511 add_options = [opt for opt in add_options if opt!='--force']+\
5512 (['--force'] if '--force' in add_options else [])
5513 return_code = misc.call([sys.executable, pjoin(MG5DIR,'HEPTools',
5514 'HEPToolsInstallers','HEPToolInstaller.py'),'pythia8',
5515 '--prefix=%s' % prefix]
5516 + lhapdf_option + compiler_options + add_options)
5517 else:
5518 logger.info('Now installing %s. Be patient...'%tool)
5519
5520 add_options = list(set(add_options))
5521
5522 add_options = [opt for opt in add_options if opt!='--force']+\
5523 (['--force'] if '--force' in add_options else [])
5524 return_code = misc.call([sys.executable, pjoin(MG5DIR,'HEPTools',
5525 'HEPToolsInstallers', 'HEPToolInstaller.py'), tool,'--prefix=%s'%
5526 prefix] + compiler_options + add_options)
5527
5528 if return_code == 0:
5529 logger.info("%s successfully installed in %s."%(
5530 tool_to_install, prefix),'$MG:color:GREEN')
5531
5532 if tool=='madanalysis5':
5533 if not any(o.startswith(('--with_','--veto_','--update')) for o in add_options):
5534 logger.info(' To install recasting capabilities of madanalysis5 and/or', '$MG:color:BLACK')
5535 logger.info(' to allow delphes analysis at parton level.','$MG:color:BLACK')
5536 logger.info(' Please run \'install MadAnalysis5 --with_delphes --update\':', '$MG:color:BLACK')
5537
5538 elif return_code == 66:
5539 answer = self.ask(question=
5540 """\033[33;34mTool %s already installed in %s."""%(tool_to_install, prefix)+
5541 """ Do you want to overwrite its installation?\033[0m \033[33;32my\033[0m/\033[33;31mn\033[0m >"""
5542 ,default='y',text_format='33;32')
5543 if not answer.lower() in ['y','']:
5544 logger.info("Installation of %s aborted."%tool_to_install,
5545 '$MG:color:GREEN')
5546 return
5547 else:
5548 return self.advanced_install(tool_to_install,
5549 additional_options=add_options+['--force'])
5550 else:
5551 if tool=='madanalysis5' and '--update' not in add_options and \
5552 ('--no_MA5_further_install' not in add_options or
5553 '--no_root_in_MA5' in add_options):
5554 if not __debug__:
5555 logger.warning('Default installation of Madanalys5 failed.')
5556 logger.warning("MG5aMC will now attempt to reinstall it with the options '--no_MA5_further_install --no_root_in_MA5'.")
5557 logger.warning("This will however limit MA5 applicability for hadron-level analysis.")
5558 logger.warning("If you would like to prevent MG5aMC to re-attempt MA5 installation, start MG5aMC with './bin/mg5_aMC --debug'.")
5559 for option in ['--no_MA5_further_install', '--no_root_in_MA5', '--force']:
5560 if option not in add_options:
5561 add_options.append(option)
5562 self.advanced_install('madanalysis5',
5563 HepToolsInstaller_web_address=HepToolsInstaller_web_address,
5564 additional_options=add_options)
5565 else:
5566 logger.critical("Default installation of Madanalys5 failed, we suggest you try again with the options '--no_MA5_further_install --no_root_in_MA5'.")
5567 raise self.InvalidCmd("Installation of %s failed."%tool_to_install)
5568
5569
5570 if tool == 'pythia8':
5571 self.options['pythia8_path'] = pjoin(prefix,'pythia8')
5572 self.exec_cmd('save options %s pythia8_path' % config_file, printcmd=False, log=False)
5573
5574
5575 self.advanced_install('mg5amc_py8_interface',
5576 additional_options=add_options+['--force'])
5577 elif tool == 'lhapdf6':
5578 self.options['lhapdf'] = pjoin(prefix,'lhapdf6','bin', 'lhapdf-config')
5579 self.exec_cmd('save options %s lhapdf' % config_file)
5580 elif tool == 'lhapdf5':
5581 self.options['lhapdf'] = pjoin(prefix,'lhapdf5','bin', 'lhapdf-config')
5582 self.exec_cmd('save options %s lhapdf' % config_file, printcmd=False, log=False)
5583 elif tool == 'madanalysis5':
5584 self.options['madanalysis5_path'] = pjoin(prefix, 'madanalysis5','madanalysis5')
5585 self.exec_cmd('save options madanalysis5_path', printcmd=False, log=False)
5586 elif tool == 'mg5amc_py8_interface':
5587
5588 if self.options['pythia8_path'] in ['',None,'None']:
5589 self.options['pythia8_path'] = pjoin(prefix,'pythia8')
5590 self.options['mg5amc_py8_interface_path'] = pjoin(prefix, 'MG5aMC_PY8_interface')
5591 self.exec_cmd('save options %s mg5amc_py8_interface_path' % config_file,
5592 printcmd=False, log=False)
5593 elif tool == 'collier':
5594 self.options['collier'] = pjoin(prefix,'lib')
5595 self.exec_cmd('save options %s collier' % config_file, printcmd=False, log=False)
5596 elif tool == 'ninja':
5597 if not misc.get_ninja_quad_prec_support(pjoin(
5598 prefix,'ninja','lib')):
5599 logger.warning(
5600 """Successful installation of Ninja, but without support for quadruple precision
5601 arithmetics. If you want to enable this (hence improving the treatment of numerically
5602 unstable points in the loop matrix elements) you can try to reinstall Ninja with:
5603 MG5aMC>install ninja
5604 After having made sure to have selected a C++ compiler in the 'cpp' option of
5605 MG5aMC that supports quadruple precision (typically g++ based on gcc 4.6+).""")
5606 self.options['ninja'] = pjoin(prefix,'lib')
5607 self.exec_cmd('save options %s ninja' % config_file, printcmd=False, log=False)
5608
5609
5610
5611 path_to_be_set = []
5612 if sys.platform == "darwin":
5613 library_variables = ["DYLD_LIBRARY_PATH"]
5614 else:
5615 library_variables = ["LD_LIBRARY_PATH"]
5616 for variable in library_variables:
5617 if (variable not in os.environ) or \
5618 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','lib'))==\
5619 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5620 path_to_be_set.append((variable,
5621 os.path.abspath(pjoin(MG5DIR,'HEPTools','lib'))))
5622 for variable in ["PATH"]:
5623 if (variable not in os.environ) or \
5624 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','bin'))==\
5625 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5626 path_to_be_set.append((variable,
5627 os.path.abspath(pjoin(MG5DIR,'HEPTools','bin'))))
5628 if (variable not in os.environ) or \
5629 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','include'))==\
5630 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5631 path_to_be_set.append((variable,
5632 os.path.abspath(pjoin(MG5DIR,'HEPTools','include'))))
5633
5634 if len(path_to_be_set)>0:
5635 shell_type = misc.get_shell_type()
5636 if shell_type in ['bash',None]:
5637 modification_line = r"printf '\n# MG5aMC paths:\n%s\n' >> ~/.bashrc"%\
5638 (r'\n'.join('export %s=%s%s'%
5639 (var,path,'%s$%s'%(os.pathsep,var)) for var,path in path_to_be_set))
5640 elif shell_type=='tcsh':
5641 modification_line = r"printf '\n# MG5aMC paths:\n%s\n' >> ~/.cshrc"%\
5642 (r'\n'.join('setenv %s %s%s'%
5643 (var,path,'%s$%s'%(os.pathsep,var)) for var,path in path_to_be_set))
5644
5645 logger.debug("==========")
5646 logger.debug("We recommend that you add to the following paths"+\
5647 " to your environment variables, so that you are guaranteed that"+\
5648 " at runtime, MG5_aMC will use the tools you have just installed"+\
5649 " and not some other versions installed elsewhere on your system.\n"+\
5650 "You can do so by running the following command in your terminal:"
5651 "\n %s"%modification_line)
5652 logger.debug("==========")
5653
5654
5655 return True
5656
5657 - def do_install(self, line, paths=None, additional_options=[]):
5658 """Install optional package from the MG suite.
5659 The argument 'additional_options' will be passed to the advanced_install
5660 functions. If it contains the option '--force', then the advanced_install
5661 function will overwrite any existing installation of the tool without
5662 warnings.
5663 """
5664
5665
5666 add_options = list(additional_options)
5667
5668 args = self.split_arg(line)
5669
5670 install_options = self.check_install(args)
5671
5672 if sys.platform == "darwin":
5673 program = "curl"
5674 else:
5675 program = "wget"
5676
5677
5678 if args[0] == 'update':
5679 self.install_update(['update']+install_options['update_options'],wget=program)
5680 return
5681
5682 plugin = ['maddm']
5683
5684 advertisements = {'pythia-pgs':['arXiv:0603175'],
5685 'Delphes':['arXiv:1307.6346'],
5686 'Delphes2':['arXiv:0903.2225'],
5687 'SysCalc':['arXiv:XXXX.YYYYY'],
5688 'Golem95':['arXiv:0807.0605'],
5689 'PJFry':['arXiv:1210.4095','arXiv:1112.0500'],
5690 'QCDLoop':['arXiv:0712.1851'],
5691 'pythia8':['arXiv:1410.3012'],
5692 'lhapdf6':['arXiv:1412.7420'],
5693 'lhapdf5':['arXiv:0605240'],
5694 'hepmc':['CPC 134 (2001) 41-46'],
5695 'mg5amc_py8_interface':['arXiv:1410.3012','arXiv:XXXX.YYYYY'],
5696 'ninja':['arXiv:1203.0291','arXiv:1403.1229','arXiv:1604.01363'],
5697 'MadAnalysis5':['arXiv:1206.1599'],
5698 'MadAnalysis':['arXiv:1206.1599'],
5699 'collier':['arXiv:1604.06792'],
5700 'oneloop':['arXiv:1007.4716'],
5701 'maddm':['arXiv:1505.04190']}
5702
5703
5704 if args[0] in advertisements:
5705
5706
5707
5708
5709
5710 logger.info(" You are installing '%s', please cite ref(s): \033[92m%s\033[0m. " % (args[0], ', '.join(advertisements[args[0]])), '$MG:color:BLACK')
5711
5712
5713 import urllib
5714 if paths:
5715 path = paths
5716 else:
5717 path = {}
5718
5719 data_path = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
5720 'http://madgraph.physics.illinois.edu/package_info.dat']
5721
5722 r = random.randint(0,1)
5723 r = [r, (1-r)]
5724
5725 if any(a.startswith('--source=') for a in args):
5726 source = [a[9:] for a in args if a.startswith('--source=')][-1]
5727 if source == 'uiuc':
5728 r = [1]
5729 elif source == 'ucl':
5730 r = [0]
5731 else:
5732 data_path.append(source)
5733 r = [2]
5734 else:
5735 r = random.randint(0,1)
5736 r = [r, (1-r)]
5737
5738
5739
5740 for index in r:
5741 cluster_path = data_path[index]
5742 try:
5743 data = urllib.urlopen(cluster_path)
5744 except Exception:
5745 continue
5746 break
5747 else:
5748 raise MadGraph5Error, '''Impossible to connect any of us servers.
5749 Please check your internet connection or retry later'''
5750 for line in data:
5751 split = line.split()
5752 path[split[0]] = split[1]
5753
5754
5755
5756
5757
5758
5759
5760 if args[0] == 'Delphes':
5761 args[0] = 'Delphes3'
5762
5763 try:
5764 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
5765 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
5766 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'madanalysis5',
5767 'MadAnalysis4':'MadAnalysis',
5768 'SysCalc':'SysCalc', 'Golem95': 'golem95',
5769 'PJFry':'PJFry','QCDLoop':'QCDLoop','MadAnalysis5':'madanalysis5'
5770 }
5771 name = name[args[0]]
5772 except KeyError:
5773 name = args[0]
5774
5775 if args[0] in self._advanced_install_opts:
5776
5777
5778
5779
5780 MG5aMC_PY8_interface_path = path['MG5aMC_PY8_interface'] if \
5781 'MG5aMC_PY8_interface' in path else 'NA'
5782 add_options.append('--mg5amc_py8_interface_tarball=%s'%\
5783 MG5aMC_PY8_interface_path)
5784 add_options.extend(install_options['options_for_HEPToolsInstaller'])
5785 if not any(opt.startswith('--logging=') for opt in add_options):
5786 add_options.append('--logging=%d' % logger.level)
5787
5788 return self.advanced_install(name, path['HEPToolsInstaller'],
5789 additional_options = add_options)
5790
5791 if args[0] == 'PJFry' and not os.path.exists(
5792 pjoin(MG5DIR,'QCDLoop','lib','libqcdloop1.a')):
5793 logger.info("Installing PJFRY's dependence QCDLoop...")
5794 self.do_install('QCDLoop', paths=path)
5795
5796 if args[0] == 'Delphes':
5797 args[0] = 'Delphes3'
5798 if args[0] == 'MadAnalysis4':
5799 args[0] = 'MadAnalysis'
5800 try:
5801 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
5802 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
5803 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'MadAnalysis',
5804 'SysCalc':'SysCalc', 'Golem95': 'golem95',
5805 'PJFry':'PJFry','QCDLoop':'QCDLoop',
5806 'maddm':'maddm'
5807 }
5808 name = name[args[0]]
5809 except:
5810 pass
5811
5812
5813 substitution={'Delphes2':'Delphes','pythia-pgs':'pythia8'}
5814 if args[0] in substitution:
5815 logger.warning("Please Note that this package is NOT maintained anymore by their author(s).\n"+\
5816 " You should consider installing and using %s, with:\n"%substitution[args[0]]+
5817 " > install %s"%substitution[args[0]])
5818
5819 try:
5820 os.system('rm -rf %s' % pjoin(MG5DIR, name))
5821 except Exception:
5822 pass
5823
5824
5825 logger.info('Downloading %s' % path[args[0]])
5826 if sys.platform == "darwin":
5827 misc.call(['curl', path[args[0]], '-o%s.tgz' % name], cwd=MG5DIR)
5828 else:
5829 misc.call(['wget', path[args[0]], '--output-document=%s.tgz'% name], cwd=MG5DIR)
5830
5831
5832 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
5833 stdout=open(os.devnull, 'w'))
5834
5835 if returncode:
5836 raise MadGraph5Error, 'Fail to download correctly the File. Stop'
5837
5838
5839
5840 if not os.path.exists(pjoin(MG5DIR, name)):
5841 created_name = [n for n in os.listdir(MG5DIR) if n.lower().startswith(
5842 name.lower()) and not n.endswith('gz')]
5843 if not created_name:
5844 raise MadGraph5Error, 'The file was not loaded correctly. Stop'
5845 else:
5846 created_name = created_name[0]
5847 files.mv(pjoin(MG5DIR, created_name), pjoin(MG5DIR, name))
5848
5849
5850 logger.info('compile %s. This might take a while.' % name)
5851
5852
5853 if args[0] == "pythia-pgs" and sys.maxsize > 2**32:
5854 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
5855 text = open(path).read()
5856 text = text.replace('MBITS=32','MBITS=64')
5857 open(path, 'w').writelines(text)
5858 if not os.path.exists(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib')):
5859 os.mkdir(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib'))
5860
5861 make_flags = []
5862
5863
5864 if 'FC' not in os.environ or not os.environ['FC']:
5865 if self.options['fortran_compiler'] and self.options['fortran_compiler'] != 'None':
5866 compiler = self.options['fortran_compiler']
5867 elif misc.which('gfortran'):
5868 compiler = 'gfortran'
5869 elif misc.which('g77'):
5870 compiler = 'g77'
5871 else:
5872 raise self.InvalidCmd('Require g77 or Gfortran compiler')
5873
5874 path = None
5875 base_compiler= ['FC=g77','FC=gfortran']
5876 if args[0] == "pythia-pgs":
5877 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
5878 elif args[0] == 'MadAnalysis':
5879 path = os.path.join(MG5DIR, 'MadAnalysis', 'makefile')
5880 if path:
5881 text = open(path).read()
5882 for base in base_compiler:
5883 text = text.replace(base,'FC=%s' % compiler)
5884 open(path, 'w').writelines(text)
5885 os.environ['FC'] = compiler
5886
5887
5888 if name == 'golem95':
5889
5890 ld_path = misc.Popen(['./configure',
5891 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC']],
5892 cwd=pjoin(MG5DIR,'golem95'),stdout=subprocess.PIPE).communicate()[0]
5893
5894
5895 if name == 'PJFry':
5896
5897 ld_path = misc.Popen(['./configure',
5898 '--prefix=%s'%str(pjoin(MG5DIR, name)),
5899 '--enable-golem-mode', '--with-integrals=qcdloop1',
5900 'LDFLAGS=-L%s'%str(pjoin(MG5DIR,'QCDLoop','lib')),
5901 'FC=%s'%os.environ['FC'],
5902 'F77=%s'%os.environ['FC']], cwd=pjoin(MG5DIR,name),
5903 stdout=subprocess.PIPE).communicate()[0]
5904
5905
5906 if name == 'QCDLoop':
5907
5908 ld_path = misc.Popen(['./configure',
5909 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC'],
5910 'F77=%s'%os.environ['FC']], cwd=pjoin(MG5DIR,name),
5911 stdout=subprocess.PIPE).communicate()[0]
5912
5913
5914 if args[0] == 'Delphes3':
5915
5916
5917
5918
5919 rootsys = os.environ['ROOTSYS']
5920 text = open(pjoin(MG5DIR, 'Delphes','Makefile')).read()
5921 text = text.replace('DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS)',
5922 'DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS) -Wl,-rpath,%s/lib/' % rootsys)
5923 open(pjoin(MG5DIR, 'Delphes','Makefile'),'w').write(text)
5924
5925
5926 if name == 'SysCalc':
5927 if self.options['lhapdf']:
5928 ld_path = misc.Popen([self.options['lhapdf'], '--libdir'],
5929 stdout=subprocess.PIPE).communicate()[0]
5930 ld_path = ld_path.replace('\n','')
5931 if 'LD_LIBRARY_PATH' not in os.environ:
5932 os.environ['LD_LIBRARY_PATH'] = ld_path
5933 elif not os.environ['LD_LIBRARY_PATH']:
5934 os.environ['LD_LIBRARY_PATH'] = ld_path
5935 elif ld_path not in os.environ['LD_LIBRARY_PATH']:
5936 os.environ['LD_LIBRARY_PATH'] += ';%s' % ld_path
5937 if self.options['lhapdf'] != 'lhapdf-config':
5938 if misc.which('lhapdf-config') != os.path.realpath(self.options['lhapdf']):
5939 os.environ['PATH'] = '%s:%s' % (os.path.realpath(self.options['lhapdf']),os.environ['PATH'])
5940 else:
5941 raise self.InvalidCmd('lhapdf is required to compile/use SysCalc. Specify his path or install it via install lhapdf6')
5942 if self.options['cpp_compiler']:
5943 make_flags.append('CXX=%s' % self.options['cpp_compiler'])
5944
5945
5946 if name in plugin:
5947 logger.info('no compilation needed for plugin. Loading plugin information')
5948 try:
5949 shutil.rmtree(pjoin(MG5DIR, 'PLUGIN', name))
5950 except Exception:
5951 pass
5952 shutil.move(pjoin(os.path.join(MG5DIR, name)), os.path.join(MG5DIR, 'PLUGIN', name))
5953
5954 try:
5955 __import__('PLUGIN.%s' % name, globals(), locals(), [], -1)
5956 plugin = sys.modules['PLUGIN.%s' % name]
5957 new_interface = plugin.new_interface
5958 new_output = plugin.new_output
5959 latest_validated_version = plugin.latest_validated_version
5960 minimal_mg5amcnlo_version = plugin.minimal_mg5amcnlo_version
5961 maximal_mg5amcnlo_version = plugin.maximal_mg5amcnlo_version
5962 except Exception, error:
5963 raise Exception, 'Plugin %s fail to be loaded. Please contact the author of the PLUGIN\n Error %s' % (name, error)
5964
5965 logger.info('Plugin %s correctly interfaced. Latest official validition for MG5aMC version %s.' % (name, '.'.join(`i` for i in latest_validated_version)))
5966 if new_interface:
5967 ff = open(pjoin(MG5DIR, 'bin', '%s.py' % name) , 'w')
5968 if __debug__:
5969 text = '''#! /usr/bin/env python
5970 import os
5971 import sys
5972 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
5973 exe_path = os.path.join(root_path,'bin','mg5_aMC')
5974 sys.argv.pop(0)
5975 os.system('%s -tt %s %s --mode={0}' %(sys.executable, str(exe_path) , ' '.join(sys.argv) ))
5976 '''.format(name)
5977 else:
5978 text = '''#! /usr/bin/env python
5979 import os
5980 import sys
5981 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
5982 exe_path = os.path.join(root_path,'bin','mg5_aMC')
5983 sys.argv.pop(0)
5984 os.system('%s -O -W ignore::DeprecationWarning %s %s --mode={0}' %(sys.executable, str(exe_path) , ' '.join(sys.argv) ))
5985 '''.format(name)
5986 ff.write(text)
5987 ff.close()
5988 import stat
5989 os.chmod(pjoin(MG5DIR, 'bin', '%s.py' % name), stat.S_IRWXU)
5990 logger.info('To use this module, you need to quite MG5aMC and run the executable bin/%s.py' % name)
5991 status=0
5992
5993 elif logger.level <= logging.INFO:
5994 devnull = open(os.devnull,'w')
5995 try:
5996 misc.call(['make', 'clean'], stdout=devnull, stderr=-2)
5997 except Exception:
5998 pass
5999 if name == 'pythia-pgs':
6000
6001 status = misc.call(['make'], cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
6002 if name in ['golem95','QCDLoop','PJFry']:
6003 status = misc.call(['make','install'],
6004 cwd = os.path.join(MG5DIR, name))
6005 else:
6006 status = misc.call(['make']+make_flags, cwd = os.path.join(MG5DIR, name))
6007 else:
6008 try:
6009 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
6010 except Exception:
6011 pass
6012 if name == 'pythia-pgs':
6013
6014 status = self.compile(mode='', cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
6015 if name in ['golem95','QCDLoop','PJFry']:
6016 status = misc.compile(['install'], mode='',
6017 cwd = os.path.join(MG5DIR, name))
6018 else:
6019 status = self.compile(make_flags, mode='',
6020 cwd = os.path.join(MG5DIR, name))
6021
6022 if not status:
6023 logger.info('Installation succeeded')
6024 else:
6025
6026 if name == 'pythia-pgs':
6027 to_comment = ['libraries/PGS4/src/stdhep-dir/mcfio/arch_mcfio',
6028 'libraries/PGS4/src/stdhep-dir/src/stdhep_Arch']
6029 for f in to_comment:
6030 f = pjoin(MG5DIR, name, *f.split('/'))
6031 text = "".join(l for l in open(f) if 'fno-second-underscore' not in l)
6032 fsock = open(f,'w').write(text)
6033 try:
6034 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
6035 except Exception:
6036 pass
6037 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
6038 if not status:
6039 logger.info('Compilation succeeded')
6040 else:
6041 logger.warning('Error detected during the compilation. Please check the compilation error and run make manually.')
6042
6043
6044
6045 if args[0] == 'MadAnalysis':
6046 try:
6047 os.system('rm -rf td')
6048 os.mkdir(pjoin(MG5DIR, 'td'))
6049 except Exception, error:
6050 print error
6051 pass
6052
6053 if sys.platform == "darwin":
6054 logger.info('Downloading TD for Mac')
6055 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td_mac_intel.tar.gz'
6056 misc.call(['curl', target, '-otd.tgz'],
6057 cwd=pjoin(MG5DIR,'td'))
6058 misc.call(['tar', '-xzpvf', 'td.tgz'],
6059 cwd=pjoin(MG5DIR,'td'))
6060 files.mv(MG5DIR + '/td/td_mac_intel',MG5DIR+'/td/td')
6061 else:
6062 if sys.maxsize > 2**32:
6063 logger.info('Downloading TD for Linux 64 bit')
6064 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td64/td'
6065 logger.warning('''td program (needed by MadAnalysis) is not compile for 64 bit computer.
6066 In 99% of the case, this is perfectly fine. If you do not have plot, please follow
6067 instruction in https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/TopDrawer .''')
6068 else:
6069 logger.info('Downloading TD for Linux 32 bit')
6070 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td'
6071 misc.call(['wget', target], cwd=pjoin(MG5DIR,'td'))
6072 os.chmod(pjoin(MG5DIR,'td','td'), 0775)
6073 self.options['td_path'] = pjoin(MG5DIR,'td')
6074
6075 if not misc.which('gs'):
6076 logger.warning('''gosthscript not install on your system. This is not required to run MA.
6077 but this prevent to create jpg files and therefore to have the plots in the html output.''')
6078 if sys.platform == "darwin":
6079 logger.warning('''You can download this program at the following link:
6080 http://www.macupdate.com/app/mac/9980/gpl-ghostscript''')
6081
6082 if args[0] == 'Delphes2':
6083 data = open(pjoin(MG5DIR, 'Delphes','data','DetectorCard.dat')).read()
6084 data = data.replace('data/', 'DELPHESDIR/data/')
6085 out = open(pjoin(MG5DIR, 'Template','Common', 'Cards', 'delphes_card_default.dat'), 'w')
6086 out.write(data)
6087 if args[0] == 'Delphes3':
6088 if os.path.exists(pjoin(MG5DIR, 'Delphes','cards')):
6089 card_dir = pjoin(MG5DIR, 'Delphes','cards')
6090 else:
6091 card_dir = pjoin(MG5DIR, 'Delphes','examples')
6092 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
6093 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_default.dat'))
6094 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
6095 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_CMS.dat'))
6096 files.cp(pjoin(card_dir,'delphes_card_ATLAS.tcl'),
6097 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_ATLAS.dat'))
6098
6099
6100
6101 options_name = {'Delphes': 'delphes_path',
6102 'Delphes2': 'delphes_path',
6103 'Delphes3': 'delphes_path',
6104 'ExRootAnalysis': 'exrootanalysis_path',
6105 'MadAnalysis': 'madanalysis_path',
6106 'SysCalc': 'syscalc_path',
6107 'pythia-pgs':'pythia-pgs_path',
6108 'Golem95': 'golem',
6109 'PJFry': 'pjfry'}
6110
6111 if args[0] in options_name:
6112 opt = options_name[args[0]]
6113 if opt=='golem':
6114 self.options[opt] = pjoin(MG5DIR,name,'lib')
6115 self.exec_cmd('save options %s' % opt, printcmd=False)
6116 elif opt=='pjfry':
6117 self.options[opt] = pjoin(MG5DIR,'PJFry','lib')
6118 self.exec_cmd('save options %s' % opt, printcmd=False)
6119 elif self.options[opt] != self.options_configuration[opt]:
6120 self.options[opt] = self.options_configuration[opt]
6121 self.exec_cmd('save options %s' % opt, printcmd=False)
6122
6123
6124
6126 """ check if the current version of mg5 is up-to-date.
6127 and allow user to install the latest version of MG5 """
6128
6129 def apply_patch(filetext):
6130 """function to apply the patch"""
6131 text = filetext.read()
6132 pattern = re.compile(r'''=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
6133
6134 for orig, new in pattern.findall(text):
6135 shutil.copytree(pjoin(MG5DIR, orig), pjoin(MG5DIR, 'UPDATE_TMP'))
6136 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
6137 for i, name in enumerate(full_path):
6138 path = os.path.sep.join(full_path[:i+1])
6139 if path and not os.path.isdir(path):
6140 os.mkdir(path)
6141 shutil.copytree(pjoin(MG5DIR, 'UPDATE_TMP'), pjoin(MG5DIR, new))
6142 shutil.rmtree(pjoin(MG5DIR, 'UPDATE_TMP'))
6143
6144 pattern = re.compile(r'''=== renamed file \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
6145
6146 for orig, new in pattern.findall(text):
6147 print 'move %s to %s' % (orig, new)
6148 try:
6149 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
6150 except IOError:
6151 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
6152 for i, name in enumerate(full_path):
6153 path = os.path.sep.join(full_path[:i+1])
6154 if path and not os.path.isdir(path):
6155 os.mkdir(path)
6156 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
6157
6158 pattern = re.compile(r'''^=== added file \'(?P<new>[^\']*)\'''',re.M)
6159 all_add = pattern.findall(text)
6160
6161
6162 pattern=re.compile(r'''=== removed file \'(?P<new>[^\']*)\'(?=.*=== added file \'(?P=new)\')''',re.S)
6163 print 'this step can take a few minuts. please be patient'
6164 all_rm_add = pattern.findall(text)
6165
6166 for new in all_add:
6167 if new in all_rm_add:
6168 continue
6169 if os.path.isfile(pjoin(MG5DIR, new)):
6170 os.remove(pjoin(MG5DIR, new))
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182 p= subprocess.Popen(['patch', '-p1'], stdin=subprocess.PIPE,
6183 cwd=MG5DIR)
6184 p.communicate(text)
6185
6186
6187
6188
6189
6190 pattern=re.compile('''=== modified file \'(?P<new>[^\']*)\'[^\n]*\n\-\-\- old/(?P<old>\S*)[^\n]*\n\+\+\+ new/(?P=new)''',re.S)
6191 for match in pattern.findall(text):
6192 new = pjoin(MG5DIR, match[0])
6193 old = pjoin(MG5DIR, match[1])
6194 if new == old:
6195 continue
6196 elif os.path.exists(old):
6197 if not os.path.exists(os.path.dirname(new)):
6198 split = new.split('/')
6199 for i in range(1,len(split)):
6200 path = '/'.join(split[:i])
6201 if not os.path.exists(path):
6202 print 'mkdir', path
6203 os.mkdir(path)
6204 files.cp(old,new)
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225 for path in misc.glob('*', pjoin(MG5DIR, 'bin')):
6226 misc.call(['chmod', '+x', path])
6227 for path in misc.glob(pjoin('*','bin','*'), pjoin(MG5DIR, 'Template')):
6228 misc.call(['chmod', '+x', path])
6229 for path in misc.glob(pjoin('*','bin','internal','*'), pjoin(MG5DIR, 'Template')):
6230 misc.call(['chmod', '+x', path])
6231 for path in misc.glob(pjoin('*','*', '*.py'), pjoin(MG5DIR, 'Template')):
6232 misc.call(['chmod', '+x', path])
6233 for path in misc.glob(pjoin('*','*','*.sh'), pjoin(MG5DIR, 'Template')):
6234 misc.call(['chmod', '+x', path])
6235
6236
6237 pattern=re.compile('''^=== touch (file|directory) \'(?P<new>[^\']*)\'''',re.M)
6238 for match in pattern.findall(text):
6239 if match[0] == 'file':
6240 new = os.path.dirname(pjoin(MG5DIR, match[1]))
6241 else:
6242 new = pjoin(MG5DIR, match[1])
6243 if not os.path.exists(new):
6244 split = new.split('/')
6245 for i in range(1,len(split)+1):
6246 path = '/'.join(split[:i])
6247 if path and not os.path.exists(path):
6248 print 'mkdir', path
6249 os.mkdir(path)
6250 if match[0] == 'file':
6251 print 'touch ', pjoin(MG5DIR, match[1])
6252 misc.call(['touch', pjoin(MG5DIR, match[1])])
6253
6254 pattern=re.compile('''^=== link file \'(?P<new>[^\']*)\' \'(?P<old>[^\']*)\'''', re.M)
6255 for new, old in pattern.findall(text):
6256 if not os.path.exists(pjoin(MG5DIR, new)):
6257 files.ln(old, os.path.dirname(new), os.path.basename(new))
6258
6259
6260 if os.path.isfile(pjoin(MG5DIR,'vendor','CutTools','includects','libcts.a')):
6261 misc.compile(arg=['-j1'],cwd=pjoin(MG5DIR,'vendor','CutTools'),nb_core=1)
6262 if os.path.isfile(pjoin(MG5DIR,'vendor','IREGI','src','libiregi.a')):
6263 misc.compile(cwd=pjoin(MG5DIR,'vendor','IREGI','src'))
6264
6265
6266 pattern = re.compile("""^Binary files old/(\S*).*and new/(\S*).*$""", re.M)
6267 if pattern.search(text):
6268 return True
6269 else:
6270 return False
6271
6272 mode = [arg.split('=',1)[1] for arg in args if arg.startswith('--mode=')]
6273 if mode:
6274 mode = mode[-1]
6275 else:
6276 mode = "userrequest"
6277 force = any([arg=='-f' for arg in args])
6278 timeout = [arg.split('=',1)[1] for arg in args if arg.startswith('--timeout=')]
6279 if timeout:
6280 try:
6281 timeout = int(timeout[-1])
6282 except ValueError:
6283 raise self.InvalidCmd('%s: invalid argument for timeout (integer expected)'%timeout[-1])
6284 else:
6285 timeout = self.options['timeout']
6286 input_path = [arg.split('=',1)[1] for arg in args if arg.startswith('--input=')]
6287
6288 if input_path:
6289 fsock = open(input_path[0])
6290 need_binary = apply_patch(fsock)
6291 logger.info('manual patch apply. Please test your version.')
6292 if need_binary:
6293 logger.warning('Note that some files need to be loaded separately!')
6294 sys.exit(0)
6295
6296 options = ['y','n','on_exit']
6297 if mode == 'mg5_start':
6298 timeout = 2
6299 default = 'n'
6300 update_delay = self.options['auto_update'] * 24 * 3600
6301 if update_delay == 0:
6302 return
6303 elif mode == 'mg5_end':
6304 timeout = 5
6305 default = 'n'
6306 update_delay = self.options['auto_update'] * 24 * 3600
6307 if update_delay == 0:
6308 return
6309 options.remove('on_exit')
6310 elif mode == "userrequest":
6311 default = 'y'
6312 update_delay = 0
6313 else:
6314 raise self.InvalidCmd('Unknown mode for command install update')
6315
6316 if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')) or \
6317 os.path.exists(os.path.join(MG5DIR,'.bzr')):
6318 error_text = """This version of MG5 doesn\'t support auto-update. Common reasons are:
6319 1) This version was loaded via bazaar (use bzr pull to update instead).
6320 2) This version is a beta release of MG5."""
6321 if mode == 'userrequest':
6322 raise self.ConfigurationError(error_text)
6323 return
6324
6325 if not misc.which('patch'):
6326 error_text = """Not able to find program \'patch\'. Please reload a clean version
6327 or install that program and retry."""
6328 if mode == 'userrequest':
6329 raise self.ConfigurationError(error_text)
6330 return
6331
6332
6333 data = {}
6334 for line in open(os.path.join(MG5DIR,'input','.autoupdate')):
6335 if not line.strip():
6336 continue
6337 sline = line.split()
6338 data[sline[0]] = int(sline[1])
6339
6340
6341 if 'version_nb' not in data:
6342 if mode == 'userrequest':
6343 error_text = 'This version of MG5 doesn\'t support auto-update. (Invalid information)'
6344 raise self.ConfigurationError(error_text)
6345 return
6346 elif 'last_check' not in data:
6347 data['last_check'] = time.time()
6348
6349
6350 if time.time() - data['last_check'] < update_delay:
6351 return
6352
6353 logger.info('Checking if MG5 is up-to-date... (takes up to %ss)' % timeout)
6354 class TimeOutError(Exception): pass
6355
6356 def handle_alarm(signum, frame):
6357 raise TimeOutError
6358
6359 signal.signal(signal.SIGALRM, handle_alarm)
6360 signal.alarm(timeout)
6361 to_update = 0
6362 try:
6363 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/mg5amc_build_nb')
6364 signal.alarm(0)
6365 web_version = int(filetext.read().strip())
6366 except (TimeOutError, ValueError, IOError):
6367 signal.alarm(0)
6368 print 'failed to connect server'
6369 if mode == 'mg5_end':
6370
6371 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6372 fsock.write("version_nb %s\n" % data['version_nb'])
6373 fsock.write("last_check %s\n" % \
6374 int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1))
6375 fsock.close()
6376 return
6377
6378 if web_version == data['version_nb']:
6379 logger.info('No new version of MG5 available')
6380
6381 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6382 fsock.write("version_nb %s\n" % data['version_nb'])
6383 fsock.write("last_check %s\n" % int(time.time()))
6384 fsock.close()
6385 return
6386 elif data['version_nb'] > web_version:
6387 logger_stderr.info('impossible to update: local %s web %s' % (data['version_nb'], web_version))
6388 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6389 fsock.write("version_nb %s\n" % data['version_nb'])
6390 fsock.write("last_check %s\n" % int(time.time()))
6391 fsock.close()
6392 return
6393 else:
6394 if not force:
6395 answer = self.ask('New Version of MG5 available! Do you want to update your current version?',
6396 default, options)
6397 else:
6398 answer = default
6399
6400
6401 if answer == 'y':
6402 logger.info('start updating code')
6403 fail = 0
6404 for i in range(data['version_nb'], web_version):
6405 try:
6406 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/patch/build%s.patch' %(i+1))
6407
6408 except Exception:
6409 print 'fail to load patch to build #%s' % (i+1)
6410 fail = i
6411 break
6412 need_binary = apply_patch(filetext)
6413 if need_binary:
6414 path = "http://madgraph.phys.ucl.ac.be/binary/binary_file%s.tgz" %(i+1)
6415 name = "extra_file%i" % (i+1)
6416 if sys.platform == "darwin":
6417 misc.call(['curl', path, '-o%s.tgz' % name], cwd=MG5DIR)
6418 else:
6419 misc.call(['wget', path, '--output-document=%s.tgz'% name], cwd=MG5DIR)
6420
6421 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
6422 stdout=open(os.devnull, 'w'))
6423
6424 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6425 if not fail:
6426 fsock.write("version_nb %s\n" % web_version)
6427 else:
6428 fsock.write("version_nb %s\n" % fail)
6429 fsock.write("last_check %s\n" % int(time.time()))
6430 fsock.close()
6431 logger.info('Refreshing installation of MG5aMC_PY8_interface.')
6432 self.do_install('mg5amc_py8_interface',additional_options=['--force'])
6433 logger.info('Checking current version. (type ctrl-c to bypass the check)')
6434 subprocess.call([os.path.join('tests','test_manager.py')],
6435 cwd=MG5DIR)
6436 print 'new version installed, please relaunch mg5'
6437 try:
6438 os.remove(pjoin(MG5DIR, 'Template','LO','Source','make_opts'))
6439 shutil.copy(pjoin(MG5DIR, 'Template','LO','Source','.make_opts'),
6440 pjoin(MG5DIR, 'Template','LO','Source','make_opts'))
6441 except:
6442 pass
6443 sys.exit(0)
6444 elif answer == 'n':
6445
6446 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6447 fsock.write("version_nb %s\n" % data['version_nb'])
6448 fsock.write("last_check %s\n" % int(time.time()))
6449 fsock.close()
6450 logger.info('Update bypassed.')
6451 logger.info('The next check for a new version will be performed in %s days' \
6452 % abs(self.options['auto_update']))
6453 logger.info('In order to change this delay. Enter the command:')
6454 logger.info('set auto_update X')
6455 logger.info('Putting X to zero will prevent this check at anytime.')
6456 logger.info('You can upgrade your version at any time by typing:')
6457 logger.info('install update')
6458 else:
6459
6460
6461 self.options['auto_update'] = -1 * self.options['auto_update']
6462
6463
6464
6466 """ assign all configuration variable from file
6467 ./input/mg5_configuration.txt. assign to default if not define """
6468
6469 if not self.options:
6470 self.options = dict(self.options_configuration)
6471 self.options.update(self.options_madgraph)
6472 self.options.update(self.options_madevent)
6473
6474 if not config_path:
6475 if os.environ.has_key('MADGRAPH_BASE'):
6476 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
6477 self.set_configuration(config_path, final=False)
6478 if 'HOME' in os.environ:
6479 config_path = pjoin(os.environ['HOME'],'.mg5',
6480 'mg5_configuration.txt')
6481 if os.path.exists(config_path):
6482 self.set_configuration(config_path, final=False)
6483 config_path = os.path.relpath(pjoin(MG5DIR,'input',
6484 'mg5_configuration.txt'))
6485 return self.set_configuration(config_path, final)
6486
6487 if not os.path.exists(config_path):
6488 files.cp(pjoin(MG5DIR,'input','.mg5_configuration_default.txt'), config_path)
6489 config_file = open(config_path)
6490
6491
6492 logger.info('load MG5 configuration from %s ' % config_file.name)
6493 for line in config_file:
6494 if '#' in line:
6495 line = line.split('#',1)[0]
6496 line = line.replace('\n','').replace('\r\n','')
6497 try:
6498 name, value = line.split('=')
6499 except ValueError:
6500 pass
6501 else:
6502 name = name.strip()
6503 value = value.strip()
6504 if name != 'mg5_path':
6505 self.options[name] = value
6506 if value.lower() == "none" or value=="":
6507 self.options[name] = None
6508 config_file.close()
6509 self.options['stdout_level'] = logging.getLogger('madgraph').level
6510 if not final:
6511 return self.options
6512
6513
6514
6515
6516 for key in self.options:
6517 if key in ['pythia8_path', 'hwpp_path', 'thepeg_path', 'hepmc_path',
6518 'mg5amc_py8_interface_path','madanalysis5_path']:
6519 if self.options[key] in ['None', None]:
6520 self.options[key] = None
6521 continue
6522 path = self.options[key]
6523
6524 if key == 'pythia8_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Pythia8', 'Pythia.h')):
6525 if not os.path.isfile(pjoin(path, 'include', 'Pythia8', 'Pythia.h')):
6526 self.options['pythia8_path'] = None
6527 else:
6528 continue
6529
6530 if key == 'mg5amc_py8_interface_path' and not os.path.isfile(pjoin(MG5DIR, path, 'MG5aMC_PY8_interface')):
6531 if not os.path.isfile(pjoin(path, 'MG5aMC_PY8_interface')):
6532 self.options['mg5amc_py8_interface_path'] = None
6533 else:
6534 continue
6535
6536 if key == 'madanalysis5_path' and not os.path.isfile(pjoin(MG5DIR, path,'bin','ma5')):
6537 if not os.path.isfile(pjoin(path,'bin','ma5')):
6538 self.options['madanalysis5_path'] = None
6539 else:
6540 continue
6541
6542 if key == 'hwpp_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
6543 if not os.path.isfile(pjoin(path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
6544 self.options['hwpp_path'] = None
6545 else:
6546 continue
6547
6548 elif key == 'thepeg_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
6549 if not os.path.isfile(pjoin(path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
6550 self.options['thepeg_path'] = None
6551 else:
6552 continue
6553
6554 elif key == 'hepmc_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'HepMC', 'HEPEVT_Wrapper.h')):
6555 if not os.path.isfile(pjoin(path, 'include', 'HepMC', 'HEPEVT_Wrapper.h')):
6556 self.options['hepmc_path'] = None
6557 else:
6558 continue
6559
6560 elif key in ['pjfry','golem','samurai']:
6561 if isinstance(self.options[key],str) and self.options[key].lower() == 'auto':
6562
6563 program = misc.which_lib('lib%s.a'%key)
6564 if program != None:
6565 fpath, _ = os.path.split(program)
6566 logger.info('Using %s library in %s' % (key,fpath))
6567 self.options[key]=fpath
6568 else:
6569
6570 local_install = {'pjfry':'PJFRY', 'golem':'golem95',
6571 'samurai':'samurai'}
6572 if os.path.isfile(pjoin(MG5DIR,local_install[key],'lib', 'lib%s.a' % key)):
6573 self.options[key]=pjoin(MG5DIR,local_install[key],'lib')
6574 else:
6575 self.options[key]=None
6576
6577 if key=='samurai' and \
6578 isinstance(self.options[key],str) and \
6579 self.options[key].lower() != 'auto':
6580 if os.path.isfile(pjoin(self.options[key],os.pardir,'AUTHORS')):
6581 try:
6582 version = open(pjoin(self.options[key],os.pardir,
6583 'VERSION'),'r').read()
6584 except IOError:
6585 version = None
6586 if version is None:
6587 self.options[key] = None
6588 logger.info('--------')
6589 logger.info(
6590 """The version of 'samurai' automatically detected seems too old to be compatible
6591 with MG5aMC and it will be turned off. Ask the authors for the latest version if
6592 you want to use samurai.
6593 If you want to enforce its use as-it-is, then specify directly its library folder
6594 in the MG5aMC option 'samurai' (instead of leaving it to its default 'auto').""")
6595 logger.info('--------')
6596
6597 elif key.endswith('path'):
6598 pass
6599 elif key in ['run_mode', 'auto_update']:
6600 self.options[key] = int(self.options[key])
6601 elif key in ['cluster_type','automatic_html_opening']:
6602 pass
6603 elif key in ['notification_center']:
6604 if self.options[key] in ['False', 'True']:
6605 self.allow_notification_center = eval(self.options[key])
6606 self.options[key] = self.allow_notification_center
6607 elif key not in ['text_editor','eps_viewer','web_browser', 'stdout_level']:
6608
6609 try:
6610 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
6611 except MadGraph5Error, error:
6612 print error
6613 logger.warning("Option %s from config file not understood" \
6614 % key)
6615 else:
6616 if key in self.options_madgraph:
6617 self.history.append('set %s %s' % (key, self.options[key]))
6618
6619 warnings = madevent_interface.MadEventCmd.mg5amc_py8_interface_consistency_warning(self.options)
6620 if warnings:
6621 logger.warning(warnings)
6622
6623
6624 launch_ext.open_file.configure(self.options)
6625 return self.options
6626
6628 """Check if the files is in a valid export directory and assign it to
6629 export path if if is"""
6630
6631
6632 if self._export_dir:
6633 return
6634
6635 if os.path.exists(pjoin(os.getcwd(), 'Cards')):
6636 self._export_dir = os.getcwd()
6637 return
6638
6639 path_split = filepath.split(os.path.sep)
6640 if len(path_split) > 2 and path_split[-2] == 'Cards':
6641 self._export_dir = os.path.sep.join(path_split[:-2])
6642 return
6643
6645 """Main commands: Ask for editing the parameter and then
6646 Execute the code (madevent/standalone/...)
6647 """
6648
6649
6650 current_options = dict([(name, self.options[name]) for name in self.options_madgraph])
6651 start_cwd = os.getcwd()
6652
6653 args = self.split_arg(line)
6654
6655 (options, args) = _launch_parser.parse_args(args)
6656 self.check_launch(args, options)
6657 options = options.__dict__
6658
6659
6660 if args[0].startswith('standalone'):
6661 if os.path.isfile(os.path.join(os.getcwd(),args[1],'Cards',\
6662 'MadLoopParams.dat')) and not os.path.isfile(os.path.join(\
6663 os.getcwd(),args[1],'SubProcesses','check_poles.f')):
6664 ext_program = launch_ext.MadLoopLauncher(self, args[1], \
6665 options=self.options, **options)
6666 else:
6667 ext_program = launch_ext.SALauncher(self, args[1], \
6668 options=self.options, **options)
6669 elif args[0] == 'madevent':
6670 if options['interactive']:
6671
6672 if isinstance(self, cmd.CmdShell):
6673 ME = madevent_interface.MadEventCmdShell(me_dir=args[1], options=self.options)
6674 else:
6675 ME = madevent_interface.MadEventCmd(me_dir=args[1],options=self.options)
6676 ME.pass_in_web_mode()
6677 stop = self.define_child_cmd_interface(ME)
6678 return stop
6679
6680
6681 if not self._generate_info:
6682
6683
6684 info = open(pjoin(args[1],'SubProcesses','procdef_mg5.dat')).read()
6685 generate_info = info.split('# Begin PROCESS',1)[1].split('\n')[1]
6686 generate_info = generate_info.split('#')[0]
6687 else:
6688 generate_info = self._generate_info
6689
6690 if len(generate_info.split('>')[0].strip().split())>1:
6691 ext_program = launch_ext.MELauncher(args[1], self,
6692 shell = isinstance(self, cmd.CmdShell),
6693 options=self.options,**options)
6694 else:
6695
6696 ext_program = launch_ext.MELauncher(args[1], self, unit='GeV',
6697 shell = isinstance(self, cmd.CmdShell),
6698 options=self.options,**options)
6699
6700 elif args[0] == 'pythia8':
6701 ext_program = launch_ext.Pythia8Launcher( args[1], self, **options)
6702
6703 elif args[0] == 'aMC@NLO':
6704 if options['interactive']:
6705 if isinstance(self, cmd.CmdShell):
6706 ME = amcatnlo_run.aMCatNLOCmdShell(me_dir=args[1], options=self.options)
6707 else:
6708 ME = amcatnlo_run.aMCatNLOCmd(me_dir=args[1],options=self.options)
6709 ME.pass_in_web_mode()
6710
6711 config_line = [l for l in self.history if l.strip().startswith('set')]
6712 for line in config_line:
6713 ME.exec_cmd(line)
6714 stop = self.define_child_cmd_interface(ME)
6715 return stop
6716 ext_program = launch_ext.aMCatNLOLauncher( args[1], self,
6717 shell = isinstance(self, cmd.CmdShell),
6718 **options)
6719 elif args[0] == 'madweight':
6720 import madgraph.interface.madweight_interface as madweight_interface
6721 if options['interactive']:
6722 if isinstance(self, cmd.CmdShell):
6723 MW = madweight_interface.MadWeightCmdShell(me_dir=args[1], options=self.options)
6724 else:
6725 MW = madweight_interface.MadWeightCmd(me_dir=args[1],options=self.options)
6726
6727 config_line = [l for l in self.history if l.strip().startswith('set')]
6728 for line in config_line:
6729 MW.exec_cmd(line)
6730 stop = self.define_child_cmd_interface(MW)
6731 return stop
6732 ext_program = launch_ext.MWLauncher( self, args[1],
6733 shell = isinstance(self, cmd.CmdShell),
6734 options=self.options,**options)
6735 else:
6736 os.chdir(start_cwd)
6737 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
6738
6739
6740 ext_program.run()
6741 os.chdir(start_cwd)
6742
6743 for key, value in current_options.items():
6744 self.options[key] = value
6745
6802
6803
6805 """create a restriction card in a interactive way"""
6806
6807 args = self.split_arg(line)
6808 self.check_customize_model(args)
6809
6810 model_path = self._curr_model.get('modelpath')
6811 if not os.path.exists(pjoin(model_path,'build_restrict.py')):
6812 raise self.InvalidCmd('''Model not compatible with this option.''')
6813
6814
6815 self._curr_model = import_ufo.import_model(model_path, restrict=False)
6816
6817
6818 out_path = StringIO.StringIO()
6819 param_writer.ParamCardWriter(self._curr_model, out_path)
6820
6821 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
6822
6823
6824 all_categories = self.ask('','0',[], ask_class=AskforCustomize)
6825 put_to_one = []
6826
6827 for block in param_card:
6828 value_dict = {}
6829 for param in param_card[block]:
6830 value = param.value
6831 if value == 0:
6832 param.value = 0.000001e-99
6833 elif value == 1:
6834 if block != 'qnumbers':
6835 put_to_one.append((block,param.lhacode))
6836 param.value = random.random()
6837 elif abs(value) in value_dict:
6838 param.value += value_dict[abs(value)] * 1e-4 * param.value
6839 value_dict[abs(value)] += 1
6840 else:
6841 value_dict[abs(value)] = 1
6842
6843 for category in all_categories:
6844 for options in category:
6845 if not options.status:
6846 continue
6847 param = param_card[options.lhablock].get(options.lhaid)
6848 param.value = options.value
6849
6850 logger.info('Loading the resulting model')
6851
6852 self._curr_model = import_ufo.RestrictModel(self._curr_model)
6853 model_name = self._curr_model.get('name')
6854 if model_name == 'mssm':
6855 keep_external=True
6856 else:
6857 keep_external=False
6858 self._curr_model.restrict_model(param_card,keep_external=keep_external)
6859
6860 if args:
6861 name = args[0].split('=',1)[1]
6862 path = pjoin(model_path,'restrict_%s.dat' % name)
6863 logger.info('Save restriction file as %s' % path)
6864 param_card.write(path)
6865 self._curr_model['name'] += '-%s' % name
6866
6867
6868 if put_to_one:
6869 out_path = StringIO.StringIO()
6870 param_writer.ParamCardWriter(self._curr_model, out_path)
6871
6872 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
6873
6874 for (block, lhacode) in put_to_one:
6875 misc.sprint(block, lhacode)
6876 try:
6877 param_card[block].get(lhacode).value = 1
6878 except:
6879 pass
6880 self._curr_model.set_parameters_and_couplings(param_card)
6881
6882 if args:
6883 name = args[0].split('=',1)[1]
6884 path = pjoin(model_path,'paramcard_%s.dat' % name)
6885 logger.info('Save default card file as %s' % path)
6886 param_card.write(path)
6887
6888 - def do_save(self, line, check=True, to_keep={}, log=True):
6889 """Not in help: Save information to file"""
6890
6891
6892 args = self.split_arg(line)
6893
6894 if check:
6895 self.check_save(args)
6896
6897 if args[0] == 'model':
6898 if self._curr_model:
6899
6900 if save_load_object.save_to_file(args[1], self._curr_model):
6901 logger.info('Saved model to file %s' % args[1])
6902 else:
6903 raise self.InvalidCmd('No model to save!')
6904 elif args[0] == 'processes':
6905 if self._curr_amps:
6906 if save_load_object.save_to_file(args[1], (self._curr_amps,self._curr_proc_defs) ):
6907 logger.info('Saved processes to file %s' % args[1])
6908 else:
6909 raise self.InvalidCmd('No processes to save!')
6910
6911 elif args[0] == 'options':
6912 partial_save = False
6913 to_define = {}
6914
6915 if any(not arg.startswith('--') and arg in self.options
6916 for arg in args):
6917
6918 partial_save = True
6919 all_arg = [arg for arg in args[1:] if not arg.startswith('--') and
6920 arg in self.options]
6921 for key in all_arg:
6922 to_define[key] = self.options[key]
6923 else:
6924
6925 for key, default in self.options_configuration.items():
6926 if self.options_configuration[key] != self.options[key] and not self.options_configuration[key] is None:
6927 to_define[key] = self.options[key]
6928
6929 if not '--auto' in args:
6930 for key, default in self.options_madevent.items():
6931 if self.options_madevent[key] != self.options[key] != None:
6932 if '_path' in key and os.path.basename(self.options[key]) == 'None':
6933 continue
6934 to_define[key] = self.options[key]
6935 elif key == 'cluster_queue' and self.options[key] is None:
6936 to_define[key] = self.options[key]
6937
6938 if '--all' in args:
6939 for key, default in self.options_madgraph.items():
6940 if self.options_madgraph[key] != self.options[key] != None and \
6941 key != 'stdout_level':
6942 to_define[key] = self.options[key]
6943 elif not '--auto' in args:
6944 for key, default in self.options_madgraph.items():
6945 if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level':
6946 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
6947 % (key,self.options_madgraph[key]) )
6948 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
6949
6950 if len(args) >1 and not args[1].startswith('--') and args[1] not in self.options:
6951 filepath = args[1]
6952 else:
6953 filepath = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
6954
6955 basedir = MG5DIR
6956 if partial_save:
6957 basefile = filepath
6958 else:
6959 basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt')
6960
6961
6962
6963 if to_keep:
6964 to_define = to_keep
6965 self.write_configuration(filepath, basefile, basedir, to_define)
6966
6967
6968 - def do_set(self, line, log=True, model_reload=True):
6969 """Set an option, which will be default for coming generations/outputs.
6970 """
6971
6972
6973
6974 args = self.split_arg(line)
6975
6976
6977 self.check_set(args)
6978
6979 if args[0] == 'ignore_six_quark_processes':
6980 if args[1] == 'False':
6981 self.options[args[0]] = False
6982 return
6983 self.options[args[0]] = list(set([abs(p) for p in \
6984 self._multiparticles[args[1]]\
6985 if self._curr_model.get_particle(p).\
6986 is_fermion() and \
6987 self._curr_model.get_particle(abs(p)).\
6988 get('color') == 3]))
6989 if log:
6990 logger.info('Ignore processes with >= 6 quarks (%s)' % \
6991 ",".join([\
6992 self._curr_model.get_particle(q).get('name') \
6993 for q in self.options[args[0]]]))
6994
6995 elif args[0] == 'group_subprocesses':
6996 if args[1] not in ['Auto', 'NLO']:
6997 self.options[args[0]] = eval(args[1])
6998 else:
6999 self.options[args[0]] = args[1]
7000 if log:
7001 logger.info('Set group_subprocesses to %s' % \
7002 str(self.options[args[0]]))
7003 logger.info('Note that you need to regenerate all processes')
7004 self._curr_amps = diagram_generation.AmplitudeList()
7005 self._curr_proc_defs = base_objects.ProcessDefinitionList()
7006 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7007
7008 elif args[0] == "stdout_level":
7009 if args[1].isdigit():
7010 level = int(args[1])
7011 else:
7012 level = eval('logging.' + args[1])
7013 logging.root.setLevel(level)
7014 logging.getLogger('madgraph').setLevel(level)
7015 logging.getLogger('madevent').setLevel(level)
7016 self.options[args[0]] = level
7017 if log:
7018 logger.info('set output information to level: %s' % level)
7019 elif args[0].lower() == "ewscheme":
7020 logger.info("Change EW scheme to %s for the model %s. Note that YOU are responsible of the full validity of the input in that scheme." %\
7021 (self._curr_model.get('name'), args[1]))
7022 logger.info("Importing a model will restore the default scheme")
7023 self._curr_model.change_electroweak_mode(args[1])
7024 elif args[0] == "complex_mass_scheme":
7025 old = self.options[args[0]]
7026 self.options[args[0]] = eval(args[1])
7027 aloha.complex_mass = eval(args[1])
7028 aloha_lib.KERNEL.clean()
7029 if self.options[args[0]]:
7030 if old:
7031 if log:
7032 logger.info('Complex mass already activated.')
7033 return
7034 if log:
7035 logger.info('Activate complex mass scheme.')
7036 else:
7037 if not old:
7038 if log:
7039 logger.info('Complex mass already desactivated.')
7040 return
7041 if log:
7042 logger.info('Desactivate complex mass scheme.')
7043 if not self._curr_model:
7044 return
7045 self.exec_cmd('import model %s' % self._curr_model.get('name'))
7046
7047 elif args[0] == "gauge":
7048
7049 if not self._curr_model:
7050 if args[1] == 'unitary':
7051 aloha.unitary_gauge = True
7052 else:
7053 aloha.unitary_gauge = False
7054 aloha_lib.KERNEL.clean()
7055 self.options[args[0]] = args[1]
7056 if log: logger.info('Passing to gauge %s.' % args[1])
7057 return
7058
7059
7060 able_to_mod = True
7061 if args[1] == 'unitary':
7062 if 0 in self._curr_model.get('gauge'):
7063 aloha.unitary_gauge = True
7064 else:
7065 able_to_mod = False
7066 if log: logger.warning('Note that unitary gauge is not allowed for your current model %s' \
7067 % self._curr_model.get('name'))
7068 else:
7069 if 1 in self._curr_model.get('gauge'):
7070 aloha.unitary_gauge = False
7071 else:
7072 able_to_mod = False
7073 if log: logger.warning('Note that Feynman gauge is not allowed for your current model %s' \
7074 % self._curr_model.get('name'))
7075
7076 if self.options['gauge'] == args[1]:
7077 return
7078
7079
7080 self.options[args[0]] = args[1]
7081
7082 if able_to_mod and log and args[0] == 'gauge' and \
7083 args[1] == 'unitary' and not self.options['gauge']=='unitary' and \
7084 isinstance(self._curr_model,loop_base_objects.LoopModel) and \
7085 not self._curr_model['perturbation_couplings'] in [[],['QCD']]:
7086 logger.warning('You will only be able to do tree level'+\
7087 ' and QCD corrections in the unitary gauge.')
7088
7089
7090
7091
7092 model_name = self._curr_model.get('modelpath+restriction')
7093 self._curr_model = None
7094 self._curr_amps = diagram_generation.AmplitudeList()
7095 self._curr_proc_defs = base_objects.ProcessDefinitionList()
7096 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7097 self._curr_helas_model = None
7098 self._curr_exporter = None
7099 self._done_export = False
7100 import_ufo._import_once = []
7101 logger.info('Passing to gauge %s.' % args[1])
7102
7103 if able_to_mod:
7104
7105
7106
7107 MadGraphCmd.do_import(self,'model %s' %model_name, force=True)
7108 elif log:
7109 logger.info('Note that you have to reload the model')
7110
7111 elif args[0] == 'fortran_compiler':
7112 if args[1] != 'None':
7113 if log:
7114 logger.info('set fortran compiler to %s' % args[1])
7115 self.options['fortran_compiler'] = args[1]
7116 else:
7117 self.options['fortran_compiler'] = None
7118 elif args[0] == 'f2py_compiler':
7119 if args[1] != 'None':
7120 if log:
7121 logger.info('set f2py compiler to %s' % args[1])
7122 self.options['f2py_compiler'] = args[1]
7123 else:
7124 self.options['f2py_compiler'] = None
7125
7126 elif args[0] == 'loop_optimized_output':
7127 if log:
7128 logger.info('set loop optimized output to %s' % args[1])
7129 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7130 self.options[args[0]] = args[1]
7131 if not self.options['loop_optimized_output'] and \
7132 self.options['loop_color_flows']:
7133 logger.warning("Turning off option 'loop_color_flows'"+\
7134 " since it is not available for non-optimized loop output.")
7135 self.do_set('loop_color_flows False',log=False)
7136 elif args[0] == 'loop_color_flows':
7137 if log:
7138 logger.info('set loop color flows to %s' % args[1])
7139 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7140 self.options[args[0]] = args[1]
7141 if self.options['loop_color_flows'] and \
7142 not self.options['loop_optimized_output']:
7143 logger.warning("Turning on option 'loop_optimized'"+\
7144 " needed for loop color flow computation.")
7145 self.do_set('loop_optimized_output True',False)
7146
7147 elif args[0] == 'fastjet':
7148 try:
7149 p = subprocess.Popen([args[1], '--version'], stdout=subprocess.PIPE,
7150 stderr=subprocess.PIPE)
7151 output, error = p.communicate()
7152 res = 0
7153 except Exception:
7154 res = 1
7155
7156 if res != 0 or error:
7157 logger.info('%s does not seem to correspond to a valid fastjet-config ' % args[1] + \
7158 'executable (v3+). We will use fjcore instead.\n Please set the \'fastjet\'' + \
7159 'variable to the full (absolute) /PATH/TO/fastjet-config (including fastjet-config).' +
7160 '\n MG5_aMC> set fastjet /PATH/TO/fastjet-config\n')
7161 self.options[args[0]] = None
7162 self.history.pop()
7163 elif int(output.split('.')[0]) < 3:
7164 logger.warning('%s is not ' % args[1] + \
7165 'v3 or greater. Please install FastJet v3+.')
7166 self.options[args[0]] = None
7167 self.history.pop()
7168 else:
7169 logger.info('set fastjet to %s' % args[1])
7170 self.options[args[0]] = args[1]
7171
7172 elif args[0] in ['pjfry','golem','samurai','ninja','collier'] and \
7173 not (args[0] in ['ninja','collier'] and args[1]=='./HEPTools/lib'):
7174 if args[1] in ['None',"''",'""']:
7175 self.options[args[0]] = None
7176 else:
7177 program = misc.which_lib(os.path.join(args[1],'lib%s.a'%args[0]))
7178 if program!=None:
7179 res = 0
7180 logger.info('set %s to %s' % (args[0],args[1]))
7181 self.options[args[0]] = args[1]
7182 else:
7183 res = 1
7184
7185 if res != 0 :
7186 logger.warning('%s does not seem to correspond to a valid %s lib ' % (args[1],args[0]) + \
7187 '. Please enter the full PATH/TO/%s/lib .\n'%args[0] + \
7188 'You will NOT be able to run %s otherwise.\n'%args[0])
7189
7190 elif args[0] == 'lhapdf':
7191 try:
7192 res = misc.call([args[1], '--version'], stdout=subprocess.PIPE,
7193 stderr=subprocess.PIPE)
7194 logger.info('set lhapdf to %s' % args[1])
7195 self.options[args[0]] = args[1]
7196 except Exception:
7197 res = 1
7198 if res != 0:
7199 logger.info('%s does not seem to correspond to a valid lhapdf-config ' % args[1] + \
7200 'executable. \nPlease set the \'lhapdf\' variable to the (absolute) ' + \
7201 '/PATH/TO/lhapdf-config (including lhapdf-config).\n' + \
7202 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n' + \
7203 ' MG5_aMC> set lhapdf /PATH/TO/lhapdf-config\n')
7204
7205 elif args[0] in ['timeout', 'auto_update', 'cluster_nb_retry',
7206 'cluster_retry_wait', 'cluster_size', 'max_npoint_for_channel']:
7207 self.options[args[0]] = int(args[1])
7208
7209 elif args[0] in ['cluster_local_path']:
7210 self.options[args[0]] = args[1].strip()
7211
7212 elif args[0] == 'cluster_status_update':
7213 if '(' in args[1]:
7214 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
7215 data = data.replace('(','').replace(')','').replace(',',' ').split()
7216 first, second = data[:2]
7217 else:
7218 first, second = args[1:3]
7219
7220 self.options[args[0]] = (int(first), int(second))
7221
7222 elif args[0] == 'OLP':
7223
7224
7225 self._curr_amps = diagram_generation.AmplitudeList()
7226 self._curr_proc_defs = base_objects.ProcessDefinitionList()
7227 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7228 self._curr_exporter = None
7229 self.options[args[0]] = args[1]
7230
7231 elif args[0] =='output_dependencies':
7232 self.options[args[0]] = args[1]
7233 elif args[0] =='notification_center':
7234 if args[1] in ['None','True','False']:
7235 self.options[args[0]] = eval(args[1])
7236 self.allow_notification_center = self.options[args[0]]
7237 else:
7238 raise self.InvalidCmd('expected bool for notification_center')
7239
7240 elif args[0] in ['crash_on_error']:
7241 tmp = banner_module.ConfigFile.format_variable(args[1], bool, 'crash_on_error')
7242 self.options[args[0]] = tmp
7243 elif args[0] in ['cluster_queue']:
7244 self.options[args[0]] = args[1].strip()
7245 elif args[0] in self.options:
7246 if args[1] in ['None','True','False']:
7247 self.options[args[0]] = eval(args[1])
7248 else:
7249 self.options[args[0]] = args[1]
7250
7251 - def post_set(self, stop, line):
7252 """Check if we need to save this in the option file"""
7253
7254 args = self.split_arg(line)
7255
7256 try:
7257 self.check_set(args, log=False)
7258 except Exception:
7259 return stop
7260
7261 if args[0] in self.options_configuration and '--no_save' not in args:
7262 self.exec_cmd('save options %s' % args[0] , log=False)
7263 elif args[0] in self.options_madevent:
7264 if not '--no_save' in line:
7265 logger.info('This option will be the default in any output that you are going to create in this session.')
7266 logger.info('In order to keep this changes permanent please run \'save options\'')
7267 else:
7268
7269 if not self.history or self.history[-1].split() != line.split():
7270 self.history.append('set %s' % line)
7271 self.avoid_history_duplicate('set %s' % args[0], ['define', 'set'])
7272 return stop
7273
7283
7285 """Main commands: Initialize a new Template or reinitialize one"""
7286
7287 args = self.split_arg(line)
7288
7289 self.check_output(args)
7290
7291
7292 noclean = '-noclean' in args
7293 force = '-f' in args
7294 nojpeg = '-nojpeg' in args
7295 flaglist = []
7296
7297 if '--postpone_model' in args:
7298 flaglist.append('store_model')
7299
7300 main_file_name = ""
7301 try:
7302 main_file_name = args[args.index('-name') + 1]
7303 except Exception:
7304 pass
7305
7306
7307
7308
7309
7310 if self._export_format == 'aloha':
7311
7312 format = [d[9:] for d in args if d.startswith('--format=')]
7313 if not format:
7314 format = 'Fortran'
7315 else:
7316 format = format[-1]
7317
7318 output = [d for d in args if d.startswith('--output=')]
7319 if not output:
7320 output = import_ufo.find_ufo_path(self._curr_model['name'])
7321 output = pjoin(output, format)
7322 if not os.path.isdir(output):
7323 os.mkdir(output)
7324 else:
7325 output = output[-1]
7326 if not os.path.isdir(output):
7327 raise self.InvalidCmd('%s is not a valid directory' % output)
7328 logger.info('creating routines in directory %s ' % output)
7329
7330 names = [d for d in args if not d.startswith('-')]
7331 wanted_lorentz = aloha_fct.guess_routine_from_name(names)
7332
7333 aloha_model = create_aloha.AbstractALOHAModel(self._curr_model.get('name'))
7334 aloha_model.add_Lorentz_object(self._curr_model.get('lorentz'))
7335 if wanted_lorentz:
7336 aloha_model.compute_subset(wanted_lorentz)
7337 else:
7338 aloha_model.compute_all(save=False)
7339 aloha_model.write(output, format)
7340 return
7341
7342
7343
7344
7345
7346
7347
7348
7349 config = {}
7350 config['madevent'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7351 config['matrix'] = {'check': False, 'exporter': 'v4', 'output':'dir'}
7352 config['standalone'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7353 config['standalone_msF'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7354 config['standalone_msP'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7355 config['standalone_rw'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7356 config['standalone_cpp'] = {'check': False, 'exporter': 'cpp', 'output': 'Template'}
7357 config['pythia8'] = {'check': False, 'exporter': 'cpp', 'output':'dir'}
7358 config['matchbox_cpp'] = {'check': True, 'exporter': 'cpp', 'output': 'Template'}
7359 config['matchbox'] = {'check': True, 'exporter': 'v4', 'output': 'Template'}
7360 config['madweight'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7361
7362 if self._export_format == 'plugin':
7363 options = {'check': self._export_plugin.check, 'exporter':self._export_plugin.exporter, 'output':self._export_plugin.output}
7364 else:
7365 options = config[self._export_format]
7366
7367
7368 if os.path.realpath(self._export_dir) == os.getcwd():
7369 if len(args) == 0:
7370 i=0
7371 while 1:
7372 if os.path.exists('Pythia8_proc_%i' %i):
7373 i+=1
7374 else:
7375 break
7376 os.mkdir('Pythia8_proc_%i' %i)
7377 self._export_dir = pjoin(self._export_dir, 'Pythia8_proc_%i' %i)
7378 logger.info('Create output in %s' % self._export_dir)
7379 elif not args[0] in ['.', '-f']:
7380 raise self.InvalidCmd, 'Wrong path directory to create in local directory use \'.\''
7381 elif not noclean and os.path.isdir(self._export_dir) and options['check']:
7382 if not force:
7383
7384 logger.info('INFO: directory %s already exists.' % self._export_dir)
7385 logger.info('If you continue this directory will be deleted and replaced.')
7386 answer = self.ask('Do you want to continue?', 'y', ['y','n'])
7387 else:
7388 answer = 'y'
7389 if answer != 'y':
7390 raise self.InvalidCmd('Stopped by user request')
7391 else:
7392 shutil.rmtree(self._export_dir)
7393
7394
7395
7396 if self.options['group_subprocesses'] in [True, False]:
7397 group_processes = self.options['group_subprocesses']
7398 elif self.options['group_subprocesses'] == 'Auto':
7399
7400 group_processes = True
7401
7402
7403
7404
7405 if self._curr_amps[0].get_ninitial() == 1 and \
7406 len(self._curr_amps)>1:
7407 processes = [amp.get('process') for amp in self._curr_amps]
7408 if len(set(proc.get('id') for proc in processes))!=len(processes):
7409
7410 if any(proc['perturbation_couplings'] != [] for proc in
7411 processes) and self._export_format == 'madevent':
7412 logger.warning("""
7413 || The loop-induced decay process you have specified contains several
7414 || subprocesses and, in order to be able to compute individual branching ratios,
7415 || MG5_aMC will *not* group them. Integration channels will also be considered
7416 || for each diagrams and as a result integration will be inefficient.
7417 || It is therefore recommended to perform this simulation by setting the MG5_aMC
7418 || option 'group_subprocesses' to 'True' (before the output of the process).
7419 || Notice that when doing so, processes for which one still wishes to compute
7420 || branching ratios independently can be specified using the syntax:
7421 || -> add process <proc_def>
7422 """)
7423 group_processes = False
7424
7425
7426 if options['exporter'] == 'v4':
7427 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
7428 group_subprocesses=group_processes)
7429 elif options['exporter'] == 'cpp':
7430 self._curr_exporter = export_cpp.ExportCPPFactory(self, group_subprocesses=group_processes)
7431
7432 self._curr_exporter.pass_information_from_cmd(self)
7433
7434 if options['output'] == 'Template':
7435 self._curr_exporter.copy_template(self._curr_model)
7436 elif options['output'] == 'dir' and not os.path.isdir(self._export_dir):
7437 os.makedirs(self._export_dir)
7438
7439
7440 self._done_export = False
7441
7442 if self._export_format == "madevent":
7443
7444
7445 if self.options['max_npoint_for_channel']:
7446 base_objects.Vertex.max_n_loop_for_multichanneling = self.options['max_npoint_for_channel']
7447 else:
7448 base_objects.Vertex.max_n_loop_for_multichanneling = 3
7449
7450
7451 self.export(nojpeg, main_file_name, group_processes, args)
7452
7453
7454 self.finalize(nojpeg, flaglist=flaglist)
7455
7456
7457 self._done_export = (self._export_dir, self._export_format)
7458
7459
7460 self._export_dir = None
7461
7462
7463 - def export(self, nojpeg = False, main_file_name = "", group_processes=True,
7464 args=[]):
7465 """Export a generated amplitude to file."""
7466
7467
7468 if self._curr_exporter.exporter == 'cpp':
7469 self._curr_helas_model = helas_call_writers.CPPUFOHelasCallWriter(self._curr_model)
7470 elif self._model_v4_path:
7471 assert self._curr_exporter.exporter == 'v4'
7472 self._curr_helas_model = helas_call_writers.FortranHelasCallWriter(self._curr_model)
7473 else:
7474 assert self._curr_exporter.exporter == 'v4'
7475 self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model)
7476
7477 version = [arg[10:] for arg in args if arg.startswith('--version=')]
7478 if version:
7479 version = version[-1]
7480 else:
7481 version = '8.2'
7482
7483 def generate_matrix_elements(self, group_processes=True):
7484 """Helper function to generate the matrix elements before
7485 exporting. Uses the main function argument 'group_processes' to decide
7486 whether to use group_subprocess or not. (it has been set in do_output to
7487 the appropriate value if the MG5 option 'group_subprocesses' was set
7488 to 'Auto'."""
7489
7490 if self._export_format in ['standalone_msP', 'standalone_msF', 'standalone_mw']:
7491 to_distinguish = []
7492 for part in self._curr_model.get('particles'):
7493 if part.get('name') in args and part.get('antiname') in args and\
7494 part.get('name') != part.get('antiname'):
7495 to_distinguish.append(abs(part.get('pdg_code')))
7496
7497
7498 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \
7499 a1.get_number_of_diagrams())
7500
7501 cpu_time1 = time.time()
7502 ndiags = 0
7503 if not self._curr_matrix_elements.get_matrix_elements():
7504 if group_processes:
7505 cpu_time1 = time.time()
7506 dc_amps = diagram_generation.DecayChainAmplitudeList(\
7507 [amp for amp in self._curr_amps if isinstance(amp, \
7508 diagram_generation.DecayChainAmplitude)])
7509 non_dc_amps = diagram_generation.AmplitudeList(\
7510 [amp for amp in self._curr_amps if not \
7511 isinstance(amp, \
7512 diagram_generation.DecayChainAmplitude)])
7513 subproc_groups = group_subprocs.SubProcessGroupList()
7514 matrix_elements_opts = {'optimized_output':
7515 self.options['loop_optimized_output']}
7516
7517 grouping_criteria = self._curr_exporter.grouped_mode
7518 if non_dc_amps:
7519 subproc_groups.extend(\
7520 group_subprocs.SubProcessGroup.group_amplitudes(\
7521 non_dc_amps,grouping_criteria,
7522 matrix_elements_opts=matrix_elements_opts))
7523
7524 if dc_amps:
7525 dc_subproc_group = \
7526 group_subprocs.DecayChainSubProcessGroup.\
7527 group_amplitudes(dc_amps, grouping_criteria,
7528 matrix_elements_opts=matrix_elements_opts)
7529 subproc_groups.extend(dc_subproc_group.\
7530 generate_helas_decay_chain_subproc_groups())
7531
7532 ndiags = sum([len(m.get('diagrams')) for m in \
7533 subproc_groups.get_matrix_elements()])
7534 self._curr_matrix_elements = subproc_groups
7535
7536 uid = 0
7537 for group in subproc_groups:
7538 uid += 1
7539 for me in group.get('matrix_elements'):
7540 me.get('processes')[0].set('uid', uid)
7541 else:
7542 mode = {}
7543 if self._export_format in [ 'standalone_msP' ,
7544 'standalone_msF', 'standalone_rw']:
7545 mode['mode'] = 'MadSpin'
7546
7547
7548 if isinstance(self._curr_amps[0],
7549 loop_diagram_generation.LoopAmplitude):
7550 mode['optimized_output']=self.options['loop_optimized_output']
7551 HelasMultiProcessClass = loop_helas_objects.LoopHelasProcess
7552 compute_loop_nc = True
7553 else:
7554 HelasMultiProcessClass = helas_objects.HelasMultiProcess
7555 compute_loop_nc = False
7556
7557 self._curr_matrix_elements = HelasMultiProcessClass(
7558 self._curr_amps, compute_loop_nc=compute_loop_nc,
7559 matrix_element_opts=mode)
7560
7561 ndiags = sum([len(me.get('diagrams')) for \
7562 me in self._curr_matrix_elements.\
7563 get_matrix_elements()])
7564
7565 uid = 0
7566 for me in self._curr_matrix_elements.get_matrix_elements()[:]:
7567 uid += 1
7568 me.get('processes')[0].set('uid', uid)
7569
7570 cpu_time2 = time.time()
7571
7572
7573 return ndiags, cpu_time2 - cpu_time1
7574
7575
7576
7577 ndiags, cpu_time = generate_matrix_elements(self,group_processes)
7578
7579 calls = 0
7580
7581 path = self._export_dir
7582
7583 cpu_time1 = time.time()
7584
7585
7586
7587
7588
7589 if self._export_format == 'madevent':
7590 path = pjoin(path, 'SubProcesses')
7591 calls += self._curr_exporter.export_processes(self._curr_matrix_elements,
7592 self._curr_helas_model)
7593
7594
7595 card_path = pjoin(path, os.path.pardir, 'SubProcesses', \
7596 'procdef_mg5.dat')
7597 if self._generate_info:
7598 self._curr_exporter.write_procdef_mg5(card_path,
7599 self._curr_model['name'],
7600 self._generate_info)
7601 try:
7602 cmd.Cmd.onecmd(self, 'history .')
7603 except Exception:
7604 misc.sprint('command history fails.', 10)
7605 pass
7606
7607
7608 elif self._export_format == 'pythia8':
7609
7610 process_names = []
7611 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
7612 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
7613 exporter = self._curr_exporter.generate_process_directory(\
7614 me_group.get('matrix_elements'), self._curr_helas_model,
7615 process_string = me_group.get('name'),
7616 process_number = group_number,
7617 version = version)
7618 process_names.append(exporter.process_name)
7619 else:
7620 exporter = self._curr_exporter.generate_process_directory(\
7621 self._curr_matrix_elements, self._curr_helas_model,
7622 process_string = self._generate_info, version = version)
7623 process_names.append(exporter.process_file_name)
7624
7625
7626 model_name, model_path = exporter.convert_model_to_pythia8(\
7627 self._curr_model, self._export_dir)
7628
7629
7630 filename, make_filename = \
7631 self._curr_exporter.generate_example_file_pythia8(path,
7632 model_path,
7633 process_names,
7634 exporter,
7635 main_file_name)
7636
7637
7638 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7639
7640 if self._export_format == 'matrix':
7641 for me in matrix_elements:
7642 filename = pjoin(path, 'matrix_' + \
7643 me.get('processes')[0].shell_string() + ".f")
7644 if os.path.isfile(filename):
7645 logger.warning("Overwriting existing file %s" % filename)
7646 else:
7647 logger.info("Creating new file %s" % filename)
7648 calls = calls + self._curr_exporter.write_matrix_element_v4(\
7649 writers.FortranWriter(filename),\
7650 me, self._curr_helas_model)
7651 elif self._export_format in ['madevent', 'pythia8']:
7652 pass
7653
7654 elif isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList) and\
7655 self._curr_exporter.grouped_mode:
7656 modify, self._curr_matrix_elements = self._curr_exporter.modify_grouping(self._curr_matrix_elements)
7657 if modify:
7658 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7659
7660 for me_number, me in enumerate(self._curr_matrix_elements):
7661 calls = calls + \
7662 self._curr_exporter.generate_subprocess_directory(\
7663 me, self._curr_helas_model, me_number)
7664
7665
7666 else:
7667 for nb,me in enumerate(matrix_elements[:]):
7668 new_calls = self._curr_exporter.generate_subprocess_directory(\
7669 me, self._curr_helas_model, nb)
7670 if isinstance(new_calls, int):
7671 if new_calls ==0:
7672 matrix_elements.remove(me)
7673 else:
7674 calls = calls + new_calls
7675
7676 cpu_time2 = time.time() - cpu_time1
7677
7678 logger.info(("Generated helas calls for %d subprocesses " + \
7679 "(%d diagrams) in %0.3f s") % \
7680 (len(matrix_elements),
7681 ndiags, cpu_time))
7682
7683 if calls:
7684 if "cpu_time2" in locals():
7685 logger.info("Wrote files for %d helas calls in %0.3f s" % \
7686 (calls, cpu_time2))
7687 else:
7688 logger.info("Wrote files for %d helas calls" % \
7689 (calls))
7690
7691 if self._export_format == 'pythia8':
7692 logger.info("- All necessary files for Pythia 8 generated.")
7693 logger.info("- Run \"launch\" and select %s.cc," % filename)
7694 logger.info(" or go to %s/examples and run" % path)
7695 logger.info(" make -f %s" % make_filename)
7696 logger.info(" (with process_name replaced by process name).")
7697 logger.info(" You can then run ./%s to produce events for the process" % \
7698 filename)
7699
7700
7701
7702
7703 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7704 self._curr_amps = diagram_generation.AmplitudeList(\
7705 [me.get('base_amplitude') for me in \
7706 matrix_elements])
7707
7708 - def finalize(self, nojpeg, online = False, flaglist=[]):
7709 """Make the html output, write proc_card_mg5.dat and create
7710 madevent.tar.gz for a MadEvent directory"""
7711
7712 compiler_dict = {'fortran': self.options['fortran_compiler'],
7713 'cpp': self.options['cpp_compiler'],
7714 'f2py': self.options['f2py_compiler']}
7715
7716
7717 if self._model_v4_path:
7718 logger.info('Copy %s model files to directory %s' % \
7719 (os.path.basename(self._model_v4_path), self._export_dir))
7720 self._curr_exporter.export_model_files(self._model_v4_path)
7721 self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS'))
7722 else:
7723
7724
7725
7726 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
7727 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
7728
7729
7730 if hasattr(self, 'previous_lorentz'):
7731 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz))
7732 wanted_couplings = list(set(self.previous_couplings + wanted_couplings))
7733 del self.previous_lorentz
7734 del self.previous_couplings
7735 if 'store_model' in flaglist:
7736 self.previous_lorentz = wanted_lorentz
7737 self.previous_couplings = wanted_couplings
7738 else:
7739 self._curr_exporter.convert_model(self._curr_model,
7740 wanted_lorentz,
7741 wanted_couplings)
7742
7743
7744 if nojpeg:
7745 flaglist.append('nojpeg')
7746 if online:
7747 flaglist.append('online')
7748
7749
7750
7751 if self._export_format in ['NLO']:
7752
7753
7754 filename = os.path.join(self._export_dir, 'Cards', 'amcatnlo_configuration.txt')
7755 opts_to_keep = ['lhapdf', 'fastjet', 'pythia8_path', 'hwpp_path', 'thepeg_path',
7756 'hepmc_path']
7757 to_keep = {}
7758 for opt in opts_to_keep:
7759 if self.options[opt]:
7760 to_keep[opt] = self.options[opt]
7761 self.do_save('options %s' % filename.replace(' ', '\ '), check=False, \
7762 to_keep = to_keep)
7763
7764 elif self._export_format in ['madevent', 'madweight']:
7765
7766 filename = os.path.join(self._export_dir, 'Cards', 'me5_configuration.txt')
7767 self.do_save('options %s' % filename.replace(' ', '\ '), check=False,
7768 to_keep={'mg5_path':MG5DIR})
7769
7770
7771 self._curr_exporter.finalize(self._curr_matrix_elements,
7772 self.history,
7773 self.options,
7774 flaglist)
7775
7776 if self._export_format in ['madevent', 'standalone', 'standalone_cpp','madweight', 'matchbox']:
7777 logger.info('Output to directory ' + self._export_dir + ' done.')
7778
7779 if self._export_format in ['madevent', 'NLO']:
7780 logger.info('Type \"launch\" to generate events from this process, or see')
7781 logger.info(self._export_dir + '/README')
7782 logger.info('Run \"open index.html\" to see more information about this process.')
7783
7785 """ propose some usefull possible action """
7786
7787 super(MadGraphCmd,self).do_help(line)
7788
7789 if line:
7790 return
7791
7792 if len(self.history) == 0:
7793 last_action_2 = 'mg5_start'
7794 last_action = 'mg5_start'
7795 else:
7796 args = self.history[-1].split()
7797 last_action = args[0]
7798 if len(args)>1:
7799 last_action_2 = '%s %s' % (last_action, args[1])
7800 else:
7801 last_action_2 = 'none'
7802
7803
7804
7805
7807 """Documented commands:Generate amplitudes for decay width calculation, with fixed
7808 number of final particles (called level)
7809 syntax; compute_widths particle [other particles] [--options=]
7810
7811 - particle/other particles can also be multiparticle name (can also be
7812 pid of the particle)
7813
7814 --body_decay=X [default=4.0025] allow to choose the precision.
7815 if X is an integer: compute all X body decay
7816 if X is a float <1: compute up to the time that total error < X
7817 if X is a float >1: stops at the first condition.
7818
7819 --path=X. Use a given file for the param_card. (default UFO built-in)
7820
7821 special argument:
7822 - skip_2body: allow to not consider those decay (use FR)
7823 - model: use the model pass in argument.
7824
7825 """
7826
7827
7828
7829 self.change_principal_cmd('MadGraph')
7830 if '--nlo' not in line:
7831 warning_text = """Please note that the automatic computation of the width is
7832 only valid in narrow-width approximation and at tree-level."""
7833 logger.warning(warning_text)
7834
7835 if not model:
7836 modelname = self._curr_model.get('modelpath+restriction')
7837 with misc.MuteLogger(['madgraph'], ['INFO']):
7838 model = import_ufo.import_model(modelname, decay=True)
7839 self._curr_model = model
7840
7841 if not isinstance(model, model_reader.ModelReader):
7842 model = model_reader.ModelReader(model)
7843
7844 if '--nlo' in line:
7845
7846 self.compute_widths_SMWidth(line, model=model)
7847 return
7848
7849
7850 particles, opts = self.check_compute_widths(self.split_arg(line))
7851
7852 if opts['path']:
7853 correct = True
7854 param_card = check_param_card.ParamCard(opts['path'])
7855 for param in param_card['decay']:
7856 if param.value == "auto":
7857 param.value = 1
7858 param.format = 'float'
7859 correct = False
7860 if not correct:
7861 if opts['output']:
7862 param_card.write(opts['output'])
7863 opts['path'] = opts['output']
7864 else:
7865 param_card.write(opts['path'])
7866
7867 data = model.set_parameters_and_couplings(opts['path'])
7868
7869
7870 if do2body:
7871 skip_2body = True
7872 decay_info = {}
7873 for pid in particles:
7874 particle = model.get_particle(pid)
7875 if not hasattr(particle, 'partial_widths'):
7876 skip_2body = False
7877 break
7878 elif not decay_info:
7879 logger_mg.info('Get two body decay from FeynRules formula')
7880 decay_info[pid] = []
7881 mass = abs(eval(str(particle.get('mass')), data).real)
7882 data = model.set_parameters_and_couplings(opts['path'], scale= mass)
7883 total = 0
7884
7885 for mode, expr in particle.partial_widths.items():
7886 tmp_mass = mass
7887 for p in mode:
7888 try:
7889 value_mass = eval(str(p.mass), data)
7890 except Exception:
7891
7892
7893 value_mass = eval(str(model.get_particle(p.pdg_code).get('mass')), data)
7894 tmp_mass -= abs(value_mass)
7895 if tmp_mass <=0:
7896 continue
7897
7898 decay_to = [p.get('pdg_code') for p in mode]
7899 value = eval(expr,{'cmath':cmath},data).real
7900 if -1e-10 < value < 0:
7901 value = 0
7902 if -1e-5 < value < 0:
7903 logger.warning('Partial width for %s > %s negative: %s automatically set to zero' %
7904 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value))
7905 value = 0
7906 elif value < 0:
7907 raise Exception, 'Partial width for %s > %s negative: %s' % \
7908 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value)
7909 elif 0 < value < 0.1 and particle['color'] !=1:
7910 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
7911 % (particle.get('name'), value, decay_to))
7912 value = 0
7913
7914 decay_info[particle.get('pdg_code')].append([decay_to, value])
7915 total += value
7916 else:
7917 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
7918 opts['path'], opts['output'])
7919 if float(opts['body_decay']) == 2:
7920 return
7921 else:
7922 skip_2body = True
7923
7924
7925
7926
7927 self.do_decay_diagram('%s %s' % (' '.join([`id` for id in particles]),
7928 ' '.join('--%s=%s' % (key,value)
7929 for key,value in opts.items()
7930 if key not in ['precision_channel'])
7931 ), skip_2body=skip_2body, model=decaymodel)
7932
7933 if self._curr_amps:
7934 logger.info('Pass to numerical integration for computing the widths:')
7935 else:
7936 logger.info('No need for N body-decay (N>2). Results are in %s' % opts['output'])
7937
7938
7939
7940 return
7941
7942
7943 with misc.TMP_directory(dir=os.getcwd()) as path:
7944 decay_dir = pjoin(path,'temp_decay')
7945 logger_mg.info('More info in temporary files:\n %s/index.html' % (decay_dir))
7946 with misc.MuteLogger(['madgraph','ALOHA','cmdprint','madevent'], [40,40,40,40]):
7947 self.exec_cmd('output %s -f' % decay_dir,child=False)
7948
7949 if os.path.exists(opts['output']):
7950 files.cp(opts['output'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
7951 else:
7952 files.cp(opts['path'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
7953 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
7954 check_param_card.convert_to_slha1(pjoin(decay_dir, 'Cards', 'param_card.dat'))
7955
7956 me_cmd = madevent_interface.MadEventCmd(decay_dir)
7957
7958 me_cmd.model_name = self._curr_model['name']
7959 me_cmd.options['automatic_html_opening'] = False
7960
7961 me_opts=[('accuracy', opts['precision_channel']),
7962 ('points', 1000),
7963 ('iterations',9)]
7964 me_cmd.exec_cmd('survey decay -f %s' % (
7965 " ".join(['--%s=%s' % val for val in me_opts])),
7966 postcmd=False)
7967 me_cmd.exec_cmd('combine_events', postcmd=False)
7968
7969 me_cmd.collect_decay_widths()
7970 me_cmd.do_quit('')
7971
7972 del me_cmd
7973
7974 param = check_param_card.ParamCard(pjoin(decay_dir, 'Events', 'decay','param_card.dat'))
7975
7976 for pid in particles:
7977 width = param['decay'].get((pid,)).value
7978 particle = self._curr_model.get_particle(pid)
7979
7980
7981
7982
7983
7984
7985 if not pid in param['decay'].decay_table:
7986 continue
7987 if pid not in decay_info:
7988 decay_info[pid] = []
7989 for BR in param['decay'].decay_table[pid]:
7990 if len(BR.lhacode) == 3 and skip_2body:
7991 continue
7992 if 0 < BR.value * width <0.1 and particle['color'] !=1:
7993 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
7994 % (particle.get('name'), BR.value * width, BR.lhacode[1:]))
7995
7996 continue
7997
7998 decay_info[pid].append([BR.lhacode[1:], BR.value * width])
7999
8000 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
8001 opts['path'], opts['output'])
8002
8003 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
8004 check_param_card.convert_to_slha1(opts['output'])
8005 return
8006
8007
8008
8009
8011 """Compute widths with SMWidth.
8012 """
8013
8014
8015 particles, opts = self.check_compute_widths(self.split_arg(line))
8016
8017 if opts['path']:
8018 correct = True
8019 param_card = check_param_card.ParamCard(opts['path'])
8020 for param in param_card['decay']:
8021 if param.value == "auto":
8022 param.value = 1
8023 param.format = 'float'
8024 correct = False
8025 if not correct:
8026 if opts['output']:
8027 param_card.write(opts['output'])
8028 opts['path'] = opts['output']
8029 else:
8030 param_card.write(opts['path'])
8031
8032 if not model:
8033 model_path = self._curr_model.get('modelpath')
8034 model_name = self._curr_model.get('name')
8035 currmodel = self._curr_model
8036 else:
8037 model_path = model.get('modelpath')
8038 model_name = model.get('name')
8039 currmodel = model
8040
8041 if not os.path.exists(pjoin(model_path, 'SMWidth')):
8042 raise self.InvalidCmd, "Model %s is not valid for computing NLO width with SMWidth"%model_name
8043
8044
8045 externparam = [(param.lhablock.lower(),param.name.lower()) for param \
8046 in currmodel.get('parameters')[('external',)]]
8047
8048 if ('sminputs','aewm1') in externparam:
8049
8050 arg2 = "1"
8051 elif ('sminputs','mdl_gf') in externparam or ('sminputs','gf') in externparam:
8052
8053 arg2 = "2"
8054 else:
8055 raise Exception, "Do not know the EW scheme in the model %s"%model_name
8056
8057
8058 if not os.path.exists(pjoin(model_path, 'SMWidth','smwidth')):
8059 logger.info('Compiling SMWidth. This has to be done only once and'+\
8060 ' can take a couple of minutes.','$MG:color:BLACK')
8061 current = misc.detect_current_compiler(pjoin(model_path, 'SMWidth',
8062 'makefile_MW5'))
8063 new = 'gfortran' if self.options_configuration['fortran_compiler'] is None else \
8064 self.options_configuration['fortran_compiler']
8065 if current != new:
8066 misc.mod_compilator(pjoin(model_path, 'SMWidth'), new, current)
8067 misc.mod_compilator(pjoin(model_path, 'SMWidth','oneloop'), new, current)
8068 misc.mod_compilator(pjoin(model_path, 'SMWidth','hdecay'), new, current)
8069 misc.compile(cwd=pjoin(model_path, 'SMWidth'))
8070
8071
8072 identpath=" "
8073 carddir=os.path.dirname(opts['path'])
8074 if 'ident_card.dat' in os.listdir(carddir):
8075 identpath=pjoin(carddir,'ident_card.dat')
8076
8077 output,error = misc.Popen(['./smwidth',opts['path'],identpath,arg2],
8078 stdout=subprocess.PIPE,
8079 stdin=subprocess.PIPE,
8080 cwd=pjoin(model_path, 'SMWidth')).communicate()
8081 pattern = re.compile(r''' decay\s+(\+?\-?\d+)\s+(\+?\-?\d+\.\d+E\+?\-?\d+)''',re.I)
8082 width_list = pattern.findall(output)
8083 width_dict = {}
8084 for pid,width in width_list:
8085 width_dict[int(pid)] = float(width)
8086
8087 for pid in particles:
8088 if not pid in width_dict:
8089 width = 0
8090 else:
8091 width = width_dict[pid]
8092 param = param_card['decay'].get((pid,))
8093 param.value = width
8094 param.format = 'float'
8095 if pid not in param_card['decay'].decay_table:
8096 continue
8097 del param_card['decay'].decay_table[pid]
8098
8099 if opts['output']:
8100 param_card.write(opts['output'])
8101 logger.info('Results are written in %s' % opts['output'])
8102 else:
8103 param_card.write(opts['path'])
8104 logger.info('Results are written in %s' % opts['path'])
8105 return
8106
8107
8109 """Not in help: Generate amplitudes for decay width calculation, with fixed
8110 number of final particles (called level)
8111 syntax; decay_diagram part_name level param_path
8112 args; part_name level param_path
8113 part_name = name of the particle you want to calculate width
8114 level = a.) when level is int,
8115 it means the max number of decay products
8116 b.) when level is float,
8117 it means the required precision for width.
8118 param_path = path for param_card
8119 (this is necessary to determine whether a channel is onshell or not)
8120 e.g. calculate width for higgs up to 2-body decays.
8121 calculate_width h 2 [path]
8122 N.B. param_card must be given so that the program knows which channel
8123 is on shell and which is not.
8124
8125 special argument:
8126 - skip_2body: allow to not consider those decay (use FR)
8127 - model: use the model pass in argument.
8128 """
8129
8130 if model:
8131 self._curr_decaymodel = model
8132
8133
8134 args = self.split_arg(line)
8135
8136 particles, args = self.check_decay_diagram(args)
8137
8138 pids = particles
8139 level = float(args['body_decay'])
8140 param_card_path = args['path']
8141 min_br = float(args['min_br'])
8142
8143
8144 self._curr_amps = diagram_generation.AmplitudeList()
8145 self._curr_proc_defs = base_objects.ProcessDefinitionList()
8146
8147 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
8148
8149 self._done_export = False
8150
8151 self._export_format = None
8152
8153
8154
8155 if not model:
8156 self._curr_decaymodel = decay_objects.DecayModel(self._curr_model,
8157 True)
8158 self._curr_decaymodel.read_param_card(param_card_path)
8159 else:
8160 self._curr_decaymodel = model
8161 model = self._curr_decaymodel
8162
8163 if isinstance(pids, int):
8164 pids = [pids]
8165
8166 first =True
8167 for part_nb,pid in enumerate(pids):
8168 part = self._curr_decaymodel.get_particle(pid)
8169 if part.get('width').lower() == 'zero':
8170 continue
8171 logger_mg.info('get decay diagram for %s' % part['name'])
8172
8173 if level // 1 == level and level >1:
8174 level = int(level)
8175 self._curr_decaymodel.find_channels(part, level, min_br)
8176 if not skip_2body:
8177 amp = part.get_amplitudes(2)
8178 if amp:
8179 self._curr_amps.extend(amp)
8180
8181 for l in range(3, level+1):
8182 amp = part.get_amplitudes(l)
8183 if amp:
8184 self._curr_amps.extend(amp)
8185 else:
8186 max_level = level // 1
8187 if max_level < 2:
8188 max_level = 999
8189 precision = level % 1
8190 if first:
8191 model.find_all_channels(2,generate_abstract=False)
8192 first = False
8193 if not skip_2body:
8194 amp = part.get_amplitudes(2)
8195 if amp:
8196 self._curr_amps.extend(amp)
8197 clevel = 2
8198 while part.get('apx_decaywidth_err').real > precision:
8199 clevel += 1
8200 if clevel > max_level:
8201 logger_mg.info(' stop to %s body-decay. approximate error: %s' %
8202 (max_level, part.get('apx_decaywidth_err')) )
8203 break
8204 if clevel > 3:
8205 logger_mg.info(' current estimated error: %s go to %s-body decay:' %\
8206 (part.get('apx_decaywidth_err'), clevel))
8207 part.find_channels_nextlevel(model, min_br)
8208
8209 amp = part.get_amplitudes(clevel)
8210 if amp:
8211 self._curr_amps.extend(amp)
8212 part.update_decay_attributes(False, True, True, model)
8213
8214
8215
8216 if len(self._curr_amps) > 0:
8217 process = self._curr_amps[0]['process'].nice_string()
8218
8219 self._generate_info = process[9:]
8220
8221 else:
8222 logger.info("No decay is found")
8223
8225 """Temporary parser"""
8226
8227
8228
8229
8230
8231 _draw_usage = "draw FILEPATH [options]\n" + \
8232 "-- draw the diagrams in eps format\n" + \
8233 " Files will be FILEPATH/diagrams_\"process_string\".eps \n" + \
8234 " Example: draw plot_dir . \n"
8235 _draw_parser = misc.OptionParser(usage=_draw_usage)
8236 _draw_parser.add_option("", "--horizontal", default=False,
8237 action='store_true', help="force S-channel to be horizontal")
8238 _draw_parser.add_option("", "--external", default=0, type='float',
8239 help="authorizes external particles to end at top or " + \
8240 "bottom of diagram. If bigger than zero this tune the " + \
8241 "length of those line.")
8242 _draw_parser.add_option("", "--max_size", default=1.5, type='float',
8243 help="this forbids external line bigger than max_size")
8244 _draw_parser.add_option("", "--non_propagating", default=True, \
8245 dest="contract_non_propagating", action='store_false',
8246 help="avoid contractions of non propagating lines")
8247 _draw_parser.add_option("", "--add_gap", default=0, type='float', \
8248 help="set the x-distance between external particles")
8249
8250
8251 _launch_usage = "launch [DIRPATH] [options]\n" + \
8252 "-- execute the madevent/standalone/standalone_cpp/pythia8/NLO output present in DIRPATH\n" + \
8253 " By default DIRPATH is the latest created directory \n" + \
8254 " (for pythia8, it should be the Pythia 8 main directory) \n" + \
8255 " Example: launch PROC_sm_1 --name=run2 \n" + \
8256 " Example: launch ../pythia8 \n"
8257 _launch_parser = misc.OptionParser(usage=_launch_usage)
8258 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
8259 help="Use the card present in the directory in order to launch the different program")
8260 _launch_parser.add_option("-n", "--name", default='', type='str',
8261 help="Provide a name to the run (for madevent run)")
8262 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
8263 help="submit the job on the cluster")
8264 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
8265 help="submit the job on multicore core")
8266
8267 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
8268 help="Use Interactive Console [if available]")
8269 _launch_parser.add_option("-s", "--laststep", default='',
8270 help="last program run in MadEvent run. [auto|parton|pythia|pgs|delphes]")
8271 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true',
8272 help="Run the reweight module (reweighting by different model parameter")
8273 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true',
8274 help="Run the madspin package")
8280 """A class for asking a question where in addition you can have the
8281 set command define and modifying the param_card/run_card correctly"""
8282
8283 - def __init__(self, question, allow_arg=[], default=None,
8284 mother_interface=None, *arg, **opt):
8285
8286 model_path = mother_interface._curr_model.get('modelpath')
8287
8288 ufo_model = ufomodels.load_model(model_path)
8289 self.all_categories = ufo_model.build_restrict.all_categories
8290
8291 question = self.get_question()
8292
8293
8294 allow_arg = ['0']
8295 self.name2options = {}
8296 for category in self.all_categories:
8297 for options in category:
8298 if not options.first:
8299 continue
8300 self.name2options[str(len(allow_arg))] = options
8301 self.name2options[options.name.replace(' ','')] = options
8302 allow_arg.append(len(allow_arg))
8303 allow_arg.append('done')
8304
8305 cmd.SmartQuestion.__init__(self, question, allow_arg, default, mother_interface)
8306
8307
8308
8310 """Default action if line is not recognized"""
8311
8312 line = line.strip()
8313 args = line.split()
8314 if line == '' and self.default_value is not None:
8315 self.value = self.default_value
8316
8317 elif hasattr(self, 'do_%s' % args[0]):
8318 self.do_set(' '.join(args[1:]))
8319 elif line.strip() != '0' and line.strip() != 'done' and \
8320 str(line) != 'EOF' and line.strip() in self.allow_arg:
8321 option = self.name2options[line.strip()]
8322 option.status = not option.status
8323 self.value = 'repeat'
8324 else:
8325 self.value = line
8326
8327 return self.all_categories
8328
8329 - def reask(self, reprint_opt=True):
8334
8336 """ """
8337 self.value = 'repeat'
8338
8339 args = line.split()
8340 if args[0] not in self.name2options:
8341 logger.warning('Invalid set command. %s not recognize options. Valid options are: \n %s' %
8342 (args[0], ', '.join(self.name2options.keys()) ))
8343 return
8344 elif len(args) != 2:
8345 logger.warning('Invalid set command. Not correct number of argument')
8346 return
8347
8348
8349 if args[1] in ['True','1','.true.','T',1,True,'true','TRUE']:
8350 self.name2options[args[0]].status = True
8351 elif args[1] in ['False','0','.false.','F',0,False,'false','FALSE']:
8352 self.name2options[args[0]].status = False
8353 else:
8354 logger.warning('%s is not True/False. Didn\'t do anything.' % args[1])
8355
8356
8357
8359 """define the current question."""
8360 question = ''
8361 i=0
8362 for category in self.all_categories:
8363 question += category.name + ':\n'
8364 for options in category:
8365 if not options.first:
8366 continue
8367 i+=1
8368 question += ' %s: %s [%s]\n' % (i, options.name,
8369 options.display(options.status))
8370 question += 'Enter a number to change it\'s status or press enter to validate.\n'
8371 question += 'For scripting this function, please type: \'help\''
8372 return question
8373
8374
8376 """ Complete the set command"""
8377 signal.alarm(0)
8378 args = self.split_arg(line[0:begidx])
8379
8380 if len(args) == 1:
8381 possibilities = [x for x in self.name2options if not x.isdigit()]
8382 return self.list_completion(text, possibilities, line)
8383 else:
8384 return self.list_completion(text,['True', 'False'], line)
8385
8386
8388 '''help message'''
8389
8390 print 'This allows you to optimize your model to your needs.'
8391 print 'Enter the number associate to the possible restriction/add-on'
8392 print ' to change the status of this restriction/add-on.'
8393 print ''
8394 print 'In order to allow scripting of this function you can use the '
8395 print 'function \'set\'. This function takes two argument:'
8396 print 'set NAME VALUE'
8397 print ' NAME is the description of the option where you remove all spaces'
8398 print ' VALUE is either True or False'
8399 print ' Example: For the question'
8400 print ''' sm customization:
8401 1: diagonal ckm [True]
8402 2: c mass = 0 [True]
8403 3: b mass = 0 [False]
8404 4: tau mass = 0 [False]
8405 5: muon mass = 0 [True]
8406 6: electron mass = 0 [True]
8407 Enter a number to change it's status or press enter to validate.'''
8408 print ''' you can answer by'''
8409 print ' set diagonalckm False'
8410 print ' set taumass=0 True'
8411
8415
8416
8417
8418
8419
8420
8421
8422 if __name__ == '__main__':
8423
8424 run_option = sys.argv
8425 if len(run_option) > 1:
8426
8427 input_file = open(run_option[1], 'rU')
8428 cmd_line = MadGraphCmd(stdin=input_file)
8429 cmd_line.use_rawinput = False
8430 cmd_line.cmdloop()
8431 else:
8432
8433 MadGraphCmd().cmdloop()
8434