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