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