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