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