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