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