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