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 }
2813
2814 options_madgraph= {'group_subprocesses': 'Auto',
2815 'ignore_six_quark_processes': False,
2816 'low_mem_multicore_nlo_generation': False,
2817 'complex_mass_scheme': False,
2818 'gauge':'unitary',
2819 'stdout_level':None,
2820 'loop_optimized_output':True,
2821 'loop_color_flows':False,
2822 'max_npoint_for_channel': 0
2823 }
2824
2825 options_madevent = {'automatic_html_opening':True,
2826 'run_mode':2,
2827 'nb_core': None,
2828 'notification_center': True
2829 }
2830
2831
2832
2833 _curr_model = None
2834 _curr_amps = diagram_generation.AmplitudeList()
2835 _curr_proc_defs = base_objects.ProcessDefinitionList()
2836 _curr_matrix_elements = helas_objects.HelasMultiProcess()
2837 _curr_helas_model = None
2838 _curr_exporter = None
2839 _done_export = False
2840 _curr_decaymodel = None
2841
2842 helporder = ['Main commands', 'Documented commands']
2843
2844
2858
2859
2860 - def __init__(self, mgme_dir = '', *completekey, **stdin):
2861 """ add a tracker of the history """
2862
2863 CmdExtended.__init__(self, *completekey, **stdin)
2864
2865
2866 if mgme_dir:
2867 if os.path.isdir(pjoin(mgme_dir, 'Template')):
2868 self._mgme_dir = mgme_dir
2869 logger.info('Setting MG/ME directory to %s' % mgme_dir)
2870 else:
2871 logger.warning('Warning: Directory %s not valid MG/ME directory' % \
2872 mgme_dir)
2873 self._mgme_dir = MG4DIR
2874
2875
2876 make_opts = pjoin(MG5DIR, 'Template','LO','Source','make_opts')
2877 make_opts_source = pjoin(MG5DIR, 'Template','LO','Source','.make_opts')
2878 if not os.path.exists(make_opts):
2879 shutil.copy(make_opts_source, make_opts)
2880 elif os.path.getmtime(make_opts) < os.path.getmtime(make_opts_source):
2881 shutil.copy(make_opts_source, make_opts)
2882
2883
2884 self._multiparticles = {}
2885 self.options = {}
2886 self._generate_info = ""
2887 self._model_v4_path = None
2888 self._export_dir = None
2889 self._export_format = 'madevent'
2890 self._mgme_dir = MG4DIR
2891 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
2892 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
2893 self._comparisons = None
2894 self._cms_checks = []
2895 self._nlo_modes_for_completion = ['all','virt','real','LOonly']
2896
2897
2898 self.set_configuration()
2899
2919
2933
2934
2935
2937 """Generate an amplitude for a given process and add to
2938 existing amplitudes
2939 or merge two model
2940 """
2941
2942 args = self.split_arg(line)
2943
2944
2945 warning_duplicate = True
2946 if '--no_warning=duplicate' in args:
2947 warning_duplicate = False
2948 args.remove('--no_warning=duplicate')
2949
2950 diagram_filter = False
2951 if '--diagram_filter' in args:
2952 diagram_filter = True
2953 args.remove('--diagram_filter')
2954
2955 standalone_only = False
2956 if '--standalone' in args:
2957 standalone_only = True
2958 args.remove('--standalone')
2959
2960
2961 self.check_add(args)
2962
2963 if args[0] == 'model':
2964 return self.add_model(args[1:])
2965
2966
2967
2968 if args[-1].startswith('--optimize'):
2969 optimize = True
2970 args.pop()
2971 else:
2972 optimize = False
2973
2974 if args[0] == 'process':
2975
2976 line = ' '.join(args[1:])
2977
2978
2979 if not self._generate_info:
2980 self._generate_info = line
2981
2982
2983 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2984
2985
2986 if ',' in line:
2987 if ']' in line or '[' in line:
2988 error_msg=\
2989 """The '[' and ']' syntax cannot be used in cunjunction with decay chains.
2990 This implies that with decay chains:
2991 > Squared coupling order limitations are not available.
2992 > Loop corrections cannot be considered."""
2993 raise MadGraph5Error(error_msg)
2994 else:
2995 nb_proc = len([l for l in self.history if l.startswith(('generate','add process'))])
2996 myprocdef, line = self.extract_decay_chain_process(line, proc_number=nb_proc)
2997
2998
2999
3000 if myprocdef.are_decays_perturbed():
3001 raise MadGraph5Error("Decay processes cannot be perturbed.")
3002
3003
3004
3005 if myprocdef.decays_have_squared_orders() or \
3006 myprocdef['squared_orders']!={}:
3007 raise MadGraph5Error("Decay processes cannot specify "+\
3008 "squared orders constraints.")
3009 if myprocdef.are_negative_orders_present():
3010 raise MadGraph5Error("Decay processes cannot include negative"+\
3011 " coupling orders constraints.")
3012 else:
3013 nb_proc = len([l for l in self.history if l.startswith(('generate','add process'))])
3014 myprocdef = self.extract_process(line, proc_number=nb_proc)
3015
3016
3017
3018
3019 if not myprocdef:
3020 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3021
3022
3023 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
3024 myprocdef.get_ninitial() and not standalone_only:
3025 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
3026
3027 self._curr_proc_defs.append(myprocdef)
3028
3029
3030
3031 if len([1 for val in myprocdef.get('orders').values()+\
3032 myprocdef.get('squared_orders').values() if val<0])>1:
3033 raise MadGraph5Error("Negative coupling order constraints"+\
3034 " can only be given on one type of coupling and either on"+\
3035 " squared orders or amplitude orders, not both.")
3036
3037 cpu_time1 = time.time()
3038
3039
3040 if self.options['group_subprocesses'] == 'Auto':
3041 collect_mirror_procs = True
3042 else:
3043 collect_mirror_procs = self.options['group_subprocesses']
3044 ignore_six_quark_processes = \
3045 self.options['ignore_six_quark_processes'] if \
3046 "ignore_six_quark_processes" in self.options \
3047 else []
3048
3049 myproc = diagram_generation.MultiProcess(myprocdef,
3050 collect_mirror_procs = collect_mirror_procs,
3051 ignore_six_quark_processes = ignore_six_quark_processes,
3052 optimize=optimize, diagram_filter=diagram_filter)
3053
3054
3055 for amp in myproc.get('amplitudes'):
3056 if amp not in self._curr_amps:
3057 self._curr_amps.append(amp)
3058 elif warning_duplicate:
3059 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
3060 amp.nice_string_processes()
3061
3062
3063 self._done_export = False
3064
3065 cpu_time2 = time.time()
3066
3067 nprocs = len(myproc.get('amplitudes'))
3068 ndiags = sum([amp.get_number_of_diagrams() for \
3069 amp in myproc.get('amplitudes')])
3070
3071 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
3072 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
3073 ndiags = sum([amp.get_number_of_diagrams() for \
3074 amp in self._curr_amps])
3075 logger.info("Total: %i processes with %i diagrams" % \
3076 (len(self._curr_amps), ndiags))
3077
3079 """merge two model"""
3080
3081 model_path = args[0]
3082 recreate = ('--recreate' in args)
3083 keep_decay = ('--keep_decay' in args)
3084 output_dir = [a.split('=',1)[1] for a in args if a.startswith('--output')]
3085 if output_dir:
3086 output_dir = output_dir[0]
3087 recreate = True
3088 restrict_name = ''
3089 else:
3090 name = os.path.basename(self._curr_model.get('modelpath'))
3091 restrict_name = self._curr_model.get('restrict_name')
3092 output_dir = pjoin(MG5DIR, 'models', '%s__%s' % (name,
3093 os.path.basename(model_path)))
3094
3095 if os.path.exists(output_dir):
3096 if recreate:
3097 shutil.rmtree(output_dir)
3098 else:
3099 logger.info('Model already created! Loading it from %s' % output_dir)
3100 oldmodel = self._curr_model.get('modelpath')
3101 new_model_name = output_dir
3102 if restrict_name:
3103 new_model_name = '%s-%s' % (output_dir, restrict_name)
3104 try:
3105 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
3106 printcmd=False, precmd=True, postcmd=True)
3107 except Exception, error:
3108 logger.debug('fail to load model %s with error:\n %s' % (output_dir, error))
3109 logger.warning('Fail to load the model. Restore previous model')
3110 self.exec_cmd('import model %s' % oldmodel, errorhandling=False,
3111 printcmd=False, precmd=True, postcmd=True)
3112 raise Exception('Invalid Model! Please retry with the option \'--recreate\'.')
3113 else:
3114 return
3115
3116
3117 import models.usermod as usermod
3118 base_model = copy.deepcopy(usermod.UFOModel(self._curr_model.get('modelpath')))
3119
3120 identify = dict(tuple(a.split('=')) for a in args if '=' in a)
3121 base_model.add_model(path=model_path, identify_particles=identify)
3122 base_model.write(output_dir)
3123
3124 if keep_decay and os.path.exists(pjoin(self._curr_model.get('modelpath'), 'decays.py')):
3125 base_model.mod_file(pjoin(pjoin(self._curr_model.get('modelpath'), 'decays.py')),
3126 pjoin(pjoin(output_dir, 'decays.py')))
3127
3128 new_model_name = output_dir
3129 if restrict_name:
3130 new_model_name = '%s-%s' % (output_dir, restrict_name)
3131
3132 if 'modelname' in self.history.get('full_model_line'):
3133 opts = '--modelname'
3134 else:
3135 opts=''
3136 self.exec_cmd('import model %s %s' % (new_model_name, opts), errorhandling=False,
3137 printcmd=False, precmd=True, postcmd=True)
3138
3139
3140
3178
3179
3181 """Display current internal status"""
3182
3183 args = self.split_arg(line)
3184
3185 self.check_display(args)
3186
3187 if args[0] == 'diagrams':
3188 self.draw(' '.join(args[1:]))
3189
3190 if args[0] == 'particles' and len(args) == 1:
3191 propagating_particle = []
3192 nb_unpropagating = 0
3193 for particle in self._curr_model['particles']:
3194 if particle.get('propagating'):
3195 propagating_particle.append(particle)
3196 else:
3197 nb_unpropagating += 1
3198
3199 print "Current model contains %i particles:" % \
3200 len(propagating_particle)
3201 part_antipart = [part for part in propagating_particle \
3202 if not part['self_antipart']]
3203 part_self = [part for part in propagating_particle \
3204 if part['self_antipart']]
3205 for part in part_antipart:
3206 print part['name'] + '/' + part['antiname'],
3207 print ''
3208 for part in part_self:
3209 print part['name'],
3210 print ''
3211 if nb_unpropagating:
3212 print 'In addition of %s un-physical particle mediating new interactions.' \
3213 % nb_unpropagating
3214
3215 elif args[0] == 'particles':
3216 for arg in args[1:]:
3217 if arg.isdigit() or (arg[0] == '-' and arg[1:].isdigit()):
3218 particle = self._curr_model.get_particle(abs(int(arg)))
3219 else:
3220 particle = self._curr_model['particles'].find_name(arg)
3221 if not particle:
3222 raise self.InvalidCmd, 'no particle %s in current model' % arg
3223
3224 print "Particle %s has the following properties:" % particle.get_name()
3225 print str(particle)
3226
3227 elif args[0] == 'interactions' and len(args) == 1:
3228 text = "Current model contains %i interactions\n" % \
3229 len(self._curr_model['interactions'])
3230 for i, inter in enumerate(self._curr_model['interactions']):
3231 text += str(i+1) + ':'
3232 for part in inter['particles']:
3233 if part['is_part']:
3234 text += part['name']
3235 else:
3236 text += part['antiname']
3237 text += " "
3238 text += " ".join(order + '=' + str(inter['orders'][order]) \
3239 for order in inter['orders'])
3240 text += '\n'
3241 pydoc.pager(text)
3242
3243 elif args[0] == 'interactions' and len(args)==2 and args[1].isdigit():
3244 for arg in args[1:]:
3245 if int(arg) > len(self._curr_model['interactions']):
3246 raise self.InvalidCmd, 'no interaction %s in current model' % arg
3247 if int(arg) == 0:
3248 print 'Special interactions which identify two particles'
3249 else:
3250 print "Interactions %s has the following property:" % arg
3251 print self._curr_model['interactions'][int(arg)-1]
3252
3253 elif args[0] == 'interactions':
3254 request_part = args[1:]
3255 text = ''
3256 for i, inter in enumerate(self._curr_model['interactions']):
3257 present_part = [part['is_part'] and part['name'] or part['antiname']
3258 for part in inter['particles']
3259 if (part['is_part'] and part['name'] in request_part) or
3260 (not part['is_part'] and part['antiname'] in request_part)]
3261 if len(present_part) < len(request_part):
3262 continue
3263
3264 if set(present_part) != set(request_part):
3265 continue
3266
3267 if len(request_part) > len(set(request_part)):
3268 for p in request_part:
3269 if request_part.count(p) > present_part.count(p):
3270 continue
3271
3272 name = str(i+1) + ' : '
3273 for part in inter['particles']:
3274 if part['is_part']:
3275 name += part['name']
3276 else:
3277 name += part['antiname']
3278 name += " "
3279 text += "\nInteractions %s has the following property:\n" % name
3280 text += str(self._curr_model['interactions'][i])
3281
3282 text += '\n'
3283 print name
3284 if text =='':
3285 text += 'No matching for any interactions'
3286 pydoc.pager(text)
3287
3288
3289 elif args[0] == 'parameters' and len(args) == 1:
3290 text = "Current model contains %i parameters\n" % \
3291 sum([len(part) for part in
3292 self._curr_model['parameters'].values()])
3293 keys = self._curr_model['parameters'].keys()
3294 def key_sort(x, y):
3295 if ('external',) == x:
3296 return -1
3297 elif ('external',) == y:
3298 return +1
3299 elif len(x) < len(y):
3300 return -1
3301 else:
3302 return 1
3303 keys.sort(key_sort)
3304 for key in keys:
3305 item = self._curr_model['parameters'][key]
3306 text += '\nparameter type: %s\n' % str(key)
3307 for value in item:
3308 if hasattr(value, 'expr'):
3309 if value.value is not None:
3310 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3311 else:
3312 text+= ' %s = %s\n' % (value.name, value.expr)
3313 else:
3314 if value.value is not None:
3315 text+= ' %s = %s\n' % (value.name, value.value)
3316 else:
3317 text+= ' %s \n' % (value.name)
3318 pydoc.pager(text)
3319
3320 elif args[0] == 'processes':
3321 for amp in self._curr_amps:
3322 print amp.nice_string_processes()
3323
3324 elif args[0] == 'diagrams_text':
3325 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
3326 pydoc.pager(text)
3327
3328 elif args[0] == 'multiparticles':
3329 print 'Multiparticle labels:'
3330 for key in self._multiparticles:
3331 print self.multiparticle_string(key)
3332
3333 elif args[0] == 'coupling_order':
3334 hierarchy = self._curr_model['order_hierarchy'].items()
3335
3336 def order(first, second):
3337 if first[1] < second[1]:
3338 return -1
3339 else:
3340 return 1
3341 hierarchy.sort(order)
3342 for order in hierarchy:
3343 print ' %s : weight = %s' % order
3344
3345 elif args[0] == 'couplings' and len(args) == 1:
3346 if self._model_v4_path:
3347 print 'No couplings information available in V4 model'
3348 return
3349 text = ''
3350 text = "Current model contains %i couplings\n" % \
3351 sum([len(part) for part in
3352 self._curr_model['couplings'].values()])
3353 keys = self._curr_model['couplings'].keys()
3354 def key_sort(x, y):
3355 if ('external',) == x:
3356 return -1
3357 elif ('external',) == y:
3358 return +1
3359 elif len(x) < len(y):
3360 return -1
3361 else:
3362 return 1
3363 keys.sort(key_sort)
3364 for key in keys:
3365 item = self._curr_model['couplings'][key]
3366 text += '\ncouplings type: %s\n' % str(key)
3367 for value in item:
3368 if value.value is not None:
3369 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3370 else:
3371 text+= ' %s = %s\n' % (value.name, value.expr)
3372
3373 pydoc.pager(text)
3374
3375 elif args[0] == 'couplings':
3376 if self._model_v4_path:
3377 print 'No couplings information available in V4 model'
3378 return
3379
3380 try:
3381 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3382 print 'Note that this is the UFO informations.'
3383 print ' "display couplings" present the actual definition'
3384 print 'prints the current states of mode'
3385 print eval('ufomodel.couplings.%s.nice_string()'%args[1])
3386 except Exception:
3387 raise self.InvalidCmd, 'no couplings %s in current model' % args[1]
3388
3389 elif args[0] == 'lorentz':
3390 if self._model_v4_path:
3391 print 'No lorentz information available in V4 model'
3392 return
3393 elif len(args) == 1:
3394 raise self.InvalidCmd,\
3395 'display lorentz require an argument: the name of the lorentz structure.'
3396 return
3397 try:
3398 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3399 print eval('ufomodel.lorentz.%s.nice_string()'%args[1])
3400 except Exception:
3401 raise self.InvalidCmd, 'no lorentz %s in current model' % args[1]
3402
3403 elif args[0] == 'checks':
3404 outstr = ''
3405 if self._comparisons:
3406 comparisons = self._comparisons[0]
3407 if len(args) > 1 and args[1] == 'failed':
3408 comparisons = [c for c in comparisons if not c['passed']]
3409 outstr += "Process check results:"
3410 for comp in comparisons:
3411 outstr += "\n%s:" % comp['process'].nice_string()
3412 outstr += "\n Phase space point: (px py pz E)"
3413 for i, p in enumerate(comp['momenta']):
3414 outstr += "\n%2s %+.9e %+.9e %+.9e %+.9e" % tuple([i] + p)
3415 outstr += "\n Permutation values:"
3416 outstr += "\n " + str(comp['values'])
3417 if comp['passed']:
3418 outstr += "\n Process passed (rel. difference %.9e)" % \
3419 comp['difference']
3420 else:
3421 outstr += "\n Process failed (rel. difference %.9e)" % \
3422 comp['difference']
3423
3424 used_aloha = sorted(self._comparisons[1])
3425 if used_aloha:
3426 outstr += "\nChecked ALOHA routines:"
3427 for aloha in used_aloha:
3428 aloha_str = aloha[0]
3429 if aloha[1]:
3430 aloha_str += 'C' + 'C'.join([str(ia) for ia in aloha[1]])
3431 aloha_str += "_%d" % aloha[2]
3432 outstr += "\n" + aloha_str
3433
3434 outstr += '\n'
3435 for cms_check in self._cms_checks:
3436 outstr += '*'*102+'\n'
3437 outstr += 'Complex Mass Scheme check:\n'
3438 outstr += ' -> check %s\n'%cms_check['line']
3439 outstr += '*'*102+'\n'
3440 tmp_options = copy.copy(cms_check['options'])
3441 tmp_options['show_plot']=False
3442 outstr += process_checks.output_complex_mass_scheme(
3443 cms_check['cms_result'], cms_check['output_path'],
3444 tmp_options, self._curr_model) + '\n'
3445 outstr += '*'*102+'\n\n'
3446 pydoc.pager(outstr)
3447
3448 elif args[0] == 'options':
3449 if len(args) == 1:
3450 to_print = lambda name: True
3451 else:
3452 to_print = lambda name: any(poss in name for poss in args[1:])
3453
3454 outstr = " MadGraph5_aMC@NLO Options \n"
3455 outstr += " ---------------- \n"
3456 keys = self.options_madgraph.keys()
3457 keys.sort()
3458 for key in keys:
3459 if not to_print(key):
3460 continue
3461 default = self.options_madgraph[key]
3462 value = self.options[key]
3463 if value == default:
3464 outstr += " %25s \t:\t%s\n" % (key,value)
3465 else:
3466 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3467 outstr += "\n"
3468 outstr += " MadEvent Options \n"
3469 outstr += " ---------------- \n"
3470 keys = self.options_madevent.keys()
3471 keys.sort()
3472 for key in keys:
3473 if not to_print(key):
3474 continue
3475 default = self.options_madevent[key]
3476 value = self.options[key]
3477 if value == default:
3478 outstr += " %25s \t:\t%s\n" % (key,value)
3479 else:
3480 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3481 outstr += "\n"
3482 outstr += " Configuration Options \n"
3483 outstr += " --------------------- \n"
3484 keys = self.options_configuration.keys()
3485 keys.sort()
3486 for key in keys:
3487 if not to_print(key):
3488 continue
3489 default = self.options_configuration[key]
3490 value = self.options[key]
3491 if value == default:
3492 outstr += " %25s \t:\t%s\n" % (key,value)
3493 else:
3494 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3495
3496 output.write(outstr)
3497 elif args[0] in ["variable"]:
3498 super(MadGraphCmd, self).do_display(line, output)
3499
3500
3501 - def multiparticle_string(self, key):
3502 """Returns a nicely formatted string for the multiparticle"""
3503
3504 if self._multiparticles[key] and \
3505 isinstance(self._multiparticles[key][0], list):
3506 return "%s = %s" % (key, "|".join([" ".join([self._curr_model.\
3507 get('particle_dict')[part_id].get_name() \
3508 for part_id in id_list]) \
3509 for id_list in self._multiparticles[key]]))
3510 else:
3511 return "%s = %s" % (key, " ".join([self._curr_model.\
3512 get('particle_dict')[part_id].get_name() \
3513 for part_id in self._multiparticles[key]]))
3514
3540
3541
3542
3543 - def draw(self, line,selection='all',type=''):
3599
3600
3602 """Check a given process or set of processes"""
3603
3604 def create_lambda_values_list(lower_bound, N):
3605 """ Returns a list of values spanning the range [1.0, lower_bound] with
3606 lower_bound < 1.0 and with each interval [1e-i, 1e-(i+1)] covered
3607 by N values uniformly distributed. For example, lower_bound=1e-2
3608 and N=5 returns:
3609 [1, 0.8, 0.6, 0.4, 0.2, 0.1, 0.08, 0.06, 0.04, 0.02, 0.01]"""
3610
3611 lCMS_values = [1]
3612 exp = 0
3613 n = 0
3614 while lCMS_values[-1]>=lower_bound:
3615 n = (n+1)
3616 lCMS_values.append(float('1.0e-%d'%exp)*((N-n%N)/float(N)))
3617 if lCMS_values[-1]==lCMS_values[-2]:
3618 lCMS_values.pop()
3619 exp = (n+1)//N
3620
3621 lCMS_values = lCMS_values[:-1]
3622 if lCMS_values[-1]!=lower_bound:
3623 lCMS_values.append(lower_bound)
3624
3625 return lCMS_values
3626
3627
3628
3629 args = self.split_arg(line)
3630
3631 param_card = self.check_check(args)
3632
3633 options= {'events':None}
3634 if param_card and 'banner' == madevent_interface.MadEventCmd.detect_card_type(param_card):
3635 logger_check.info("Will use the param_card contained in the banner and the events associated")
3636 import madgraph.various.banner as banner
3637 options['events'] = param_card
3638 mybanner = banner.Banner(param_card)
3639 param_card = mybanner.charge_card('param_card')
3640
3641 aloha_lib.KERNEL.clean()
3642
3643 gauge = str(self.options['gauge'])
3644 options['reuse'] = args[1]=="-reuse"
3645 args = args[:1]+args[2:]
3646
3647
3648 if args[0] in ['stability', 'profile']:
3649 options['npoints'] = int(args[1])
3650 args = args[:1]+args[2:]
3651
3652 MLoptions={}
3653 i=-1
3654 CMS_options = {}
3655 while args[i].startswith('--'):
3656 option = args[i].split('=')
3657 if option[0] =='--energy':
3658 options['energy']=float(option[1])
3659 elif option[0]=='--split_orders':
3660 options['split_orders']=int(option[1])
3661 elif option[0]=='--helicity':
3662 try:
3663 options['helicity']=int(option[1])
3664 except ValueError:
3665 raise self.InvalidCmd("The value of the 'helicity' option"+\
3666 " must be an integer, not %s."%option[1])
3667 elif option[0]=='--reduction':
3668 MLoptions['MLReductionLib']=[int(ir) for ir in option[1].split('|')]
3669 elif option[0]=='--collier_mode':
3670 MLoptions['COLLIERMode']=int(option[1])
3671 elif option[0]=='--collier_cache':
3672 MLoptions['COLLIERGlobalCache']=int(option[1])
3673 elif option[0]=='--collier_req_acc':
3674 if option[1]!='auto':
3675 MLoptions['COLLIERRequiredAccuracy']=float(option[1])
3676 elif option[0]=='--collier_internal_stability_test':
3677 MLoptions['COLLIERUseInternalStabilityTest']=eval(option[1])
3678 elif option[0]=='--CTModeRun':
3679 try:
3680 MLoptions['CTModeRun']=int(option[1])
3681 except ValueError:
3682 raise self.InvalidCmd("The value of the 'CTModeRun' option"+\
3683 " must be an integer, not %s."%option[1])
3684 elif option[0]=='--offshellness':
3685 CMS_options['offshellness'] = float(option[1])
3686 if CMS_options['offshellness']<=-1.0:
3687 raise self.InvalidCmd('Offshellness must be number larger or'+
3688 ' equal to -1.0, not %f'%CMS_options['offshellness'])
3689 elif option[0]=='--analyze':
3690 options['analyze'] = option[1]
3691 elif option[0]=='--show_plot':
3692 options['show_plot'] = 'true' in option[1].lower()
3693 elif option[0]=='--report':
3694 options['report'] = option[1].lower()
3695 elif option[0]=='--seed':
3696 options['seed'] = int(option[1])
3697 elif option[0]=='--name':
3698 if '.' in option[1]:
3699 raise self.InvalidCmd("Do not specify the extension in the"+
3700 " name of the run")
3701 CMS_options['name'] = option[1]
3702 elif option[0]=='--resonances':
3703 if option[1]=='all':
3704 CMS_options['resonances'] = 'all'
3705 else:
3706 try:
3707 resonances=eval(option[1])
3708 except:
3709 raise self.InvalidCmd("Could not evaluate 'resonances'"+
3710 " option '%s'"%option[1])
3711 if isinstance(resonances,int) and resonances>0:
3712 CMS_options['resonances'] = resonances
3713 elif isinstance(resonances,list) and all(len(res)==2 and
3714 isinstance(res[0],int) and all(isinstance(i, int) for i in
3715 res[1]) for res in resonances):
3716 CMS_options['resonances'] = resonances
3717 else:
3718 raise self.InvalidCmd("The option 'resonances' can only be 'all'"+
3719 " or and integer or a list of tuples of the form "+
3720 "(resPDG,(res_mothers_ID)). You gave '%s'"%option[1])
3721 elif option[0]=='--tweak':
3722
3723 value = option[1]
3724
3725 if value=='alltweaks':
3726 value=str(['default','seed667(seed667)','seed668(seed668)',
3727 'allwidths->0.9*allwidths(widths_x_0.9)',
3728 'allwidths->0.99*allwidths(widths_x_0.99)',
3729 'allwidths->1.01*allwidths(widths_x_1.01)',
3730 'allwidths->1.1*allwidths(widths_x_1.1)',
3731 'logp->logm(logp2logm)','logm->logp(logm2logp)'])
3732 try:
3733 tweaks = eval(value)
3734 if isinstance(tweaks, str):
3735 tweaks = [value]
3736 elif not isinstance(tweaks,list):
3737 tweaks = [value]
3738 except:
3739 tweaks = [value]
3740 if not all(isinstance(t,str) for t in tweaks):
3741 raise self.InvalidCmd("Invalid specificaiton of tweaks: %s"%value)
3742 CMS_options['tweak'] = []
3743 for tweakID, tweakset in enumerate(tweaks):
3744 specs =re.match(r'^(?P<tweakset>.*)\((?P<name>.*)\)$', tweakset)
3745 if specs:
3746 tweakset = specs.group('tweakset')
3747 name = specs.group('name')
3748 else:
3749 if tweakset!='default':
3750 name = 'tweak_%d'%(tweakID+1)
3751 else:
3752 name = ''
3753 new_tweak_set = {'custom':[],'params':{},'name':name}
3754 for tweak in tweakset.split('&'):
3755 if tweak=='default':
3756 continue
3757 if tweak.startswith('seed'):
3758 new_tweak_set['custom'].append(tweak)
3759 continue
3760 try:
3761 param, replacement = tweak.split('->')
3762 except ValueError:
3763 raise self.InvalidCmd("Tweak specification '%s'"%\
3764 tweak+" is incorrect. It should be of"+\
3765 " the form a->_any_function_of_(a,lambdaCMS).")
3766 if param in ['logp','logm','log'] and \
3767 replacement in ['logp','logm','log']:
3768 new_tweak_set['custom'].append(tweak)
3769 continue
3770 try:
3771
3772
3773 orig_param, orig_replacement = param, replacement
3774 replacement = replacement.replace(param,
3775 '__tmpprefix__%s'%param)
3776 param = '__tmpprefix__%s'%param
3777 res = float(eval(replacement.lower(),
3778 {'lambdacms':1.0,param.lower():98.85}))
3779 except:
3780 raise self.InvalidCmd("The substitution expression "+
3781 "'%s' for the tweaked parameter"%orig_replacement+
3782 " '%s' could not be evaluated. It must be an "%orig_param+
3783 "expression of the parameter and 'lambdaCMS'.")
3784 new_tweak_set['params'][param.lower()] = replacement.lower()
3785 CMS_options['tweak'].append(new_tweak_set)
3786
3787 elif option[0]=='--recompute_width':
3788 if option[1].lower() not in ['never','always','first_time','auto']:
3789 raise self.InvalidCmd("The option 'recompute_width' can "+\
3790 "only be 'never','always', 'first_time' or 'auto' (default).")
3791 CMS_options['recompute_width'] = option[1]
3792 elif option[0]=='--loop_filter':
3793
3794
3795
3796 CMS_options['loop_filter'] = '='.join(option[1:])
3797 elif option[0]=='--diff_lambda_power':
3798
3799
3800
3801
3802 try:
3803 CMS_options['diff_lambda_power']=float(option[1])
3804 except ValueError:
3805 raise self.InvalidCmd("the '--diff_lambda_power' option"+\
3806 " must be an integer or float, not '%s'."%option[1])
3807 elif option[0]=='--lambda_plot_range':
3808 try:
3809 plot_range=eval(option[1])
3810 except Exception as e:
3811 raise self.InvalidCmd("The plot range specified %s"%option[1]+\
3812 " is not a valid syntax. Error:\n%s"%str(e))
3813 if not isinstance(plot_range,(list,tuple)) or \
3814 len(plot_range)!=2 or any(not isinstance(p,(float,int))
3815 for p in plot_range):
3816 raise self.InvalidCmd("The plot range specified %s"\
3817 %option[1]+" is invalid")
3818 CMS_options['lambda_plot_range']=list([float(p) for p in plot_range])
3819 elif option[0]=='--lambdaCMS':
3820 try:
3821 lambda_values = eval(option[1])
3822 except SyntaxError:
3823 raise self.InvalidCmd("'%s' is not a correct"%option[1]+
3824 " python expression for lambdaCMS values.")
3825 if isinstance(lambda_values,list):
3826 if lambda_values[0]!=1.0:
3827 raise self.InvalidCmd("The first value of the lambdaCMS values"+
3828 " specified must be 1.0, not %s"%str(lambda_values))
3829 for l in lambda_values:
3830 if not isinstance(l,float):
3831 raise self.InvalidCmd("All lambda CMS values must be"+
3832 " float, not '%s'"%str(l))
3833 elif isinstance(lambda_values,(tuple,float)):
3834
3835
3836
3837
3838 if isinstance(lambda_values, float):
3839
3840 lower_bound = lambda_values
3841 N = 10
3842 else:
3843 if isinstance(lambda_values[0],float) and \
3844 isinstance(lambda_values[1],int):
3845 lower_bound = lambda_values[0]
3846 N = lambda_values[1]
3847 else:
3848 raise self.InvalidCmd("'%s' must be a "%option[1]+
3849 "tuple with types (float, int).")
3850 lambda_values = create_lambda_values_list(lower_bound,N)
3851 else:
3852 raise self.InvalidCmd("'%s' must be an expression"%option[1]+
3853 " for either a float, tuple or list.")
3854 lower_bound = lambda_values[-1]
3855
3856
3857
3858
3859
3860
3861 CMS_options['lambdaCMS'] = lambda_values
3862 elif option[0]=='--cms':
3863 try:
3864 CMS_expansion_orders, CMS_expansion_parameters = \
3865 option[1].split(',')
3866 except ValueError:
3867 raise self.InvalidCmd("CMS expansion specification '%s'"%\
3868 args[i]+" is incorrect.")
3869 CMS_options['expansion_orders'] = [expansion_order for
3870 expansion_order in CMS_expansion_orders.split('&')]
3871 CMS_options['expansion_parameters'] = {}
3872 for expansion_parameter in CMS_expansion_parameters.split('&'):
3873 try:
3874 param, replacement = expansion_parameter.split('->')
3875 except ValueError:
3876 raise self.InvalidCmd("CMS expansion specification '%s'"%\
3877 expansion_parameter+" is incorrect. It should be of"+\
3878 " the form a->_any_function_of_(a,lambdaCMS).")
3879 try:
3880
3881
3882 orig_param, orig_replacement = param, replacement
3883 replacement = replacement.replace(param,
3884 '__tmpprefix__%s'%param)
3885 param = '__tmpprefix__%s'%param
3886 res = float(eval(replacement.lower(),
3887 {'lambdacms':1.0,param.lower():98.85}))
3888 except:
3889 raise self.InvalidCmd("The substitution expression "+
3890 "'%s' for CMS expansion parameter"%orig_replacement+
3891 " '%s' could not be evaluated. It must be an "%orig_param+
3892 "expression of the parameter and 'lambdaCMS'.")
3893
3894
3895 CMS_options['expansion_parameters'][param.lower()]=\
3896 replacement.lower()
3897 else:
3898 raise self.InvalidCmd("The option '%s' is not reckognized."%option[0])
3899
3900 i=i-1
3901 args = args[:i+1]
3902
3903 if args[0]=='options':
3904
3905 logger_check.info("Options for the command 'check' are:")
3906 logger_check.info("{:<20} {}".format(' name','default value'))
3907 logger_check.info("-"*40)
3908 for key, value in options.items():
3909 logger_check.info("{:<20} = {}".format('--%s'%key,str(value)))
3910 return
3911
3912 if args[0].lower()=='cmsoptions':
3913
3914 logger_check.info("Special options for the command 'check cms' are:")
3915 logger_check.info("{:<20} {}".format(' name','default value'))
3916 logger_check.info("-"*40)
3917 for key, value in CMS_options.items():
3918 logger_check.info("{:<20} = {}".format('--%s'%key,str(value)))
3919 return
3920
3921
3922 if args[0]!='cms' and options['seed']!=-1:
3923
3924
3925
3926 logger_check.info('Setting random seed to %d.'%options['seed'])
3927 random.seed(options['seed'])
3928
3929 proc_line = " ".join(args[1:])
3930
3931 if not (args[0]=='cms' and options['analyze']!='None'):
3932 myprocdef = self.extract_process(proc_line)
3933
3934
3935 if not myprocdef:
3936 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3937
3938 if myprocdef.get('NLO_mode')=='all':
3939 myprocdef.set('NLO_mode','virt')
3940 else:
3941 myprocdef = None
3942
3943
3944
3945 output_path = os.getcwd()
3946
3947 if args[0] in ['timing','stability', 'profile'] and not \
3948 myprocdef.get('perturbation_couplings'):
3949 raise self.InvalidCmd("Only loop processes can have their "+
3950 " timings or stability checked.")
3951
3952 if args[0]=='gauge' and \
3953 not myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3954 raise self.InvalidCmd(
3955 """Feynman vs unitary gauge comparisons can only be done if there are no loop
3956 propagators affected by this gauge. Typically, either processes at tree level
3957 or including only QCD perturbations can be considered here.""")
3958
3959 if args[0]=='gauge' and len(self._curr_model.get('gauge')) < 2:
3960 raise self.InvalidCmd("The current model does not allow for both "+\
3961 "Feynman and unitary gauge.")
3962
3963
3964 loggers = [logging.getLogger('madgraph.diagram_generation'),
3965 logging.getLogger('madgraph.loop_diagram_generation'),
3966 logging.getLogger('ALOHA'),
3967 logging.getLogger('madgraph.helas_objects'),
3968 logging.getLogger('madgraph.loop_exporter'),
3969 logging.getLogger('madgraph.export_v4'),
3970 logging.getLogger('cmdprint'),
3971 logging.getLogger('madgraph.model'),
3972 logging.getLogger('madgraph.base_objects')]
3973 old_levels = [log.level for log in loggers]
3974 for log in loggers:
3975 log.setLevel(logging.WARNING)
3976
3977
3978 cpu_time1 = time.time()
3979
3980
3981
3982
3983
3984
3985
3986 if myprocdef:
3987 if myprocdef.get('perturbation_couplings')==[]:
3988 aloha.loop_mode = False
3989
3990 comparisons = []
3991 gauge_result = []
3992 gauge_result_no_brs = []
3993 lorentz_result =[]
3994 nb_processes = 0
3995 timings = []
3996 stability = []
3997 profile_time = []
3998 profile_stab = []
3999 cms_results = []
4000
4001 if "_cuttools_dir" in dir(self):
4002 CT_dir = self._cuttools_dir
4003 else:
4004 CT_dir =""
4005 if "MLReductionLib" in MLoptions:
4006 if 1 in MLoptions["MLReductionLib"]:
4007 MLoptions["MLReductionLib"].remove(1)
4008
4009 TIR_dir={}
4010 if "_iregi_dir" in dir(self):
4011 TIR_dir['iregi_dir']=self._iregi_dir
4012 else:
4013 if "MLReductionLib" in MLoptions:
4014 if 3 in MLoptions["MLReductionLib"]:
4015 logger_check.warning('IREGI not available on your system; it will be skipped.')
4016 MLoptions["MLReductionLib"].remove(3)
4017
4018 if 'pjfry' in self.options and isinstance(self.options['pjfry'],str):
4019 TIR_dir['pjfry_dir']=self.options['pjfry']
4020 else:
4021 if "MLReductionLib" in MLoptions:
4022 if 2 in MLoptions["MLReductionLib"]:
4023 logger_check.warning('PJFRY not available on your system; it will be skipped.')
4024 MLoptions["MLReductionLib"].remove(2)
4025
4026 if 'golem' in self.options and isinstance(self.options['golem'],str):
4027 TIR_dir['golem_dir']=self.options['golem']
4028 else:
4029 if "MLReductionLib" in MLoptions:
4030 if 4 in MLoptions["MLReductionLib"]:
4031 logger_check.warning('GOLEM not available on your system; it will be skipped.')
4032 MLoptions["MLReductionLib"].remove(4)
4033
4034 if 'samurai' in self.options and isinstance(self.options['samurai'],str):
4035 TIR_dir['samurai_dir']=self.options['samurai']
4036 else:
4037 if "MLReductionLib" in MLoptions:
4038 if 5 in MLoptions["MLReductionLib"]:
4039 logger_check.warning('Samurai not available on your system; it will be skipped.')
4040 MLoptions["MLReductionLib"].remove(5)
4041
4042 if 'collier' in self.options and isinstance(self.options['collier'],str):
4043 TIR_dir['collier_dir']=self.options['collier']
4044 else:
4045 if "MLReductionLib" in MLoptions:
4046 if 7 in MLoptions["MLReductionLib"]:
4047 logger_check.warning('Collier not available on your system; it will be skipped.')
4048 MLoptions["MLReductionLib"].remove(7)
4049
4050 if 'ninja' in self.options and isinstance(self.options['ninja'],str):
4051 TIR_dir['ninja_dir']=self.options['ninja']
4052 else:
4053 if "MLReductionLib" in MLoptions:
4054 if 6 in MLoptions["MLReductionLib"]:
4055 logger_check.warning('Ninja not available on your system; it will be skipped.')
4056 MLoptions["MLReductionLib"].remove(6)
4057
4058 if args[0] in ['timing']:
4059 timings = process_checks.check_timing(myprocdef,
4060 param_card = param_card,
4061 cuttools=CT_dir,
4062 tir=TIR_dir,
4063 options = options,
4064 cmd = self,
4065 output_path = output_path,
4066 MLOptions = MLoptions
4067 )
4068
4069 if args[0] in ['stability']:
4070 stability=process_checks.check_stability(myprocdef,
4071 param_card = param_card,
4072 cuttools=CT_dir,
4073 tir=TIR_dir,
4074 options = options,
4075 output_path = output_path,
4076 cmd = self,
4077 MLOptions = MLoptions)
4078
4079 if args[0] in ['profile']:
4080
4081
4082 profile_time, profile_stab = process_checks.check_profile(myprocdef,
4083 param_card = param_card,
4084 cuttools=CT_dir,
4085 tir=TIR_dir,
4086 options = options,
4087 MLOptions = MLoptions,
4088 output_path = output_path,
4089 cmd = self)
4090
4091 if args[0] in ['gauge', 'full'] and \
4092 len(self._curr_model.get('gauge')) == 2 and\
4093 myprocdef.get('perturbation_couplings') in [[],['QCD']]:
4094
4095 line = " ".join(args[1:])
4096 myprocdef = self.extract_process(line)
4097 if gauge == 'unitary':
4098 myprocdef_unit = myprocdef
4099 self.do_set('gauge Feynman', log=False)
4100 myprocdef_feyn = self.extract_process(line)
4101 else:
4102 myprocdef_feyn = myprocdef
4103 self.do_set('gauge unitary', log=False)
4104 myprocdef_unit = self.extract_process(line)
4105
4106 nb_part_unit = len(myprocdef_unit.get('model').get('particles'))
4107 nb_part_feyn = len(myprocdef_feyn.get('model').get('particles'))
4108 if nb_part_feyn == nb_part_unit:
4109 logger_check.error('No Goldstone present for this check!!')
4110 gauge_result_no_brs = process_checks.check_unitary_feynman(
4111 myprocdef_unit, myprocdef_feyn,
4112 param_card = param_card,
4113 options=options,
4114 cuttools=CT_dir,
4115 tir=TIR_dir,
4116 reuse = options['reuse'],
4117 output_path = output_path,
4118 cmd = self)
4119
4120
4121 self.do_set('gauge %s' % gauge, log=False)
4122 nb_processes += len(gauge_result_no_brs)
4123
4124 if args[0] in ['permutation', 'full']:
4125 comparisons = process_checks.check_processes(myprocdef,
4126 param_card = param_card,
4127 quick = True,
4128 cuttools=CT_dir,
4129 tir=TIR_dir,
4130 reuse = options['reuse'],
4131 cmd = self,
4132 output_path = output_path,
4133 options=options)
4134 nb_processes += len(comparisons[0])
4135
4136 if args[0] in ['lorentz', 'full']:
4137 myprocdeff = copy.copy(myprocdef)
4138 lorentz_result = process_checks.check_lorentz(myprocdeff,
4139 param_card = param_card,
4140 cuttools=CT_dir,
4141 tir=TIR_dir,
4142 reuse = options['reuse'],
4143 cmd = self,
4144 output_path = output_path,
4145 options=options)
4146 nb_processes += len(lorentz_result)
4147
4148 if args[0] in ['brs', 'full']:
4149 gauge_result = process_checks.check_gauge(myprocdef,
4150 param_card = param_card,
4151 cuttools=CT_dir,
4152 tir=TIR_dir,
4153 reuse = options['reuse'],
4154 cmd = self,
4155 output_path = output_path,
4156 options=options)
4157 nb_processes += len(gauge_result)
4158
4159
4160
4161 if args[0] in ['cms']:
4162
4163 cms_original_setup = self.options['complex_mass_scheme']
4164 process_line = " ".join(args[1:])
4165
4166 for key, value in CMS_options.items():
4167 if key=='tweak':
4168 continue
4169 if key not in options:
4170 options[key] = value
4171 else:
4172 raise MadGraph5Error,"Option '%s' is both in the option"%key+\
4173 " and CMS_option dictionary."
4174
4175 if options['analyze']=='None':
4176 cms_results = []
4177 for tweak in CMS_options['tweak']:
4178 options['tweak']=tweak
4179
4180 guessed_proc = myprocdef.get_process(
4181 [leg.get('ids')[0] for leg in myprocdef.get('legs')
4182 if not leg.get('state')],
4183 [leg.get('ids')[0] for leg in myprocdef.get('legs')
4184 if leg.get('state')])
4185 save_path = process_checks.CMS_save_path('pkl',
4186 {'ordered_processes':[guessed_proc.base_string()],
4187 'perturbation_orders':guessed_proc.get('perturbation_couplings')},
4188 self._curr_model, options, output_path=output_path)
4189 if os.path.isfile(save_path) and options['reuse']:
4190 cms_result = save_load_object.load_from_file(save_path)
4191 logger_check.info("The cms check for tweak %s is recycled from file:\n %s"%
4192 (tweak['name'],save_path))
4193 if cms_result is None:
4194 raise self.InvalidCmd('The complex mass scheme check result'+
4195 " file below could not be read.\n %s"%save_path)
4196 else:
4197 cms_result = process_checks.check_complex_mass_scheme(
4198 process_line,
4199 param_card = param_card,
4200 cuttools=CT_dir,
4201 tir=TIR_dir,
4202 cmd = self,
4203 output_path = output_path,
4204 MLOptions = MLoptions,
4205 options=options)
4206
4207 save_path = process_checks.CMS_save_path('pkl', cms_result,
4208 self._curr_model, options, output_path=output_path)
4209 cms_results.append((cms_result,save_path,tweak['name']))
4210 else:
4211 cms_result = save_load_object.load_from_file(
4212 options['analyze'].split(',')[0])
4213 cms_results.append((cms_result,options['analyze'].split(',')[0],
4214 CMS_options['tweak'][0]['name']))
4215 if cms_result is None:
4216 raise self.InvalidCmd('The complex mass scheme check result'+
4217 " file below could not be read.\n %s"
4218 %options['analyze'].split(',')[0])
4219
4220
4221 self.do_set('complex_mass_scheme %s'%str(cms_original_setup),
4222 log=False)
4223
4224 nb_processes += len(cms_result['ordered_processes'])
4225
4226 cpu_time2 = time.time()
4227 logger_check.info("%i check performed in %s"% (nb_processes,
4228 misc.format_time(int(cpu_time2 - cpu_time1))))
4229
4230 if args[0] in ['cms']:
4231 text = "Note that the complex mass scheme test in principle only\n"
4232 text+= "works for stable particles in final states.\n\ns"
4233 if args[0] not in ['timing','stability', 'profile', 'cms']:
4234 if self.options['complex_mass_scheme']:
4235 text = "Note that Complex mass scheme gives gauge/lorentz invariant\n"
4236 text+= "results only for stable particles in final states.\n\ns"
4237 elif not myprocdef.get('perturbation_couplings'):
4238 text = "Note That all width have been set to zero for those checks\n\n"
4239 else:
4240 text = "\n"
4241 else:
4242 text ="\n"
4243
4244 if timings:
4245 text += 'Timing result for the '+('optimized' if \
4246 self.options['loop_optimized_output'] else 'default')+' output:\n'
4247
4248 text += process_checks.output_timings(myprocdef, timings)
4249 if stability:
4250 text += 'Stability result for the '+('optimized' if \
4251 self.options['loop_optimized_output'] else 'default')+' output:\n'
4252 text += process_checks.output_stability(stability,output_path)
4253
4254 if profile_time and profile_stab:
4255 text += 'Timing result '+('optimized' if \
4256 self.options['loop_optimized_output'] else 'default')+':\n'
4257 text += process_checks.output_profile(myprocdef, profile_stab,
4258 profile_time, output_path, options['reuse']) + '\n'
4259 if lorentz_result:
4260 text += 'Lorentz invariance results:\n'
4261 text += process_checks.output_lorentz_inv(lorentz_result) + '\n'
4262 if gauge_result:
4263 text += 'Gauge results:\n'
4264 text += process_checks.output_gauge(gauge_result) + '\n'
4265 if gauge_result_no_brs:
4266 text += 'Gauge results (switching between Unitary/Feynman):\n'
4267 text += process_checks.output_unitary_feynman(gauge_result_no_brs) + '\n'
4268 if cms_results:
4269 text += 'Complex mass scheme results (varying width in the off-shell regions):\n'
4270 cms_result = cms_results[0][0]
4271 if len(cms_results)>1:
4272 analyze = []
4273 for i, (cms_res, save_path, tweakname) in enumerate(cms_results):
4274 save_load_object.save_to_file(save_path, cms_res)
4275 logger_check.info("Pickle file for tweak '%s' saved to disk at:\n ->%s"%
4276 (tweakname,save_path))
4277 if i==0:
4278 analyze.append(save_path)
4279 else:
4280 analyze.append('%s(%s)'%(save_path,tweakname))
4281 options['analyze']=','.join(analyze)
4282 options['tweak'] = CMS_options['tweak'][0]
4283
4284 self._cms_checks.append({'line':line, 'cms_result':cms_result,
4285 'options':options, 'output_path':output_path})
4286 text += process_checks.output_complex_mass_scheme(cms_result,
4287 output_path, options, self._curr_model,
4288 output='concise_text' if options['report']=='concise' else 'text')+'\n'
4289
4290 if comparisons and len(comparisons[0])>0:
4291 text += 'Process permutation results:\n'
4292 text += process_checks.output_comparisons(comparisons[0]) + '\n'
4293 self._comparisons = comparisons
4294
4295
4296 if len(text.split('\n'))>20 and not '-reuse' in line and text!='':
4297 if 'test_manager' not in sys.argv[0]:
4298 pydoc.pager(text)
4299
4300
4301 for i, log in enumerate(loggers):
4302 log.setLevel(old_levels[i])
4303
4304
4305
4306 if len(text.split('\n'))<=20 or options['reuse']:
4307
4308 logging.getLogger('madgraph.check_cmd').info(text)
4309 else:
4310 logging.getLogger('madgraph.check_cmd').debug(text)
4311
4312
4313 process_checks.clean_added_globals(process_checks.ADDED_GLOBAL)
4314 if not options['reuse']:
4315 process_checks.clean_up(self._mgme_dir)
4316
4317
4339
4341 """Extract a process definition from a string. Returns
4342 a ProcessDefinition."""
4343
4344 orig_line = line
4345
4346 if not len(re.findall('>\D', line)) in [1,2]:
4347 self.do_help('generate')
4348 raise self.InvalidCmd('Wrong use of \">\" special character.')
4349
4350
4351
4352
4353 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
4354 line = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
4355
4356
4357
4358
4359
4360
4361 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
4362 proc_number_re = proc_number_pattern.match(line)
4363 if proc_number_re:
4364 proc_number = int(proc_number_re.group(2))
4365 line = proc_number_re.group(1)+ proc_number_re.group(3)
4366
4367
4368
4369 perturbation_couplings_pattern = \
4370 re.compile("^(?P<proc>.+>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*"+\
4371 "(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
4372 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
4373 perturbation_couplings = ""
4374 LoopOption= 'tree'
4375 HasBorn= True
4376 if perturbation_couplings_re:
4377 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
4378 option=perturbation_couplings_re.group("option")
4379 if option:
4380 if option in self._valid_nlo_modes:
4381 LoopOption=option
4382 if option=='sqrvirt':
4383 LoopOption='virt'
4384 HasBorn=False
4385 elif option=='noborn':
4386 HasBorn=False
4387 else:
4388 raise self.InvalidCmd, "NLO mode %s is not valid. "%option+\
4389 "Valid modes are %s. "%str(self._valid_nlo_modes)
4390 else:
4391 LoopOption='all'
4392
4393 line = perturbation_couplings_re.group("proc")+\
4394 perturbation_couplings_re.group("rest")
4395
4396
4397 order_pattern = re.compile(\
4398 "^(?P<before>.+>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
4399 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*")
4400 order_re = order_pattern.match(line)
4401 squared_orders = {}
4402 orders = {}
4403 constrained_orders = {}
4404
4405
4406
4407
4408 split_orders = []
4409 while order_re:
4410 type = order_re.group('type')
4411 if order_re.group('name').endswith('^2'):
4412 if type not in self._valid_sqso_types:
4413 raise self.InvalidCmd, "Type of squared order "+\
4414 "constraint '%s'"% type+" is not supported."
4415 if type == '=':
4416 name = order_re.group('name')
4417 value = order_re.group('value')
4418 logger.warning("Interpreting '%(n)s=%(v)s' as '%(n)s<=%(v)s'" %\
4419 {'n':name, 'v': value})
4420 type = "<="
4421 squared_orders[order_re.group('name')[:-2]] = \
4422 (int(order_re.group('value')),type)
4423 else:
4424 if type not in self._valid_amp_so_types:
4425 raise self.InvalidCmd, \
4426 "Amplitude order constraints can only be of type %s"%\
4427 (', '.join(self._valid_amp_so_types))+", not '%s'."%type
4428 name = order_re.group('name')
4429 value = int(order_re.group('value'))
4430 if type in ['=', '<=']:
4431 if type == '=' and value != 0:
4432 logger.warning("Interpreting '%(n)s=%(v)s' as '%(n)s<=%(v)s'" %\
4433 {'n':name, 'v': value})
4434 orders[name] = value
4435 elif type == "==":
4436 constrained_orders[name] = (value, type)
4437 if name not in squared_orders:
4438 squared_orders[name] = (2 * value,'==')
4439 if True:
4440 orders[name] = value
4441
4442 elif type == ">":
4443 constrained_orders[name] = (value, type)
4444 if name not in squared_orders:
4445 squared_orders[name] = (2 * value,'>')
4446
4447 line = order_re.group('before')
4448 order_re = order_pattern.match(line)
4449
4450
4451 if constrained_orders and LoopOption != 'tree':
4452 raise self.InvalidCmd, \
4453 "Amplitude order constraints (for not LO processes) can only be of type %s"%\
4454 (', '.join(['<=']))+", not '%s'."%type
4455
4456
4457
4458
4459
4460
4461 if orders=={} and squared_orders!={}:
4462 for order in squared_orders.keys():
4463 if squared_orders[order][0]>=0 and squared_orders[order][1]!='>':
4464 orders[order]=squared_orders[order][0]
4465 else:
4466 orders[order]=99
4467
4468 if not self._curr_model['case_sensitive']:
4469
4470 line = line.lower()
4471
4472
4473 slash = line.find("/")
4474 dollar = line.find("$")
4475 forbidden_particles = ""
4476 if slash > 0:
4477 if dollar > slash:
4478 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
4479 else:
4480 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
4481 if forbidden_particles_re:
4482 forbidden_particles = forbidden_particles_re.group(2)
4483 line = forbidden_particles_re.group(1)
4484 if len(forbidden_particles_re.groups()) > 2:
4485 line = line + forbidden_particles_re.group(3)
4486
4487
4488 forbidden_schannels_re = re.match("^(.+)\s*\$\s*\$\s*(.+)\s*$", line)
4489 forbidden_schannels = ""
4490 if forbidden_schannels_re:
4491 forbidden_schannels = forbidden_schannels_re.group(2)
4492 line = forbidden_schannels_re.group(1)
4493
4494
4495 forbidden_onsh_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
4496 forbidden_onsh_schannels = ""
4497 if forbidden_onsh_schannels_re:
4498 forbidden_onsh_schannels = forbidden_onsh_schannels_re.group(2)
4499 line = forbidden_onsh_schannels_re.group(1)
4500
4501
4502 required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
4503 required_schannels = ""
4504 if required_schannels_re:
4505 required_schannels = required_schannels_re.group(2)
4506 line = required_schannels_re.group(1) + ">" + \
4507 required_schannels_re.group(3)
4508
4509 args = self.split_arg(line)
4510
4511 myleglist = base_objects.MultiLegList()
4512 state = False
4513
4514
4515 for part_name in args:
4516 if part_name == '>':
4517 if not myleglist:
4518 raise self.InvalidCmd, "No final state particles"
4519 state = True
4520 continue
4521
4522 mylegids = []
4523 if part_name in self._multiparticles:
4524 if isinstance(self._multiparticles[part_name][0], list):
4525 raise self.InvalidCmd,\
4526 "Multiparticle %s is or-multiparticle" % part_name + \
4527 " which can be used only for required s-channels"
4528 mylegids.extend(self._multiparticles[part_name])
4529 elif part_name.isdigit() or part_name.startswith('-') and part_name[1:].isdigit():
4530 if int(part_name) in self._curr_model.get('particle_dict'):
4531 mylegids.append(int(part_name))
4532 else:
4533 raise self.InvalidCmd, \
4534 "No pdg_code %s in model" % part_name
4535 else:
4536 mypart = self._curr_model['particles'].get_copy(part_name)
4537 if mypart:
4538 mylegids.append(mypart.get_pdg_code())
4539
4540 if mylegids:
4541 myleglist.append(base_objects.MultiLeg({'ids':mylegids,
4542 'state':state}))
4543 else:
4544 raise self.InvalidCmd, "No particle %s in model" % part_name
4545
4546
4547 if perturbation_couplings.lower()=='all':
4548 perturbation_couplings=' '.join(self._curr_model['perturbation_couplings'])
4549
4550 if filter(lambda leg: leg.get('state') == True, myleglist):
4551
4552
4553 perturbation_couplings_list = perturbation_couplings.split()
4554 if perturbation_couplings_list==['']:
4555 perturbation_couplings_list=[]
4556
4557
4558 split_orders=list(set(perturbation_couplings_list+squared_orders.keys()))
4559 try:
4560 split_orders.sort(key=lambda elem: 0 if elem=='WEIGHTED' else
4561 self._curr_model['order_hierarchy']
4562 [elem if not elem.endswith('.sqrt') else elem[:-5]])
4563 except KeyError:
4564 raise self.InvalidCmd, "The loaded model does not defined a "+\
4565 " coupling order hierarchy for these couplings: %s"%\
4566 str([so for so in split_orders if so!='WEIGHTED' and so not
4567 in self._curr_model['order_hierarchy'].keys()])
4568
4569
4570
4571
4572 if LoopOption=='tree':
4573 perturbation_couplings_list = []
4574 if perturbation_couplings_list and LoopOption not in ['real', 'LOonly']:
4575 if not isinstance(self._curr_model,loop_base_objects.LoopModel):
4576 raise self.InvalidCmd(\
4577 "The current model does not allow for loop computations.")
4578 else:
4579 for pert_order in perturbation_couplings_list:
4580 if pert_order not in self._curr_model['perturbation_couplings']:
4581 raise self.InvalidCmd(\
4582 "Perturbation order %s is not among" % pert_order + \
4583 " the perturbation orders allowed for by the loop model.")
4584 if not self.options['loop_optimized_output'] and \
4585 LoopOption not in ['tree','real'] and split_orders!=[]:
4586 logger.warning('The default output mode (loop_optimized_output'+\
4587 ' = False) does not support evaluations for given powers of'+\
4588 ' coupling orders. MadLoop output will therefore not be'+\
4589 ' able to provide such quantities.')
4590 split_orders = []
4591
4592
4593 forbidden_particle_ids = \
4594 self.extract_particle_ids(forbidden_particles)
4595 if forbidden_particle_ids and \
4596 isinstance(forbidden_particle_ids[0], list):
4597 raise self.InvalidCmd(\
4598 "Multiparticle %s is or-multiparticle" % part_name + \
4599 " which can be used only for required s-channels")
4600 forbidden_onsh_schannel_ids = \
4601 self.extract_particle_ids(forbidden_onsh_schannels)
4602 forbidden_schannel_ids = \
4603 self.extract_particle_ids(forbidden_schannels)
4604 if forbidden_onsh_schannel_ids and \
4605 isinstance(forbidden_onsh_schannel_ids[0], list):
4606 raise self.InvalidCmd,\
4607 "Multiparticle %s is or-multiparticle" % part_name + \
4608 " which can be used only for required s-channels"
4609 if forbidden_schannel_ids and \
4610 isinstance(forbidden_schannel_ids[0], list):
4611 raise self.InvalidCmd,\
4612 "Multiparticle %s is or-multiparticle" % part_name + \
4613 " which can be used only for required s-channels"
4614 required_schannel_ids = \
4615 self.extract_particle_ids(required_schannels)
4616 if required_schannel_ids and not \
4617 isinstance(required_schannel_ids[0], list):
4618 required_schannel_ids = [required_schannel_ids]
4619
4620 sqorders_values = dict([(k,v[0]) for k, v in squared_orders.items()])
4621 if len([1 for sqo_v in sqorders_values.values() if sqo_v<0])>1:
4622 raise self.InvalidCmd(
4623 "At most one negative squared order constraint can be specified.")
4624
4625 sqorders_types = dict([(k,v[1]) for k, v in squared_orders.items()])
4626
4627
4628 out = base_objects.ProcessDefinition({'legs': myleglist,
4629 'model': self._curr_model,
4630 'id': proc_number,
4631 'orders': orders,
4632 'squared_orders':sqorders_values,
4633 'sqorders_types':sqorders_types,
4634 'constrained_orders': constrained_orders,
4635 'forbidden_particles': forbidden_particle_ids,
4636 'forbidden_onsh_s_channels': forbidden_onsh_schannel_ids,
4637 'forbidden_s_channels': forbidden_schannel_ids,
4638 'required_s_channels': required_schannel_ids,
4639 'overall_orders': overall_orders,
4640 'perturbation_couplings': perturbation_couplings_list,
4641 'has_born':HasBorn,
4642 'NLO_mode':LoopOption,
4643 'split_orders':split_orders
4644 })
4645 return out
4646
4647
4648
4650 """ Routine to create the MultiProcess for the loop-induced case"""
4651
4652 args = self.split_arg(line)
4653
4654 warning_duplicate = True
4655 if '--no_warning=duplicate' in args:
4656 warning_duplicate = False
4657 args.remove('--no_warning=duplicate')
4658
4659
4660 self.check_add(args)
4661 if args[0] == 'process':
4662 args = args[1:]
4663
4664
4665
4666 if args[-1].startswith('--optimize'):
4667 optimize = True
4668 args.pop()
4669 else:
4670 optimize = False
4671
4672
4673 if not myprocdef:
4674 myprocdef = self.extract_process(' '.join(args))
4675
4676 myprocdef.set('NLO_mode', 'noborn')
4677
4678
4679 if not self._generate_info:
4680 self._generate_info = line
4681
4682
4683
4684
4685
4686
4687
4688 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
4689 myprocdef.get_ninitial():
4690 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
4691
4692 if self._curr_amps and (not isinstance(self._curr_amps[0], loop_diagram_generation.LoopAmplitude) or \
4693 self._curr_amps[0]['has_born']):
4694 raise self.InvalidCmd("Can not mix loop induced process with not loop induced process")
4695
4696
4697
4698 if len([1 for val in myprocdef.get('orders').values()+\
4699 myprocdef.get('squared_orders').values() if val<0])>1:
4700 raise MadGraph5Error("Negative coupling order constraints"+\
4701 " can only be given on one type of coupling and either on"+\
4702 " squared orders or amplitude orders, not both.")
4703
4704 cpu_time1 = time.time()
4705
4706
4707 if self.options['group_subprocesses'] == 'Auto':
4708 collect_mirror_procs = True
4709 else:
4710 collect_mirror_procs = self.options['group_subprocesses']
4711 ignore_six_quark_processes = \
4712 self.options['ignore_six_quark_processes'] if \
4713 "ignore_six_quark_processes" in self.options \
4714 else []
4715
4716
4717
4718 myproc = loop_diagram_generation.LoopInducedMultiProcess(myprocdef,
4719 collect_mirror_procs = collect_mirror_procs,
4720 ignore_six_quark_processes = ignore_six_quark_processes,
4721 optimize=optimize)
4722
4723 for amp in myproc.get('amplitudes'):
4724 if amp not in self._curr_amps:
4725 self._curr_amps.append(amp)
4726 if amp['has_born']:
4727 raise Exception
4728 elif warning_duplicate:
4729 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
4730 amp.nice_string_processes()
4731
4732
4733 self._done_export = False
4734
4735 cpu_time2 = time.time()
4736
4737 nprocs = len(myproc.get('amplitudes'))
4738 ndiags = sum([amp.get_number_of_diagrams() for \
4739 amp in myproc.get('amplitudes')])
4740 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
4741 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
4742 ndiags = sum([amp.get_number_of_diagrams() for \
4743 amp in self._curr_amps])
4744 logger.info("Total: %i processes with %i diagrams" % \
4745 (len(self._curr_amps), ndiags))
4746
4747 @staticmethod
4749 """Takes a valid process and return
4750 a tuple (core_process, options). This removes
4751 - any NLO specifications.
4752 - any options
4753 [Used by MadSpin]
4754 """
4755
4756
4757
4758 line=procline
4759 pos1=line.find("[")
4760 if pos1>0:
4761 pos2=line.find("]")
4762 if pos2 >pos1:
4763 line=line[:pos1]+line[pos2+1:]
4764
4765
4766
4767
4768 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
4769 proc_number_re = proc_number_pattern.match(line)
4770 if proc_number_re:
4771 line = proc_number_re.group(1) + proc_number_re.group(3)
4772
4773
4774 pos=1000
4775
4776 order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
4777 order_re = order_pattern.match(line)
4778 if (order_re):
4779 pos_order=line.find(order_re.group(2))
4780 if pos_order>0 and pos_order < pos : pos=pos_order
4781
4782
4783 slash = line.find("/")
4784 if slash > 0 and slash < pos: pos=slash
4785 dollar = line.find("$")
4786 if dollar > 0 and dollar < pos: pos=dollar
4787
4788 if pos<1000:
4789 proc_option=line[pos:]
4790 line=line[:pos]
4791 else:
4792 proc_option=""
4793
4794 return line, proc_option
4795
4797 """Takes a valid process and return
4798 a set of id of final states particles. [Used by MadSpin]
4799 """
4800
4801 if not self._curr_model['case_sensitive']:
4802 procline = procline.lower()
4803 pids = self._curr_model.get('name2pdg')
4804
4805
4806
4807
4808
4809
4810
4811 if ',' in procline:
4812 core, decay = procline.split(',', 1)
4813 core_final = self.get_final_part(core)
4814
4815
4816 all_decays = decay.split(',')
4817 nb_level, tmp_decay = 0, ''
4818 decays = []
4819
4820 for one_decay in all_decays:
4821 if '(' in one_decay:
4822 nb_level += 1
4823 if ')' in one_decay:
4824 nb_level -= 1
4825
4826 if nb_level:
4827 if tmp_decay:
4828 tmp_decay += ', %s' % one_decay
4829 else:
4830 tmp_decay = one_decay
4831 elif tmp_decay:
4832 final = '%s,%s' % (tmp_decay, one_decay)
4833 final = final.strip()
4834 assert final[0] == '(' and final[-1] == ')'
4835 final = final[1:-1]
4836 decays.append(final)
4837 tmp_decay = ''
4838 else:
4839 decays.append(one_decay)
4840
4841 for one_decay in decays:
4842 first = one_decay.split('>',1)[0].strip()
4843 if first in pids:
4844 pid = set([pids[first]])
4845 elif first in self._multiparticles:
4846 pid = set(self._multiparticles[first])
4847 else:
4848 raise Exception, 'invalid particle name: %s. ' % first
4849 core_final.difference_update(pid)
4850 core_final.update(self.get_final_part(one_decay))
4851
4852 return core_final
4853
4854
4855 final = set()
4856 final_states = re.search(r'> ([^\/\$\=\@>]*)(\[|\s\S+\=|\$|\/|\@|$)', procline)
4857 particles = final_states.groups()[0]
4858 for particle in particles.split():
4859 if particle in pids:
4860 final.add(pids[particle])
4861 elif particle in self._multiparticles:
4862 final.update(set(self._multiparticles[particle]))
4863 return final
4864
4865 - def extract_particle_ids(self, args):
4866 """Extract particle ids from a list of particle names. If
4867 there are | in the list, this corresponds to an or-list, which
4868 is represented as a list of id lists. An or-list is used to
4869 allow multiple required s-channel propagators to be specified
4870 (e.g. Z/gamma)."""
4871
4872 if isinstance(args, basestring):
4873 args.replace("|", " | ")
4874 args = self.split_arg(args)
4875 all_ids = []
4876 ids=[]
4877 for part_name in args:
4878 mypart = self._curr_model['particles'].get_copy(part_name)
4879 if mypart:
4880 ids.append([mypart.get_pdg_code()])
4881 elif part_name in self._multiparticles:
4882 ids.append(self._multiparticles[part_name])
4883 elif part_name == "|":
4884
4885 if ids:
4886 all_ids.append(ids)
4887 ids = []
4888 elif part_name.isdigit() or (part_name.startswith('-') and part_name[1:].isdigit()):
4889 ids.append([int(part_name)])
4890 else:
4891 raise self.InvalidCmd("No particle %s in model" % part_name)
4892 all_ids.append(ids)
4893
4894
4895 res_lists = []
4896 for i, id_list in enumerate(all_ids):
4897 res_lists.extend(diagram_generation.expand_list_list(id_list))
4898
4899 for ilist, idlist in enumerate(res_lists):
4900 set_dict = {}
4901 res_lists[ilist] = [set_dict.setdefault(i,i) for i in idlist \
4902 if i not in set_dict]
4903
4904 if len(res_lists) == 1:
4905 res_lists = res_lists[0]
4906
4907 return res_lists
4908
4910 """Optimize the order of particles in a pdg list, so that
4911 similar particles are next to each other. Sort according to:
4912 1. pdg > 0, 2. spin, 3. color, 4. mass > 0"""
4913
4914 if not pdg_list:
4915 return
4916 if not isinstance(pdg_list[0], int):
4917 return
4918
4919 model = self._curr_model
4920 pdg_list.sort(key = lambda i: i < 0)
4921 pdg_list.sort(key = lambda i: model.get_particle(i).is_fermion())
4922 pdg_list.sort(key = lambda i: model.get_particle(i).get('color'),
4923 reverse = True)
4924 pdg_list.sort(key = lambda i: \
4925 model.get_particle(i).get('mass').lower() != 'zero')
4926
4928 """Recursively extract a decay chain process definition from a
4929 string. Returns a ProcessDefinition."""
4930
4931
4932 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*((\w+\s*=\s*\d+\s*)*)$")
4933 proc_number_re = proc_number_pattern.match(line)
4934 overall_orders = {}
4935 if proc_number_re:
4936 proc_number = int(proc_number_re.group(2))
4937 line = proc_number_re.group(1)
4938 if proc_number_re.group(3):
4939 order_pattern = re.compile("^(.*?)\s*(\w+)\s*=\s*(\d+)\s*$")
4940 order_line = proc_number_re.group(3)
4941 order_re = order_pattern.match(order_line)
4942 while order_re:
4943 overall_orders[order_re.group(2)] = int(order_re.group(3))
4944 order_line = order_re.group(1)
4945 order_re = order_pattern.match(order_line)
4946 logger.info(line)
4947
4948
4949 index_comma = line.find(",")
4950 index_par = line.find(")")
4951 min_index = index_comma
4952 if index_par > -1 and (index_par < min_index or min_index == -1):
4953 min_index = index_par
4954
4955 if min_index > -1:
4956 core_process = self.extract_process(line[:min_index], proc_number,
4957 overall_orders)
4958 else:
4959 core_process = self.extract_process(line, proc_number,
4960 overall_orders)
4961
4962
4963
4964 while index_comma > -1:
4965 line = line[index_comma + 1:]
4966 if not line.strip():
4967 break
4968 index_par = line.find(')')
4969
4970 if line.lstrip()[0] == '(' and index_par !=-1 and \
4971 not ',' in line[:index_par]:
4972 par_start = line.find('(')
4973 line = '%s %s' % (line[par_start+1:index_par], line[index_par+1:])
4974 index_par = line.find(')')
4975 if line.lstrip()[0] == '(':
4976
4977
4978 line = line.lstrip()[1:]
4979
4980 decay_process, line = \
4981 self.extract_decay_chain_process(line,
4982 level_down=True)
4983 index_comma = line.find(",")
4984 index_par = line.find(')')
4985 else:
4986 index_comma = line.find(",")
4987 min_index = index_comma
4988 if index_par > -1 and \
4989 (index_par < min_index or min_index == -1):
4990 min_index = index_par
4991 if min_index > -1:
4992 decay_process = self.extract_process(line[:min_index])
4993 else:
4994 decay_process = self.extract_process(line)
4995
4996 core_process.get('decay_chains').append(decay_process)
4997
4998 if level_down:
4999 if index_par == -1:
5000 raise self.InvalidCmd, \
5001 "Missing ending parenthesis for decay process"
5002
5003 if index_par < index_comma:
5004 line = line[index_par + 1:]
5005 level_down = False
5006 break
5007
5008 if level_down:
5009 index_par = line.find(')')
5010 if index_par == -1:
5011 raise self.InvalidCmd, \
5012 "Missing ending parenthesis for decay process"
5013 line = line[index_par + 1:]
5014
5015
5016
5017 return core_process, line
5018
5019
5020
5022 """Main commands: Import files with external formats"""
5023
5024 args = self.split_arg(line)
5025
5026 self.check_import(args)
5027 if args[0].startswith('model'):
5028 self._model_v4_path = None
5029
5030 self._curr_amps = diagram_generation.AmplitudeList()
5031
5032 self._curr_proc_defs = base_objects.ProcessDefinitionList()
5033 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5034
5035 if args[0].endswith('_v4'):
5036 self._curr_model, self._model_v4_path = \
5037 import_v4.import_model(args[1], self._mgme_dir)
5038 else:
5039
5040 if (args[1].startswith('loop_qcd_qed_sm') or\
5041 args[1].split('/')[-1].startswith('loop_qcd_qed_sm')) and\
5042 self.options['gauge']!='Feynman':
5043 logger.info('Switching to Feynman gauge because '+\
5044 'it is the only one supported by the model %s.'%args[1])
5045 self._curr_model = None
5046 self.do_set('gauge Feynman',log=False)
5047 prefix = not '--noprefix' in args
5048 if prefix:
5049 aloha.aloha_prefix='mdl_'
5050 else:
5051 aloha.aloha_prefix=''
5052
5053 try:
5054 self._curr_model = import_ufo.import_model(args[1], prefix=prefix,
5055 complex_mass_scheme=self.options['complex_mass_scheme'])
5056 except import_ufo.UFOImportError, error:
5057 if 'not a valid UFO model' in str(error):
5058 logger_stderr.warning('WARNING: %s' % error)
5059 logger_stderr.warning('Try to recover by running '+\
5060 'automatically `import model_v4 %s` instead.'% args[1])
5061 self.exec_cmd('import model_v4 %s ' % args[1], precmd=True)
5062 return
5063 if self.options['gauge']=='unitary':
5064 if not force and isinstance(self._curr_model,\
5065 loop_base_objects.LoopModel) and \
5066 self._curr_model.get('perturbation_couplings') not in \
5067 [[],['QCD']]:
5068 if 1 not in self._curr_model.get('gauge') :
5069 logger_stderr.warning('This model does not allow Feynman '+\
5070 'gauge. You will only be able to do tree level '+\
5071 'QCD loop cmputations with it.')
5072 else:
5073 logger.info('Change to the gauge to Feynman because '+\
5074 'this loop model allows for more than just tree level'+\
5075 ' and QCD perturbations.')
5076 self.do_set('gauge Feynman', log=False)
5077 return
5078 if 0 not in self._curr_model.get('gauge') :
5079 logger_stderr.warning('Change the gauge to Feynman since '+\
5080 'the model does not allow unitary gauge')
5081 self.do_set('gauge Feynman', log=False)
5082 return
5083 else:
5084 if 1 not in self._curr_model.get('gauge') :
5085 logger_stderr.warning('Change the gauge to unitary since the'+\
5086 ' model does not allow Feynman gauge.'+\
5087 ' Please re-import the model')
5088 self._curr_model = None
5089 self.do_set('gauge unitary', log= False)
5090 return
5091
5092 if '-modelname' not in args:
5093 self._curr_model.pass_particles_name_in_mg_default()
5094
5095
5096 self.process_model()
5097
5098 self._curr_amps = diagram_generation.AmplitudeList()
5099
5100 self._curr_proc_defs = base_objects.ProcessDefinitionList()
5101 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5102 process_checks.store_aloha = []
5103
5104 elif args[0] == 'command':
5105
5106 if not os.path.isfile(args[1]):
5107 raise self.InvalidCmd("Path %s is not a valid pathname" % args[1])
5108 else:
5109
5110
5111 self.check_for_export_dir(args[1])
5112
5113 self.import_command_file(args[1])
5114
5115 elif args[0] == 'banner':
5116 type = madevent_interface.MadEventCmd.detect_card_type(args[1])
5117 if type != 'banner':
5118 raise self.InvalidCmd, 'The File should be a valid banner'
5119 ban = banner_module.Banner(args[1])
5120
5121 if 'mg5proccard' in ban:
5122 for line in ban['mg5proccard'].split('\n'):
5123 if line.startswith('#') or line.startswith('<'):
5124 continue
5125 self.exec_cmd(line)
5126 else:
5127 raise self.InvalidCmd, 'Only MG5 banner are supported'
5128
5129 if not self._done_export:
5130 self.exec_cmd('output . -f')
5131
5132 ban.split(self._done_export[0])
5133 logger.info('All Cards from the banner have been place in directory %s' % pjoin(self._done_export[0], 'Cards'))
5134 if '--no_launch' not in args:
5135 self.exec_cmd('launch')
5136
5137 elif args[0] == 'proc_v4':
5138
5139 if len(args) == 1 and self._export_dir:
5140 proc_card = pjoin(self._export_dir, 'Cards', \
5141 'proc_card.dat')
5142 elif len(args) == 2:
5143 proc_card = args[1]
5144
5145
5146 self.check_for_export_dir(os.path.realpath(proc_card))
5147 else:
5148 raise MadGraph5Error('No default directory in output')
5149
5150
5151
5152 self.import_mg4_proc_card(proc_card)
5153
5155 """ For simple decay chain: remove diagram that are not in the BR.
5156 param_card should be a ParamCard instance."""
5157
5158 assert isinstance(param_card, check_param_card.ParamCard)
5159
5160
5161 amplitudes = diagram_generation.AmplitudeList()
5162 for amp in self._curr_amps:
5163 amplitudes.extend(amp.get_amplitudes())
5164
5165 decay_tables = param_card['decay'].decay_table
5166 to_remove = []
5167 for amp in amplitudes:
5168 mother = [l.get('id') for l in amp['process'].get('legs') \
5169 if not l.get('state')]
5170 if 1 == len(mother):
5171 try:
5172 decay_table = decay_tables[abs(mother[0])]
5173 except KeyError:
5174 logger.warning("No decay table for %s. decay of this particle with MadSpin should be discarded" % abs(mother[0]))
5175 continue
5176
5177 child = [l.get('id') for l in amp['process'].get('legs') \
5178 if l.get('state')]
5179 if not mother[0] > 0:
5180 child = [x if self._curr_model.get_particle(x)['self_antipart']
5181 else -x for x in child]
5182 child.sort()
5183 child.insert(0, len(child))
5184
5185 if tuple(child) not in decay_table.keys():
5186 to_remove.append(amp)
5187
5188 def remove_amp(amps):
5189 for amp in amps[:]:
5190 if amp in to_remove:
5191 amps.remove(amp)
5192 if isinstance(amp, diagram_generation.DecayChainAmplitude):
5193 remove_amp(amp.get('decay_chains'))
5194 for decay in amp.get('decay_chains'):
5195 remove_amp(decay.get('amplitudes'))
5196 remove_amp(self._curr_amps)
5197
5198
5203
5205 """Set variables _particle_names and _couplings for tab
5206 completion, define multiparticles"""
5207
5208
5209 self._particle_names = [p.get('name') for p in self._curr_model.get('particles')\
5210 if p.get('propagating')] + \
5211 [p.get('antiname') for p in self._curr_model.get('particles') \
5212 if p.get('propagating')]
5213
5214 self._couplings = list(set(sum([i.get('orders').keys() for i in \
5215 self._curr_model.get('interactions')], [])))
5216
5217 self.add_default_multiparticles()
5218
5219
5248
5250 """ add default particle from file interface.multiparticles_default.txt
5251 """
5252
5253 defined_multiparticles = self._multiparticles.keys()
5254 removed_multiparticles = []
5255
5256
5257
5258 for key in self._multiparticles.keys():
5259 try:
5260 for part in self._multiparticles[key]:
5261 self._curr_model.get('particle_dict')[part]
5262 except Exception:
5263 del self._multiparticles[key]
5264 defined_multiparticles.remove(key)
5265 removed_multiparticles.append(key)
5266
5267
5268 for line in open(pjoin(MG5DIR, 'input', \
5269 'multiparticles_default.txt')):
5270 if line.startswith('#'):
5271 continue
5272 try:
5273 if not self._curr_model['case_sensitive']:
5274 multipart_name = line.lower().split()[0]
5275 else:
5276 multipart_name = line.split()[0]
5277 if multipart_name not in self._multiparticles:
5278
5279 self.exec_cmd('define %s' % line, printcmd=False, precmd=True)
5280 except self.InvalidCmd, why:
5281 logger_stderr.warning('impossible to set default multiparticles %s because %s' %
5282 (line.split()[0],why))
5283 if self.history[-1] == 'define %s' % line.strip():
5284 self.history.pop(-1)
5285 else:
5286 misc.sprint([self.history[-1], 'define %s' % line.strip()])
5287
5288 scheme = "old"
5289 for qcd_container in ['p', 'j']:
5290 if qcd_container not in self._multiparticles:
5291 continue
5292 multi = self._multiparticles[qcd_container]
5293 b = self._curr_model.get_particle(5)
5294 if not b:
5295 break
5296
5297 if 5 in multi:
5298 if b['mass'] != 'ZERO':
5299 multi.remove(5)
5300 multi.remove(-5)
5301 scheme = 4
5302 elif b['mass'] == 'ZERO':
5303 multi.append(5)
5304 multi.append(-5)
5305 scheme = 5
5306
5307 if scheme in [4,5]:
5308 logger.warning("Pass the definition of \'j\' and \'p\' to %s flavour scheme." % scheme)
5309 for container in ['p', 'j']:
5310 if container in defined_multiparticles:
5311 defined_multiparticles.remove(container)
5312 self.history.append("define p = %s # pass to %s flavors" % \
5313 (' ' .join([`i` for i in self._multiparticles['p']]),
5314 scheme)
5315 )
5316 self.history.append("define j = p")
5317
5318
5319 if defined_multiparticles:
5320 if 'all' in defined_multiparticles:
5321 defined_multiparticles.remove('all')
5322 logger.info("Kept definitions of multiparticles %s unchanged" % \
5323 " / ".join(defined_multiparticles))
5324
5325 for removed_part in removed_multiparticles:
5326 if removed_part in self._multiparticles:
5327 removed_multiparticles.remove(removed_part)
5328
5329 if removed_multiparticles:
5330 logger.info("Removed obsolete multiparticles %s" % \
5331 " / ".join(removed_multiparticles))
5332
5333
5334 line = []
5335 for part in self._curr_model.get('particles'):
5336 line.append('%s %s' % (part.get('name'), part.get('antiname')))
5337 line = 'all =' + ' '.join(line)
5338 self.do_define(line)
5339
5340 - def advanced_install(self, tool_to_install,
5341 HepToolsInstaller_web_address=None,
5342 additional_options=[]):
5343 """ Uses the HEPToolsInstaller.py script maintened online to install
5344 HEP tools with more complicated dependences.
5345 Additional options will be added to the list when calling HEPInstaller"""
5346
5347
5348 add_options = list(additional_options)
5349
5350
5351 if not os.path.isdir(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers')):
5352 if HepToolsInstaller_web_address is None:
5353 raise MadGraph5Error, "The option 'HepToolsInstaller_web_address'"+\
5354 " must be specified in function advanced_install"+\
5355 " if the installers are not already downloaded."
5356 if not os.path.isdir(pjoin(MG5DIR,'HEPTools')):
5357 os.mkdir(pjoin(MG5DIR,'HEPTools'))
5358 elif not HepToolsInstaller_web_address is None:
5359 shutil.rmtree(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5360 if not HepToolsInstaller_web_address is None:
5361 logger.info('Downloading the HEPToolInstaller at:\n %s'%
5362 HepToolsInstaller_web_address)
5363
5364 if '//' in HepToolsInstaller_web_address:
5365 if sys.platform == "darwin":
5366 misc.call(['curl', HepToolsInstaller_web_address, '-o%s'
5367 %pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz')],
5368 stderr=open(os.devnull,'w'), stdout=open(os.devnull,'w'),
5369 cwd=MG5DIR)
5370 else:
5371 misc.call(['wget', HepToolsInstaller_web_address,
5372 '--output-document=%s'% pjoin(MG5DIR,'HEPTools',
5373 'HEPToolsInstallers.tar.gz')], stderr=open(os.devnull, 'w'),
5374 stdout=open(os.devnull, 'w'), cwd=MG5DIR)
5375 else:
5376
5377 shutil.copyfile(HepToolsInstaller_web_address,
5378 pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz'))
5379
5380
5381 returncode = misc.call(['tar', '-xzpf', 'HEPToolsInstallers.tar.gz'],
5382 cwd=pjoin(MG5DIR,'HEPTools'), stdout=open(os.devnull, 'w'))
5383
5384
5385 os.remove(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz'))
5386
5387
5388
5389 if '--local' in add_options:
5390 add_options.remove('--local')
5391 logger.warning('you are using a local installer. This is intended for debugging only!')
5392 shutil.rmtree(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5393 shutil.copytree(os.path.abspath(pjoin(MG5DIR,os.path.pardir,
5394 'HEPToolsInstallers')),pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5395
5396
5397 name_map = {}
5398 try:
5399 tool = name_map[tool_to_install]
5400 except:
5401 tool = tool_to_install
5402
5403
5404 compiler_options = []
5405 if self.options['cpp_compiler'] is not None:
5406 compiler_options.append('--cpp_compiler=%s'%
5407 self.options['cpp_compiler'])
5408 compiler_options.append('--cpp_standard_lib=%s'%
5409 misc.detect_cpp_std_lib_dependence(self.options['cpp_compiler']))
5410 elif misc.which('g++'):
5411 compiler_options.append('--cpp_standard_lib=%s'%
5412 misc.detect_cpp_std_lib_dependence('g++'))
5413 else:
5414 compiler_options.append('--cpp_standard_lib=%s'%
5415 misc.detect_cpp_std_lib_dependence(None))
5416
5417 if not self.options['fortran_compiler'] is None:
5418 compiler_options.append('--fortran_compiler=%s'%
5419 self.options['fortran_compiler'])
5420
5421 if 'heptools_install_dir' in self.options:
5422 prefix = self.options['heptools_install_dir']
5423 config_file = '~/.mg5/mg5_configuration.txt'
5424 else:
5425 prefix = pjoin(MG5DIR, 'HEPTools')
5426 config_file = ''
5427
5428
5429 if tool=='mg5amc_py8_interface':
5430 add_options.append('--mg5_path=%s'%MG5DIR)
5431
5432 if misc.which('gnuplot') is None:
5433 logger.warning("==========")
5434 logger.warning("The optional dependency 'gnuplot' for the tool"+\
5435 " 'mg5amc_py8_interface' was not found. We recommend that you"+\
5436 " install it so as to be able to view the plots related to "+\
5437 " merging with Pythia 8.")
5438 logger.warning("==========")
5439 if self.options['pythia8_path']:
5440 add_options.append(
5441 '--with_pythia8=%s'%self.options['pythia8_path'])
5442
5443
5444 if tool=='madanalysis5':
5445 add_options.append('--mg5_path=%s'%MG5DIR)
5446 if not any(opt.startswith(('--with_fastjet', '--veto_fastjet')) for opt in add_options):
5447 fastjet_config = misc.which(self.options['fastjet'])
5448 if fastjet_config:
5449 add_options.append('--with_fastjet=%s'%fastjet_config)
5450
5451 if self.options['delphes_path'] and os.path.isdir(
5452 os.path.normpath(pjoin(MG5DIR,self.options['delphes_path']))):
5453 add_options.append('--with_delphes3=%s'%\
5454 os.path.normpath(pjoin(MG5DIR,self.options['delphes_path'])))
5455
5456 if tool=='pythia8':
5457
5458 lhapdf_config = misc.which(self.options['lhapdf'])
5459 lhapdf_version = None
5460 if lhapdf_config is None:
5461 lhapdf_version = None
5462 else:
5463 try:
5464 version = misc.Popen(
5465 [lhapdf_config,'--version'], stdout=subprocess.PIPE)
5466 lhapdf_version = int(version.stdout.read()[0])
5467 if lhapdf_version not in [5,6]:
5468 raise
5469 except:
5470 raise self.InvalidCmd('Could not detect LHAPDF version. Make'+
5471 " sure '%s --version ' runs properly."%lhapdf_config)
5472
5473 if lhapdf_version is None:
5474 answer = self.ask(question=
5475 "\033[33;34mLHAPDF was not found. Do you want to install LHPADF6? "+
5476 "(recommended) \033[0m \033[33;32my\033[0m/\033[33;31mn\033[0m >",
5477 default='y',text_format='33;32')
5478 if not answer.lower() in ['y','']:
5479 lhapdf_path = None
5480 else:
5481 self.advanced_install('lhapdf6',
5482 additional_options=add_options)
5483 lhapdf_path = pjoin(MG5DIR,'HEPTools','lhapdf6')
5484 lhapdf_version = 6
5485 else:
5486 lhapdf_path = os.path.abspath(pjoin(os.path.dirname(\
5487 lhapdf_config),os.path.pardir))
5488 if lhapdf_version is None:
5489 logger.warning('You decided not to link the Pythia8 installation'+
5490 ' to LHAPDF. Beware that only built-in PDF sets can be used then.')
5491 else:
5492 logger.info('Pythia8 will be linked to LHAPDF v%d.'%lhapdf_version)
5493 logger.info('Now installing Pythia8. Be patient...','$MG:color:GREEN')
5494 lhapdf_option = []
5495 if lhapdf_version is None:
5496 lhapdf_option.append('--with_lhapdf6=OFF')
5497 lhapdf_option.append('--with_lhapdf5=OFF')
5498 elif lhapdf_version==5:
5499 lhapdf_option.append('--with_lhapdf5=%s'%lhapdf_path)
5500 lhapdf_option.append('--with_lhapdf6=OFF')
5501 elif lhapdf_version==6:
5502 lhapdf_option.append('--with_lhapdf5=OFF')
5503 lhapdf_option.append('--with_lhapdf6=%s'%lhapdf_path)
5504
5505 add_options = list(set(add_options))
5506
5507 add_options = [opt for opt in add_options if opt!='--force']+\
5508 (['--force'] if '--force' in add_options else [])
5509 return_code = misc.call([sys.executable, pjoin(MG5DIR,'HEPTools',
5510 'HEPToolsInstallers','HEPToolInstaller.py'),'pythia8',
5511 '--prefix=%s' % prefix]
5512 + lhapdf_option + compiler_options + add_options)
5513 else:
5514 logger.info('Now installing %s. Be patient...'%tool)
5515
5516 add_options = list(set(add_options))
5517
5518 add_options = [opt for opt in add_options if opt!='--force']+\
5519 (['--force'] if '--force' in add_options else [])
5520 return_code = misc.call([sys.executable, pjoin(MG5DIR,'HEPTools',
5521 'HEPToolsInstallers', 'HEPToolInstaller.py'), tool,'--prefix=%s'%
5522 prefix] + compiler_options + add_options)
5523
5524 if return_code == 0:
5525 logger.info("%s successfully installed in %s."%(
5526 tool_to_install, prefix),'$MG:color:GREEN')
5527
5528 if tool=='madanalysis5':
5529 if not any(o.startswith(('--with_','--veto_','--update')) for o in add_options):
5530 logger.info(' To install recasting capabilities of madanalysis5 and/or', '$MG:color:BLACK')
5531 logger.info(' to allow delphes analysis at parton level.','$MG:color:BLACK')
5532 logger.info(' Please run \'install MadAnalysis5 --with_delphes --update\':', '$MG:color:BLACK')
5533
5534 elif return_code == 66:
5535 answer = self.ask(question=
5536 """\033[33;34mTool %s already installed in %s."""%(tool_to_install, prefix)+
5537 """ Do you want to overwrite its installation?\033[0m \033[33;32my\033[0m/\033[33;31mn\033[0m >"""
5538 ,default='y',text_format='33;32')
5539 if not answer.lower() in ['y','']:
5540 logger.info("Installation of %s aborted."%tool_to_install,
5541 '$MG:color:GREEN')
5542 return
5543 else:
5544 return self.advanced_install(tool_to_install,
5545 additional_options=add_options+['--force'])
5546 else:
5547 if tool=='madanalysis5' and '--update' not in add_options and \
5548 ('--no_MA5_further_install' not in add_options or
5549 '--no_root_in_MA5' in add_options):
5550 if not __debug__:
5551 logger.warning('Default installation of Madanalys5 failed.')
5552 logger.warning("MG5aMC will now attempt to reinstall it with the options '--no_MA5_further_install --no_root_in_MA5'.")
5553 logger.warning("This will however limit MA5 applicability for hadron-level analysis.")
5554 logger.warning("If you would like to prevent MG5aMC to re-attempt MA5 installation, start MG5aMC with './bin/mg5_aMC --debug'.")
5555 for option in ['--no_MA5_further_install', '--no_root_in_MA5', '--force']:
5556 if option not in add_options:
5557 add_options.append(option)
5558 self.advanced_install('madanalysis5',
5559 HepToolsInstaller_web_address=HepToolsInstaller_web_address,
5560 additional_options=add_options)
5561 else:
5562 logger.critical("Default installation of Madanalys5 failed, we suggest you try again with the options '--no_MA5_further_install --no_root_in_MA5'.")
5563 raise self.InvalidCmd("Installation of %s failed."%tool_to_install)
5564
5565
5566 if tool == 'pythia8':
5567 self.options['pythia8_path'] = pjoin(prefix,'pythia8')
5568 self.exec_cmd('save options %s pythia8_path' % config_file, printcmd=False, log=False)
5569
5570
5571 self.advanced_install('mg5amc_py8_interface',
5572 additional_options=add_options+['--force'])
5573 elif tool == 'lhapdf6':
5574 self.options['lhapdf'] = pjoin(prefix,'lhapdf6','bin', 'lhapdf-config')
5575 self.exec_cmd('save options %s lhapdf' % config_file)
5576 elif tool == 'lhapdf5':
5577 self.options['lhapdf'] = pjoin(prefix,'lhapdf5','bin', 'lhapdf-config')
5578 self.exec_cmd('save options %s lhapdf' % config_file, printcmd=False, log=False)
5579 elif tool == 'madanalysis5':
5580 self.options['madanalysis5_path'] = pjoin(prefix, 'madanalysis5','madanalysis5')
5581 self.exec_cmd('save options madanalysis5_path', printcmd=False, log=False)
5582 elif tool == 'mg5amc_py8_interface':
5583
5584 if self.options['pythia8_path'] in ['',None,'None']:
5585 self.options['pythia8_path'] = pjoin(prefix,'pythia8')
5586 self.options['mg5amc_py8_interface_path'] = pjoin(prefix, 'MG5aMC_PY8_interface')
5587 self.exec_cmd('save options %s mg5amc_py8_interface_path' % config_file,
5588 printcmd=False, log=False)
5589 elif tool == 'collier':
5590 self.options['collier'] = pjoin(prefix,'lib')
5591 self.exec_cmd('save options %s collier' % config_file, printcmd=False, log=False)
5592 elif tool == 'ninja':
5593 if not misc.get_ninja_quad_prec_support(pjoin(
5594 prefix,'ninja','lib')):
5595 logger.warning(
5596 """Successful installation of Ninja, but without support for quadruple precision
5597 arithmetics. If you want to enable this (hence improving the treatment of numerically
5598 unstable points in the loop matrix elements) you can try to reinstall Ninja with:
5599 MG5aMC>install ninja
5600 After having made sure to have selected a C++ compiler in the 'cpp' option of
5601 MG5aMC that supports quadruple precision (typically g++ based on gcc 4.6+).""")
5602 self.options['ninja'] = pjoin(prefix,'lib')
5603 self.exec_cmd('save options %s ninja' % config_file, printcmd=False, log=False)
5604
5605
5606
5607 path_to_be_set = []
5608 if sys.platform == "darwin":
5609 library_variables = ["DYLD_LIBRARY_PATH"]
5610 else:
5611 library_variables = ["LD_LIBRARY_PATH"]
5612 for variable in library_variables:
5613 if (variable not in os.environ) or \
5614 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','lib'))==\
5615 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5616 path_to_be_set.append((variable,
5617 os.path.abspath(pjoin(MG5DIR,'HEPTools','lib'))))
5618 for variable in ["PATH"]:
5619 if (variable not in os.environ) or \
5620 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','bin'))==\
5621 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5622 path_to_be_set.append((variable,
5623 os.path.abspath(pjoin(MG5DIR,'HEPTools','bin'))))
5624 if (variable not in os.environ) or \
5625 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','include'))==\
5626 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5627 path_to_be_set.append((variable,
5628 os.path.abspath(pjoin(MG5DIR,'HEPTools','include'))))
5629
5630 if len(path_to_be_set)>0:
5631 shell_type = misc.get_shell_type()
5632 if shell_type in ['bash',None]:
5633 modification_line = r"printf '\n# MG5aMC paths:\n%s\n' >> ~/.bashrc"%\
5634 (r'\n'.join('export %s=%s%s'%
5635 (var,path,'%s$%s'%(os.pathsep,var)) for var,path in path_to_be_set))
5636 elif shell_type=='tcsh':
5637 modification_line = r"printf '\n# MG5aMC paths:\n%s\n' >> ~/.cshrc"%\
5638 (r'\n'.join('setenv %s %s%s'%
5639 (var,path,'%s$%s'%(os.pathsep,var)) for var,path in path_to_be_set))
5640
5641 logger.debug("==========")
5642 logger.debug("We recommend that you add to the following paths"+\
5643 " to your environment variables, so that you are guaranteed that"+\
5644 " at runtime, MG5_aMC will use the tools you have just installed"+\
5645 " and not some other versions installed elsewhere on your system.\n"+\
5646 "You can do so by running the following command in your terminal:"
5647 "\n %s"%modification_line)
5648 logger.debug("==========")
5649
5650
5651 return True
5652
5653 - def do_install(self, line, paths=None, additional_options=[]):
5654 """Install optional package from the MG suite.
5655 The argument 'additional_options' will be passed to the advanced_install
5656 functions. If it contains the option '--force', then the advanced_install
5657 function will overwrite any existing installation of the tool without
5658 warnings.
5659 """
5660
5661
5662 add_options = list(additional_options)
5663
5664 args = self.split_arg(line)
5665
5666 install_options = self.check_install(args)
5667
5668 if sys.platform == "darwin":
5669 program = "curl"
5670 else:
5671 program = "wget"
5672
5673
5674 if args[0] == 'update':
5675 self.install_update(['update']+install_options['update_options'],wget=program)
5676 return
5677
5678 plugin = ['maddm']
5679
5680 advertisements = {'pythia-pgs':['arXiv:0603175'],
5681 'Delphes':['arXiv:1307.6346'],
5682 'Delphes2':['arXiv:0903.2225'],
5683 'SysCalc':['arXiv:XXXX.YYYYY'],
5684 'Golem95':['arXiv:0807.0605'],
5685 'PJFry':['arXiv:1210.4095','arXiv:1112.0500'],
5686 'QCDLoop':['arXiv:0712.1851'],
5687 'pythia8':['arXiv:1410.3012'],
5688 'lhapdf6':['arXiv:1412.7420'],
5689 'lhapdf5':['arXiv:0605240'],
5690 'hepmc':['CPC 134 (2001) 41-46'],
5691 'mg5amc_py8_interface':['arXiv:1410.3012','arXiv:XXXX.YYYYY'],
5692 'ninja':['arXiv:1203.0291','arXiv:1403.1229','arXiv:1604.01363'],
5693 'MadAnalysis5':['arXiv:1206.1599'],
5694 'MadAnalysis':['arXiv:1206.1599'],
5695 'collier':['arXiv:1604.06792'],
5696 'oneloop':['arXiv:1007.4716'],
5697 'maddm':['arXiv:1505.04190']}
5698
5699
5700 if args[0] in advertisements:
5701
5702
5703
5704
5705
5706 logger.info(" You are installing '%s', please cite ref(s): \033[92m%s\033[0m. " % (args[0], ', '.join(advertisements[args[0]])), '$MG:color:BLACK')
5707
5708
5709 import urllib
5710 if paths:
5711 path = paths
5712 else:
5713 path = {}
5714
5715 data_path = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
5716 'http://madgraph.physics.illinois.edu/package_info.dat']
5717
5718 r = random.randint(0,1)
5719 r = [r, (1-r)]
5720
5721 if any(a.startswith('--source=') for a in args):
5722 source = [a[9:] for a in args if a.startswith('--source=')][-1]
5723 if source == 'uiuc':
5724 r = [1]
5725 elif source == 'ucl':
5726 r = [0]
5727 else:
5728 data_path.append(source)
5729 r = [2]
5730 else:
5731 r = random.randint(0,1)
5732 r = [r, (1-r)]
5733
5734
5735
5736 for index in r:
5737 cluster_path = data_path[index]
5738 try:
5739 data = urllib.urlopen(cluster_path)
5740 except Exception:
5741 continue
5742 break
5743 else:
5744 raise MadGraph5Error, '''Impossible to connect any of us servers.
5745 Please check your internet connection or retry later'''
5746 for line in data:
5747 split = line.split()
5748 path[split[0]] = split[1]
5749
5750
5751
5752
5753
5754
5755
5756 if args[0] == 'Delphes':
5757 args[0] = 'Delphes3'
5758
5759 try:
5760 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
5761 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
5762 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'madanalysis5',
5763 'MadAnalysis4':'MadAnalysis',
5764 'SysCalc':'SysCalc', 'Golem95': 'golem95',
5765 'PJFry':'PJFry','QCDLoop':'QCDLoop','MadAnalysis5':'madanalysis5'
5766 }
5767 name = name[args[0]]
5768 except KeyError:
5769 name = args[0]
5770
5771 if args[0] in self._advanced_install_opts:
5772
5773
5774
5775
5776 MG5aMC_PY8_interface_path = path['MG5aMC_PY8_interface'] if \
5777 'MG5aMC_PY8_interface' in path else 'NA'
5778 add_options.append('--mg5amc_py8_interface_tarball=%s'%\
5779 MG5aMC_PY8_interface_path)
5780 add_options.extend(install_options['options_for_HEPToolsInstaller'])
5781 if not any(opt.startswith('--logging=') for opt in add_options):
5782 add_options.append('--logging=%d' % logger.level)
5783
5784 return self.advanced_install(name, path['HEPToolsInstaller'],
5785 additional_options = add_options)
5786
5787 if args[0] == 'PJFry' and not os.path.exists(
5788 pjoin(MG5DIR,'QCDLoop','lib','libqcdloop1.a')):
5789 logger.info("Installing PJFRY's dependence QCDLoop...")
5790 self.do_install('QCDLoop', paths=path)
5791
5792 if args[0] == 'Delphes':
5793 args[0] = 'Delphes3'
5794 if args[0] == 'MadAnalysis4':
5795 args[0] = 'MadAnalysis'
5796 try:
5797 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
5798 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
5799 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'MadAnalysis',
5800 'SysCalc':'SysCalc', 'Golem95': 'golem95',
5801 'PJFry':'PJFry','QCDLoop':'QCDLoop',
5802 'maddm':'maddm'
5803 }
5804 name = name[args[0]]
5805 except:
5806 pass
5807
5808
5809 substitution={'Delphes2':'Delphes','pythia-pgs':'pythia8'}
5810 if args[0] in substitution:
5811 logger.warning("Please Note that this package is NOT maintained anymore by their author(s).\n"+\
5812 " You should consider installing and using %s, with:\n"%substitution[args[0]]+
5813 " > install %s"%substitution[args[0]])
5814
5815 try:
5816 os.system('rm -rf %s' % pjoin(MG5DIR, name))
5817 except Exception:
5818 pass
5819
5820
5821 logger.info('Downloading %s' % path[args[0]])
5822 if sys.platform == "darwin":
5823 misc.call(['curl', path[args[0]], '-o%s.tgz' % name], cwd=MG5DIR)
5824 else:
5825 misc.call(['wget', path[args[0]], '--output-document=%s.tgz'% name], cwd=MG5DIR)
5826
5827
5828 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
5829 stdout=open(os.devnull, 'w'))
5830
5831 if returncode:
5832 raise MadGraph5Error, 'Fail to download correctly the File. Stop'
5833
5834
5835
5836 if not os.path.exists(pjoin(MG5DIR, name)):
5837 created_name = [n for n in os.listdir(MG5DIR) if n.lower().startswith(
5838 name.lower()) and not n.endswith('gz')]
5839 if not created_name:
5840 raise MadGraph5Error, 'The file was not loaded correctly. Stop'
5841 else:
5842 created_name = created_name[0]
5843 files.mv(pjoin(MG5DIR, created_name), pjoin(MG5DIR, name))
5844
5845
5846 logger.info('compile %s. This might take a while.' % name)
5847
5848
5849 if args[0] == "pythia-pgs" and sys.maxsize > 2**32:
5850 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
5851 text = open(path).read()
5852 text = text.replace('MBITS=32','MBITS=64')
5853 open(path, 'w').writelines(text)
5854 if not os.path.exists(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib')):
5855 os.mkdir(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib'))
5856
5857 make_flags = []
5858
5859
5860 if 'FC' not in os.environ or not os.environ['FC']:
5861 if self.options['fortran_compiler'] and self.options['fortran_compiler'] != 'None':
5862 compiler = self.options['fortran_compiler']
5863 elif misc.which('gfortran'):
5864 compiler = 'gfortran'
5865 elif misc.which('g77'):
5866 compiler = 'g77'
5867 else:
5868 raise self.InvalidCmd('Require g77 or Gfortran compiler')
5869
5870 path = None
5871 base_compiler= ['FC=g77','FC=gfortran']
5872 if args[0] == "pythia-pgs":
5873 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
5874 elif args[0] == 'MadAnalysis':
5875 path = os.path.join(MG5DIR, 'MadAnalysis', 'makefile')
5876 if path:
5877 text = open(path).read()
5878 for base in base_compiler:
5879 text = text.replace(base,'FC=%s' % compiler)
5880 open(path, 'w').writelines(text)
5881 os.environ['FC'] = compiler
5882
5883
5884 if name == 'golem95':
5885
5886 ld_path = misc.Popen(['./configure',
5887 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC']],
5888 cwd=pjoin(MG5DIR,'golem95'),stdout=subprocess.PIPE).communicate()[0]
5889
5890
5891 if name == 'PJFry':
5892
5893 ld_path = misc.Popen(['./configure',
5894 '--prefix=%s'%str(pjoin(MG5DIR, name)),
5895 '--enable-golem-mode', '--with-integrals=qcdloop1',
5896 'LDFLAGS=-L%s'%str(pjoin(MG5DIR,'QCDLoop','lib')),
5897 'FC=%s'%os.environ['FC'],
5898 'F77=%s'%os.environ['FC']], cwd=pjoin(MG5DIR,name),
5899 stdout=subprocess.PIPE).communicate()[0]
5900
5901
5902 if name == 'QCDLoop':
5903
5904 ld_path = misc.Popen(['./configure',
5905 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC'],
5906 'F77=%s'%os.environ['FC']], cwd=pjoin(MG5DIR,name),
5907 stdout=subprocess.PIPE).communicate()[0]
5908
5909
5910 if args[0] == 'Delphes3':
5911
5912
5913
5914
5915 rootsys = os.environ['ROOTSYS']
5916 text = open(pjoin(MG5DIR, 'Delphes','Makefile')).read()
5917 text = text.replace('DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS)',
5918 'DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS) -Wl,-rpath,%s/lib/' % rootsys)
5919 open(pjoin(MG5DIR, 'Delphes','Makefile'),'w').write(text)
5920
5921
5922 if name == 'SysCalc':
5923 if self.options['lhapdf']:
5924 ld_path = misc.Popen([self.options['lhapdf'], '--libdir'],
5925 stdout=subprocess.PIPE).communicate()[0]
5926 ld_path = ld_path.replace('\n','')
5927 if 'LD_LIBRARY_PATH' not in os.environ:
5928 os.environ['LD_LIBRARY_PATH'] = ld_path
5929 elif not os.environ['LD_LIBRARY_PATH']:
5930 os.environ['LD_LIBRARY_PATH'] = ld_path
5931 elif ld_path not in os.environ['LD_LIBRARY_PATH']:
5932 os.environ['LD_LIBRARY_PATH'] += ';%s' % ld_path
5933 if self.options['lhapdf'] != 'lhapdf-config':
5934 if misc.which('lhapdf-config') != os.path.realpath(self.options['lhapdf']):
5935 os.environ['PATH'] = '%s:%s' % (os.path.realpath(self.options['lhapdf']),os.environ['PATH'])
5936 else:
5937 raise self.InvalidCmd('lhapdf is required to compile/use SysCalc. Specify his path or install it via install lhapdf6')
5938 if self.options['cpp_compiler']:
5939 make_flags.append('CXX=%s' % self.options['cpp_compiler'])
5940
5941
5942 if name in plugin:
5943 logger.info('no compilation needed for plugin. Loading plugin information')
5944 try:
5945 shutil.rmtree(pjoin(MG5DIR, 'PLUGIN', name))
5946 except Exception:
5947 pass
5948 shutil.move(pjoin(os.path.join(MG5DIR, name)), os.path.join(MG5DIR, 'PLUGIN', name))
5949
5950 try:
5951 __import__('PLUGIN.%s' % name, globals(), locals(), [], -1)
5952 plugin = sys.modules['PLUGIN.%s' % name]
5953 new_interface = plugin.new_interface
5954 new_output = plugin.new_output
5955 latest_validated_version = plugin.latest_validated_version
5956 minimal_mg5amcnlo_version = plugin.minimal_mg5amcnlo_version
5957 maximal_mg5amcnlo_version = plugin.maximal_mg5amcnlo_version
5958 except Exception, error:
5959 raise Exception, 'Plugin %s fail to be loaded. Please contact the author of the PLUGIN\n Error %s' % (name, error)
5960
5961 logger.info('Plugin %s correctly interfaced. Latest official validition for MG5aMC version %s.' % (name, '.'.join(`i` for i in latest_validated_version)))
5962 if new_interface:
5963 ff = open(pjoin(MG5DIR, 'bin', '%s.py' % name) , 'w')
5964 if __debug__:
5965 text = '''#! /usr/bin/env python
5966 import os
5967 import sys
5968 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
5969 exe_path = os.path.join(root_path,'bin','mg5_aMC')
5970 sys.argv.pop(0)
5971 os.system('%s -tt %s %s --mode={0}' %(sys.executable, str(exe_path) , ' '.join(sys.argv) ))
5972 '''.format(name)
5973 else:
5974 text = '''#! /usr/bin/env python
5975 import os
5976 import sys
5977 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
5978 exe_path = os.path.join(root_path,'bin','mg5_aMC')
5979 sys.argv.pop(0)
5980 os.system('%s -O -W ignore::DeprecationWarning %s %s --mode={0}' %(sys.executable, str(exe_path) , ' '.join(sys.argv) ))
5981 '''.format(name)
5982 ff.write(text)
5983 ff.close()
5984 import stat
5985 os.chmod(pjoin(MG5DIR, 'bin', '%s.py' % name), stat.S_IRWXU)
5986 logger.info('To use this module, you need to quite MG5aMC and run the executable bin/%s.py' % name)
5987 status=0
5988
5989 elif logger.level <= logging.INFO:
5990 devnull = open(os.devnull,'w')
5991 try:
5992 misc.call(['make', 'clean'], stdout=devnull, stderr=-2)
5993 except Exception:
5994 pass
5995 if name == 'pythia-pgs':
5996
5997 status = misc.call(['make'], cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
5998 if name in ['golem95','QCDLoop','PJFry']:
5999 status = misc.call(['make','install'],
6000 cwd = os.path.join(MG5DIR, name))
6001 else:
6002 status = misc.call(['make']+make_flags, cwd = os.path.join(MG5DIR, name))
6003 else:
6004 try:
6005 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
6006 except Exception:
6007 pass
6008 if name == 'pythia-pgs':
6009
6010 status = self.compile(mode='', cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
6011 if name in ['golem95','QCDLoop','PJFry']:
6012 status = misc.compile(['install'], mode='',
6013 cwd = os.path.join(MG5DIR, name))
6014 else:
6015 status = self.compile(make_flags, mode='',
6016 cwd = os.path.join(MG5DIR, name))
6017
6018 if not status:
6019 logger.info('Installation succeeded')
6020 else:
6021
6022 if name == 'pythia-pgs':
6023 to_comment = ['libraries/PGS4/src/stdhep-dir/mcfio/arch_mcfio',
6024 'libraries/PGS4/src/stdhep-dir/src/stdhep_Arch']
6025 for f in to_comment:
6026 f = pjoin(MG5DIR, name, *f.split('/'))
6027 text = "".join(l for l in open(f) if 'fno-second-underscore' not in l)
6028 fsock = open(f,'w').write(text)
6029 try:
6030 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
6031 except Exception:
6032 pass
6033 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
6034 if not status:
6035 logger.info('Compilation succeeded')
6036 else:
6037 logger.warning('Error detected during the compilation. Please check the compilation error and run make manually.')
6038
6039
6040
6041 if args[0] == 'MadAnalysis':
6042 try:
6043 os.system('rm -rf td')
6044 os.mkdir(pjoin(MG5DIR, 'td'))
6045 except Exception, error:
6046 print error
6047 pass
6048
6049 if sys.platform == "darwin":
6050 logger.info('Downloading TD for Mac')
6051 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td_mac_intel.tar.gz'
6052 misc.call(['curl', target, '-otd.tgz'],
6053 cwd=pjoin(MG5DIR,'td'))
6054 misc.call(['tar', '-xzpvf', 'td.tgz'],
6055 cwd=pjoin(MG5DIR,'td'))
6056 files.mv(MG5DIR + '/td/td_mac_intel',MG5DIR+'/td/td')
6057 else:
6058 if sys.maxsize > 2**32:
6059 logger.info('Downloading TD for Linux 64 bit')
6060 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td64/td'
6061 logger.warning('''td program (needed by MadAnalysis) is not compile for 64 bit computer.
6062 In 99% of the case, this is perfectly fine. If you do not have plot, please follow
6063 instruction in https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/TopDrawer .''')
6064 else:
6065 logger.info('Downloading TD for Linux 32 bit')
6066 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td'
6067 misc.call(['wget', target], cwd=pjoin(MG5DIR,'td'))
6068 os.chmod(pjoin(MG5DIR,'td','td'), 0775)
6069 self.options['td_path'] = pjoin(MG5DIR,'td')
6070
6071 if not misc.which('gs'):
6072 logger.warning('''gosthscript not install on your system. This is not required to run MA.
6073 but this prevent to create jpg files and therefore to have the plots in the html output.''')
6074 if sys.platform == "darwin":
6075 logger.warning('''You can download this program at the following link:
6076 http://www.macupdate.com/app/mac/9980/gpl-ghostscript''')
6077
6078 if args[0] == 'Delphes2':
6079 data = open(pjoin(MG5DIR, 'Delphes','data','DetectorCard.dat')).read()
6080 data = data.replace('data/', 'DELPHESDIR/data/')
6081 out = open(pjoin(MG5DIR, 'Template','Common', 'Cards', 'delphes_card_default.dat'), 'w')
6082 out.write(data)
6083 if args[0] == 'Delphes3':
6084 if os.path.exists(pjoin(MG5DIR, 'Delphes','cards')):
6085 card_dir = pjoin(MG5DIR, 'Delphes','cards')
6086 else:
6087 card_dir = pjoin(MG5DIR, 'Delphes','examples')
6088 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
6089 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_default.dat'))
6090 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
6091 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_CMS.dat'))
6092 files.cp(pjoin(card_dir,'delphes_card_ATLAS.tcl'),
6093 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_ATLAS.dat'))
6094
6095
6096
6097 options_name = {'Delphes': 'delphes_path',
6098 'Delphes2': 'delphes_path',
6099 'Delphes3': 'delphes_path',
6100 'ExRootAnalysis': 'exrootanalysis_path',
6101 'MadAnalysis': 'madanalysis_path',
6102 'SysCalc': 'syscalc_path',
6103 'pythia-pgs':'pythia-pgs_path',
6104 'Golem95': 'golem',
6105 'PJFry': 'pjfry'}
6106
6107 if args[0] in options_name:
6108 opt = options_name[args[0]]
6109 if opt=='golem':
6110 self.options[opt] = pjoin(MG5DIR,name,'lib')
6111 self.exec_cmd('save options', printcmd=False)
6112 elif opt=='pjfry':
6113 self.options[opt] = pjoin(MG5DIR,'PJFry','lib')
6114 self.exec_cmd('save options', printcmd=False)
6115 elif self.options[opt] != self.options_configuration[opt]:
6116 self.options[opt] = self.options_configuration[opt]
6117 self.exec_cmd('save options',printcmd=False)
6118
6119
6120
6122 """ check if the current version of mg5 is up-to-date.
6123 and allow user to install the latest version of MG5 """
6124
6125 def apply_patch(filetext):
6126 """function to apply the patch"""
6127 text = filetext.read()
6128 pattern = re.compile(r'''=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
6129
6130 for orig, new in pattern.findall(text):
6131 shutil.copytree(pjoin(MG5DIR, orig), pjoin(MG5DIR, 'UPDATE_TMP'))
6132 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
6133 for i, name in enumerate(full_path):
6134 path = os.path.sep.join(full_path[:i+1])
6135 if path and not os.path.isdir(path):
6136 os.mkdir(path)
6137 shutil.copytree(pjoin(MG5DIR, 'UPDATE_TMP'), pjoin(MG5DIR, new))
6138 shutil.rmtree(pjoin(MG5DIR, 'UPDATE_TMP'))
6139
6140 pattern = re.compile(r'''=== renamed file \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
6141
6142 for orig, new in pattern.findall(text):
6143 print 'move %s to %s' % (orig, new)
6144 try:
6145 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
6146 except IOError:
6147 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
6148 for i, name in enumerate(full_path):
6149 path = os.path.sep.join(full_path[:i+1])
6150 if path and not os.path.isdir(path):
6151 os.mkdir(path)
6152 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
6153
6154 pattern = re.compile(r'''^=== added file \'(?P<new>[^\']*)\'''',re.M)
6155 all_add = pattern.findall(text)
6156
6157
6158 pattern=re.compile(r'''=== removed file \'(?P<new>[^\']*)\'(?=.*=== added file \'(?P=new)\')''',re.S)
6159 print 'this step can take a few minuts. please be patient'
6160 all_rm_add = pattern.findall(text)
6161
6162 for new in all_add:
6163 if new in all_rm_add:
6164 continue
6165 if os.path.isfile(pjoin(MG5DIR, new)):
6166 os.remove(pjoin(MG5DIR, new))
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178 p= subprocess.Popen(['patch', '-p1'], stdin=subprocess.PIPE,
6179 cwd=MG5DIR)
6180 p.communicate(text)
6181
6182
6183
6184
6185
6186 pattern=re.compile('''=== modified file \'(?P<new>[^\']*)\'[^\n]*\n\-\-\- old/(?P<old>\S*)[^\n]*\n\+\+\+ new/(?P=new)''',re.S)
6187 for match in pattern.findall(text):
6188 new = pjoin(MG5DIR, match[0])
6189 old = pjoin(MG5DIR, match[1])
6190 if new == old:
6191 continue
6192 elif os.path.exists(old):
6193 if not os.path.exists(os.path.dirname(new)):
6194 split = new.split('/')
6195 for i in range(1,len(split)):
6196 path = '/'.join(split[:i])
6197 if not os.path.exists(path):
6198 print 'mkdir', path
6199 os.mkdir(path)
6200 files.cp(old,new)
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221 for path in misc.glob('*', pjoin(MG5DIR, 'bin')):
6222 misc.call(['chmod', '+x', path])
6223 for path in misc.glob(pjoin('*','bin','*'), pjoin(MG5DIR, 'Template')):
6224 misc.call(['chmod', '+x', path])
6225 for path in misc.glob(pjoin('*','bin','internal','*'), pjoin(MG5DIR, 'Template')):
6226 misc.call(['chmod', '+x', path])
6227 for path in misc.glob(pjoin('*','*', '*.py'), pjoin(MG5DIR, 'Template')):
6228 misc.call(['chmod', '+x', path])
6229 for path in misc.glob(pjoin('*','*','*.sh'), pjoin(MG5DIR, 'Template')):
6230 misc.call(['chmod', '+x', path])
6231
6232
6233 pattern=re.compile('''^=== touch (file|directory) \'(?P<new>[^\']*)\'''',re.M)
6234 for match in pattern.findall(text):
6235 if match[0] == 'file':
6236 new = os.path.dirname(pjoin(MG5DIR, match[1]))
6237 else:
6238 new = pjoin(MG5DIR, match[1])
6239 if not os.path.exists(new):
6240 split = new.split('/')
6241 for i in range(1,len(split)+1):
6242 path = '/'.join(split[:i])
6243 if path and not os.path.exists(path):
6244 print 'mkdir', path
6245 os.mkdir(path)
6246 if match[0] == 'file':
6247 print 'touch ', pjoin(MG5DIR, match[1])
6248 misc.call(['touch', pjoin(MG5DIR, match[1])])
6249
6250 pattern=re.compile('''^=== link file \'(?P<new>[^\']*)\' \'(?P<old>[^\']*)\'''', re.M)
6251 for new, old in pattern.findall(text):
6252 if not os.path.exists(pjoin(MG5DIR, new)):
6253 files.ln(old, os.path.dirname(new), os.path.basename(new))
6254
6255
6256 if os.path.isfile(pjoin(MG5DIR,'vendor','CutTools','includects','libcts.a')):
6257 misc.compile(arg=['-j1'],cwd=pjoin(MG5DIR,'vendor','CutTools'),nb_core=1)
6258 if os.path.isfile(pjoin(MG5DIR,'vendor','IREGI','src','libiregi.a')):
6259 misc.compile(cwd=pjoin(MG5DIR,'vendor','IREGI','src'))
6260
6261
6262 pattern = re.compile("""^Binary files old/(\S*).*and new/(\S*).*$""", re.M)
6263 if pattern.search(text):
6264 return True
6265 else:
6266 return False
6267
6268 mode = [arg.split('=',1)[1] for arg in args if arg.startswith('--mode=')]
6269 if mode:
6270 mode = mode[-1]
6271 else:
6272 mode = "userrequest"
6273 force = any([arg=='-f' for arg in args])
6274 timeout = [arg.split('=',1)[1] for arg in args if arg.startswith('--timeout=')]
6275 if timeout:
6276 try:
6277 timeout = int(timeout[-1])
6278 except ValueError:
6279 raise self.InvalidCmd('%s: invalid argument for timeout (integer expected)'%timeout[-1])
6280 else:
6281 timeout = self.options['timeout']
6282 input_path = [arg.split('=',1)[1] for arg in args if arg.startswith('--input=')]
6283
6284 if input_path:
6285 fsock = open(input_path[0])
6286 need_binary = apply_patch(fsock)
6287 logger.info('manual patch apply. Please test your version.')
6288 if need_binary:
6289 logger.warning('Note that some files need to be loaded separately!')
6290 sys.exit(0)
6291
6292 options = ['y','n','on_exit']
6293 if mode == 'mg5_start':
6294 timeout = 2
6295 default = 'n'
6296 update_delay = self.options['auto_update'] * 24 * 3600
6297 if update_delay == 0:
6298 return
6299 elif mode == 'mg5_end':
6300 timeout = 5
6301 default = 'n'
6302 update_delay = self.options['auto_update'] * 24 * 3600
6303 if update_delay == 0:
6304 return
6305 options.remove('on_exit')
6306 elif mode == "userrequest":
6307 default = 'y'
6308 update_delay = 0
6309 else:
6310 raise self.InvalidCmd('Unknown mode for command install update')
6311
6312 if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')) or \
6313 os.path.exists(os.path.join(MG5DIR,'.bzr')):
6314 error_text = """This version of MG5 doesn\'t support auto-update. Common reasons are:
6315 1) This version was loaded via bazaar (use bzr pull to update instead).
6316 2) This version is a beta release of MG5."""
6317 if mode == 'userrequest':
6318 raise self.ConfigurationError(error_text)
6319 return
6320
6321 if not misc.which('patch'):
6322 error_text = """Not able to find program \'patch\'. Please reload a clean version
6323 or install that program and retry."""
6324 if mode == 'userrequest':
6325 raise self.ConfigurationError(error_text)
6326 return
6327
6328
6329 data = {}
6330 for line in open(os.path.join(MG5DIR,'input','.autoupdate')):
6331 if not line.strip():
6332 continue
6333 sline = line.split()
6334 data[sline[0]] = int(sline[1])
6335
6336
6337 if 'version_nb' not in data:
6338 if mode == 'userrequest':
6339 error_text = 'This version of MG5 doesn\'t support auto-update. (Invalid information)'
6340 raise self.ConfigurationError(error_text)
6341 return
6342 elif 'last_check' not in data:
6343 data['last_check'] = time.time()
6344
6345
6346 if time.time() - data['last_check'] < update_delay:
6347 return
6348
6349 logger.info('Checking if MG5 is up-to-date... (takes up to %ss)' % timeout)
6350 class TimeOutError(Exception): pass
6351
6352 def handle_alarm(signum, frame):
6353 raise TimeOutError
6354
6355 signal.signal(signal.SIGALRM, handle_alarm)
6356 signal.alarm(timeout)
6357 to_update = 0
6358 try:
6359 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/mg5amc_build_nb')
6360 signal.alarm(0)
6361 web_version = int(filetext.read().strip())
6362 except (TimeOutError, ValueError, IOError):
6363 signal.alarm(0)
6364 print 'failed to connect server'
6365 if mode == 'mg5_end':
6366
6367 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6368 fsock.write("version_nb %s\n" % data['version_nb'])
6369 fsock.write("last_check %s\n" % \
6370 int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1))
6371 fsock.close()
6372 return
6373
6374 if web_version == data['version_nb']:
6375 logger.info('No new version of MG5 available')
6376
6377 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6378 fsock.write("version_nb %s\n" % data['version_nb'])
6379 fsock.write("last_check %s\n" % int(time.time()))
6380 fsock.close()
6381 return
6382 elif data['version_nb'] > web_version:
6383 logger_stderr.info('impossible to update: local %s web %s' % (data['version_nb'], web_version))
6384 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6385 fsock.write("version_nb %s\n" % data['version_nb'])
6386 fsock.write("last_check %s\n" % int(time.time()))
6387 fsock.close()
6388 return
6389 else:
6390 if not force:
6391 answer = self.ask('New Version of MG5 available! Do you want to update your current version?',
6392 default, options)
6393 else:
6394 answer = default
6395
6396
6397 if answer == 'y':
6398 logger.info('start updating code')
6399 fail = 0
6400 for i in range(data['version_nb'], web_version):
6401 try:
6402 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/patch/build%s.patch' %(i+1))
6403
6404 except Exception:
6405 print 'fail to load patch to build #%s' % (i+1)
6406 fail = i
6407 break
6408 need_binary = apply_patch(filetext)
6409 if need_binary:
6410 path = "http://madgraph.phys.ucl.ac.be/binary/binary_file%s.tgz" %(i+1)
6411 name = "extra_file%i" % (i+1)
6412 if sys.platform == "darwin":
6413 misc.call(['curl', path, '-o%s.tgz' % name], cwd=MG5DIR)
6414 else:
6415 misc.call(['wget', path, '--output-document=%s.tgz'% name], cwd=MG5DIR)
6416
6417 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
6418 stdout=open(os.devnull, 'w'))
6419
6420 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6421 if not fail:
6422 fsock.write("version_nb %s\n" % web_version)
6423 else:
6424 fsock.write("version_nb %s\n" % fail)
6425 fsock.write("last_check %s\n" % int(time.time()))
6426 fsock.close()
6427 logger.info('Refreshing installation of MG5aMC_PY8_interface.')
6428 self.do_install('mg5amc_py8_interface',additional_options=['--force'])
6429 logger.info('Checking current version. (type ctrl-c to bypass the check)')
6430 subprocess.call([os.path.join('tests','test_manager.py')],
6431 cwd=MG5DIR)
6432 print 'new version installed, please relaunch mg5'
6433 try:
6434 os.remove(pjoin(MG5DIR, 'Template','LO','Source','make_opts'))
6435 shutil.copy(pjoin(MG5DIR, 'Template','LO','Source','.make_opts'),
6436 pjoin(MG5DIR, 'Template','LO','Source','make_opts'))
6437 except:
6438 pass
6439 sys.exit(0)
6440 elif answer == 'n':
6441
6442 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6443 fsock.write("version_nb %s\n" % data['version_nb'])
6444 fsock.write("last_check %s\n" % int(time.time()))
6445 fsock.close()
6446 logger.info('Update bypassed.')
6447 logger.info('The next check for a new version will be performed in %s days' \
6448 % abs(self.options['auto_update']))
6449 logger.info('In order to change this delay. Enter the command:')
6450 logger.info('set auto_update X')
6451 logger.info('Putting X to zero will prevent this check at anytime.')
6452 logger.info('You can upgrade your version at any time by typing:')
6453 logger.info('install update')
6454 else:
6455
6456
6457 self.options['auto_update'] = -1 * self.options['auto_update']
6458
6459
6460
6462 """ assign all configuration variable from file
6463 ./input/mg5_configuration.txt. assign to default if not define """
6464
6465 if not self.options:
6466 self.options = dict(self.options_configuration)
6467 self.options.update(self.options_madgraph)
6468 self.options.update(self.options_madevent)
6469
6470 if not config_path:
6471 if os.environ.has_key('MADGRAPH_BASE'):
6472 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
6473 self.set_configuration(config_path, final=False)
6474 if 'HOME' in os.environ:
6475 config_path = pjoin(os.environ['HOME'],'.mg5',
6476 'mg5_configuration.txt')
6477 if os.path.exists(config_path):
6478 self.set_configuration(config_path, final=False)
6479 config_path = os.path.relpath(pjoin(MG5DIR,'input',
6480 'mg5_configuration.txt'))
6481 return self.set_configuration(config_path, final)
6482
6483 if not os.path.exists(config_path):
6484 files.cp(pjoin(MG5DIR,'input','.mg5_configuration_default.txt'), config_path)
6485 config_file = open(config_path)
6486
6487
6488 logger.info('load MG5 configuration from %s ' % config_file.name)
6489 for line in config_file:
6490 if '#' in line:
6491 line = line.split('#',1)[0]
6492 line = line.replace('\n','').replace('\r\n','')
6493 try:
6494 name, value = line.split('=')
6495 except ValueError:
6496 pass
6497 else:
6498 name = name.strip()
6499 value = value.strip()
6500 if name != 'mg5_path':
6501 self.options[name] = value
6502 if value.lower() == "none" or value=="":
6503 self.options[name] = None
6504 config_file.close()
6505 self.options['stdout_level'] = logging.getLogger('madgraph').level
6506 if not final:
6507 return self.options
6508
6509
6510
6511
6512 for key in self.options:
6513 if key in ['pythia8_path', 'hwpp_path', 'thepeg_path', 'hepmc_path',
6514 'mg5amc_py8_interface_path','madanalysis5_path']:
6515 if self.options[key] in ['None', None]:
6516 self.options[key] = None
6517 continue
6518 path = self.options[key]
6519
6520 if key == 'pythia8_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Pythia8', 'Pythia.h')):
6521 if not os.path.isfile(pjoin(path, 'include', 'Pythia8', 'Pythia.h')):
6522 self.options['pythia8_path'] = None
6523 else:
6524 continue
6525
6526 if key == 'mg5amc_py8_interface_path' and not os.path.isfile(pjoin(MG5DIR, path, 'MG5aMC_PY8_interface')):
6527 if not os.path.isfile(pjoin(path, 'MG5aMC_PY8_interface')):
6528 self.options['mg5amc_py8_interface_path'] = None
6529 else:
6530 continue
6531
6532 if key == 'madanalysis5_path' and not os.path.isfile(pjoin(MG5DIR, path,'bin','ma5')):
6533 if not os.path.isfile(pjoin(path,'bin','ma5')):
6534 self.options['madanalysis5_path'] = None
6535 else:
6536 continue
6537
6538 if key == 'hwpp_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
6539 if not os.path.isfile(pjoin(path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
6540 self.options['hwpp_path'] = None
6541 else:
6542 continue
6543
6544 elif key == 'thepeg_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
6545 if not os.path.isfile(pjoin(path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
6546 self.options['thepeg_path'] = None
6547 else:
6548 continue
6549
6550 elif key == 'hepmc_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'HepMC', 'HEPEVT_Wrapper.h')):
6551 if not os.path.isfile(pjoin(path, 'include', 'HepMC', 'HEPEVT_Wrapper.h')):
6552 self.options['hepmc_path'] = None
6553 else:
6554 continue
6555
6556 elif key in ['pjfry','golem','samurai']:
6557 if isinstance(self.options[key],str) and self.options[key].lower() == 'auto':
6558
6559 program = misc.which_lib('lib%s.a'%key)
6560 if program != None:
6561 fpath, _ = os.path.split(program)
6562 logger.info('Using %s library in %s' % (key,fpath))
6563 self.options[key]=fpath
6564 else:
6565
6566 local_install = {'pjfry':'PJFRY', 'golem':'golem95',
6567 'samurai':'samurai'}
6568 if os.path.isfile(pjoin(MG5DIR,local_install[key],'lib', 'lib%s.a' % key)):
6569 self.options[key]=pjoin(MG5DIR,local_install[key],'lib')
6570 else:
6571 self.options[key]=None
6572
6573 if key=='samurai' and \
6574 isinstance(self.options[key],str) and \
6575 self.options[key].lower() != 'auto':
6576 if os.path.isfile(pjoin(self.options[key],os.pardir,'AUTHORS')):
6577 try:
6578 version = open(pjoin(self.options[key],os.pardir,
6579 'VERSION'),'r').read()
6580 except IOError:
6581 version = None
6582 if version is None:
6583 self.options[key] = None
6584 logger.info('--------')
6585 logger.info(
6586 """The version of 'samurai' automatically detected seems too old to be compatible
6587 with MG5aMC and it will be turned off. Ask the authors for the latest version if
6588 you want to use samurai.
6589 If you want to enforce its use as-it-is, then specify directly its library folder
6590 in the MG5aMC option 'samurai' (instead of leaving it to its default 'auto').""")
6591 logger.info('--------')
6592
6593 elif key.endswith('path'):
6594 pass
6595 elif key in ['run_mode', 'auto_update']:
6596 self.options[key] = int(self.options[key])
6597 elif key in ['cluster_type','automatic_html_opening']:
6598 pass
6599 elif key in ['notification_center']:
6600 if self.options[key] in ['False', 'True']:
6601 self.allow_notification_center = eval(self.options[key])
6602 self.options[key] = self.allow_notification_center
6603 elif key not in ['text_editor','eps_viewer','web_browser', 'stdout_level']:
6604
6605 try:
6606 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
6607 except MadGraph5Error, error:
6608 print error
6609 logger.warning("Option %s from config file not understood" \
6610 % key)
6611 else:
6612 if key in self.options_madgraph:
6613 self.history.append('set %s %s' % (key, self.options[key]))
6614
6615 warnings = madevent_interface.MadEventCmd.mg5amc_py8_interface_consistency_warning(self.options)
6616 if warnings:
6617 logger.warning(warnings)
6618
6619
6620 launch_ext.open_file.configure(self.options)
6621 return self.options
6622
6624 """Check if the files is in a valid export directory and assign it to
6625 export path if if is"""
6626
6627
6628 if self._export_dir:
6629 return
6630
6631 if os.path.exists(pjoin(os.getcwd(), 'Cards')):
6632 self._export_dir = os.getcwd()
6633 return
6634
6635 path_split = filepath.split(os.path.sep)
6636 if len(path_split) > 2 and path_split[-2] == 'Cards':
6637 self._export_dir = os.path.sep.join(path_split[:-2])
6638 return
6639
6641 """Main commands: Ask for editing the parameter and then
6642 Execute the code (madevent/standalone/...)
6643 """
6644
6645
6646 current_options = dict([(name, self.options[name]) for name in self.options_madgraph])
6647 start_cwd = os.getcwd()
6648
6649 args = self.split_arg(line)
6650
6651 (options, args) = _launch_parser.parse_args(args)
6652 self.check_launch(args, options)
6653 options = options.__dict__
6654
6655
6656 if args[0].startswith('standalone'):
6657 if os.path.isfile(os.path.join(os.getcwd(),args[1],'Cards',\
6658 'MadLoopParams.dat')) and not os.path.isfile(os.path.join(\
6659 os.getcwd(),args[1],'SubProcesses','check_poles.f')):
6660 ext_program = launch_ext.MadLoopLauncher(self, args[1], \
6661 options=self.options, **options)
6662 else:
6663 ext_program = launch_ext.SALauncher(self, args[1], \
6664 options=self.options, **options)
6665 elif args[0] == 'madevent':
6666 if options['interactive']:
6667
6668 if isinstance(self, cmd.CmdShell):
6669 ME = madevent_interface.MadEventCmdShell(me_dir=args[1], options=self.options)
6670 else:
6671 ME = madevent_interface.MadEventCmd(me_dir=args[1],options=self.options)
6672 ME.pass_in_web_mode()
6673 stop = self.define_child_cmd_interface(ME)
6674 return stop
6675
6676
6677 if not self._generate_info:
6678
6679
6680 info = open(pjoin(args[1],'SubProcesses','procdef_mg5.dat')).read()
6681 generate_info = info.split('# Begin PROCESS',1)[1].split('\n')[1]
6682 generate_info = generate_info.split('#')[0]
6683 else:
6684 generate_info = self._generate_info
6685
6686 if len(generate_info.split('>')[0].strip().split())>1:
6687 ext_program = launch_ext.MELauncher(args[1], self,
6688 shell = isinstance(self, cmd.CmdShell),
6689 options=self.options,**options)
6690 else:
6691
6692 ext_program = launch_ext.MELauncher(args[1], self, unit='GeV',
6693 shell = isinstance(self, cmd.CmdShell),
6694 options=self.options,**options)
6695
6696 elif args[0] == 'pythia8':
6697 ext_program = launch_ext.Pythia8Launcher( args[1], self, **options)
6698
6699 elif args[0] == 'aMC@NLO':
6700 if options['interactive']:
6701 if isinstance(self, cmd.CmdShell):
6702 ME = amcatnlo_run.aMCatNLOCmdShell(me_dir=args[1], options=self.options)
6703 else:
6704 ME = amcatnlo_run.aMCatNLOCmd(me_dir=args[1],options=self.options)
6705 ME.pass_in_web_mode()
6706
6707 config_line = [l for l in self.history if l.strip().startswith('set')]
6708 for line in config_line:
6709 ME.exec_cmd(line)
6710 stop = self.define_child_cmd_interface(ME)
6711 return stop
6712 ext_program = launch_ext.aMCatNLOLauncher( args[1], self,
6713 shell = isinstance(self, cmd.CmdShell),
6714 **options)
6715 elif args[0] == 'madweight':
6716 import madgraph.interface.madweight_interface as madweight_interface
6717 if options['interactive']:
6718 if isinstance(self, cmd.CmdShell):
6719 MW = madweight_interface.MadWeightCmdShell(me_dir=args[1], options=self.options)
6720 else:
6721 MW = madweight_interface.MadWeightCmd(me_dir=args[1],options=self.options)
6722
6723 config_line = [l for l in self.history if l.strip().startswith('set')]
6724 for line in config_line:
6725 MW.exec_cmd(line)
6726 stop = self.define_child_cmd_interface(MW)
6727 return stop
6728 ext_program = launch_ext.MWLauncher( self, args[1],
6729 shell = isinstance(self, cmd.CmdShell),
6730 options=self.options,**options)
6731 else:
6732 os.chdir(start_cwd)
6733 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
6734
6735
6736 ext_program.run()
6737 os.chdir(start_cwd)
6738
6739 for key, value in current_options.items():
6740 self.options[key] = value
6741
6798
6799
6801 """create a restriction card in a interactive way"""
6802
6803 args = self.split_arg(line)
6804 self.check_customize_model(args)
6805
6806 model_path = self._curr_model.get('modelpath')
6807 if not os.path.exists(pjoin(model_path,'build_restrict.py')):
6808 raise self.InvalidCmd('''Model not compatible with this option.''')
6809
6810
6811 self._curr_model = import_ufo.import_model(model_path, restrict=False)
6812
6813
6814 out_path = StringIO.StringIO()
6815 param_writer.ParamCardWriter(self._curr_model, out_path)
6816
6817 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
6818
6819
6820 all_categories = self.ask('','0',[], ask_class=AskforCustomize)
6821 put_to_one = []
6822
6823 for block in param_card:
6824 value_dict = {}
6825 for param in param_card[block]:
6826 value = param.value
6827 if value == 0:
6828 param.value = 0.000001e-99
6829 elif value == 1:
6830 if block != 'qnumbers':
6831 put_to_one.append((block,param.lhacode))
6832 param.value = random.random()
6833 elif abs(value) in value_dict:
6834 param.value += value_dict[abs(value)] * 1e-4 * param.value
6835 value_dict[abs(value)] += 1
6836 else:
6837 value_dict[abs(value)] = 1
6838
6839 for category in all_categories:
6840 for options in category:
6841 if not options.status:
6842 continue
6843 param = param_card[options.lhablock].get(options.lhaid)
6844 param.value = options.value
6845
6846 logger.info('Loading the resulting model')
6847
6848 self._curr_model = import_ufo.RestrictModel(self._curr_model)
6849 model_name = self._curr_model.get('name')
6850 if model_name == 'mssm':
6851 keep_external=True
6852 else:
6853 keep_external=False
6854 self._curr_model.restrict_model(param_card,keep_external=keep_external)
6855
6856 if args:
6857 name = args[0].split('=',1)[1]
6858 path = pjoin(model_path,'restrict_%s.dat' % name)
6859 logger.info('Save restriction file as %s' % path)
6860 param_card.write(path)
6861 self._curr_model['name'] += '-%s' % name
6862
6863
6864 if put_to_one:
6865 out_path = StringIO.StringIO()
6866 param_writer.ParamCardWriter(self._curr_model, out_path)
6867
6868 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
6869
6870 for (block, lhacode) in put_to_one:
6871 misc.sprint(block, lhacode)
6872 try:
6873 param_card[block].get(lhacode).value = 1
6874 except:
6875 pass
6876 self._curr_model.set_parameters_and_couplings(param_card)
6877
6878 if args:
6879 name = args[0].split('=',1)[1]
6880 path = pjoin(model_path,'paramcard_%s.dat' % name)
6881 logger.info('Save default card file as %s' % path)
6882 param_card.write(path)
6883
6884 - def do_save(self, line, check=True, to_keep={}, log=True):
6885 """Not in help: Save information to file"""
6886
6887 args = self.split_arg(line)
6888
6889 if check:
6890 self.check_save(args)
6891
6892 if args[0] == 'model':
6893 if self._curr_model:
6894
6895 if save_load_object.save_to_file(args[1], self._curr_model):
6896 logger.info('Saved model to file %s' % args[1])
6897 else:
6898 raise self.InvalidCmd('No model to save!')
6899 elif args[0] == 'processes':
6900 if self._curr_amps:
6901 if save_load_object.save_to_file(args[1], (self._curr_amps,self._curr_proc_defs) ):
6902 logger.info('Saved processes to file %s' % args[1])
6903 else:
6904 raise self.InvalidCmd('No processes to save!')
6905
6906 elif args[0] == 'options':
6907 partial_save = False
6908 to_define = {}
6909
6910 if any(not arg.startswith('--') and arg in self.options
6911 for arg in args):
6912
6913 partial_save = True
6914 all_arg = [arg for arg in args[1:] if not arg.startswith('--') and
6915 arg in self.options]
6916 for key in all_arg:
6917 to_define[key] = self.options[key]
6918 else:
6919
6920 for key, default in self.options_configuration.items():
6921 if self.options_configuration[key] != self.options[key] and not self.options_configuration[key] is None:
6922 to_define[key] = self.options[key]
6923
6924 if not '--auto' in args:
6925 for key, default in self.options_madevent.items():
6926 if self.options_madevent[key] != self.options[key] != None:
6927 if '_path' in key and os.path.basename(self.options[key]) == 'None':
6928 continue
6929 to_define[key] = self.options[key]
6930 elif key == 'cluster_queue' and self.options[key] is None:
6931 to_define[key] = self.options[key]
6932
6933 if '--all' in args:
6934 for key, default in self.options_madgraph.items():
6935 if self.options_madgraph[key] != self.options[key] != None and \
6936 key != 'stdout_level':
6937 to_define[key] = self.options[key]
6938 elif not '--auto' in args:
6939 for key, default in self.options_madgraph.items():
6940 if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level':
6941 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
6942 % (key,self.options_madgraph[key]) )
6943 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
6944
6945 if len(args) >1 and not args[1].startswith('--') and args[1] not in self.options:
6946 filepath = args[1]
6947 else:
6948 filepath = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
6949
6950 basedir = MG5DIR
6951 if partial_save:
6952 basefile = filepath
6953 else:
6954 basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt')
6955
6956
6957
6958 if to_keep:
6959 to_define = to_keep
6960 self.write_configuration(filepath, basefile, basedir, to_define)
6961
6962
6963 - def do_set(self, line, log=True, model_reload=True):
6964 """Set an option, which will be default for coming generations/outputs.
6965 """
6966
6967
6968
6969 args = self.split_arg(line)
6970
6971
6972 self.check_set(args)
6973
6974 if args[0] == 'ignore_six_quark_processes':
6975 if args[1] == 'False':
6976 self.options[args[0]] = False
6977 return
6978 self.options[args[0]] = list(set([abs(p) for p in \
6979 self._multiparticles[args[1]]\
6980 if self._curr_model.get_particle(p).\
6981 is_fermion() and \
6982 self._curr_model.get_particle(abs(p)).\
6983 get('color') == 3]))
6984 if log:
6985 logger.info('Ignore processes with >= 6 quarks (%s)' % \
6986 ",".join([\
6987 self._curr_model.get_particle(q).get('name') \
6988 for q in self.options[args[0]]]))
6989
6990 elif args[0] == 'group_subprocesses':
6991 if args[1] not in ['Auto', 'NLO']:
6992 self.options[args[0]] = eval(args[1])
6993 else:
6994 self.options[args[0]] = args[1]
6995 if log:
6996 logger.info('Set group_subprocesses to %s' % \
6997 str(self.options[args[0]]))
6998 logger.info('Note that you need to regenerate all processes')
6999 self._curr_amps = diagram_generation.AmplitudeList()
7000 self._curr_proc_defs = base_objects.ProcessDefinitionList()
7001 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7002
7003 elif args[0] == "stdout_level":
7004 if args[1].isdigit():
7005 level = int(args[1])
7006 else:
7007 level = eval('logging.' + args[1])
7008 logging.root.setLevel(level)
7009 logging.getLogger('madgraph').setLevel(level)
7010 logging.getLogger('madevent').setLevel(level)
7011 self.options[args[0]] = level
7012 if log:
7013 logger.info('set output information to level: %s' % level)
7014 elif args[0].lower() == "ewscheme":
7015 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." %\
7016 (self._curr_model.get('name'), args[1]))
7017 logger.info("Importing a model will restore the default scheme")
7018 self._curr_model.change_electroweak_mode(args[1])
7019 elif args[0] == "complex_mass_scheme":
7020 old = self.options[args[0]]
7021 self.options[args[0]] = eval(args[1])
7022 aloha.complex_mass = eval(args[1])
7023 aloha_lib.KERNEL.clean()
7024 if self.options[args[0]]:
7025 if old:
7026 if log:
7027 logger.info('Complex mass already activated.')
7028 return
7029 if log:
7030 logger.info('Activate complex mass scheme.')
7031 else:
7032 if not old:
7033 if log:
7034 logger.info('Complex mass already desactivated.')
7035 return
7036 if log:
7037 logger.info('Desactivate complex mass scheme.')
7038 if not self._curr_model:
7039 return
7040 self.exec_cmd('import model %s' % self._curr_model.get('name'))
7041
7042 elif args[0] == "gauge":
7043
7044 if not self._curr_model:
7045 if args[1] == 'unitary':
7046 aloha.unitary_gauge = True
7047 else:
7048 aloha.unitary_gauge = False
7049 aloha_lib.KERNEL.clean()
7050 self.options[args[0]] = args[1]
7051 if log: logger.info('Passing to gauge %s.' % args[1])
7052 return
7053
7054
7055 able_to_mod = True
7056 if args[1] == 'unitary':
7057 if 0 in self._curr_model.get('gauge'):
7058 aloha.unitary_gauge = True
7059 else:
7060 able_to_mod = False
7061 if log: logger.warning('Note that unitary gauge is not allowed for your current model %s' \
7062 % self._curr_model.get('name'))
7063 else:
7064 if 1 in self._curr_model.get('gauge'):
7065 aloha.unitary_gauge = False
7066 else:
7067 able_to_mod = False
7068 if log: logger.warning('Note that Feynman gauge is not allowed for your current model %s' \
7069 % self._curr_model.get('name'))
7070
7071 if self.options['gauge'] == args[1]:
7072 return
7073
7074
7075 self.options[args[0]] = args[1]
7076
7077 if able_to_mod and log and args[0] == 'gauge' and \
7078 args[1] == 'unitary' and not self.options['gauge']=='unitary' and \
7079 isinstance(self._curr_model,loop_base_objects.LoopModel) and \
7080 not self._curr_model['perturbation_couplings'] in [[],['QCD']]:
7081 logger.warning('You will only be able to do tree level'+\
7082 ' and QCD corrections in the unitary gauge.')
7083
7084
7085
7086
7087 model_name = self._curr_model.get('modelpath+restriction')
7088 self._curr_model = None
7089 self._curr_amps = diagram_generation.AmplitudeList()
7090 self._curr_proc_defs = base_objects.ProcessDefinitionList()
7091 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7092 self._curr_helas_model = None
7093 self._curr_exporter = None
7094 self._done_export = False
7095 import_ufo._import_once = []
7096 logger.info('Passing to gauge %s.' % args[1])
7097
7098 if able_to_mod:
7099
7100
7101
7102 MadGraphCmd.do_import(self,'model %s' %model_name, force=True)
7103 elif log:
7104 logger.info('Note that you have to reload the model')
7105
7106 elif args[0] == 'fortran_compiler':
7107 if args[1] != 'None':
7108 if log:
7109 logger.info('set fortran compiler to %s' % args[1])
7110 self.options['fortran_compiler'] = args[1]
7111 else:
7112 self.options['fortran_compiler'] = None
7113 elif args[0] == 'f2py_compiler':
7114 if args[1] != 'None':
7115 if log:
7116 logger.info('set f2py compiler to %s' % args[1])
7117 self.options['f2py_compiler'] = args[1]
7118 else:
7119 self.options['f2py_compiler'] = None
7120
7121 elif args[0] == 'loop_optimized_output':
7122 if log:
7123 logger.info('set loop optimized output to %s' % args[1])
7124 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7125 self.options[args[0]] = args[1]
7126 if not self.options['loop_optimized_output'] and \
7127 self.options['loop_color_flows']:
7128 logger.warning("Turning off option 'loop_color_flows'"+\
7129 " since it is not available for non-optimized loop output.")
7130 self.do_set('loop_color_flows False',log=False)
7131 elif args[0] == 'loop_color_flows':
7132 if log:
7133 logger.info('set loop color flows to %s' % args[1])
7134 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7135 self.options[args[0]] = args[1]
7136 if self.options['loop_color_flows'] and \
7137 not self.options['loop_optimized_output']:
7138 logger.warning("Turning on option 'loop_optimized'"+\
7139 " needed for loop color flow computation.")
7140 self.do_set('loop_optimized_output True',False)
7141
7142 elif args[0] == 'fastjet':
7143 try:
7144 p = subprocess.Popen([args[1], '--version'], stdout=subprocess.PIPE,
7145 stderr=subprocess.PIPE)
7146 output, error = p.communicate()
7147 res = 0
7148 except Exception:
7149 res = 1
7150
7151 if res != 0 or error:
7152 logger.info('%s does not seem to correspond to a valid fastjet-config ' % args[1] + \
7153 'executable (v3+). We will use fjcore instead.\n Please set the \'fastjet\'' + \
7154 'variable to the full (absolute) /PATH/TO/fastjet-config (including fastjet-config).' +
7155 '\n MG5_aMC> set fastjet /PATH/TO/fastjet-config\n')
7156 self.options[args[0]] = None
7157 self.history.pop()
7158 elif int(output.split('.')[0]) < 3:
7159 logger.warning('%s is not ' % args[1] + \
7160 'v3 or greater. Please install FastJet v3+.')
7161 self.options[args[0]] = None
7162 self.history.pop()
7163 else:
7164 logger.info('set fastjet to %s' % args[1])
7165 self.options[args[0]] = args[1]
7166
7167 elif args[0] in ['pjfry','golem','samurai','ninja','collier'] and \
7168 not (args[0] in ['ninja','collier'] and args[1]=='./HEPTools/lib'):
7169 if args[1] in ['None',"''",'""']:
7170 self.options[args[0]] = None
7171 else:
7172 program = misc.which_lib(os.path.join(args[1],'lib%s.a'%args[0]))
7173 if program!=None:
7174 res = 0
7175 logger.info('set %s to %s' % (args[0],args[1]))
7176 self.options[args[0]] = args[1]
7177 else:
7178 res = 1
7179
7180 if res != 0 :
7181 logger.warning('%s does not seem to correspond to a valid %s lib ' % (args[1],args[0]) + \
7182 '. Please enter the full PATH/TO/%s/lib .\n'%args[0] + \
7183 'You will NOT be able to run %s otherwise.\n'%args[0])
7184
7185 elif args[0] == 'lhapdf':
7186 try:
7187 res = misc.call([args[1], '--version'], stdout=subprocess.PIPE,
7188 stderr=subprocess.PIPE)
7189 logger.info('set lhapdf to %s' % args[1])
7190 self.options[args[0]] = args[1]
7191 except Exception:
7192 res = 1
7193 if res != 0:
7194 logger.info('%s does not seem to correspond to a valid lhapdf-config ' % args[1] + \
7195 'executable. \nPlease set the \'lhapdf\' variable to the (absolute) ' + \
7196 '/PATH/TO/lhapdf-config (including lhapdf-config).\n' + \
7197 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n' + \
7198 ' MG5_aMC> set lhapdf /PATH/TO/lhapdf-config\n')
7199
7200 elif args[0] in ['timeout', 'auto_update', 'cluster_nb_retry',
7201 'cluster_retry_wait', 'cluster_size', 'max_npoint_for_channel']:
7202 self.options[args[0]] = int(args[1])
7203
7204 elif args[0] in ['cluster_local_path']:
7205 self.options[args[0]] = args[1].strip()
7206
7207 elif args[0] == 'cluster_status_update':
7208 if '(' in args[1]:
7209 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
7210 data = data.replace('(','').replace(')','').replace(',',' ').split()
7211 first, second = data[:2]
7212 else:
7213 first, second = args[1:3]
7214
7215 self.options[args[0]] = (int(first), int(second))
7216
7217 elif args[0] == 'OLP':
7218
7219
7220 self._curr_amps = diagram_generation.AmplitudeList()
7221 self._curr_proc_defs = base_objects.ProcessDefinitionList()
7222 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7223 self._curr_exporter = None
7224 self.options[args[0]] = args[1]
7225
7226 elif args[0] =='output_dependencies':
7227 self.options[args[0]] = args[1]
7228 elif args[0] =='notification_center':
7229 if args[1] in ['None','True','False']:
7230 self.options[args[0]] = eval(args[1])
7231 self.allow_notification_center = self.options[args[0]]
7232 else:
7233 raise self.InvalidCmd('expected bool for notification_center')
7234 elif args[0] in ['cluster_queue']:
7235 self.options[args[0]] = args[1].strip()
7236 elif args[0] in self.options:
7237 if args[1] in ['None','True','False']:
7238 self.options[args[0]] = eval(args[1])
7239 else:
7240 self.options[args[0]] = args[1]
7241
7242 - def post_set(self, stop, line):
7243 """Check if we need to save this in the option file"""
7244
7245 args = self.split_arg(line)
7246
7247 try:
7248 self.check_set(args, log=False)
7249 except Exception:
7250 return stop
7251
7252 if args[0] in self.options_configuration and '--no_save' not in args:
7253 self.exec_cmd('save options --auto', log=False)
7254 elif args[0] in self.options_madevent:
7255 if not '--no_save' in line:
7256 logger.info('This option will be the default in any output that you are going to create in this session.')
7257 logger.info('In order to keep this changes permanent please run \'save options\'')
7258 else:
7259
7260 if not self.history or self.history[-1].split() != line.split():
7261 self.history.append('set %s' % line)
7262 self.avoid_history_duplicate('set %s' % args[0], ['define', 'set'])
7263 return stop
7264
7274
7276 """Main commands: Initialize a new Template or reinitialize one"""
7277
7278 args = self.split_arg(line)
7279
7280 self.check_output(args)
7281
7282
7283 noclean = '-noclean' in args
7284 force = '-f' in args
7285 nojpeg = '-nojpeg' in args
7286 flaglist = []
7287
7288 if '--postpone_model' in args:
7289 flaglist.append('store_model')
7290
7291 main_file_name = ""
7292 try:
7293 main_file_name = args[args.index('-name') + 1]
7294 except Exception:
7295 pass
7296
7297
7298
7299
7300
7301 if self._export_format == 'aloha':
7302
7303 format = [d[9:] for d in args if d.startswith('--format=')]
7304 if not format:
7305 format = 'Fortran'
7306 else:
7307 format = format[-1]
7308
7309 output = [d for d in args if d.startswith('--output=')]
7310 if not output:
7311 output = import_ufo.find_ufo_path(self._curr_model['name'])
7312 output = pjoin(output, format)
7313 if not os.path.isdir(output):
7314 os.mkdir(output)
7315 else:
7316 output = output[-1]
7317 if not os.path.isdir(output):
7318 raise self.InvalidCmd('%s is not a valid directory' % output)
7319 logger.info('creating routines in directory %s ' % output)
7320
7321 names = [d for d in args if not d.startswith('-')]
7322 wanted_lorentz = aloha_fct.guess_routine_from_name(names)
7323
7324 aloha_model = create_aloha.AbstractALOHAModel(self._curr_model.get('name'))
7325 aloha_model.add_Lorentz_object(self._curr_model.get('lorentz'))
7326 if wanted_lorentz:
7327 aloha_model.compute_subset(wanted_lorentz)
7328 else:
7329 aloha_model.compute_all(save=False)
7330 aloha_model.write(output, format)
7331 return
7332
7333
7334
7335
7336
7337
7338
7339
7340 config = {}
7341 config['madevent'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7342 config['matrix'] = {'check': False, 'exporter': 'v4', 'output':'dir'}
7343 config['standalone'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7344 config['standalone_msF'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7345 config['standalone_msP'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7346 config['standalone_rw'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7347 config['standalone_cpp'] = {'check': False, 'exporter': 'cpp', 'output': 'Template'}
7348 config['pythia8'] = {'check': False, 'exporter': 'cpp', 'output':'dir'}
7349 config['matchbox_cpp'] = {'check': True, 'exporter': 'cpp', 'output': 'Template'}
7350 config['matchbox'] = {'check': True, 'exporter': 'v4', 'output': 'Template'}
7351 config['madweight'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7352
7353 if self._export_format == 'plugin':
7354 options = {'check': self._export_plugin.check, 'exporter':self._export_plugin.exporter, 'output':self._export_plugin.output}
7355 else:
7356 options = config[self._export_format]
7357
7358
7359 if os.path.realpath(self._export_dir) == os.getcwd():
7360 if len(args) == 0:
7361 i=0
7362 while 1:
7363 if os.path.exists('Pythia8_proc_%i' %i):
7364 i+=1
7365 else:
7366 break
7367 os.mkdir('Pythia8_proc_%i' %i)
7368 self._export_dir = pjoin(self._export_dir, 'Pythia8_proc_%i' %i)
7369 logger.info('Create output in %s' % self._export_dir)
7370 elif not args[0] in ['.', '-f']:
7371 raise self.InvalidCmd, 'Wrong path directory to create in local directory use \'.\''
7372 elif not noclean and os.path.isdir(self._export_dir) and options['check']:
7373 if not force:
7374
7375 logger.info('INFO: directory %s already exists.' % self._export_dir)
7376 logger.info('If you continue this directory will be deleted and replaced.')
7377 answer = self.ask('Do you want to continue?', 'y', ['y','n'])
7378 else:
7379 answer = 'y'
7380 if answer != 'y':
7381 raise self.InvalidCmd('Stopped by user request')
7382 else:
7383 shutil.rmtree(self._export_dir)
7384
7385
7386
7387 if self.options['group_subprocesses'] in [True, False]:
7388 group_processes = self.options['group_subprocesses']
7389 elif self.options['group_subprocesses'] == 'Auto':
7390
7391 group_processes = True
7392
7393
7394
7395
7396 if self._curr_amps[0].get_ninitial() == 1 and \
7397 len(self._curr_amps)>1:
7398 processes = [amp.get('process') for amp in self._curr_amps]
7399 if len(set(proc.get('id') for proc in processes))!=len(processes):
7400
7401 if any(proc['perturbation_couplings'] != [] for proc in
7402 processes) and self._export_format == 'madevent':
7403 logger.warning("""
7404 || The loop-induced decay process you have specified contains several
7405 || subprocesses and, in order to be able to compute individual branching ratios,
7406 || MG5_aMC will *not* group them. Integration channels will also be considered
7407 || for each diagrams and as a result integration will be inefficient.
7408 || It is therefore recommended to perform this simulation by setting the MG5_aMC
7409 || option 'group_subprocesses' to 'True' (before the output of the process).
7410 || Notice that when doing so, processes for which one still wishes to compute
7411 || branching ratios independently can be specified using the syntax:
7412 || -> add process <proc_def>
7413 """)
7414 group_processes = False
7415
7416
7417 if options['exporter'] == 'v4':
7418 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
7419 group_subprocesses=group_processes)
7420 elif options['exporter'] == 'cpp':
7421 self._curr_exporter = export_cpp.ExportCPPFactory(self, group_subprocesses=group_processes)
7422
7423 self._curr_exporter.pass_information_from_cmd(self)
7424
7425 if options['output'] == 'Template':
7426 self._curr_exporter.copy_template(self._curr_model)
7427 elif options['output'] == 'dir' and not os.path.isdir(self._export_dir):
7428 os.makedirs(self._export_dir)
7429
7430
7431 self._done_export = False
7432
7433 if self._export_format == "madevent":
7434
7435
7436 if self.options['max_npoint_for_channel']:
7437 base_objects.Vertex.max_n_loop_for_multichanneling = self.options['max_npoint_for_channel']
7438 else:
7439 base_objects.Vertex.max_n_loop_for_multichanneling = 3
7440
7441
7442 self.export(nojpeg, main_file_name, group_processes, args)
7443
7444
7445 self.finalize(nojpeg, flaglist=flaglist)
7446
7447
7448 self._done_export = (self._export_dir, self._export_format)
7449
7450
7451 self._export_dir = None
7452
7453
7454 - def export(self, nojpeg = False, main_file_name = "", group_processes=True,
7455 args=[]):
7456 """Export a generated amplitude to file."""
7457
7458
7459 if self._curr_exporter.exporter == 'cpp':
7460 self._curr_helas_model = helas_call_writers.CPPUFOHelasCallWriter(self._curr_model)
7461 elif self._model_v4_path:
7462 assert self._curr_exporter.exporter == 'v4'
7463 self._curr_helas_model = helas_call_writers.FortranHelasCallWriter(self._curr_model)
7464 else:
7465 assert self._curr_exporter.exporter == 'v4'
7466 self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model)
7467
7468 version = [arg[10:] for arg in args if arg.startswith('--version=')]
7469 if version:
7470 version = version[-1]
7471 else:
7472 version = '8.2'
7473
7474 def generate_matrix_elements(self, group_processes=True):
7475 """Helper function to generate the matrix elements before
7476 exporting. Uses the main function argument 'group_processes' to decide
7477 whether to use group_subprocess or not. (it has been set in do_output to
7478 the appropriate value if the MG5 option 'group_subprocesses' was set
7479 to 'Auto'."""
7480
7481 if self._export_format in ['standalone_msP', 'standalone_msF', 'standalone_mw']:
7482 to_distinguish = []
7483 for part in self._curr_model.get('particles'):
7484 if part.get('name') in args and part.get('antiname') in args and\
7485 part.get('name') != part.get('antiname'):
7486 to_distinguish.append(abs(part.get('pdg_code')))
7487
7488
7489 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \
7490 a1.get_number_of_diagrams())
7491
7492 cpu_time1 = time.time()
7493 ndiags = 0
7494 if not self._curr_matrix_elements.get_matrix_elements():
7495 if group_processes:
7496 cpu_time1 = time.time()
7497 dc_amps = diagram_generation.DecayChainAmplitudeList(\
7498 [amp for amp in self._curr_amps if isinstance(amp, \
7499 diagram_generation.DecayChainAmplitude)])
7500 non_dc_amps = diagram_generation.AmplitudeList(\
7501 [amp for amp in self._curr_amps if not \
7502 isinstance(amp, \
7503 diagram_generation.DecayChainAmplitude)])
7504 subproc_groups = group_subprocs.SubProcessGroupList()
7505 matrix_elements_opts = {'optimized_output':
7506 self.options['loop_optimized_output']}
7507
7508 grouping_criteria = self._curr_exporter.grouped_mode
7509 if non_dc_amps:
7510 subproc_groups.extend(\
7511 group_subprocs.SubProcessGroup.group_amplitudes(\
7512 non_dc_amps,grouping_criteria,
7513 matrix_elements_opts=matrix_elements_opts))
7514
7515 if dc_amps:
7516 dc_subproc_group = \
7517 group_subprocs.DecayChainSubProcessGroup.\
7518 group_amplitudes(dc_amps, grouping_criteria,
7519 matrix_elements_opts=matrix_elements_opts)
7520 subproc_groups.extend(dc_subproc_group.\
7521 generate_helas_decay_chain_subproc_groups())
7522
7523 ndiags = sum([len(m.get('diagrams')) for m in \
7524 subproc_groups.get_matrix_elements()])
7525 self._curr_matrix_elements = subproc_groups
7526
7527 uid = 0
7528 for group in subproc_groups:
7529 uid += 1
7530 for me in group.get('matrix_elements'):
7531 me.get('processes')[0].set('uid', uid)
7532 else:
7533 mode = {}
7534 if self._export_format in [ 'standalone_msP' ,
7535 'standalone_msF', 'standalone_rw']:
7536 mode['mode'] = 'MadSpin'
7537
7538
7539 if isinstance(self._curr_amps[0],
7540 loop_diagram_generation.LoopAmplitude):
7541 mode['optimized_output']=self.options['loop_optimized_output']
7542 HelasMultiProcessClass = loop_helas_objects.LoopHelasProcess
7543 compute_loop_nc = True
7544 else:
7545 HelasMultiProcessClass = helas_objects.HelasMultiProcess
7546 compute_loop_nc = False
7547
7548 self._curr_matrix_elements = HelasMultiProcessClass(
7549 self._curr_amps, compute_loop_nc=compute_loop_nc,
7550 matrix_element_opts=mode)
7551
7552 ndiags = sum([len(me.get('diagrams')) for \
7553 me in self._curr_matrix_elements.\
7554 get_matrix_elements()])
7555
7556 uid = 0
7557 for me in self._curr_matrix_elements.get_matrix_elements()[:]:
7558 uid += 1
7559 me.get('processes')[0].set('uid', uid)
7560
7561 cpu_time2 = time.time()
7562
7563
7564 return ndiags, cpu_time2 - cpu_time1
7565
7566
7567
7568 ndiags, cpu_time = generate_matrix_elements(self,group_processes)
7569
7570 calls = 0
7571
7572 path = self._export_dir
7573
7574 cpu_time1 = time.time()
7575
7576
7577
7578
7579
7580 if self._export_format == 'madevent':
7581 path = pjoin(path, 'SubProcesses')
7582 calls += self._curr_exporter.export_processes(self._curr_matrix_elements,
7583 self._curr_helas_model)
7584
7585
7586 card_path = pjoin(path, os.path.pardir, 'SubProcesses', \
7587 'procdef_mg5.dat')
7588 if self._generate_info:
7589 self._curr_exporter.write_procdef_mg5(card_path,
7590 self._curr_model['name'],
7591 self._generate_info)
7592 try:
7593 cmd.Cmd.onecmd(self, 'history .')
7594 except Exception:
7595 misc.sprint('command history fails.', 10)
7596 pass
7597
7598
7599 elif self._export_format == 'pythia8':
7600
7601 process_names = []
7602 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
7603 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
7604 exporter = self._curr_exporter.generate_process_directory(\
7605 me_group.get('matrix_elements'), self._curr_helas_model,
7606 process_string = me_group.get('name'),
7607 process_number = group_number,
7608 version = version)
7609 process_names.append(exporter.process_name)
7610 else:
7611 exporter = self._curr_exporter.generate_process_directory(\
7612 self._curr_matrix_elements, self._curr_helas_model,
7613 process_string = self._generate_info, version = version)
7614 process_names.append(exporter.process_file_name)
7615
7616
7617 model_name, model_path = exporter.convert_model_to_pythia8(\
7618 self._curr_model, self._export_dir)
7619
7620
7621 filename, make_filename = \
7622 self._curr_exporter.generate_example_file_pythia8(path,
7623 model_path,
7624 process_names,
7625 exporter,
7626 main_file_name)
7627
7628
7629 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7630
7631 if self._export_format == 'matrix':
7632 for me in matrix_elements:
7633 filename = pjoin(path, 'matrix_' + \
7634 me.get('processes')[0].shell_string() + ".f")
7635 if os.path.isfile(filename):
7636 logger.warning("Overwriting existing file %s" % filename)
7637 else:
7638 logger.info("Creating new file %s" % filename)
7639 calls = calls + self._curr_exporter.write_matrix_element_v4(\
7640 writers.FortranWriter(filename),\
7641 me, self._curr_helas_model)
7642 elif self._export_format in ['madevent', 'pythia8']:
7643 pass
7644
7645 elif isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList) and\
7646 self._curr_exporter.grouped_mode:
7647 modify, self._curr_matrix_elements = self._curr_exporter.modify_grouping(self._curr_matrix_elements)
7648 if modify:
7649 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7650
7651 for me_number, me in enumerate(self._curr_matrix_elements):
7652 calls = calls + \
7653 self._curr_exporter.generate_subprocess_directory(\
7654 me, self._curr_helas_model, me_number)
7655
7656
7657 else:
7658 for nb,me in enumerate(matrix_elements[:]):
7659 new_calls = self._curr_exporter.generate_subprocess_directory(\
7660 me, self._curr_helas_model, nb)
7661 if isinstance(new_calls, int):
7662 if new_calls ==0:
7663 matrix_elements.remove(me)
7664 else:
7665 calls = calls + new_calls
7666
7667 cpu_time2 = time.time() - cpu_time1
7668
7669 logger.info(("Generated helas calls for %d subprocesses " + \
7670 "(%d diagrams) in %0.3f s") % \
7671 (len(matrix_elements),
7672 ndiags, cpu_time))
7673
7674 if calls:
7675 if "cpu_time2" in locals():
7676 logger.info("Wrote files for %d helas calls in %0.3f s" % \
7677 (calls, cpu_time2))
7678 else:
7679 logger.info("Wrote files for %d helas calls" % \
7680 (calls))
7681
7682 if self._export_format == 'pythia8':
7683 logger.info("- All necessary files for Pythia 8 generated.")
7684 logger.info("- Run \"launch\" and select %s.cc," % filename)
7685 logger.info(" or go to %s/examples and run" % path)
7686 logger.info(" make -f %s" % make_filename)
7687 logger.info(" (with process_name replaced by process name).")
7688 logger.info(" You can then run ./%s to produce events for the process" % \
7689 filename)
7690
7691
7692
7693
7694 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7695 self._curr_amps = diagram_generation.AmplitudeList(\
7696 [me.get('base_amplitude') for me in \
7697 matrix_elements])
7698
7699 - def finalize(self, nojpeg, online = False, flaglist=[]):
7700 """Make the html output, write proc_card_mg5.dat and create
7701 madevent.tar.gz for a MadEvent directory"""
7702
7703 compiler_dict = {'fortran': self.options['fortran_compiler'],
7704 'cpp': self.options['cpp_compiler'],
7705 'f2py': self.options['f2py_compiler']}
7706
7707
7708 if self._model_v4_path:
7709 logger.info('Copy %s model files to directory %s' % \
7710 (os.path.basename(self._model_v4_path), self._export_dir))
7711 self._curr_exporter.export_model_files(self._model_v4_path)
7712 self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS'))
7713 else:
7714
7715
7716
7717 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
7718 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
7719
7720
7721 if hasattr(self, 'previous_lorentz'):
7722 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz))
7723 wanted_couplings = list(set(self.previous_couplings + wanted_couplings))
7724 del self.previous_lorentz
7725 del self.previous_couplings
7726 if 'store_model' in flaglist:
7727 self.previous_lorentz = wanted_lorentz
7728 self.previous_couplings = wanted_couplings
7729 else:
7730 self._curr_exporter.convert_model(self._curr_model,
7731 wanted_lorentz,
7732 wanted_couplings)
7733
7734
7735 if nojpeg:
7736 flaglist.append('nojpeg')
7737 if online:
7738 flaglist.append('online')
7739
7740
7741
7742 if self._export_format in ['NLO']:
7743
7744
7745 filename = os.path.join(self._export_dir, 'Cards', 'amcatnlo_configuration.txt')
7746 opts_to_keep = ['lhapdf', 'fastjet', 'pythia8_path', 'hwpp_path', 'thepeg_path',
7747 'hepmc_path']
7748 to_keep = {}
7749 for opt in opts_to_keep:
7750 if self.options[opt]:
7751 to_keep[opt] = self.options[opt]
7752 self.do_save('options %s' % filename.replace(' ', '\ '), check=False, \
7753 to_keep = to_keep)
7754
7755 elif self._export_format in ['madevent', 'madweight']:
7756
7757 filename = os.path.join(self._export_dir, 'Cards', 'me5_configuration.txt')
7758 self.do_save('options %s' % filename.replace(' ', '\ '), check=False,
7759 to_keep={'mg5_path':MG5DIR})
7760
7761
7762 self._curr_exporter.finalize(self._curr_matrix_elements,
7763 self.history,
7764 self.options,
7765 flaglist)
7766
7767 if self._export_format in ['madevent', 'standalone', 'standalone_cpp','madweight', 'matchbox']:
7768 logger.info('Output to directory ' + self._export_dir + ' done.')
7769
7770 if self._export_format in ['madevent', 'NLO']:
7771 logger.info('Type \"launch\" to generate events from this process, or see')
7772 logger.info(self._export_dir + '/README')
7773 logger.info('Run \"open index.html\" to see more information about this process.')
7774
7776 """ propose some usefull possible action """
7777
7778 super(MadGraphCmd,self).do_help(line)
7779
7780 if line:
7781 return
7782
7783 if len(self.history) == 0:
7784 last_action_2 = 'mg5_start'
7785 last_action = 'mg5_start'
7786 else:
7787 args = self.history[-1].split()
7788 last_action = args[0]
7789 if len(args)>1:
7790 last_action_2 = '%s %s' % (last_action, args[1])
7791 else:
7792 last_action_2 = 'none'
7793
7794
7795
7796
7798 """Documented commands:Generate amplitudes for decay width calculation, with fixed
7799 number of final particles (called level)
7800 syntax; compute_widths particle [other particles] [--options=]
7801
7802 - particle/other particles can also be multiparticle name (can also be
7803 pid of the particle)
7804
7805 --body_decay=X [default=4.0025] allow to choose the precision.
7806 if X is an integer: compute all X body decay
7807 if X is a float <1: compute up to the time that total error < X
7808 if X is a float >1: stops at the first condition.
7809
7810 --path=X. Use a given file for the param_card. (default UFO built-in)
7811
7812 special argument:
7813 - skip_2body: allow to not consider those decay (use FR)
7814 - model: use the model pass in argument.
7815
7816 """
7817
7818
7819
7820 self.change_principal_cmd('MadGraph')
7821 if '--nlo' not in line:
7822 warning_text = """Please note that the automatic computation of the width is
7823 only valid in narrow-width approximation and at tree-level."""
7824 logger.warning(warning_text)
7825
7826 if not model:
7827 modelname = self._curr_model.get('modelpath+restriction')
7828 with misc.MuteLogger(['madgraph'], ['INFO']):
7829 model = import_ufo.import_model(modelname, decay=True)
7830 self._curr_model = model
7831
7832 if not isinstance(model, model_reader.ModelReader):
7833 model = model_reader.ModelReader(model)
7834
7835 if '--nlo' in line:
7836
7837 self.compute_widths_SMWidth(line, model=model)
7838 return
7839
7840
7841 particles, opts = self.check_compute_widths(self.split_arg(line))
7842
7843 if opts['path']:
7844 correct = True
7845 param_card = check_param_card.ParamCard(opts['path'])
7846 for param in param_card['decay']:
7847 if param.value == "auto":
7848 param.value = 1
7849 param.format = 'float'
7850 correct = False
7851 if not correct:
7852 if opts['output']:
7853 param_card.write(opts['output'])
7854 opts['path'] = opts['output']
7855 else:
7856 param_card.write(opts['path'])
7857
7858 data = model.set_parameters_and_couplings(opts['path'])
7859
7860
7861 if do2body:
7862 skip_2body = True
7863 decay_info = {}
7864 for pid in particles:
7865 particle = model.get_particle(pid)
7866 if not hasattr(particle, 'partial_widths'):
7867 skip_2body = False
7868 break
7869 elif not decay_info:
7870 logger_mg.info('Get two body decay from FeynRules formula')
7871 decay_info[pid] = []
7872 mass = abs(eval(str(particle.get('mass')), data).real)
7873 data = model.set_parameters_and_couplings(opts['path'], scale= mass)
7874 total = 0
7875
7876 for mode, expr in particle.partial_widths.items():
7877 tmp_mass = mass
7878 for p in mode:
7879 try:
7880 value_mass = eval(str(p.mass), data)
7881 except Exception:
7882
7883
7884 value_mass = eval(str(model.get_particle(p.pdg_code).get('mass')), data)
7885 tmp_mass -= abs(value_mass)
7886 if tmp_mass <=0:
7887 continue
7888
7889 decay_to = [p.get('pdg_code') for p in mode]
7890 value = eval(expr,{'cmath':cmath},data).real
7891 if -1e-10 < value < 0:
7892 value = 0
7893 if -1e-5 < value < 0:
7894 logger.warning('Partial width for %s > %s negative: %s automatically set to zero' %
7895 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value))
7896 value = 0
7897 elif value < 0:
7898 raise Exception, 'Partial width for %s > %s negative: %s' % \
7899 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value)
7900 elif 0 < value < 0.1 and particle['color'] !=1:
7901 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
7902 % (particle.get('name'), value, decay_to))
7903 value = 0
7904
7905 decay_info[particle.get('pdg_code')].append([decay_to, value])
7906 total += value
7907 else:
7908 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
7909 opts['path'], opts['output'])
7910 if float(opts['body_decay']) == 2:
7911 return
7912 else:
7913 skip_2body = True
7914
7915
7916
7917
7918 self.do_decay_diagram('%s %s' % (' '.join([`id` for id in particles]),
7919 ' '.join('--%s=%s' % (key,value)
7920 for key,value in opts.items()
7921 if key not in ['precision_channel'])
7922 ), skip_2body=skip_2body, model=decaymodel)
7923
7924 if self._curr_amps:
7925 logger.info('Pass to numerical integration for computing the widths:')
7926 else:
7927 logger.info('No need for N body-decay (N>2). Results are in %s' % opts['output'])
7928
7929
7930
7931 return
7932
7933
7934 with misc.TMP_directory(dir=os.getcwd()) as path:
7935 decay_dir = pjoin(path,'temp_decay')
7936 logger_mg.info('More info in temporary files:\n %s/index.html' % (decay_dir))
7937 with misc.MuteLogger(['madgraph','ALOHA','cmdprint','madevent'], [40,40,40,40]):
7938 self.exec_cmd('output %s -f' % decay_dir,child=False)
7939
7940 if os.path.exists(opts['output']):
7941 files.cp(opts['output'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
7942 else:
7943 files.cp(opts['path'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
7944 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
7945 check_param_card.convert_to_slha1(pjoin(decay_dir, 'Cards', 'param_card.dat'))
7946
7947 me_cmd = madevent_interface.MadEventCmd(decay_dir)
7948
7949 me_cmd.model_name = self._curr_model['name']
7950 me_cmd.options['automatic_html_opening'] = False
7951
7952 me_opts=[('accuracy', opts['precision_channel']),
7953 ('points', 1000),
7954 ('iterations',9)]
7955 me_cmd.exec_cmd('survey decay -f %s' % (
7956 " ".join(['--%s=%s' % val for val in me_opts])),
7957 postcmd=False)
7958 me_cmd.exec_cmd('combine_events', postcmd=False)
7959
7960 me_cmd.collect_decay_widths()
7961 me_cmd.do_quit('')
7962
7963 del me_cmd
7964
7965 param = check_param_card.ParamCard(pjoin(decay_dir, 'Events', 'decay','param_card.dat'))
7966
7967 for pid in particles:
7968 width = param['decay'].get((pid,)).value
7969 particle = self._curr_model.get_particle(pid)
7970
7971
7972
7973
7974
7975
7976 if not pid in param['decay'].decay_table:
7977 continue
7978 if pid not in decay_info:
7979 decay_info[pid] = []
7980 for BR in param['decay'].decay_table[pid]:
7981 if len(BR.lhacode) == 3 and skip_2body:
7982 continue
7983 if 0 < BR.value * width <0.1 and particle['color'] !=1:
7984 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
7985 % (particle.get('name'), BR.value * width, BR.lhacode[1:]))
7986
7987 continue
7988
7989 decay_info[pid].append([BR.lhacode[1:], BR.value * width])
7990
7991 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
7992 opts['path'], opts['output'])
7993
7994 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
7995 check_param_card.convert_to_slha1(opts['output'])
7996 return
7997
7998
7999
8000
8002 """Compute widths with SMWidth.
8003 """
8004
8005
8006 particles, opts = self.check_compute_widths(self.split_arg(line))
8007
8008 if opts['path']:
8009 correct = True
8010 param_card = check_param_card.ParamCard(opts['path'])
8011 for param in param_card['decay']:
8012 if param.value == "auto":
8013 param.value = 1
8014 param.format = 'float'
8015 correct = False
8016 if not correct:
8017 if opts['output']:
8018 param_card.write(opts['output'])
8019 opts['path'] = opts['output']
8020 else:
8021 param_card.write(opts['path'])
8022
8023 if not model:
8024 model_path = self._curr_model.get('modelpath')
8025 model_name = self._curr_model.get('name')
8026 currmodel = self._curr_model
8027 else:
8028 model_path = model.get('modelpath')
8029 model_name = model.get('name')
8030 currmodel = model
8031
8032 if not os.path.exists(pjoin(model_path, 'SMWidth')):
8033 raise self.InvalidCmd, "Model %s is not valid for computing NLO width with SMWidth"%model_name
8034
8035
8036 externparam = [(param.lhablock.lower(),param.name.lower()) for param \
8037 in currmodel.get('parameters')[('external',)]]
8038
8039 if ('sminputs','aewm1') in externparam:
8040
8041 arg2 = "1"
8042 elif ('sminputs','mdl_gf') in externparam or ('sminputs','gf') in externparam:
8043
8044 arg2 = "2"
8045 else:
8046 raise Exception, "Do not know the EW scheme in the model %s"%model_name
8047
8048
8049 if not os.path.exists(pjoin(model_path, 'SMWidth','smwidth')):
8050 logger.info('Compiling SMWidth. This has to be done only once and'+\
8051 ' can take a couple of minutes.','$MG:color:BLACK')
8052 current = misc.detect_current_compiler(pjoin(model_path, 'SMWidth',
8053 'makefile_MW5'))
8054 new = 'gfortran' if self.options_configuration['fortran_compiler'] is None else \
8055 self.options_configuration['fortran_compiler']
8056 if current != new:
8057 misc.mod_compilator(pjoin(model_path, 'SMWidth'), new, current)
8058 misc.mod_compilator(pjoin(model_path, 'SMWidth','oneloop'), new, current)
8059 misc.mod_compilator(pjoin(model_path, 'SMWidth','hdecay'), new, current)
8060 misc.compile(cwd=pjoin(model_path, 'SMWidth'))
8061
8062
8063 identpath=" "
8064 carddir=os.path.dirname(opts['path'])
8065 if 'ident_card.dat' in os.listdir(carddir):
8066 identpath=pjoin(carddir,'ident_card.dat')
8067
8068 output,error = misc.Popen(['./smwidth',opts['path'],identpath,arg2],
8069 stdout=subprocess.PIPE,
8070 stdin=subprocess.PIPE,
8071 cwd=pjoin(model_path, 'SMWidth')).communicate()
8072 pattern = re.compile(r''' decay\s+(\+?\-?\d+)\s+(\+?\-?\d+\.\d+E\+?\-?\d+)''',re.I)
8073 width_list = pattern.findall(output)
8074 width_dict = {}
8075 for pid,width in width_list:
8076 width_dict[int(pid)] = float(width)
8077
8078 for pid in particles:
8079 if not pid in width_dict:
8080 width = 0
8081 else:
8082 width = width_dict[pid]
8083 param = param_card['decay'].get((pid,))
8084 param.value = width
8085 param.format = 'float'
8086 if pid not in param_card['decay'].decay_table:
8087 continue
8088 del param_card['decay'].decay_table[pid]
8089
8090 if opts['output']:
8091 param_card.write(opts['output'])
8092 logger.info('Results are written in %s' % opts['output'])
8093 else:
8094 param_card.write(opts['path'])
8095 logger.info('Results are written in %s' % opts['path'])
8096 return
8097
8098
8100 """Not in help: Generate amplitudes for decay width calculation, with fixed
8101 number of final particles (called level)
8102 syntax; decay_diagram part_name level param_path
8103 args; part_name level param_path
8104 part_name = name of the particle you want to calculate width
8105 level = a.) when level is int,
8106 it means the max number of decay products
8107 b.) when level is float,
8108 it means the required precision for width.
8109 param_path = path for param_card
8110 (this is necessary to determine whether a channel is onshell or not)
8111 e.g. calculate width for higgs up to 2-body decays.
8112 calculate_width h 2 [path]
8113 N.B. param_card must be given so that the program knows which channel
8114 is on shell and which is not.
8115
8116 special argument:
8117 - skip_2body: allow to not consider those decay (use FR)
8118 - model: use the model pass in argument.
8119 """
8120
8121 if model:
8122 self._curr_decaymodel = model
8123
8124
8125 args = self.split_arg(line)
8126
8127 particles, args = self.check_decay_diagram(args)
8128
8129 pids = particles
8130 level = float(args['body_decay'])
8131 param_card_path = args['path']
8132 min_br = float(args['min_br'])
8133
8134
8135 self._curr_amps = diagram_generation.AmplitudeList()
8136 self._curr_proc_defs = base_objects.ProcessDefinitionList()
8137
8138 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
8139
8140 self._done_export = False
8141
8142 self._export_format = None
8143
8144
8145
8146 if not model:
8147 self._curr_decaymodel = decay_objects.DecayModel(self._curr_model,
8148 True)
8149 self._curr_decaymodel.read_param_card(param_card_path)
8150 else:
8151 self._curr_decaymodel = model
8152 model = self._curr_decaymodel
8153
8154 if isinstance(pids, int):
8155 pids = [pids]
8156
8157 first =True
8158 for part_nb,pid in enumerate(pids):
8159 part = self._curr_decaymodel.get_particle(pid)
8160 if part.get('width').lower() == 'zero':
8161 continue
8162 logger_mg.info('get decay diagram for %s' % part['name'])
8163
8164 if level // 1 == level and level >1:
8165 level = int(level)
8166 self._curr_decaymodel.find_channels(part, level, min_br)
8167 if not skip_2body:
8168 amp = part.get_amplitudes(2)
8169 if amp:
8170 self._curr_amps.extend(amp)
8171
8172 for l in range(3, level+1):
8173 amp = part.get_amplitudes(l)
8174 if amp:
8175 self._curr_amps.extend(amp)
8176 else:
8177 max_level = level // 1
8178 if max_level < 2:
8179 max_level = 999
8180 precision = level % 1
8181 if first:
8182 model.find_all_channels(2,generate_abstract=False)
8183 first = False
8184 if not skip_2body:
8185 amp = part.get_amplitudes(2)
8186 if amp:
8187 self._curr_amps.extend(amp)
8188 clevel = 2
8189 while part.get('apx_decaywidth_err').real > precision:
8190 clevel += 1
8191 if clevel > max_level:
8192 logger_mg.info(' stop to %s body-decay. approximate error: %s' %
8193 (max_level, part.get('apx_decaywidth_err')) )
8194 break
8195 if clevel > 3:
8196 logger_mg.info(' current estimated error: %s go to %s-body decay:' %\
8197 (part.get('apx_decaywidth_err'), clevel))
8198 part.find_channels_nextlevel(model, min_br)
8199
8200 amp = part.get_amplitudes(clevel)
8201 if amp:
8202 self._curr_amps.extend(amp)
8203 part.update_decay_attributes(False, True, True, model)
8204
8205
8206
8207 if len(self._curr_amps) > 0:
8208 process = self._curr_amps[0]['process'].nice_string()
8209
8210 self._generate_info = process[9:]
8211
8212 else:
8213 logger.info("No decay is found")
8214
8216 """Temporary parser"""
8217
8218
8219
8220
8221
8222 _draw_usage = "draw FILEPATH [options]\n" + \
8223 "-- draw the diagrams in eps format\n" + \
8224 " Files will be FILEPATH/diagrams_\"process_string\".eps \n" + \
8225 " Example: draw plot_dir . \n"
8226 _draw_parser = misc.OptionParser(usage=_draw_usage)
8227 _draw_parser.add_option("", "--horizontal", default=False,
8228 action='store_true', help="force S-channel to be horizontal")
8229 _draw_parser.add_option("", "--external", default=0, type='float',
8230 help="authorizes external particles to end at top or " + \
8231 "bottom of diagram. If bigger than zero this tune the " + \
8232 "length of those line.")
8233 _draw_parser.add_option("", "--max_size", default=1.5, type='float',
8234 help="this forbids external line bigger than max_size")
8235 _draw_parser.add_option("", "--non_propagating", default=True, \
8236 dest="contract_non_propagating", action='store_false',
8237 help="avoid contractions of non propagating lines")
8238 _draw_parser.add_option("", "--add_gap", default=0, type='float', \
8239 help="set the x-distance between external particles")
8240
8241
8242 _launch_usage = "launch [DIRPATH] [options]\n" + \
8243 "-- execute the madevent/standalone/standalone_cpp/pythia8/NLO output present in DIRPATH\n" + \
8244 " By default DIRPATH is the latest created directory \n" + \
8245 " (for pythia8, it should be the Pythia 8 main directory) \n" + \
8246 " Example: launch PROC_sm_1 --name=run2 \n" + \
8247 " Example: launch ../pythia8 \n"
8248 _launch_parser = misc.OptionParser(usage=_launch_usage)
8249 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
8250 help="Use the card present in the directory in order to launch the different program")
8251 _launch_parser.add_option("-n", "--name", default='', type='str',
8252 help="Provide a name to the run (for madevent run)")
8253 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
8254 help="submit the job on the cluster")
8255 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
8256 help="submit the job on multicore core")
8257
8258 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
8259 help="Use Interactive Console [if available]")
8260 _launch_parser.add_option("-s", "--laststep", default='',
8261 help="last program run in MadEvent run. [auto|parton|pythia|pgs|delphes]")
8262 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true',
8263 help="Run the reweight module (reweighting by different model parameter")
8264 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true',
8265 help="Run the madspin package")
8271 """A class for asking a question where in addition you can have the
8272 set command define and modifying the param_card/run_card correctly"""
8273
8274 - def __init__(self, question, allow_arg=[], default=None,
8275 mother_interface=None, *arg, **opt):
8276
8277 model_path = mother_interface._curr_model.get('modelpath')
8278
8279 ufo_model = ufomodels.load_model(model_path)
8280 self.all_categories = ufo_model.build_restrict.all_categories
8281
8282 question = self.get_question()
8283
8284
8285 allow_arg = ['0']
8286 self.name2options = {}
8287 for category in self.all_categories:
8288 for options in category:
8289 if not options.first:
8290 continue
8291 self.name2options[str(len(allow_arg))] = options
8292 self.name2options[options.name.replace(' ','')] = options
8293 allow_arg.append(len(allow_arg))
8294 allow_arg.append('done')
8295
8296 cmd.SmartQuestion.__init__(self, question, allow_arg, default, mother_interface)
8297
8298
8299
8301 """Default action if line is not recognized"""
8302
8303 line = line.strip()
8304 args = line.split()
8305 if line == '' and self.default_value is not None:
8306 self.value = self.default_value
8307
8308 elif hasattr(self, 'do_%s' % args[0]):
8309 self.do_set(' '.join(args[1:]))
8310 elif line.strip() != '0' and line.strip() != 'done' and \
8311 str(line) != 'EOF' and line.strip() in self.allow_arg:
8312 option = self.name2options[line.strip()]
8313 option.status = not option.status
8314 self.value = 'repeat'
8315 else:
8316 self.value = line
8317
8318 return self.all_categories
8319
8320 - def reask(self, reprint_opt=True):
8325
8327 """ """
8328 self.value = 'repeat'
8329
8330 args = line.split()
8331 if args[0] not in self.name2options:
8332 logger.warning('Invalid set command. %s not recognize options. Valid options are: \n %s' %
8333 (args[0], ', '.join(self.name2options.keys()) ))
8334 return
8335 elif len(args) != 2:
8336 logger.warning('Invalid set command. Not correct number of argument')
8337 return
8338
8339
8340 if args[1] in ['True','1','.true.','T',1,True,'true','TRUE']:
8341 self.name2options[args[0]].status = True
8342 elif args[1] in ['False','0','.false.','F',0,False,'false','FALSE']:
8343 self.name2options[args[0]].status = False
8344 else:
8345 logger.warning('%s is not True/False. Didn\'t do anything.' % args[1])
8346
8347
8348
8350 """define the current question."""
8351 question = ''
8352 i=0
8353 for category in self.all_categories:
8354 question += category.name + ':\n'
8355 for options in category:
8356 if not options.first:
8357 continue
8358 i+=1
8359 question += ' %s: %s [%s]\n' % (i, options.name,
8360 options.display(options.status))
8361 question += 'Enter a number to change it\'s status or press enter to validate.\n'
8362 question += 'For scripting this function, please type: \'help\''
8363 return question
8364
8365
8367 """ Complete the set command"""
8368 signal.alarm(0)
8369 args = self.split_arg(line[0:begidx])
8370
8371 if len(args) == 1:
8372 possibilities = [x for x in self.name2options if not x.isdigit()]
8373 return self.list_completion(text, possibilities, line)
8374 else:
8375 return self.list_completion(text,['True', 'False'], line)
8376
8377
8379 '''help message'''
8380
8381 print 'This allows you to optimize your model to your needs.'
8382 print 'Enter the number associate to the possible restriction/add-on'
8383 print ' to change the status of this restriction/add-on.'
8384 print ''
8385 print 'In order to allow scripting of this function you can use the '
8386 print 'function \'set\'. This function takes two argument:'
8387 print 'set NAME VALUE'
8388 print ' NAME is the description of the option where you remove all spaces'
8389 print ' VALUE is either True or False'
8390 print ' Example: For the question'
8391 print ''' sm customization:
8392 1: diagonal ckm [True]
8393 2: c mass = 0 [True]
8394 3: b mass = 0 [False]
8395 4: tau mass = 0 [False]
8396 5: muon mass = 0 [True]
8397 6: electron mass = 0 [True]
8398 Enter a number to change it's status or press enter to validate.'''
8399 print ''' you can answer by'''
8400 print ' set diagonalckm False'
8401 print ' set taumass=0 True'
8402
8406
8407
8408
8409
8410
8411
8412
8413 if __name__ == '__main__':
8414
8415 run_option = sys.argv
8416 if len(run_option) > 1:
8417
8418 input_file = open(run_option[1], 'rU')
8419 cmd_line = MadGraphCmd(stdin=input_file)
8420 cmd_line.use_rawinput = False
8421 cmd_line.cmdloop()
8422 else:
8423
8424 MadGraphCmd().cmdloop()
8425