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