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