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+'^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
2455
2456 all_name = [name+' ' for name in all_name if name.startswith(text)
2457 and name.strip() != text]
2458
2459
2460 if all_name:
2461 completion_categories['Restricted model'] = all_name
2462
2463
2464 if os.path.sep in args[-1]:
2465 if mode.startswith('model') or mode == 'all':
2466
2467 try:
2468 cur_path = pjoin(*[a for a in args \
2469 if a.endswith(os.path.sep)])
2470 except Exception:
2471 pass
2472 else:
2473 all_dir = self.path_completion(text, cur_path, only_dirs = True)
2474 if mode in ['model_v4','all']:
2475 completion_categories['Path Completion'] = all_dir
2476
2477 new = []
2478 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2479 for name in all_dir]
2480 if data:
2481 completion_categories['Path Completion'] = all_dir + new
2482 else:
2483 try:
2484 cur_path = pjoin(*[a for a in args \
2485 if a.endswith(os.path.sep)])
2486 except Exception:
2487 pass
2488 else:
2489 all_path = self.path_completion(text, cur_path)
2490 if mode == 'all':
2491 new = []
2492 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2493 for name in all_path]
2494 if data:
2495 completion_categories['Path Completion'] = data[0]
2496 else:
2497 completion_categories['Path Completion'] = all_path
2498
2499
2500 if (len(args) == 2):
2501 is_model = True
2502 if mode == 'model':
2503 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py'))
2504 mod_name = lambda name: name
2505 elif mode == 'model_v4':
2506 file_cond = lambda p : (os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat'))
2507 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat')))
2508 mod_name = lambda name :(name[-3:] != '_v4' and name or name[:-3])
2509 elif mode == 'all':
2510 mod_name = lambda name: name
2511 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py')) \
2512 or os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat')) \
2513 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat'))
2514 else:
2515 cur_path = pjoin(*[a for a in args \
2516 if a.endswith(os.path.sep)])
2517 all_path = self.path_completion(text, cur_path)
2518 completion_categories['model name'] = all_path
2519 is_model = False
2520
2521 if is_model:
2522 model_list = [mod_name(name) for name in \
2523 self.path_completion(text,
2524 pjoin(MG5DIR,'models'),
2525 only_dirs = True) \
2526 if file_cond(name)]
2527
2528 if mode == 'model_v4':
2529 completion_categories['model name'] = model_list
2530 elif allow_restrict:
2531
2532 all_name = []
2533 for model_name in model_list:
2534 all_name += self.find_restrict_card(model_name,
2535 base_dir=pjoin(MG5DIR,'models'))
2536 else:
2537 all_name = model_list
2538
2539 if mode == 'all':
2540 cur_path = pjoin(*[a for a in args \
2541 if a.endswith(os.path.sep)])
2542 all_path = self.path_completion(text, cur_path)
2543 completion_categories['model name'] = all_path + all_name
2544 elif mode == 'model':
2545 completion_categories['model name'] = all_name
2546
2547
2548 if mode == 'all' and len(args)>1:
2549 mode = self.find_import_type(args[2])
2550
2551 if len(args) >= 3 and mode.startswith('model') and not '-modelname' in line:
2552 if not text and not completion_categories:
2553 return ['--modelname']
2554 elif not (os.path.sep in args[-1] and line[-1] != ' '):
2555 completion_categories['options'] = self.list_completion(text, ['--modelname','-modelname','--noprefix'])
2556 if len(args) >= 3 and mode.startswith('banner') and not '--no_launch' in line:
2557 completion_categories['options'] = self.list_completion(text, ['--no_launch'])
2558
2559 if treat_completion:
2560 return self.deal_multiple_categories(completion_categories)
2561 else:
2562
2563 return completion_categories
2564
2565
2567 """find the restriction file associate to a given model"""
2568
2569
2570 if no_restrict:
2571 output = [model_name]
2572 else:
2573 output = []
2574
2575
2576 if not os.path.exists(pjoin(base_dir, model_name, 'couplings.py')):
2577
2578 return output
2579
2580 if model_name.endswith(os.path.sep):
2581 model_name = model_name[:-1]
2582
2583
2584 if os.path.exists(pjoin(base_dir, model_name, 'restrict_default.dat')):
2585 output.append('%s-full' % model_name)
2586
2587
2588 for name in os.listdir(pjoin(base_dir, model_name)):
2589 if name.startswith('restrict_') and not name.endswith('default.dat') \
2590 and name.endswith('.dat'):
2591 tag = name[9:-4]
2592 while model_name.endswith(os.path.sep):
2593 model_name = model_name[:-1]
2594 output.append('%s-%s' % (model_name, tag))
2595
2596
2597 return output
2598
2609
2610
2611
2612
2613 -class MadGraphCmd(HelpToCmd, CheckValidForCmd, CompleteForCmd, CmdExtended):
2614 """The command line processor of MadGraph"""
2615
2616 writing_dir = '.'
2617
2618
2619 _display_opts = ['particles', 'interactions', 'processes', 'diagrams',
2620 'diagrams_text', 'multiparticles', 'couplings', 'lorentz',
2621 'checks', 'parameters', 'options', 'coupling_order','variable']
2622 _add_opts = ['process', 'model']
2623 _save_opts = ['model', 'processes', 'options']
2624 _tutorial_opts = ['aMCatNLO', 'stop', 'MadLoop', 'MadGraph5']
2625 _switch_opts = ['mg5','aMC@NLO','ML5']
2626 _check_opts = ['full', 'timing', 'stability', 'profile', 'permutation',
2627 'gauge','lorentz', 'brs', 'cms']
2628 _import_formats = ['model_v4', 'model', 'proc_v4', 'command', 'banner']
2629 _install_opts = ['pythia-pgs', 'Delphes', 'MadAnalysis', 'ExRootAnalysis',
2630 'update', 'Delphes2', 'SysCalc', 'Golem95', 'PJFry',
2631 'QCDLoop']
2632
2633 _advanced_install_opts = ['ninja']
2634
2635
2636
2637
2638 _install_opts.extend(_advanced_install_opts)
2639
2640 _v4_export_formats = ['madevent', 'standalone', 'standalone_msP','standalone_msF',
2641 'matrix', 'standalone_rw', 'madweight']
2642 _export_formats = _v4_export_formats + ['standalone_cpp', 'pythia8', 'aloha',
2643 'matchbox_cpp', 'matchbox']
2644 _set_options = ['group_subprocesses',
2645 'ignore_six_quark_processes',
2646 'stdout_level',
2647 'fortran_compiler',
2648 'cpp_compiler',
2649 'loop_optimized_output',
2650 'complex_mass_scheme',
2651 'gauge',
2652 'EWscheme',
2653 'max_npoint_for_channel']
2654 _valid_nlo_modes = ['all','real','virt','sqrvirt','tree','noborn','LOonly']
2655 _valid_sqso_types = ['==','<=','=','>']
2656 _valid_amp_so_types = ['=','<=', '==', '>']
2657 _OLP_supported = ['MadLoop', 'GoSam']
2658 _output_dependencies_supported = ['external', 'internal','environment_paths']
2659
2660
2661
2662 options_configuration = {'pythia8_path': './pythia8',
2663 'hwpp_path': './herwigPP',
2664 'thepeg_path': './thepeg',
2665 'hepmc_path': './hepmc',
2666 'madanalysis_path': './MadAnalysis',
2667 'pythia-pgs_path':'./pythia-pgs',
2668 'td_path':'./td',
2669 'delphes_path':'./Delphes',
2670 'exrootanalysis_path':'./ExRootAnalysis',
2671 'syscalc_path': './SysCalc',
2672 'timeout': 60,
2673 'web_browser':None,
2674 'eps_viewer':None,
2675 'text_editor':None,
2676 'fortran_compiler':None,
2677 'f2py_compiler':None,
2678 'cpp_compiler':None,
2679 'auto_update':7,
2680 'cluster_type': 'condor',
2681 'cluster_queue': None,
2682 'cluster_status_update': (600, 30),
2683 'fastjet':'fastjet-config',
2684 'pjfry':'auto',
2685 'golem':'auto',
2686 'samurai':None,
2687 'ninja':'./HEPTools/lib',
2688 'lhapdf':'lhapdf-config',
2689 'applgrid':'applgrid-config',
2690 'amcfast':'amcfast-config',
2691 'cluster_temp_path':None,
2692 'cluster_local_path': None,
2693
2694 'OLP': 'MadLoop',
2695 'cluster_nb_retry':1,
2696 'cluster_retry_wait':300,
2697 'cluster_size':100,
2698 'output_dependencies':'external'
2699 }
2700
2701 options_madgraph= {'group_subprocesses': 'Auto',
2702 'ignore_six_quark_processes': False,
2703 'low_mem_multicore_nlo_generation': False,
2704 'complex_mass_scheme': False,
2705 'gauge':'unitary',
2706 'stdout_level':None,
2707 'loop_optimized_output':True,
2708 'loop_color_flows':False,
2709 'max_npoint_for_channel': 0
2710 }
2711
2712 options_madevent = {'automatic_html_opening':True,
2713 'run_mode':2,
2714 'nb_core': None,
2715 'notification_center': True
2716 }
2717
2718
2719
2720 _curr_model = None
2721 _curr_amps = diagram_generation.AmplitudeList()
2722 _curr_matrix_elements = helas_objects.HelasMultiProcess()
2723 _curr_fortran_model = None
2724 _curr_cpp_model = None
2725 _curr_exporter = None
2726 _done_export = False
2727 _curr_decaymodel = None
2728
2729 helporder = ['Main commands', 'Documented commands']
2730
2731
2745
2746
2747 - def __init__(self, mgme_dir = '', *completekey, **stdin):
2748 """ add a tracker of the history """
2749
2750 CmdExtended.__init__(self, *completekey, **stdin)
2751
2752
2753 if mgme_dir:
2754 if os.path.isdir(pjoin(mgme_dir, 'Template')):
2755 self._mgme_dir = mgme_dir
2756 logger.info('Setting MG/ME directory to %s' % mgme_dir)
2757 else:
2758 logger.warning('Warning: Directory %s not valid MG/ME directory' % \
2759 mgme_dir)
2760 self._mgme_dir = MG4DIR
2761
2762
2763 self._multiparticles = {}
2764 self.options = {}
2765 self._generate_info = ""
2766 self._model_v4_path = None
2767 self._export_dir = None
2768 self._export_format = 'madevent'
2769 self._mgme_dir = MG4DIR
2770 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
2771 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
2772 self._comparisons = None
2773 self._cms_checks = []
2774 self._nlo_modes_for_completion = ['all','virt','real','LOonly']
2775
2776
2777 self.set_configuration()
2778
2797
2811
2812
2813
2815 """Generate an amplitude for a given process and add to
2816 existing amplitudes
2817 or merge two model
2818 """
2819
2820 args = self.split_arg(line)
2821
2822
2823 warning_duplicate = True
2824 if '--no_warning=duplicate' in args:
2825 warning_duplicate = False
2826 args.remove('--no_warning=duplicate')
2827
2828
2829 self.check_add(args)
2830
2831 if args[0] == 'model':
2832 return self.add_model(args[1:])
2833
2834
2835
2836 if args[-1].startswith('--optimize'):
2837 optimize = True
2838 args.pop()
2839 else:
2840 optimize = False
2841
2842 if args[0] == 'process':
2843
2844 line = ' '.join(args[1:])
2845
2846
2847 if not self._generate_info:
2848 self._generate_info = line
2849
2850
2851 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2852
2853
2854 if ',' in line:
2855 if ']' in line or '[' in line:
2856 error_msg=\
2857 """The '[' and ']' syntax cannot be used in cunjunction with decay chains.
2858 This implies that with decay chains:
2859 > Squared coupling order limitations are not available.
2860 > Loop corrections cannot be considered."""
2861 raise MadGraph5Error(error_msg)
2862 else:
2863 nb_proc = len([l for l in self.history if l.startswith(('generate','add process'))])
2864 myprocdef, line = self.extract_decay_chain_process(line, proc_number=nb_proc)
2865
2866
2867
2868 if myprocdef.are_decays_perturbed():
2869 raise MadGraph5Error("Decay processes cannot be perturbed.")
2870
2871
2872
2873 if myprocdef.decays_have_squared_orders() or \
2874 myprocdef['squared_orders']!={}:
2875 raise MadGraph5Error("Decay processes cannot specify "+\
2876 "squared orders constraints.")
2877 if myprocdef.are_negative_orders_present():
2878 raise MadGraph5Error("Decay processes cannot include negative"+\
2879 " coupling orders constraints.")
2880 else:
2881 nb_proc = len([l for l in self.history if l.startswith(('generate','add process'))])
2882 myprocdef = self.extract_process(line, proc_number=nb_proc)
2883
2884
2885
2886
2887 if not myprocdef:
2888 raise self.InvalidCmd("Empty or wrong format process, please try again.")
2889
2890
2891 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
2892 myprocdef.get_ninitial():
2893 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
2894
2895
2896
2897 if len([1 for val in myprocdef.get('orders').values()+\
2898 myprocdef.get('squared_orders').values() if val<0])>1:
2899 raise MadGraph5Error("Negative coupling order constraints"+\
2900 " can only be given on one type of coupling and either on"+\
2901 " squared orders or amplitude orders, not both.")
2902
2903 cpu_time1 = time.time()
2904
2905
2906 if self.options['group_subprocesses'] == 'Auto':
2907 collect_mirror_procs = True
2908 else:
2909 collect_mirror_procs = self.options['group_subprocesses']
2910 ignore_six_quark_processes = \
2911 self.options['ignore_six_quark_processes'] if \
2912 "ignore_six_quark_processes" in self.options \
2913 else []
2914
2915 myproc = diagram_generation.MultiProcess(myprocdef,
2916 collect_mirror_procs = collect_mirror_procs,
2917 ignore_six_quark_processes = ignore_six_quark_processes,
2918 optimize=optimize)
2919
2920
2921 for amp in myproc.get('amplitudes'):
2922 if amp not in self._curr_amps:
2923 self._curr_amps.append(amp)
2924 elif warning_duplicate:
2925 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
2926 amp.nice_string_processes()
2927
2928
2929 self._done_export = False
2930
2931 cpu_time2 = time.time()
2932
2933 nprocs = len(myproc.get('amplitudes'))
2934 ndiags = sum([amp.get_number_of_diagrams() for \
2935 amp in myproc.get('amplitudes')])
2936
2937 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
2938 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
2939 ndiags = sum([amp.get_number_of_diagrams() for \
2940 amp in self._curr_amps])
2941 logger.info("Total: %i processes with %i diagrams" % \
2942 (len(self._curr_amps), ndiags))
2943
2945 """merge two model"""
2946
2947 model_path = args[0]
2948 recreate = ('--recreate' in args)
2949 output_dir = [a.split('=',1)[1] for a in args if a.startswith('--output')]
2950 if output_dir:
2951 output_dir = output_dir[0]
2952 recreate = True
2953 restrict_name = ''
2954 else:
2955 name = os.path.basename(self._curr_model.get('modelpath'))
2956 restrict_name = self._curr_model.get('restrict_name')
2957 output_dir = pjoin(MG5DIR, 'models', '%s__%s' % (name,
2958 os.path.basename(model_path)))
2959
2960 if os.path.exists(output_dir):
2961 if recreate:
2962 shutil.rmtree(output_dir)
2963 else:
2964 logger.info('Model already created! Loading it from %s' % output_dir)
2965 oldmodel = self._curr_model.get('modelpath')
2966 new_model_name = output_dir
2967 if restrict_name:
2968 new_model_name = '%s-%s' % (output_dir, restrict_name)
2969 try:
2970 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
2971 printcmd=False, precmd=True, postcmd=True)
2972 except Exception, error:
2973 logger.debug('fail to load model %s with error:\n %s' % (output_dir, error))
2974 logger.warning('Fail to load the model. Restore previous model')
2975 self.exec_cmd('import model %s' % oldmodel, errorhandling=False,
2976 printcmd=False, precmd=True, postcmd=True)
2977 raise Exception('Invalid Model! Please retry with the option \'--recreate\'.')
2978 else:
2979 return
2980
2981
2982 import models.usermod as usermod
2983 base_model = usermod.UFOModel(self._curr_model.get('modelpath'))
2984
2985 identify = dict(tuple(a.split('=')) for a in args if '=' in a)
2986 base_model.add_model(path=model_path, identify_particles=identify)
2987 base_model.write(output_dir)
2988
2989 new_model_name = output_dir
2990 if restrict_name:
2991 new_model_name = '%s-%s' % (output_dir, restrict_name)
2992
2993 if 'modelname' in self.history.get('full_model_line'):
2994 opts = '--modelname'
2995 else:
2996 opts=''
2997 self.exec_cmd('import model %s %s' % (new_model_name, opts), errorhandling=False,
2998 printcmd=False, precmd=True, postcmd=True)
2999
3000
3001
3039
3040
3042 """Display current internal status"""
3043
3044 args = self.split_arg(line)
3045
3046 self.check_display(args)
3047
3048 if args[0] == 'diagrams':
3049 self.draw(' '.join(args[1:]))
3050
3051 if args[0] == 'particles' and len(args) == 1:
3052 propagating_particle = []
3053 nb_unpropagating = 0
3054 for particle in self._curr_model['particles']:
3055 if particle.get('propagating'):
3056 propagating_particle.append(particle)
3057 else:
3058 nb_unpropagating += 1
3059
3060 print "Current model contains %i particles:" % \
3061 len(propagating_particle)
3062 part_antipart = [part for part in propagating_particle \
3063 if not part['self_antipart']]
3064 part_self = [part for part in propagating_particle \
3065 if part['self_antipart']]
3066 for part in part_antipart:
3067 print part['name'] + '/' + part['antiname'],
3068 print ''
3069 for part in part_self:
3070 print part['name'],
3071 print ''
3072 if nb_unpropagating:
3073 print 'In addition of %s un-physical particle mediating new interactions.' \
3074 % nb_unpropagating
3075
3076 elif args[0] == 'particles':
3077 for arg in args[1:]:
3078 if arg.isdigit() or (arg[0] == '-' and arg[1:].isdigit()):
3079 particle = self._curr_model.get_particle(abs(int(arg)))
3080 else:
3081 particle = self._curr_model['particles'].find_name(arg)
3082 if not particle:
3083 raise self.InvalidCmd, 'no particle %s in current model' % arg
3084
3085 print "Particle %s has the following properties:" % particle.get_name()
3086 print str(particle)
3087
3088 elif args[0] == 'interactions' and len(args) == 1:
3089 text = "Current model contains %i interactions\n" % \
3090 len(self._curr_model['interactions'])
3091 for i, inter in enumerate(self._curr_model['interactions']):
3092 text += str(i+1) + ':'
3093 for part in inter['particles']:
3094 if part['is_part']:
3095 text += part['name']
3096 else:
3097 text += part['antiname']
3098 text += " "
3099 text += " ".join(order + '=' + str(inter['orders'][order]) \
3100 for order in inter['orders'])
3101 text += '\n'
3102 pydoc.pager(text)
3103
3104 elif args[0] == 'interactions' and len(args)==2 and args[1].isdigit():
3105 for arg in args[1:]:
3106 if int(arg) > len(self._curr_model['interactions']):
3107 raise self.InvalidCmd, 'no interaction %s in current model' % arg
3108 if int(arg) == 0:
3109 print 'Special interactions which identify two particles'
3110 else:
3111 print "Interactions %s has the following property:" % arg
3112 print self._curr_model['interactions'][int(arg)-1]
3113
3114 elif args[0] == 'interactions':
3115 request_part = args[1:]
3116 text = ''
3117 for i, inter in enumerate(self._curr_model['interactions']):
3118 present_part = [part['is_part'] and part['name'] or part['antiname']
3119 for part in inter['particles']
3120 if (part['is_part'] and part['name'] in request_part) or
3121 (not part['is_part'] and part['antiname'] in request_part)]
3122 if len(present_part) < len(request_part):
3123 continue
3124
3125 if set(present_part) != set(request_part):
3126 continue
3127
3128 if len(request_part) > len(set(request_part)):
3129 for p in request_part:
3130 if request_part.count(p) > present_part.count(p):
3131 continue
3132
3133 name = str(i+1) + ' : '
3134 for part in inter['particles']:
3135 if part['is_part']:
3136 name += part['name']
3137 else:
3138 name += part['antiname']
3139 name += " "
3140 text += "\nInteractions %s has the following property:\n" % name
3141 text += str(self._curr_model['interactions'][i])
3142
3143 text += '\n'
3144 print name
3145 if text =='':
3146 text += 'No matching for any interactions'
3147 pydoc.pager(text)
3148
3149
3150 elif args[0] == 'parameters' and len(args) == 1:
3151 text = "Current model contains %i parameters\n" % \
3152 sum([len(part) for part in
3153 self._curr_model['parameters'].values()])
3154 keys = self._curr_model['parameters'].keys()
3155 def key_sort(x, y):
3156 if ('external',) == x:
3157 return -1
3158 elif ('external',) == y:
3159 return +1
3160 elif len(x) < len(y):
3161 return -1
3162 else:
3163 return 1
3164 keys.sort(key_sort)
3165 for key in keys:
3166 item = self._curr_model['parameters'][key]
3167 text += '\nparameter type: %s\n' % str(key)
3168 for value in item:
3169 if hasattr(value, 'expr'):
3170 if value.value is not None:
3171 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3172 else:
3173 text+= ' %s = %s\n' % (value.name, value.expr)
3174 else:
3175 if value.value is not None:
3176 text+= ' %s = %s\n' % (value.name, value.value)
3177 else:
3178 text+= ' %s \n' % (value.name)
3179 pydoc.pager(text)
3180
3181 elif args[0] == 'processes':
3182 for amp in self._curr_amps:
3183 print amp.nice_string_processes()
3184
3185 elif args[0] == 'diagrams_text':
3186 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
3187 pydoc.pager(text)
3188
3189 elif args[0] == 'multiparticles':
3190 print 'Multiparticle labels:'
3191 for key in self._multiparticles:
3192 print self.multiparticle_string(key)
3193
3194 elif args[0] == 'coupling_order':
3195 hierarchy = self._curr_model['order_hierarchy'].items()
3196
3197 def order(first, second):
3198 if first[1] < second[1]:
3199 return -1
3200 else:
3201 return 1
3202 hierarchy.sort(order)
3203 for order in hierarchy:
3204 print ' %s : weight = %s' % order
3205
3206 elif args[0] == 'couplings' and len(args) == 1:
3207 if self._model_v4_path:
3208 print 'No couplings information available in V4 model'
3209 return
3210 text = ''
3211 text = "Current model contains %i couplings\n" % \
3212 sum([len(part) for part in
3213 self._curr_model['couplings'].values()])
3214 keys = self._curr_model['couplings'].keys()
3215 def key_sort(x, y):
3216 if ('external',) == x:
3217 return -1
3218 elif ('external',) == y:
3219 return +1
3220 elif len(x) < len(y):
3221 return -1
3222 else:
3223 return 1
3224 keys.sort(key_sort)
3225 for key in keys:
3226 item = self._curr_model['couplings'][key]
3227 text += '\ncouplings type: %s\n' % str(key)
3228 for value in item:
3229 if value.value is not None:
3230 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3231 else:
3232 text+= ' %s = %s\n' % (value.name, value.expr)
3233
3234 pydoc.pager(text)
3235
3236 elif args[0] == 'couplings':
3237 if self._model_v4_path:
3238 print 'No couplings information available in V4 model'
3239 return
3240
3241 try:
3242 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3243 print 'Note that this is the UFO informations.'
3244 print ' "display couplings" present the actual definition'
3245 print 'prints the current states of mode'
3246 print eval('ufomodel.couplings.%s.nice_string()'%args[1])
3247 except Exception:
3248 raise self.InvalidCmd, 'no couplings %s in current model' % args[1]
3249
3250 elif args[0] == 'lorentz':
3251 if self._model_v4_path:
3252 print 'No lorentz information available in V4 model'
3253 return
3254 elif len(args) == 1:
3255 raise self.InvalidCmd,\
3256 'display lorentz require an argument: the name of the lorentz structure.'
3257 return
3258 try:
3259 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3260 print eval('ufomodel.lorentz.%s.nice_string()'%args[1])
3261 except Exception:
3262 raise self.InvalidCmd, 'no lorentz %s in current model' % args[1]
3263
3264 elif args[0] == 'checks':
3265 outstr = ''
3266 if self._comparisons:
3267 comparisons = self._comparisons[0]
3268 if len(args) > 1 and args[1] == 'failed':
3269 comparisons = [c for c in comparisons if not c['passed']]
3270 outstr += "Process check results:"
3271 for comp in comparisons:
3272 outstr += "\n%s:" % comp['process'].nice_string()
3273 outstr += "\n Phase space point: (px py pz E)"
3274 for i, p in enumerate(comp['momenta']):
3275 outstr += "\n%2s %+.9e %+.9e %+.9e %+.9e" % tuple([i] + p)
3276 outstr += "\n Permutation values:"
3277 outstr += "\n " + str(comp['values'])
3278 if comp['passed']:
3279 outstr += "\n Process passed (rel. difference %.9e)" % \
3280 comp['difference']
3281 else:
3282 outstr += "\n Process failed (rel. difference %.9e)" % \
3283 comp['difference']
3284
3285 used_aloha = sorted(self._comparisons[1])
3286 if used_aloha:
3287 outstr += "\nChecked ALOHA routines:"
3288 for aloha in used_aloha:
3289 aloha_str = aloha[0]
3290 if aloha[1]:
3291 aloha_str += 'C' + 'C'.join([str(ia) for ia in aloha[1]])
3292 aloha_str += "_%d" % aloha[2]
3293 outstr += "\n" + aloha_str
3294
3295 outstr += '\n'
3296 for cms_check in self._cms_checks:
3297 outstr += '*'*102+'\n'
3298 outstr += 'Complex Mass Scheme check:\n'
3299 outstr += ' -> check %s\n'%cms_check['line']
3300 outstr += '*'*102+'\n'
3301 tmp_options = copy.copy(cms_check['options'])
3302 tmp_options['show_plot']=False
3303 outstr += process_checks.output_complex_mass_scheme(
3304 cms_check['cms_result'], cms_check['output_path'],
3305 tmp_options, self._curr_model) + '\n'
3306 outstr += '*'*102+'\n\n'
3307 pydoc.pager(outstr)
3308
3309 elif args[0] == 'options':
3310 if len(args) == 1:
3311 to_print = lambda name: True
3312 else:
3313 to_print = lambda name: any(poss in name for poss in args[1:])
3314
3315 outstr = " MadGraph5_aMC@NLO Options \n"
3316 outstr += " ---------------- \n"
3317 keys = self.options_madgraph.keys()
3318 keys.sort()
3319 for key in keys:
3320 if not to_print(key):
3321 continue
3322 default = self.options_madgraph[key]
3323 value = self.options[key]
3324 if value == default:
3325 outstr += " %25s \t:\t%s\n" % (key,value)
3326 else:
3327 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3328 outstr += "\n"
3329 outstr += " MadEvent Options \n"
3330 outstr += " ---------------- \n"
3331 keys = self.options_madevent.keys()
3332 keys.sort()
3333 for key in keys:
3334 if not to_print(key):
3335 continue
3336 default = self.options_madevent[key]
3337 value = self.options[key]
3338 if value == default:
3339 outstr += " %25s \t:\t%s\n" % (key,value)
3340 else:
3341 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3342 outstr += "\n"
3343 outstr += " Configuration Options \n"
3344 outstr += " --------------------- \n"
3345 keys = self.options_configuration.keys()
3346 keys.sort()
3347 for key in keys:
3348 if not to_print(key):
3349 continue
3350 default = self.options_configuration[key]
3351 value = self.options[key]
3352 if value == default:
3353 outstr += " %25s \t:\t%s\n" % (key,value)
3354 else:
3355 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3356
3357 output.write(outstr)
3358 elif args[0] in ["variable"]:
3359 super(MadGraphCmd, self).do_display(line, output)
3360
3361
3362 - def multiparticle_string(self, key):
3363 """Returns a nicely formatted string for the multiparticle"""
3364
3365 if self._multiparticles[key] and \
3366 isinstance(self._multiparticles[key][0], list):
3367 return "%s = %s" % (key, "|".join([" ".join([self._curr_model.\
3368 get('particle_dict')[part_id].get_name() \
3369 for part_id in id_list]) \
3370 for id_list in self._multiparticles[key]]))
3371 else:
3372 return "%s = %s" % (key, " ".join([self._curr_model.\
3373 get('particle_dict')[part_id].get_name() \
3374 for part_id in self._multiparticles[key]]))
3375
3401
3402
3403
3404 - def draw(self, line,selection='all',type=''):
3460
3461
3463 """Check a given process or set of processes"""
3464
3465 def create_lambda_values_list(lower_bound, N):
3466 """ Returns a list of values spanning the range [1.0, lower_bound] with
3467 lower_bound < 1.0 and with each interval [1e-i, 1e-(i+1)] covered
3468 by N values uniformly distributed. For example, lower_bound=1e-2
3469 and N=5 returns:
3470 [1, 0.8, 0.6, 0.4, 0.2, 0.1, 0.08, 0.06, 0.04, 0.02, 0.01]"""
3471
3472 lCMS_values = [1]
3473 exp = 0
3474 n = 0
3475 while lCMS_values[-1]>=lower_bound:
3476 n = (n+1)
3477 lCMS_values.append(float('1.0e-%d'%exp)*((N-n%N)/float(N)))
3478 if lCMS_values[-1]==lCMS_values[-2]:
3479 lCMS_values.pop()
3480 exp = (n+1)//N
3481
3482 lCMS_values = lCMS_values[:-1]
3483 if lCMS_values[-1]!=lower_bound:
3484 lCMS_values.append(lower_bound)
3485
3486 return lCMS_values
3487
3488
3489
3490 args = self.split_arg(line)
3491
3492 param_card = self.check_check(args)
3493
3494 options= {'events':None}
3495 if param_card and 'banner' == madevent_interface.MadEventCmd.detect_card_type(param_card):
3496 logger_check.info("Will use the param_card contained in the banner and the events associated")
3497 import madgraph.various.banner as banner
3498 options['events'] = param_card
3499 mybanner = banner.Banner(param_card)
3500 param_card = mybanner.charge_card('param_card')
3501
3502 aloha_lib.KERNEL.clean()
3503
3504 gauge = str(self.options['gauge'])
3505 options['reuse'] = args[1]=="-reuse"
3506 args = args[:1]+args[2:]
3507
3508
3509 if args[0] in ['stability', 'profile']:
3510 options['npoints'] = int(args[1])
3511 args = args[:1]+args[2:]
3512
3513 MLoptions={}
3514 i=-1
3515 CMS_options = {}
3516 while args[i].startswith('--'):
3517 option = args[i].split('=')
3518 if option[0] =='--energy':
3519 options['energy']=float(option[1])
3520 elif option[0]=='--split_orders':
3521 options['split_orders']=int(option[1])
3522 elif option[0]=='--helicity':
3523 try:
3524 options['helicity']=int(option[1])
3525 except ValueError:
3526 raise self.InvalidCmd("The value of the 'helicity' option"+\
3527 " must be an integer, not %s."%option[1])
3528 elif option[0]=='--reduction':
3529 MLoptions['MLReductionLib']=[int(ir) for ir in option[1].split('|')]
3530 elif option[0]=='--CTModeRun':
3531 try:
3532 MLoptions['CTModeRun']=int(option[1])
3533 except ValueError:
3534 raise self.InvalidCmd("The value of the 'CTModeRun' option"+\
3535 " must be an integer, not %s."%option[1])
3536 elif option[0]=='--offshellness':
3537 CMS_options['offshellness'] = float(option[1])
3538 if CMS_options['offshellness']<=-1.0:
3539 raise self.InvalidCmd('Offshellness must be number larger or'+
3540 ' equal to -1.0, not %f'%CMS_options['offshellness'])
3541 elif option[0]=='--analyze':
3542 options['analyze'] = option[1]
3543 elif option[0]=='--show_plot':
3544 options['show_plot'] = 'true' in option[1].lower()
3545 elif option[0]=='--report':
3546 options['report'] = option[1].lower()
3547 elif option[0]=='--seed':
3548 options['seed'] = int(option[1])
3549 elif option[0]=='--name':
3550 if '.' in option[1]:
3551 raise self.InvalidCmd("Do not specify the extension in the"+
3552 " name of the run")
3553 CMS_options['name'] = option[1]
3554 elif option[0]=='--resonances':
3555 if option[1]=='all':
3556 CMS_options['resonances'] = 'all'
3557 else:
3558 try:
3559 resonances=eval(option[1])
3560 except:
3561 raise self.InvalidCmd("Could not evaluate 'resonances'"+
3562 " option '%s'"%option[1])
3563 if isinstance(resonances,int) and resonances>0:
3564 CMS_options['resonances'] = resonances
3565 elif isinstance(resonances,list) and all(len(res)==2 and
3566 isinstance(res[0],int) and all(isinstance(i, int) for i in
3567 res[1]) for res in resonances):
3568 CMS_options['resonances'] = resonances
3569 else:
3570 raise self.InvalidCmd("The option 'resonances' can only be 'all'"+
3571 " or and integer or a list of tuples of the form "+
3572 "(resPDG,(res_mothers_ID)). You gave '%s'"%option[1])
3573 elif option[0]=='--tweak':
3574
3575 value = option[1]
3576
3577 if value=='alltweaks':
3578 value=str(['default','seed667(seed667)','seed668(seed668)',
3579 'allwidths->0.9*allwidths(widths_x_0.9)',
3580 'allwidths->0.99*allwidths(widths_x_0.99)',
3581 'allwidths->1.01*allwidths(widths_x_1.01)',
3582 'allwidths->1.1*allwidths(widths_x_1.1)',
3583 'logp->logm(logp2logm)','logm->logp(logm2logp)'])
3584 try:
3585 tweaks = eval(value)
3586 if isinstance(tweaks, str):
3587 tweaks = [value]
3588 elif not isinstance(tweaks,list):
3589 tweaks = [value]
3590 except:
3591 tweaks = [value]
3592 if not all(isinstance(t,str) for t in tweaks):
3593 raise self.InvalidCmd("Invalid specificaiton of tweaks: %s"%value)
3594 CMS_options['tweak'] = []
3595 for tweakID, tweakset in enumerate(tweaks):
3596 specs =re.match(r'^(?P<tweakset>.*)\((?P<name>.*)\)$', tweakset)
3597 if specs:
3598 tweakset = specs.group('tweakset')
3599 name = specs.group('name')
3600 else:
3601 if tweakset!='default':
3602 name = 'tweak_%d'%(tweakID+1)
3603 else:
3604 name = ''
3605 new_tweak_set = {'custom':[],'params':{},'name':name}
3606 for tweak in tweakset.split('&'):
3607 if tweak=='default':
3608 continue
3609 if tweak.startswith('seed'):
3610 new_tweak_set['custom'].append(tweak)
3611 continue
3612 try:
3613 param, replacement = tweak.split('->')
3614 except ValueError:
3615 raise self.InvalidCmd("Tweak specification '%s'"%\
3616 tweak+" is incorrect. It should be of"+\
3617 " the form a->_any_function_of_(a,lambdaCMS).")
3618 if param in ['logp','logm','log'] and \
3619 replacement in ['logp','logm','log']:
3620 new_tweak_set['custom'].append(tweak)
3621 continue
3622 try:
3623
3624
3625 orig_param, orig_replacement = param, replacement
3626 replacement = replacement.replace(param,
3627 '__tmpprefix__%s'%param)
3628 param = '__tmpprefix__%s'%param
3629 res = float(eval(replacement.lower(),
3630 {'lambdacms':1.0,param.lower():98.85}))
3631 except:
3632 raise self.InvalidCmd("The substitution expression "+
3633 "'%s' for the tweaked parameter"%orig_replacement+
3634 " '%s' could not be evaluated. It must be an "%orig_param+
3635 "expression of the parameter and 'lambdaCMS'.")
3636 new_tweak_set['params'][param.lower()] = replacement.lower()
3637 CMS_options['tweak'].append(new_tweak_set)
3638
3639 elif option[0]=='--recompute_width':
3640 if option[1].lower() not in ['never','always','first_time','auto']:
3641 raise self.InvalidCmd("The option 'recompute_width' can "+\
3642 "only be 'never','always', 'first_time' or 'auto' (default).")
3643 CMS_options['recompute_width'] = option[1]
3644 elif option[0]=='--loop_filter':
3645
3646
3647
3648 CMS_options['loop_filter'] = '='.join(option[1:])
3649 elif option[0]=='--diff_lambda_power':
3650
3651
3652
3653
3654 try:
3655 CMS_options['diff_lambda_power']=float(option[1])
3656 except ValueError:
3657 raise self.InvalidCmd("the '--diff_lambda_power' option"+\
3658 " must be an integer or float, not '%s'."%option[1])
3659 elif option[0]=='--lambda_plot_range':
3660 try:
3661 plot_range=eval(option[1])
3662 except Exception as e:
3663 raise self.InvalidCmd("The plot range specified %s"%option[1]+\
3664 " is not a valid syntax. Error:\n%s"%str(e))
3665 if not isinstance(plot_range,(list,tuple)) or \
3666 len(plot_range)!=2 or any(not isinstance(p,(float,int))
3667 for p in plot_range):
3668 raise self.InvalidCmd("The plot range specified %s"\
3669 %option[1]+" is invalid")
3670 CMS_options['lambda_plot_range']=list([float(p) for p in plot_range])
3671 elif option[0]=='--lambdaCMS':
3672 try:
3673 lambda_values = eval(option[1])
3674 except SyntaxError:
3675 raise self.InvalidCmd("'%s' is not a correct"%option[1]+
3676 " python expression for lambdaCMS values.")
3677 if isinstance(lambda_values,list):
3678 if lambda_values[0]!=1.0:
3679 raise self.InvalidCmd("The first value of the lambdaCMS values"+
3680 " specified must be 1.0, not %s"%str(lambda_values))
3681 for l in lambda_values:
3682 if not isinstance(l,float):
3683 raise self.InvalidCmd("All lambda CMS values must be"+
3684 " float, not '%s'"%str(l))
3685 elif isinstance(lambda_values,(tuple,float)):
3686
3687
3688
3689
3690 if isinstance(lambda_values, float):
3691
3692 lower_bound = lambda_values
3693 N = 10
3694 else:
3695 if isinstance(lambda_values[0],float) and \
3696 isinstance(lambda_values[1],int):
3697 lower_bound = lambda_values[0]
3698 N = lambda_values[1]
3699 else:
3700 raise self.InvalidCmd("'%s' must be a "%option[1]+
3701 "tuple with types (float, int).")
3702 lambda_values = create_lambda_values_list(lower_bound,N)
3703 else:
3704 raise self.InvalidCmd("'%s' must be an expression"%option[1]+
3705 " for either a float, tuple or list.")
3706 lower_bound = lambda_values[-1]
3707
3708
3709
3710
3711
3712
3713 CMS_options['lambdaCMS'] = lambda_values
3714 elif option[0]=='--cms':
3715 try:
3716 CMS_expansion_orders, CMS_expansion_parameters = \
3717 option[1].split(',')
3718 except ValueError:
3719 raise self.InvalidCmd("CMS expansion specification '%s'"%\
3720 args[i]+" is incorrect.")
3721 CMS_options['expansion_orders'] = [expansion_order for
3722 expansion_order in CMS_expansion_orders.split('&')]
3723 CMS_options['expansion_parameters'] = {}
3724 for expansion_parameter in CMS_expansion_parameters.split('&'):
3725 try:
3726 param, replacement = expansion_parameter.split('->')
3727 except ValueError:
3728 raise self.InvalidCmd("CMS expansion specification '%s'"%\
3729 expansion_parameter+" is incorrect. It should be of"+\
3730 " the form a->_any_function_of_(a,lambdaCMS).")
3731 try:
3732
3733
3734 orig_param, orig_replacement = param, replacement
3735 replacement = replacement.replace(param,
3736 '__tmpprefix__%s'%param)
3737 param = '__tmpprefix__%s'%param
3738 res = float(eval(replacement.lower(),
3739 {'lambdacms':1.0,param.lower():98.85}))
3740 except:
3741 raise self.InvalidCmd("The substitution expression "+
3742 "'%s' for CMS expansion parameter"%orig_replacement+
3743 " '%s' could not be evaluated. It must be an "%orig_param+
3744 "expression of the parameter and 'lambdaCMS'.")
3745
3746
3747 CMS_options['expansion_parameters'][param.lower()]=\
3748 replacement.lower()
3749 else:
3750 raise self.InvalidCmd("The option '%s' is not reckognized."%option[0])
3751
3752 i=i-1
3753 args = args[:i+1]
3754
3755 if args[0]=='options':
3756
3757 logger_check.info("Options for the command 'check' are:")
3758 logger_check.info("{:<20} {}".format(' name','default value'))
3759 logger_check.info("-"*40)
3760 for key, value in options.items():
3761 logger_check.info("{:<20} = {}".format('--%s'%key,str(value)))
3762 return
3763
3764 if args[0].lower()=='cmsoptions':
3765
3766 logger_check.info("Special options for the command 'check cms' are:")
3767 logger_check.info("{:<20} {}".format(' name','default value'))
3768 logger_check.info("-"*40)
3769 for key, value in CMS_options.items():
3770 logger_check.info("{:<20} = {}".format('--%s'%key,str(value)))
3771 return
3772
3773
3774 if args[0]!='cms' and options['seed']!=-1:
3775
3776
3777
3778 logger_check.info('Setting random seed to %d.'%options['seed'])
3779 random.seed(options['seed'])
3780
3781 proc_line = " ".join(args[1:])
3782
3783 if not (args[0]=='cms' and options['analyze']!='None'):
3784 myprocdef = self.extract_process(proc_line)
3785
3786
3787 if not myprocdef:
3788 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3789
3790 if myprocdef.get('NLO_mode')=='all':
3791 myprocdef.set('NLO_mode','virt')
3792 else:
3793 myprocdef = None
3794
3795
3796
3797 output_path = os.getcwd()
3798
3799 if args[0] in ['timing','stability', 'profile'] and not \
3800 myprocdef.get('perturbation_couplings'):
3801 raise self.InvalidCmd("Only loop processes can have their "+
3802 " timings or stability checked.")
3803
3804 if args[0]=='gauge' and \
3805 not myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3806 raise self.InvalidCmd(
3807 """Feynman vs unitary gauge comparisons can only be done if there are no loop
3808 propagators affected by this gauge. Typically, either processes at tree level
3809 or including only QCD perturbations can be considered here.""")
3810
3811 if args[0]=='gauge' and len(self._curr_model.get('gauge')) < 2:
3812 raise self.InvalidCmd("The current model does not allow for both "+\
3813 "Feynman and unitary gauge.")
3814
3815
3816 loggers = [logging.getLogger('madgraph.diagram_generation'),
3817 logging.getLogger('madgraph.loop_diagram_generation'),
3818 logging.getLogger('ALOHA'),
3819 logging.getLogger('madgraph.helas_objects'),
3820 logging.getLogger('madgraph.loop_exporter'),
3821 logging.getLogger('madgraph.export_v4'),
3822 logging.getLogger('cmdprint'),
3823 logging.getLogger('madgraph.model'),
3824 logging.getLogger('madgraph.base_objects')]
3825 old_levels = [log.level for log in loggers]
3826 for log in loggers:
3827 log.setLevel(logging.WARNING)
3828
3829
3830 cpu_time1 = time.time()
3831
3832
3833
3834
3835
3836
3837
3838 if myprocdef:
3839 if myprocdef.get('perturbation_couplings')==[]:
3840 aloha.loop_mode = False
3841
3842 comparisons = []
3843 gauge_result = []
3844 gauge_result_no_brs = []
3845 lorentz_result =[]
3846 nb_processes = 0
3847 timings = []
3848 stability = []
3849 profile_time = []
3850 profile_stab = []
3851 cms_results = []
3852
3853 if "_cuttools_dir" in dir(self):
3854 CT_dir = self._cuttools_dir
3855 else:
3856 CT_dir =""
3857 if "MLReductionLib" in MLoptions:
3858 if 1 in MLoptions["MLReductionLib"]:
3859 MLoptions["MLReductionLib"].remove(1)
3860
3861 TIR_dir={}
3862 if "_iregi_dir" in dir(self):
3863 TIR_dir['iregi_dir']=self._iregi_dir
3864 else:
3865 if "MLReductionLib" in MLoptions:
3866 if 3 in MLoptions["MLReductionLib"]:
3867 logger_check.warning('IREGI not available on your system; it will be skipped.')
3868 MLoptions["MLReductionLib"].remove(3)
3869
3870 if 'pjfry' in self.options and isinstance(self.options['pjfry'],str):
3871 TIR_dir['pjfry_dir']=self.options['pjfry']
3872 else:
3873 if "MLReductionLib" in MLoptions:
3874 if 2 in MLoptions["MLReductionLib"]:
3875 logger_check.warning('PJFRY not available on your system; it will be skipped.')
3876 MLoptions["MLReductionLib"].remove(2)
3877
3878 if 'golem' in self.options and isinstance(self.options['golem'],str):
3879 TIR_dir['golem_dir']=self.options['golem']
3880 else:
3881 if "MLReductionLib" in MLoptions:
3882 if 4 in MLoptions["MLReductionLib"]:
3883 logger_check.warning('GOLEM not available on your system; it will be skipped.')
3884 MLoptions["MLReductionLib"].remove(4)
3885
3886 if 'samurai' in self.options and isinstance(self.options['samurai'],str):
3887 TIR_dir['samurai_dir']=self.options['samurai']
3888 else:
3889 if "MLReductionLib" in MLoptions:
3890 if 5 in MLoptions["MLReductionLib"]:
3891 logger_check.warning('Samurai not available on your system; it will be skipped.')
3892 MLoptions["MLReductionLib"].remove(5)
3893
3894 if 'ninja' in self.options and isinstance(self.options['ninja'],str):
3895 TIR_dir['ninja_dir']=self.options['ninja']
3896 else:
3897 if "MLReductionLib" in MLoptions:
3898 if 6 in MLoptions["MLReductionLib"]:
3899 logger_check.warning('Ninja not available on your system; it will be skipped.')
3900 MLoptions["MLReductionLib"].remove(6)
3901
3902 if args[0] in ['timing']:
3903 timings = process_checks.check_timing(myprocdef,
3904 param_card = param_card,
3905 cuttools=CT_dir,
3906 tir=TIR_dir,
3907 options = options,
3908 cmd = self,
3909 output_path = output_path,
3910 MLOptions = MLoptions
3911 )
3912
3913 if args[0] in ['stability']:
3914 stability=process_checks.check_stability(myprocdef,
3915 param_card = param_card,
3916 cuttools=CT_dir,
3917 tir=TIR_dir,
3918 options = options,
3919 output_path = output_path,
3920 cmd = self,
3921 MLOptions = MLoptions)
3922
3923 if args[0] in ['profile']:
3924
3925
3926 profile_time, profile_stab = process_checks.check_profile(myprocdef,
3927 param_card = param_card,
3928 cuttools=CT_dir,
3929 tir=TIR_dir,
3930 options = options,
3931 MLOptions = MLoptions,
3932 output_path = output_path,
3933 cmd = self)
3934
3935 if args[0] in ['gauge', 'full'] and \
3936 len(self._curr_model.get('gauge')) == 2 and\
3937 myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3938
3939 line = " ".join(args[1:])
3940 myprocdef = self.extract_process(line)
3941 if gauge == 'unitary':
3942 myprocdef_unit = myprocdef
3943 self.do_set('gauge Feynman', log=False)
3944 myprocdef_feyn = self.extract_process(line)
3945 else:
3946 myprocdef_feyn = myprocdef
3947 self.do_set('gauge unitary', log=False)
3948 myprocdef_unit = self.extract_process(line)
3949
3950 nb_part_unit = len(myprocdef_unit.get('model').get('particles'))
3951 nb_part_feyn = len(myprocdef_feyn.get('model').get('particles'))
3952 if nb_part_feyn == nb_part_unit:
3953 logger_check.error('No Goldstone present for this check!!')
3954 gauge_result_no_brs = process_checks.check_unitary_feynman(
3955 myprocdef_unit, myprocdef_feyn,
3956 param_card = param_card,
3957 options=options,
3958 cuttools=CT_dir,
3959 tir=TIR_dir,
3960 reuse = options['reuse'],
3961 output_path = output_path,
3962 cmd = self)
3963
3964
3965 self.do_set('gauge %s' % gauge, log=False)
3966 nb_processes += len(gauge_result_no_brs)
3967
3968 if args[0] in ['permutation', 'full']:
3969 comparisons = process_checks.check_processes(myprocdef,
3970 param_card = param_card,
3971 quick = True,
3972 cuttools=CT_dir,
3973 tir=TIR_dir,
3974 reuse = options['reuse'],
3975 cmd = self,
3976 output_path = output_path,
3977 options=options)
3978 nb_processes += len(comparisons[0])
3979
3980 if args[0] in ['lorentz', 'full']:
3981 myprocdeff = copy.copy(myprocdef)
3982 lorentz_result = process_checks.check_lorentz(myprocdeff,
3983 param_card = param_card,
3984 cuttools=CT_dir,
3985 tir=TIR_dir,
3986 reuse = options['reuse'],
3987 cmd = self,
3988 output_path = output_path,
3989 options=options)
3990 nb_processes += len(lorentz_result)
3991
3992 if args[0] in ['brs', 'full']:
3993 gauge_result = process_checks.check_gauge(myprocdef,
3994 param_card = param_card,
3995 cuttools=CT_dir,
3996 tir=TIR_dir,
3997 reuse = options['reuse'],
3998 cmd = self,
3999 output_path = output_path,
4000 options=options)
4001 nb_processes += len(gauge_result)
4002
4003
4004
4005 if args[0] in ['cms']:
4006
4007 cms_original_setup = self.options['complex_mass_scheme']
4008 process_line = " ".join(args[1:])
4009
4010 for key, value in CMS_options.items():
4011 if key=='tweak':
4012 continue
4013 if key not in options:
4014 options[key] = value
4015 else:
4016 raise MadGraph5Error,"Option '%s' is both in the option"%key+\
4017 " and CMS_option dictionary."
4018
4019 if options['analyze']=='None':
4020 cms_results = []
4021 for tweak in CMS_options['tweak']:
4022 options['tweak']=tweak
4023
4024 guessed_proc = myprocdef.get_process(
4025 [leg.get('ids')[0] for leg in myprocdef.get('legs')
4026 if not leg.get('state')],
4027 [leg.get('ids')[0] for leg in myprocdef.get('legs')
4028 if leg.get('state')])
4029 save_path = process_checks.CMS_save_path('pkl',
4030 {'ordered_processes':[guessed_proc.base_string()],
4031 'perturbation_orders':guessed_proc.get('perturbation_couplings')},
4032 self._curr_model, options, output_path=output_path)
4033 if os.path.isfile(save_path) and options['reuse']:
4034 cms_result = save_load_object.load_from_file(save_path)
4035 logger_check.info("The cms check for tweak %s is recycled from file:\n %s"%
4036 (tweak['name'],save_path))
4037 if cms_result is None:
4038 raise self.InvalidCmd('The complex mass scheme check result'+
4039 " file below could not be read.\n %s"%save_path)
4040 else:
4041 cms_result = process_checks.check_complex_mass_scheme(
4042 process_line,
4043 param_card = param_card,
4044 cuttools=CT_dir,
4045 tir=TIR_dir,
4046 cmd = self,
4047 output_path = output_path,
4048 MLOptions = MLoptions,
4049 options=options)
4050
4051 save_path = process_checks.CMS_save_path('pkl', cms_result,
4052 self._curr_model, options, output_path=output_path)
4053 cms_results.append((cms_result,save_path,tweak['name']))
4054 else:
4055 cms_result = save_load_object.load_from_file(
4056 options['analyze'].split(',')[0])
4057 cms_results.append((cms_result,options['analyze'].split(',')[0],
4058 CMS_options['tweak'][0]['name']))
4059 if cms_result is None:
4060 raise self.InvalidCmd('The complex mass scheme check result'+
4061 " file below could not be read.\n %s"
4062 %options['analyze'].split(',')[0])
4063
4064
4065 self.do_set('complex_mass_scheme %s'%str(cms_original_setup),
4066 log=False)
4067
4068 nb_processes += len(cms_result['ordered_processes'])
4069
4070 cpu_time2 = time.time()
4071 logger_check.info("%i check performed in %s"% (nb_processes,
4072 misc.format_time(int(cpu_time2 - cpu_time1))))
4073
4074 if args[0] in ['cms']:
4075 text = "Note that the complex mass scheme test in principle only\n"
4076 text+= "works for stable particles in final states.\n\ns"
4077 if args[0] not in ['timing','stability', 'profile', 'cms']:
4078 if self.options['complex_mass_scheme']:
4079 text = "Note that Complex mass scheme gives gauge/lorentz invariant\n"
4080 text+= "results only for stable particles in final states.\n\ns"
4081 elif not myprocdef.get('perturbation_couplings'):
4082 text = "Note That all width have been set to zero for those checks\n\n"
4083 else:
4084 text = "\n"
4085 else:
4086 text ="\n"
4087
4088 if timings:
4089 text += 'Timing result for the '+('optimized' if \
4090 self.options['loop_optimized_output'] else 'default')+' output:\n'
4091
4092 text += process_checks.output_timings(myprocdef, timings)
4093 if stability:
4094 text += 'Stability result for the '+('optimized' if \
4095 self.options['loop_optimized_output'] else 'default')+' output:\n'
4096 text += process_checks.output_stability(stability,output_path)
4097
4098 if profile_time and profile_stab:
4099 text += 'Timing result '+('optimized' if \
4100 self.options['loop_optimized_output'] else 'default')+':\n'
4101 text += process_checks.output_profile(myprocdef, profile_stab,
4102 profile_time, output_path, options['reuse']) + '\n'
4103 if lorentz_result:
4104 text += 'Lorentz invariance results:\n'
4105 text += process_checks.output_lorentz_inv(lorentz_result) + '\n'
4106 if gauge_result:
4107 text += 'Gauge results:\n'
4108 text += process_checks.output_gauge(gauge_result) + '\n'
4109 if gauge_result_no_brs:
4110 text += 'Gauge results (switching between Unitary/Feynman):\n'
4111 text += process_checks.output_unitary_feynman(gauge_result_no_brs) + '\n'
4112 if cms_results:
4113 text += 'Complex mass scheme results (varying width in the off-shell regions):\n'
4114 cms_result = cms_results[0][0]
4115 if len(cms_results)>1:
4116 analyze = []
4117 for i, (cms_res, save_path, tweakname) in enumerate(cms_results):
4118 save_load_object.save_to_file(save_path, cms_res)
4119 logger_check.info("Pickle file for tweak '%s' saved to disk at:\n ->%s"%
4120 (tweakname,save_path))
4121 if i==0:
4122 analyze.append(save_path)
4123 else:
4124 analyze.append('%s(%s)'%(save_path,tweakname))
4125 options['analyze']=','.join(analyze)
4126 options['tweak'] = CMS_options['tweak'][0]
4127
4128 self._cms_checks.append({'line':line, 'cms_result':cms_result,
4129 'options':options, 'output_path':output_path})
4130 text += process_checks.output_complex_mass_scheme(cms_result,
4131 output_path, options, self._curr_model,
4132 output='concise_text' if options['report']=='concise' else 'text')+'\n'
4133
4134 if comparisons and len(comparisons[0])>0:
4135 text += 'Process permutation results:\n'
4136 text += process_checks.output_comparisons(comparisons[0]) + '\n'
4137 self._comparisons = comparisons
4138
4139
4140 if len(text.split('\n'))>20 and not '-reuse' in line and text!='':
4141 if 'test_manager' not in sys.argv[0]:
4142 pydoc.pager(text)
4143
4144
4145 for i, log in enumerate(loggers):
4146 log.setLevel(old_levels[i])
4147
4148
4149
4150 if len(text.split('\n'))<=20 or options['reuse']:
4151
4152 logging.getLogger('madgraph.check_cmd').info(text)
4153 else:
4154 logging.getLogger('madgraph.check_cmd').debug(text)
4155
4156
4157 process_checks.clean_added_globals(process_checks.ADDED_GLOBAL)
4158 if not options['reuse']:
4159 process_checks.clean_up(self._mgme_dir)
4160
4161
4181
4183 """Extract a process definition from a string. Returns
4184 a ProcessDefinition."""
4185
4186 orig_line = line
4187
4188 if not len(re.findall('>\D', line)) in [1,2]:
4189 self.do_help('generate')
4190 raise self.InvalidCmd('Wrong use of \">\" special character.')
4191
4192
4193
4194
4195 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
4196 line = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
4197
4198
4199
4200
4201
4202
4203 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
4204 proc_number_re = proc_number_pattern.match(line)
4205 if proc_number_re:
4206 proc_number = int(proc_number_re.group(2))
4207 line = proc_number_re.group(1)+ proc_number_re.group(3)
4208
4209
4210
4211 perturbation_couplings_pattern = \
4212 re.compile("^(?P<proc>.+>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*"+\
4213 "(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
4214 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
4215 perturbation_couplings = ""
4216 LoopOption= 'tree'
4217 HasBorn= True
4218 if perturbation_couplings_re:
4219 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
4220 option=perturbation_couplings_re.group("option")
4221 if option:
4222 if option in self._valid_nlo_modes:
4223 LoopOption=option
4224 if option=='sqrvirt':
4225 LoopOption='virt'
4226 HasBorn=False
4227 elif option=='noborn':
4228 HasBorn=False
4229 else:
4230 raise self.InvalidCmd, "NLO mode %s is not valid. "%option+\
4231 "Valid modes are %s. "%str(self._valid_nlo_modes)
4232 else:
4233 LoopOption='all'
4234
4235 line = perturbation_couplings_re.group("proc")+\
4236 perturbation_couplings_re.group("rest")
4237
4238
4239 order_pattern = re.compile(\
4240 "^(?P<before>.+>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
4241 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*$")
4242 order_re = order_pattern.match(line)
4243 squared_orders = {}
4244 orders = {}
4245 constrained_orders = {}
4246
4247
4248
4249
4250 split_orders = []
4251 while order_re:
4252 type = order_re.group('type')
4253 if order_re.group('name').endswith('^2'):
4254 if type not in self._valid_sqso_types:
4255 raise self.InvalidCmd, "Type of squared order "+\
4256 "constraint '%s'"% type+" is not supported."
4257 if type == '=':
4258 name = order_re.group('name')
4259 value = order_re.group('value')
4260 logger.warning("Interpreting '%(n)s=%(v)s' as '%(n)s<=%(v)s'" %\
4261 {'n':name, 'v': value})
4262 type = "<="
4263 squared_orders[order_re.group('name')[:-2]] = \
4264 (int(order_re.group('value')),type)
4265 else:
4266 if type not in self._valid_amp_so_types:
4267 raise self.InvalidCmd, \
4268 "Amplitude order constraints can only be of type %s"%\
4269 (', '.join(self._valid_amp_so_types))+", not '%s'."%type
4270 name = order_re.group('name')
4271 value = int(order_re.group('value'))
4272 if type in ['=', '<=']:
4273 if type == '=' and value != 0:
4274 logger.warning("Interpreting '%(n)s=%(v)s' as '%(n)s<=%(v)s'" %\
4275 {'n':name, 'v': value})
4276 orders[name] = value
4277 elif type == "==":
4278 constrained_orders[name] = (value, type)
4279 if name not in squared_orders:
4280 squared_orders[name] = (2 * value,'==')
4281 if True:
4282 orders[name] = value
4283
4284 elif type == ">":
4285 constrained_orders[name] = (value, type)
4286 if name not in squared_orders:
4287 squared_orders[name] = (2 * value,'>')
4288
4289 line = order_re.group('before')
4290 order_re = order_pattern.match(line)
4291
4292
4293 if constrained_orders and LoopOption != 'tree':
4294 raise self.InvalidCmd, \
4295 "Amplitude order constraints (for not LO processes) can only be of type %s"%\
4296 (', '.join(['<=']))+", not '%s'."%type
4297
4298
4299
4300
4301
4302
4303 if orders=={} and squared_orders!={}:
4304 for order in squared_orders.keys():
4305 if squared_orders[order][0]>=0 and squared_orders[order][1]!='>':
4306 orders[order]=squared_orders[order][0]
4307 else:
4308 orders[order]=99
4309
4310 if not self._curr_model['case_sensitive']:
4311
4312 line = line.lower()
4313
4314
4315 slash = line.find("/")
4316 dollar = line.find("$")
4317 forbidden_particles = ""
4318 if slash > 0:
4319 if dollar > slash:
4320 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
4321 else:
4322 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
4323 if forbidden_particles_re:
4324 forbidden_particles = forbidden_particles_re.group(2)
4325 line = forbidden_particles_re.group(1)
4326 if len(forbidden_particles_re.groups()) > 2:
4327 line = line + forbidden_particles_re.group(3)
4328
4329
4330 forbidden_schannels_re = re.match("^(.+)\s*\$\s*\$\s*(.+)\s*$", line)
4331 forbidden_schannels = ""
4332 if forbidden_schannels_re:
4333 forbidden_schannels = forbidden_schannels_re.group(2)
4334 line = forbidden_schannels_re.group(1)
4335
4336
4337 forbidden_onsh_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
4338 forbidden_onsh_schannels = ""
4339 if forbidden_onsh_schannels_re:
4340 forbidden_onsh_schannels = forbidden_onsh_schannels_re.group(2)
4341 line = forbidden_onsh_schannels_re.group(1)
4342
4343
4344 required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
4345 required_schannels = ""
4346 if required_schannels_re:
4347 required_schannels = required_schannels_re.group(2)
4348 line = required_schannels_re.group(1) + ">" + \
4349 required_schannels_re.group(3)
4350
4351 args = self.split_arg(line)
4352
4353 myleglist = base_objects.MultiLegList()
4354 state = False
4355
4356
4357 for part_name in args:
4358 if part_name == '>':
4359 if not myleglist:
4360 raise self.InvalidCmd, "No final state particles"
4361 state = True
4362 continue
4363
4364 mylegids = []
4365 if part_name in self._multiparticles:
4366 if isinstance(self._multiparticles[part_name][0], list):
4367 raise self.InvalidCmd,\
4368 "Multiparticle %s is or-multiparticle" % part_name + \
4369 " which can be used only for required s-channels"
4370 mylegids.extend(self._multiparticles[part_name])
4371 elif part_name.isdigit() or part_name.startswith('-') and part_name[1:].isdigit():
4372 if int(part_name) in self._curr_model.get('particle_dict'):
4373 mylegids.append(int(part_name))
4374 else:
4375 raise self.InvalidCmd, \
4376 "No pdg_code %s in model" % part_name
4377 else:
4378 mypart = self._curr_model['particles'].get_copy(part_name)
4379 if mypart:
4380 mylegids.append(mypart.get_pdg_code())
4381
4382 if mylegids:
4383 myleglist.append(base_objects.MultiLeg({'ids':mylegids,
4384 'state':state}))
4385 else:
4386 raise self.InvalidCmd, "No particle %s in model" % part_name
4387
4388
4389 if perturbation_couplings.lower()=='all':
4390 perturbation_couplings=' '.join(self._curr_model['perturbation_couplings'])
4391
4392 if filter(lambda leg: leg.get('state') == True, myleglist):
4393
4394
4395 perturbation_couplings_list = perturbation_couplings.split()
4396 if perturbation_couplings_list==['']:
4397 perturbation_couplings_list=[]
4398
4399
4400 split_orders=list(set(perturbation_couplings_list+squared_orders.keys()))
4401 try:
4402 split_orders.sort(key=lambda elem: 0 if elem=='WEIGHTED' else
4403 self._curr_model['order_hierarchy']
4404 [elem if not elem.endswith('.sqrt') else elem[:-5]])
4405 except KeyError:
4406 raise self.InvalidCmd, "The loaded model does not defined a "+\
4407 " coupling order hierarchy for these couplings: %s"%\
4408 str([so for so in split_orders if so!='WEIGHTED' and so not
4409 in self._curr_model['order_hierarchy'].keys()])
4410
4411
4412
4413
4414 if LoopOption=='tree':
4415 perturbation_couplings_list = []
4416 if perturbation_couplings_list and LoopOption not in ['real', 'LOonly']:
4417 if not isinstance(self._curr_model,loop_base_objects.LoopModel):
4418 raise self.InvalidCmd(\
4419 "The current model does not allow for loop computations.")
4420 else:
4421 for pert_order in perturbation_couplings_list:
4422 if pert_order not in self._curr_model['perturbation_couplings']:
4423 raise self.InvalidCmd(\
4424 "Perturbation order %s is not among" % pert_order + \
4425 " the perturbation orders allowed for by the loop model.")
4426 if not self.options['loop_optimized_output'] and \
4427 LoopOption not in ['tree','real'] and split_orders!=[]:
4428 logger.warning('The default output mode (loop_optimized_output'+\
4429 ' = False) does not support evaluations for given powers of'+\
4430 ' coupling orders. MadLoop output will therefore not be'+\
4431 ' able to provide such quantities.')
4432 split_orders = []
4433
4434
4435 forbidden_particle_ids = \
4436 self.extract_particle_ids(forbidden_particles)
4437 if forbidden_particle_ids and \
4438 isinstance(forbidden_particle_ids[0], list):
4439 raise self.InvalidCmd(\
4440 "Multiparticle %s is or-multiparticle" % part_name + \
4441 " which can be used only for required s-channels")
4442 forbidden_onsh_schannel_ids = \
4443 self.extract_particle_ids(forbidden_onsh_schannels)
4444 forbidden_schannel_ids = \
4445 self.extract_particle_ids(forbidden_schannels)
4446 if forbidden_onsh_schannel_ids and \
4447 isinstance(forbidden_onsh_schannel_ids[0], list):
4448 raise self.InvalidCmd,\
4449 "Multiparticle %s is or-multiparticle" % part_name + \
4450 " which can be used only for required s-channels"
4451 if forbidden_schannel_ids and \
4452 isinstance(forbidden_schannel_ids[0], list):
4453 raise self.InvalidCmd,\
4454 "Multiparticle %s is or-multiparticle" % part_name + \
4455 " which can be used only for required s-channels"
4456 required_schannel_ids = \
4457 self.extract_particle_ids(required_schannels)
4458 if required_schannel_ids and not \
4459 isinstance(required_schannel_ids[0], list):
4460 required_schannel_ids = [required_schannel_ids]
4461
4462 sqorders_values = dict([(k,v[0]) for k, v in squared_orders.items()])
4463 if len([1 for sqo_v in sqorders_values.values() if sqo_v<0])>1:
4464 raise self.InvalidCmd(
4465 "At most one negative squared order constraint can be specified.")
4466
4467 sqorders_types = dict([(k,v[1]) for k, v in squared_orders.items()])
4468
4469
4470 out = base_objects.ProcessDefinition({'legs': myleglist,
4471 'model': self._curr_model,
4472 'id': proc_number,
4473 'orders': orders,
4474 'squared_orders':sqorders_values,
4475 'sqorders_types':sqorders_types,
4476 'constrained_orders': constrained_orders,
4477 'forbidden_particles': forbidden_particle_ids,
4478 'forbidden_onsh_s_channels': forbidden_onsh_schannel_ids,
4479 'forbidden_s_channels': forbidden_schannel_ids,
4480 'required_s_channels': required_schannel_ids,
4481 'overall_orders': overall_orders,
4482 'perturbation_couplings': perturbation_couplings_list,
4483 'has_born':HasBorn,
4484 'NLO_mode':LoopOption,
4485 'split_orders':split_orders
4486 })
4487 return out
4488
4489
4490
4492 """ Routine to create the MultiProcess for the loop-induced case"""
4493
4494 args = self.split_arg(line)
4495
4496 warning_duplicate = True
4497 if '--no_warning=duplicate' in args:
4498 warning_duplicate = False
4499 args.remove('--no_warning=duplicate')
4500
4501
4502 self.check_add(args)
4503 if args[0] == 'process':
4504 args = args[1:]
4505
4506
4507
4508 if args[-1].startswith('--optimize'):
4509 optimize = True
4510 args.pop()
4511 else:
4512 optimize = False
4513
4514
4515 if not myprocdef:
4516 myprocdef = self.extract_process(' '.join(args))
4517
4518 myprocdef.set('NLO_mode', 'noborn')
4519
4520
4521 if not self._generate_info:
4522 self._generate_info = line
4523
4524
4525
4526
4527
4528
4529
4530 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
4531 myprocdef.get_ninitial():
4532 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
4533
4534 if self._curr_amps and (not isinstance(self._curr_amps[0], loop_diagram_generation.LoopAmplitude) or \
4535 self._curr_amps[0]['has_born']):
4536 raise self.InvalidCmd("Can not mix loop induced process with not loop induced process")
4537
4538
4539
4540 if len([1 for val in myprocdef.get('orders').values()+\
4541 myprocdef.get('squared_orders').values() if val<0])>1:
4542 raise MadGraph5Error("Negative coupling order constraints"+\
4543 " can only be given on one type of coupling and either on"+\
4544 " squared orders or amplitude orders, not both.")
4545
4546 cpu_time1 = time.time()
4547
4548
4549 if self.options['group_subprocesses'] == 'Auto':
4550 collect_mirror_procs = True
4551 else:
4552 collect_mirror_procs = self.options['group_subprocesses']
4553 ignore_six_quark_processes = \
4554 self.options['ignore_six_quark_processes'] if \
4555 "ignore_six_quark_processes" in self.options \
4556 else []
4557
4558
4559
4560 myproc = loop_diagram_generation.LoopInducedMultiProcess(myprocdef,
4561 collect_mirror_procs = collect_mirror_procs,
4562 ignore_six_quark_processes = ignore_six_quark_processes,
4563 optimize=optimize)
4564
4565 for amp in myproc.get('amplitudes'):
4566 if amp not in self._curr_amps:
4567 self._curr_amps.append(amp)
4568 if amp['has_born']:
4569 raise Exception
4570 elif warning_duplicate:
4571 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
4572 amp.nice_string_processes()
4573
4574
4575 self._done_export = False
4576
4577 cpu_time2 = time.time()
4578
4579 nprocs = len(myproc.get('amplitudes'))
4580 ndiags = sum([amp.get_number_of_diagrams() for \
4581 amp in myproc.get('amplitudes')])
4582 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
4583 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
4584 ndiags = sum([amp.get_number_of_diagrams() for \
4585 amp in self._curr_amps])
4586 logger.info("Total: %i processes with %i diagrams" % \
4587 (len(self._curr_amps), ndiags))
4588
4589 @staticmethod
4591 """Takes a valid process and return
4592 a tuple (core_process, options). This removes
4593 - any NLO specifications.
4594 - any options
4595 [Used by MadSpin]
4596 """
4597
4598
4599
4600 line=procline
4601 pos1=line.find("[")
4602 if pos1>0:
4603 pos2=line.find("]")
4604 if pos2 >pos1:
4605 line=line[:pos1]+line[pos2+1:]
4606
4607
4608
4609
4610 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
4611 proc_number_re = proc_number_pattern.match(line)
4612 if proc_number_re:
4613 line = proc_number_re.group(1) + proc_number_re.group(3)
4614
4615
4616 pos=1000
4617
4618 order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
4619 order_re = order_pattern.match(line)
4620 if (order_re):
4621 pos_order=line.find(order_re.group(2))
4622 if pos_order>0 and pos_order < pos : pos=pos_order
4623
4624
4625 slash = line.find("/")
4626 if slash > 0 and slash < pos: pos=slash
4627 dollar = line.find("$")
4628 if dollar > 0 and dollar < pos: pos=dollar
4629
4630 if pos<1000:
4631 proc_option=line[pos:]
4632 line=line[:pos]
4633 else:
4634 proc_option=""
4635
4636 return line, proc_option
4637
4639 """Takes a valid process and return
4640 a set of id of final states particles. [Used by MadSpin]
4641 """
4642
4643 if not self._curr_model['case_sensitive']:
4644 procline = procline.lower()
4645 pids = self._curr_model.get('name2pdg')
4646
4647
4648
4649
4650
4651
4652
4653 if ',' in procline:
4654 core, decay = procline.split(',', 1)
4655 core_final = self.get_final_part(core)
4656
4657
4658 all_decays = decay.split(',')
4659 nb_level, tmp_decay = 0, ''
4660 decays = []
4661
4662 for one_decay in all_decays:
4663 if '(' in one_decay:
4664 nb_level += 1
4665 if ')' in one_decay:
4666 nb_level -= 1
4667
4668 if nb_level:
4669 if tmp_decay:
4670 tmp_decay += ', %s' % one_decay
4671 else:
4672 tmp_decay = one_decay
4673 elif tmp_decay:
4674 final = '%s,%s' % (tmp_decay, one_decay)
4675 final = final.strip()
4676 assert final[0] == '(' and final[-1] == ')'
4677 final = final[1:-1]
4678 decays.append(final)
4679 tmp_decay = ''
4680 else:
4681 decays.append(one_decay)
4682
4683 for one_decay in decays:
4684 first = one_decay.split('>',1)[0].strip()
4685 if first in pids:
4686 pid = set([pids[first]])
4687 elif first in self._multiparticles:
4688 pid = set(self._multiparticles[first])
4689 else:
4690 raise Exception, 'invalid particle name: %s. ' % first
4691 core_final.difference_update(pid)
4692 core_final.update(self.get_final_part(one_decay))
4693
4694 return core_final
4695
4696
4697 final = set()
4698 final_states = re.search(r'> ([^\/\$\=\@>]*)(\[|\s\S+\=|\$|\/|\@|$)', procline)
4699 particles = final_states.groups()[0]
4700 for particle in particles.split():
4701 if particle in pids:
4702 final.add(pids[particle])
4703 elif particle in self._multiparticles:
4704 final.update(set(self._multiparticles[particle]))
4705 return final
4706
4707 - def extract_particle_ids(self, args):
4708 """Extract particle ids from a list of particle names. If
4709 there are | in the list, this corresponds to an or-list, which
4710 is represented as a list of id lists. An or-list is used to
4711 allow multiple required s-channel propagators to be specified
4712 (e.g. Z/gamma)."""
4713
4714 if isinstance(args, basestring):
4715 args.replace("|", " | ")
4716 args = self.split_arg(args)
4717 all_ids = []
4718 ids=[]
4719 for part_name in args:
4720 mypart = self._curr_model['particles'].get_copy(part_name)
4721 if mypart:
4722 ids.append([mypart.get_pdg_code()])
4723 elif part_name in self._multiparticles:
4724 ids.append(self._multiparticles[part_name])
4725 elif part_name == "|":
4726
4727 if ids:
4728 all_ids.append(ids)
4729 ids = []
4730 elif part_name.isdigit() or (part_name.startswith('-') and part_name[1:].isdigit()):
4731 ids.append([int(part_name)])
4732 else:
4733 raise self.InvalidCmd("No particle %s in model" % part_name)
4734 all_ids.append(ids)
4735
4736
4737 res_lists = []
4738 for i, id_list in enumerate(all_ids):
4739 res_lists.extend(diagram_generation.expand_list_list(id_list))
4740
4741 for ilist, idlist in enumerate(res_lists):
4742 set_dict = {}
4743 res_lists[ilist] = [set_dict.setdefault(i,i) for i in idlist \
4744 if i not in set_dict]
4745
4746 if len(res_lists) == 1:
4747 res_lists = res_lists[0]
4748
4749 return res_lists
4750
4752 """Optimize the order of particles in a pdg list, so that
4753 similar particles are next to each other. Sort according to:
4754 1. pdg > 0, 2. spin, 3. color, 4. mass > 0"""
4755
4756 if not pdg_list:
4757 return
4758 if not isinstance(pdg_list[0], int):
4759 return
4760
4761 model = self._curr_model
4762 pdg_list.sort(key = lambda i: i < 0)
4763 pdg_list.sort(key = lambda i: model.get_particle(i).is_fermion())
4764 pdg_list.sort(key = lambda i: model.get_particle(i).get('color'),
4765 reverse = True)
4766 pdg_list.sort(key = lambda i: \
4767 model.get_particle(i).get('mass').lower() != 'zero')
4768
4770 """Recursively extract a decay chain process definition from a
4771 string. Returns a ProcessDefinition."""
4772
4773
4774 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*((\w+\s*=\s*\d+\s*)*)$")
4775 proc_number_re = proc_number_pattern.match(line)
4776 overall_orders = {}
4777 if proc_number_re:
4778 proc_number = int(proc_number_re.group(2))
4779 line = proc_number_re.group(1)
4780 if proc_number_re.group(3):
4781 order_pattern = re.compile("^(.*?)\s*(\w+)\s*=\s*(\d+)\s*$")
4782 order_line = proc_number_re.group(3)
4783 order_re = order_pattern.match(order_line)
4784 while order_re:
4785 overall_orders[order_re.group(2)] = int(order_re.group(3))
4786 order_line = order_re.group(1)
4787 order_re = order_pattern.match(order_line)
4788 logger.info(line)
4789
4790
4791 index_comma = line.find(",")
4792 index_par = line.find(")")
4793 min_index = index_comma
4794 if index_par > -1 and (index_par < min_index or min_index == -1):
4795 min_index = index_par
4796
4797 if min_index > -1:
4798 core_process = self.extract_process(line[:min_index], proc_number,
4799 overall_orders)
4800 else:
4801 core_process = self.extract_process(line, proc_number,
4802 overall_orders)
4803
4804
4805
4806 while index_comma > -1:
4807 line = line[index_comma + 1:]
4808 if not line.strip():
4809 break
4810 index_par = line.find(')')
4811
4812 if line.lstrip()[0] == '(' and index_par !=-1 and \
4813 not ',' in line[:index_par]:
4814 par_start = line.find('(')
4815 line = '%s %s' % (line[par_start+1:index_par], line[index_par+1:])
4816 index_par = line.find(')')
4817 if line.lstrip()[0] == '(':
4818
4819
4820 line = line.lstrip()[1:]
4821
4822 decay_process, line = \
4823 self.extract_decay_chain_process(line,
4824 level_down=True)
4825 index_comma = line.find(",")
4826 index_par = line.find(')')
4827 else:
4828 index_comma = line.find(",")
4829 min_index = index_comma
4830 if index_par > -1 and \
4831 (index_par < min_index or min_index == -1):
4832 min_index = index_par
4833 if min_index > -1:
4834 decay_process = self.extract_process(line[:min_index])
4835 else:
4836 decay_process = self.extract_process(line)
4837
4838 core_process.get('decay_chains').append(decay_process)
4839
4840 if level_down:
4841 if index_par == -1:
4842 raise self.InvalidCmd, \
4843 "Missing ending parenthesis for decay process"
4844
4845 if index_par < index_comma:
4846 line = line[index_par + 1:]
4847 level_down = False
4848 break
4849
4850 if level_down:
4851 index_par = line.find(')')
4852 if index_par == -1:
4853 raise self.InvalidCmd, \
4854 "Missing ending parenthesis for decay process"
4855 line = line[index_par + 1:]
4856
4857
4858
4859 return core_process, line
4860
4861
4862
4864 """Main commands: Import files with external formats"""
4865
4866 args = self.split_arg(line)
4867
4868 self.check_import(args)
4869 if args[0].startswith('model'):
4870 self._model_v4_path = None
4871
4872 self._curr_amps = diagram_generation.AmplitudeList()
4873 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
4874
4875 if args[0].endswith('_v4'):
4876 self._curr_model, self._model_v4_path = \
4877 import_v4.import_model(args[1], self._mgme_dir)
4878 self._curr_fortran_model = \
4879 helas_call_writers.FortranHelasCallWriter(\
4880 self._curr_model)
4881 else:
4882
4883 if (args[1].startswith('loop_qcd_qed_sm') or\
4884 args[1].split('/')[-1].startswith('loop_qcd_qed_sm')) and\
4885 self.options['gauge']!='Feynman':
4886 logger.info('Switching to Feynman gauge because '+\
4887 'it is the only one supported by the model %s.'%args[1])
4888 self._curr_model = None
4889 self.do_set('gauge Feynman',log=False)
4890 prefix = not '--noprefix' in args
4891 if prefix:
4892 aloha.aloha_prefix='mdl_'
4893 else:
4894 aloha.aloha_prefix=''
4895
4896 try:
4897 self._curr_model = import_ufo.import_model(args[1], prefix=prefix,
4898 complex_mass_scheme=self.options['complex_mass_scheme'])
4899 except import_ufo.UFOImportError, error:
4900 if 'not a valid UFO model' in str(error):
4901 logger_stderr.warning('WARNING: %s' % error)
4902 logger_stderr.warning('Try to recover by running '+\
4903 'automatically `import model_v4 %s` instead.'% args[1])
4904 self.exec_cmd('import model_v4 %s ' % args[1], precmd=True)
4905 return
4906 if self.options['gauge']=='unitary':
4907 if not force and isinstance(self._curr_model,\
4908 loop_base_objects.LoopModel) and \
4909 self._curr_model.get('perturbation_couplings') not in \
4910 [[],['QCD']]:
4911 if 1 not in self._curr_model.get('gauge') :
4912 logger_stderr.warning('This model does not allow Feynman '+\
4913 'gauge. You will only be able to do tree level '+\
4914 'QCD loop cmputations with it.')
4915 else:
4916 logger.info('Change to the gauge to Feynman because '+\
4917 'this loop model allows for more than just tree level'+\
4918 ' and QCD perturbations.')
4919 self.do_set('gauge Feynman', log=False)
4920 return
4921 if 0 not in self._curr_model.get('gauge') :
4922 logger_stderr.warning('Change the gauge to Feynman since '+\
4923 'the model does not allow unitary gauge')
4924 self.do_set('gauge Feynman', log=False)
4925 return
4926 else:
4927 if 1 not in self._curr_model.get('gauge') :
4928 logger_stderr.warning('Change the gauge to unitary since the'+\
4929 ' model does not allow Feynman gauge.'+\
4930 ' Please re-import the model')
4931 self._curr_model = None
4932 self.do_set('gauge unitary', log= False)
4933 return
4934
4935 self._curr_fortran_model = \
4936 helas_call_writers.FortranUFOHelasCallWriter(\
4937 self._curr_model)
4938 self._curr_cpp_model = \
4939 helas_call_writers.CPPUFOHelasCallWriter(\
4940 self._curr_model)
4941
4942 if '-modelname' not in args:
4943 self._curr_model.pass_particles_name_in_mg_default()
4944
4945
4946 self.process_model()
4947
4948 self._curr_amps = diagram_generation.AmplitudeList()
4949 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
4950 process_checks.store_aloha = []
4951
4952 elif args[0] == 'command':
4953
4954 if not os.path.isfile(args[1]):
4955 raise self.InvalidCmd("Path %s is not a valid pathname" % args[1])
4956 else:
4957
4958
4959 self.check_for_export_dir(args[1])
4960
4961 self.import_command_file(args[1])
4962
4963 elif args[0] == 'banner':
4964 type = madevent_interface.MadEventCmd.detect_card_type(args[1])
4965 if type != 'banner':
4966 raise self.InvalidCmd, 'The File should be a valid banner'
4967 ban = banner_module.Banner(args[1])
4968
4969 if 'mg5proccard' in ban:
4970 for line in ban['mg5proccard'].split('\n'):
4971 if line.startswith('#') or line.startswith('<'):
4972 continue
4973 self.exec_cmd(line)
4974 else:
4975 raise self.InvalidCmd, 'Only MG5 banner are supported'
4976
4977 if not self._done_export:
4978 self.exec_cmd('output . -f')
4979
4980 ban.split(self._done_export[0])
4981 logger.info('All Cards from the banner have been place in directory %s' % pjoin(self._done_export[0], 'Cards'))
4982 if '--no_launch' not in args:
4983 self.exec_cmd('launch')
4984
4985 elif args[0] == 'proc_v4':
4986
4987 if len(args) == 1 and self._export_dir:
4988 proc_card = pjoin(self._export_dir, 'Cards', \
4989 'proc_card.dat')
4990 elif len(args) == 2:
4991 proc_card = args[1]
4992
4993
4994 self.check_for_export_dir(os.path.realpath(proc_card))
4995 else:
4996 raise MadGraph5Error('No default directory in output')
4997
4998
4999
5000 self.import_mg4_proc_card(proc_card)
5001
5003 """ For simple decay chain: remove diagram that are not in the BR.
5004 param_card should be a ParamCard instance."""
5005
5006 assert isinstance(param_card, check_param_card.ParamCard)
5007
5008
5009 amplitudes = diagram_generation.AmplitudeList()
5010 for amp in self._curr_amps:
5011 amplitudes.extend(amp.get_amplitudes())
5012
5013 decay_tables = param_card['decay'].decay_table
5014 to_remove = []
5015 for amp in amplitudes:
5016 mother = [l.get('id') for l in amp['process'].get('legs') \
5017 if not l.get('state')]
5018 if 1 == len(mother):
5019 try:
5020 decay_table = decay_tables[abs(mother[0])]
5021 except KeyError:
5022 logger.warning("No decay table for %s. decay of this particle with MadSpin should be discarded" % abs(mother[0]))
5023 continue
5024
5025 child = [l.get('id') for l in amp['process'].get('legs') \
5026 if l.get('state')]
5027 if not mother[0] > 0:
5028 child = [x if self._curr_model.get_particle(x)['self_antipart']
5029 else -x for x in child]
5030 child.sort()
5031 child.insert(0, len(child))
5032
5033 if tuple(child) not in decay_table.keys():
5034 to_remove.append(amp)
5035
5036 def remove_amp(amps):
5037 for amp in amps[:]:
5038 if amp in to_remove:
5039 amps.remove(amp)
5040 if isinstance(amp, diagram_generation.DecayChainAmplitude):
5041 remove_amp(amp.get('decay_chains'))
5042 for decay in amp.get('decay_chains'):
5043 remove_amp(decay.get('amplitudes'))
5044 remove_amp(self._curr_amps)
5045
5046
5055
5057 """Set variables _particle_names and _couplings for tab
5058 completion, define multiparticles"""
5059
5060
5061 self._particle_names = [p.get('name') for p in self._curr_model.get('particles')\
5062 if p.get('propagating')] + \
5063 [p.get('antiname') for p in self._curr_model.get('particles') \
5064 if p.get('propagating')]
5065
5066 self._couplings = list(set(sum([i.get('orders').keys() for i in \
5067 self._curr_model.get('interactions')], [])))
5068
5069 self.add_default_multiparticles()
5070
5071
5100
5102 """ add default particle from file interface.multiparticles_default.txt
5103 """
5104
5105 defined_multiparticles = self._multiparticles.keys()
5106 removed_multiparticles = []
5107
5108
5109
5110 for key in self._multiparticles.keys():
5111 try:
5112 for part in self._multiparticles[key]:
5113 self._curr_model.get('particle_dict')[part]
5114 except Exception:
5115 del self._multiparticles[key]
5116 defined_multiparticles.remove(key)
5117 removed_multiparticles.append(key)
5118
5119
5120 for line in open(pjoin(MG5DIR, 'input', \
5121 'multiparticles_default.txt')):
5122 if line.startswith('#'):
5123 continue
5124 try:
5125 if not self._curr_model['case_sensitive']:
5126 multipart_name = line.lower().split()[0]
5127 else:
5128 multipart_name = line.split()[0]
5129 if multipart_name not in self._multiparticles:
5130
5131 self.exec_cmd('define %s' % line, printcmd=False, precmd=True)
5132 except self.InvalidCmd, why:
5133 logger_stderr.warning('impossible to set default multiparticles %s because %s' %
5134 (line.split()[0],why))
5135 if self.history[-1] == 'define %s' % line.strip():
5136 self.history.pop(-1)
5137 else:
5138 misc.sprint([self.history[-1], 'define %s' % line.strip()])
5139
5140 scheme = "old"
5141 for qcd_container in ['p', 'j']:
5142 if qcd_container not in self._multiparticles:
5143 continue
5144 multi = self._multiparticles[qcd_container]
5145 b = self._curr_model.get_particle(5)
5146 if not b:
5147 break
5148
5149 if 5 in multi:
5150 if b['mass'] != 'ZERO':
5151 multi.remove(5)
5152 multi.remove(-5)
5153 scheme = 4
5154 elif b['mass'] == 'ZERO':
5155 multi.append(5)
5156 multi.append(-5)
5157 scheme = 5
5158
5159 if scheme in [4,5]:
5160 logger.warning("Pass the definition of \'j\' and \'p\' to %s flavour scheme." % scheme)
5161 for container in ['p', 'j']:
5162 if container in defined_multiparticles:
5163 defined_multiparticles.remove(container)
5164 self.history.append("define p = %s # pass to %s flavors" % \
5165 (' ' .join([`i` for i in self._multiparticles['p']]),
5166 scheme)
5167 )
5168 self.history.append("define j = p")
5169
5170
5171 if defined_multiparticles:
5172 if 'all' in defined_multiparticles:
5173 defined_multiparticles.remove('all')
5174 logger.info("Kept definitions of multiparticles %s unchanged" % \
5175 " / ".join(defined_multiparticles))
5176
5177 for removed_part in removed_multiparticles:
5178 if removed_part in self._multiparticles:
5179 removed_multiparticles.remove(removed_part)
5180
5181 if removed_multiparticles:
5182 logger.info("Removed obsolete multiparticles %s" % \
5183 " / ".join(removed_multiparticles))
5184
5185
5186 line = []
5187 for part in self._curr_model.get('particles'):
5188 line.append('%s %s' % (part.get('name'), part.get('antiname')))
5189 line = 'all =' + ' '.join(line)
5190 self.do_define(line)
5191
5192 - def advanced_install(self, tool_to_install,
5193 HepToolsInstaller_web_address=None,
5194 additional_options=[]):
5195 """ Uses the HEPToolsInstaller.py script maintened online to install
5196 HEP tools with more complicated dependences.
5197 Additional options will be added to the list when calling HEPInstaller"""
5198
5199
5200 if not os.path.isdir(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers')):
5201 if HepToolsInstaller_web_address is None:
5202 raise MadGraph5Error, "The option 'HepToolsInstaller_web_address'"+\
5203 " must be specified in function advanced_install"+\
5204 " if the installers are not already downloaded."
5205 if not os.path.isdir(pjoin(MG5DIR,'HEPTools')):
5206 os.mkdir(pjoin(MG5DIR,'HEPTools'))
5207 elif not HepToolsInstaller_web_address is None:
5208 shutil.rmtree(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers'))
5209 if not HepToolsInstaller_web_address is None:
5210 logger.info('Downloading the HEPToolInstaller at:\n %s'%
5211 HepToolsInstaller_web_address)
5212
5213 if '//' in HepToolsInstaller_web_address:
5214 if sys.platform == "darwin":
5215 misc.call(['curl', HepToolsInstaller_web_address, '-o%s'
5216 %pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz')],
5217 stderr=open(os.devnull,'w'), stdout=open(os.devnull,'w'),
5218 cwd=MG5DIR)
5219 else:
5220 misc.call(['wget', HepToolsInstaller_web_address,
5221 '--output-document=%s'% pjoin(MG5DIR,'HEPTools',
5222 'HEPToolsInstallers.tar.gz')], stderr=open(os.devnull, 'w'),
5223 stdout=open(os.devnull, 'w'), cwd=MG5DIR)
5224 else:
5225
5226 shutil.copyfile(HepToolsInstaller_web_address,
5227 pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz'))
5228
5229
5230 returncode = misc.call(['tar', '-xzpf', 'HEPToolsInstallers.tar.gz'],
5231 cwd=pjoin(MG5DIR,'HEPTools'), stdout=open(os.devnull, 'w'))
5232
5233
5234 os.remove(pjoin(MG5DIR,'HEPTools','HEPToolsInstallers.tar.gz'))
5235
5236
5237
5238
5239
5240
5241
5242
5243 name_map = {}
5244 try:
5245 tool = name_map[tool_to_install]
5246 except:
5247 tool = tool_to_install
5248
5249
5250 compiler_options = []
5251 if not self.options['cpp_compiler'] is None:
5252 compiler_options.append('--cpp_compiler=%s'%
5253 self.options['cpp_compiler'])
5254 compiler_options.append('--cpp_standard_lib=%s'%
5255 misc.detect_cpp_std_lib_dependence(self.options['cpp_compiler']))
5256 else:
5257 compiler_options.append('--cpp_standard_lib=%s'%
5258 misc.detect_cpp_std_lib_dependence(self.options['cpp_compiler']))
5259
5260 if not self.options['fortran_compiler'] is None:
5261 compiler_options.append('--fortran_compiler=%s'%
5262 self.options['fortran_compiler'])
5263
5264
5265 if tool=='mg5amc_py8_interface':
5266 additional_options.append('--mg5_path=%s'%MG5DIR)
5267
5268 if misc.which('gnuplot') is None:
5269 logger.warning("==========")
5270 logger.warning("The optional dependency 'gnuplot' for the tool"+\
5271 " 'mg5amc_py8_interface' was not found. We recommend that you"+\
5272 " install it so as to be able to view the plots related to "+\
5273 " merging with Pythia 8.")
5274 logger.warning("==========")
5275 if self.options['pythia8_path']:
5276 additional_options.append(
5277 '--with_pythia8=%s'%self.options['pythia8_path'])
5278
5279
5280
5281
5282
5283
5284
5285
5286 if tool=='pythia8':
5287
5288 lhapdf_config = misc.which(self.options['lhapdf'])
5289 lhapdf_version = None
5290 if lhapdf_config is None:
5291 lhapdf_version = None
5292 else:
5293 try:
5294 version = misc.Popen(
5295 [lhapdf_config,'--version'], stdout=subprocess.PIPE)
5296 lhapdf_version = int(version.stdout.read()[0])
5297 if lhapdf_version not in [5,6]:
5298 raise
5299 except:
5300 raise self.InvalidCmd('Could not detect LHAPDF version. Make'+
5301 " sure '%s --version ' runs properly."%lhapdf_config)
5302
5303 if lhapdf_version is None:
5304 answer = self.ask(question=
5305 "\033[33;34mLHAPDF was not found. Do you want to install LHPADF6? "+
5306 "(recommended) \033[0m \033[33;32my\033[0m/\033[33;31mn\033[0m >",
5307 default='y',text_format='33;32')
5308 if not answer.lower() in ['y','']:
5309 lhapdf_path = None
5310 else:
5311 self.advanced_install('lhapdf6',
5312 additional_options=additional_options)
5313 lhapdf_path = pjoin(MG5DIR,'HEPTools','lhapdf6')
5314 lhapdf_version = 6
5315 else:
5316 lhapdf_path = os.path.abspath(pjoin(os.path.dirname(\
5317 lhapdf_config),os.path.pardir))
5318 if lhapdf_version is None:
5319 logger.warning('You decided not to link the Pythia8 installation'+
5320 ' to LHAPDF. Beware that only built-in PDF sets can be used then.')
5321 else:
5322 logger.info('Pythia8 will be linked to LHAPDF v%d.'%lhapdf_version)
5323 logger.info('Now installing Pythia8. Be patient...','$MG:color:GREEN')
5324 lhapdf_option = []
5325 if lhapdf_version is None:
5326 lhapdf_option.append('--with_lhapdf6=OFF')
5327 lhapdf_option.append('--with_lhapdf5=OFF')
5328 elif lhapdf_version==5:
5329 lhapdf_option.append('--with_lhapdf5=%s'%lhapdf_path)
5330 lhapdf_option.append('--with_lhapdf6=OFF')
5331 elif lhapdf_version==6:
5332 lhapdf_option.append('--with_lhapdf5=OFF')
5333 lhapdf_option.append('--with_lhapdf6=%s'%lhapdf_path)
5334
5335 additional_options = list(set(additional_options))
5336
5337 additional_options = [opt for opt in additional_options if opt!='--force']+\
5338 (['--force'] if '--force' in additional_options else [])
5339 return_code = misc.call([pjoin(MG5DIR,'HEPTools',
5340 'HEPToolsInstallers','HEPToolInstaller.py'),'pythia8',
5341 '--prefix=%s'%pjoin(MG5DIR,'HEPTools')]
5342 + lhapdf_option + compiler_options + additional_options)
5343 else:
5344 logger.info('Now installing %s. Be patient...'%tool)
5345
5346 additional_options = list(set(additional_options))
5347
5348 additional_options = [opt for opt in additional_options if opt!='--force']+\
5349 (['--force'] if '--force' in additional_options else [])
5350 return_code = misc.call([pjoin(MG5DIR,'HEPTools',
5351 'HEPToolsInstallers', 'HEPToolInstaller.py'), tool,'--prefix=%s'%
5352 pjoin(MG5DIR,'HEPTools')] + compiler_options + additional_options)
5353
5354 if return_code == 0:
5355 logger.info("%s successfully installed in %s."%(
5356 tool_to_install, pjoin(MG5DIR,'HEPTools')),'$MG:color:GREEN')
5357 elif return_code == 66:
5358 answer = self.ask(question=
5359 """\033[33;34mTool %s already installed in %s."""%(tool_to_install, pjoin(MG5DIR,'HEPTools'))+
5360 """ Do you want to overwrite its installation?\033[0m \033[33;32my\033[0m/\033[33;31mn\033[0m >"""
5361 ,default='y',text_format='33;32')
5362 if not answer.lower() in ['y','']:
5363 logger.info("Installation of %s aborted."%tool_to_install,
5364 '$MG:color:GREEN')
5365 return
5366 else:
5367 return self.advanced_install(tool_to_install,
5368 additional_options=additional_options+['--force'])
5369 else:
5370 raise self.InvalidCmd("Installation of %s failed."%tool_to_install)
5371
5372
5373 if tool == 'pythia8':
5374 self.options['pythia8_path'] = pjoin(MG5DIR,'HEPTools','pythia8')
5375 self.exec_cmd('save options')
5376
5377
5378 self.advanced_install('mg5amc_py8_interface',
5379 additional_options=additional_options+['--force'])
5380 elif tool == 'lhapdf6':
5381 self.options['lhapdf'] = pjoin(MG5DIR,'HEPTools','lhapdf6','bin',
5382 'lhapdf-config')
5383 self.exec_cmd('save options')
5384 elif tool == 'lhapdf5':
5385 self.options['lhapdf'] = pjoin(MG5DIR,'HEPTools','lhapdf5','bin',
5386 'lhapdf-config')
5387 self.exec_cmd('save options')
5388
5389 elif tool == 'mg5amc_py8_interface':
5390 self.options['mg5amc_py8_interface_path'] = \
5391 pjoin(MG5DIR,'HEPTools','MG5aMC_PY8_interface')
5392 self.exec_cmd('save options')
5393
5394 elif tool == 'ninja':
5395 if not misc.get_ninja_quad_prec_support(pjoin(
5396 MG5DIR,'HEPTools','ninja','lib')):
5397 logger.warning(
5398 """Successful installation of Ninja, but without support for quadruple precision
5399 arithmetics. If you want to enable this (hence improving the treatment of numerically
5400 unstable points in the loop matrix elements) you can try to reinstall Ninja with:
5401 MG5aMC>install ninja
5402 After having made sure to have selected a C++ compiler in the 'cpp' option of
5403 MG5aMC that supports quadruple precision (typically g++ based on gcc 4.6+).""")
5404 self.options['ninja'] = pjoin(os.curdir,'HEPTools','lib')
5405 self.exec_cmd('save options')
5406
5407
5408
5409 path_to_be_set = []
5410 if sys.platform == "darwin":
5411 library_variables = ["DYLD_LIBRARY_PATH"]
5412 else:
5413 library_variables = ["LD_LIBRARY_PATH"]
5414 for variable in library_variables:
5415 if (variable not in os.environ) or \
5416 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','lib'))==\
5417 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5418 path_to_be_set.append((variable,
5419 os.path.abspath(pjoin(MG5DIR,'HEPTools','lib'))))
5420 for variable in ["PATH"]:
5421 if (variable not in os.environ) or \
5422 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','bin'))==\
5423 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5424 path_to_be_set.append((variable,
5425 os.path.abspath(pjoin(MG5DIR,'HEPTools','bin'))))
5426 if (variable not in os.environ) or \
5427 not any(os.path.abspath(pjoin(MG5DIR,'HEPTools','include'))==\
5428 os.path.abspath(path) for path in os.environ[variable].split(os.pathsep)):
5429 path_to_be_set.append((variable,
5430 os.path.abspath(pjoin(MG5DIR,'HEPTools','include'))))
5431
5432 if len(path_to_be_set)>0:
5433 shell_type = misc.get_shell_type()
5434 if shell_type in ['bash',None]:
5435 modification_line = r"printf '# MG5aMC paths:\n%s' >> ~/.bashrc"%\
5436 (r'\n'.join('export %s=%s%s'%
5437 (var,path,'%s$%s'%(os.pathsep,var) if var in os.environ else '')
5438 for var,path in path_to_be_set))
5439 elif shell_type=='tcsh':
5440 modification_line = r"printf '# MG5aMC paths:\n%s' >> ~/.cshrc"%\
5441 (r'\n'.join('setenv %s %s%s'%
5442 (var,path,'%s$%s'%(os.pathsep,var) if var in os.environ else '')
5443 for var,path in path_to_be_set))
5444
5445 logger.warning("==========")
5446 logger.warning("We recommend that you add to the following paths"+\
5447 " to your environment variables, so that you are guaranteed that"+\
5448 " at runtime, MG5_aMC will use the tools you have just installed"+\
5449 " and not some other versions installed elsewhere on your system.\n"+\
5450 "You can do so by running the following command in your terminal:"
5451 "\n %s"%modification_line)
5452 logger.warning("==========")
5453
5454
5455 return True
5456
5457 - def do_install(self, line, paths=None, additional_options=[]):
5458 """Install optional package from the MG suite.
5459 The argument 'additional_options' will be passed to the advanced_install
5460 functions. If it contains the option '--force', then the advanced_install
5461 function will overwrite any existing installation of the tool without
5462 warnings.
5463 """
5464
5465 args = self.split_arg(line)
5466
5467 self.check_install(args)
5468
5469 if sys.platform == "darwin":
5470 program = "curl"
5471 else:
5472 program = "wget"
5473
5474
5475 if args[0] == 'update':
5476 self.install_update(args, wget=program)
5477 return
5478
5479 advertisements = {'pythia-pgs':['arXiv:0603175'],
5480 'Delphes':['arXiv:1307.6346'],
5481 'Delphes2':['arXiv:0903.2225'],
5482 'SysCalc':['arXiv:XXXX.YYYYY'],
5483 'Golem95':['arXiv:0807.0605'],
5484 'PJFry':['arXiv:1210.4095','arXiv:1112.0500'],
5485 'QCDLoop':['arXiv:0712.1851'],
5486 'pythia8':['arXiv:1410.3012'],
5487 'lhapdf6':['arXiv:1412.7420'],
5488 'lhapdf5':['arXiv:0605240'],
5489 'hepmc':['CPC 134 (2001) 41-46'],
5490 'mg5amc_py8_interface':['arXiv:1410.3012','arXiv:XXXX.YYYYY'],
5491 'ninja':['arXiv:1203.0291','arXiv:1403.1229','arXiv:1604.01363'],
5492 'oneloop':['arXiv:1007.4716']}
5493
5494 if args[0] in advertisements:
5495 logger.info("------------------------------------------------------", '$MG:color:GREEN')
5496 logger.info(" You are installing '%s', please cite ref(s): "%args[0], '$MG:color:BLACK')
5497 for ad in advertisements[args[0]]:
5498 logger.info(" %s"%ad, '$MG:color:GREEN')
5499 logger.info(" on top of the recommended MG5_aMC citations", '$MG:color:BLACK')
5500 logger.info(" when using results produced with this tool.", '$MG:color:BLACK')
5501 logger.info("------------------------------------------------------", '$MG:color:GREEN')
5502
5503
5504
5505 import urllib
5506 if paths:
5507 path = paths
5508 else:
5509 path = {}
5510
5511 data_path = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
5512 'http://madgraph.hep.uiuc.edu/package_info.dat']
5513 r = random.randint(0,1)
5514 r = [r, (1-r)]
5515
5516
5517
5518
5519
5520 for index in r:
5521 cluster_path = data_path[index]
5522 try:
5523 data = urllib.urlopen(cluster_path)
5524 except Exception:
5525 continue
5526 break
5527 else:
5528 raise MadGraph5Error, '''Impossible to connect any of us servers.
5529 Please check your internet connection or retry later'''
5530
5531 for line in data:
5532 split = line.split()
5533 path[split[0]] = split[1]
5534
5535
5536
5537
5538
5539
5540
5541 if args[0] in self._advanced_install_opts:
5542
5543
5544
5545
5546 MG5aMC_PY8_interface_path = path['MG5aMC_PY8_interface'] if \
5547 'MG5aMC_PY8_interface' in path else 'NA'
5548 additional_options.append('--mg5amc_py8_interface_tarball=%s'%\
5549 MG5aMC_PY8_interface_path)
5550 return self.advanced_install(args[0], path['HEPToolsInstaller'],
5551 additional_options = additional_options)
5552
5553 if args[0] == 'PJFry' and not os.path.exists(
5554 pjoin(MG5DIR,'QCDLoop','lib','libqcdloop1.a')):
5555 logger.info("Installing PJFRY's dependence QCDLoop...")
5556 self.do_install('QCDLoop', paths=path)
5557
5558 if args[0] == 'Delphes':
5559 args[0] = 'Delphes3'
5560
5561 try:
5562 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
5563 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
5564 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'MadAnalysis',
5565 'SysCalc':'SysCalc', 'Golem95': 'golem95',
5566 'PJFry':'PJFry','QCDLoop':'QCDLoop',
5567 }
5568 name = name[args[0]]
5569 except:
5570 pass
5571
5572
5573 if args[0] in ['Delphes2', 'pythia-pgs']:
5574 logger.warning("Please Note that this package is NOT maintained anymore by their author(s).\n"+\
5575 " You should consider using an up-to-date version of the code.")
5576
5577 try:
5578 os.system('rm -rf %s' % pjoin(MG5DIR, name))
5579 except Exception:
5580 pass
5581
5582
5583 logger.info('Downloading %s' % path[args[0]])
5584 if sys.platform == "darwin":
5585 misc.call(['curl', path[args[0]], '-o%s.tgz' % name], cwd=MG5DIR)
5586 else:
5587 misc.call(['wget', path[args[0]], '--output-document=%s.tgz'% name], cwd=MG5DIR)
5588
5589
5590 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
5591 stdout=open(os.devnull, 'w'))
5592
5593 if returncode:
5594 raise MadGraph5Error, 'Fail to download correctly the File. Stop'
5595
5596
5597
5598 if not os.path.exists(pjoin(MG5DIR, name)):
5599 created_name = [n for n in os.listdir(MG5DIR) if n.lower().startswith(
5600 name.lower()) and not n.endswith('gz')]
5601 if not created_name:
5602 raise MadGraph5Error, 'The file was not loaded correctly. Stop'
5603 else:
5604 created_name = created_name[0]
5605 files.mv(pjoin(MG5DIR, created_name), pjoin(MG5DIR, name))
5606
5607
5608 logger.info('compile %s. This might take a while.' % name)
5609
5610
5611 if args[0] == "pythia-pgs" and sys.maxsize > 2**32:
5612 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
5613 text = open(path).read()
5614 text = text.replace('MBITS=32','MBITS=64')
5615 open(path, 'w').writelines(text)
5616 if not os.path.exists(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib')):
5617 os.mkdir(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib'))
5618
5619 make_flags = []
5620
5621
5622 if 'FC' not in os.environ or not os.environ['FC']:
5623 if self.options['fortran_compiler'] and self.options['fortran_compiler'] != 'None':
5624 compiler = self.options['fortran_compiler']
5625 elif misc.which('gfortran'):
5626 compiler = 'gfortran'
5627 elif misc.which('g77'):
5628 compiler = 'g77'
5629 else:
5630 raise self.InvalidCmd('Require g77 or Gfortran compiler')
5631
5632 path = None
5633 base_compiler= ['FC=g77','FC=gfortran']
5634 if args[0] == "pythia-pgs":
5635 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
5636 elif args[0] == 'MadAnalysis':
5637 path = os.path.join(MG5DIR, 'MadAnalysis', 'makefile')
5638 if path:
5639 text = open(path).read()
5640 for base in base_compiler:
5641 text = text.replace(base,'FC=%s' % compiler)
5642 open(path, 'w').writelines(text)
5643 os.environ['FC'] = compiler
5644
5645
5646 if name == 'golem95':
5647
5648 ld_path = misc.Popen(['./configure',
5649 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC']],
5650 cwd=pjoin(MG5DIR,'golem95'),stdout=subprocess.PIPE).communicate()[0]
5651
5652
5653 if name == 'PJFry':
5654
5655 ld_path = misc.Popen(['./configure',
5656 '--prefix=%s'%str(pjoin(MG5DIR, name)),
5657 '--enable-golem-mode', '--with-integrals=qcdloop1',
5658 'LDFLAGS=-L%s'%str(pjoin(MG5DIR,'QCDLoop','lib')),
5659 'FC=%s'%os.environ['FC'],
5660 'F77=%s'%os.environ['FC']], cwd=pjoin(MG5DIR,name),
5661 stdout=subprocess.PIPE).communicate()[0]
5662
5663
5664 if name == 'QCDLoop':
5665
5666 ld_path = misc.Popen(['./configure',
5667 '--prefix=%s'%str(pjoin(MG5DIR, name)),'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 args[0] == 'Delphes3':
5673
5674
5675
5676
5677 rootsys = os.environ['ROOTSYS']
5678 text = open('./Delphes/Makefile').read()
5679 text = text.replace('DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS)',
5680 'DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS) -Wl,-rpath,%s/lib/' % rootsys)
5681 open('./Delphes/Makefile','w').write(text)
5682
5683
5684 if name == 'SysCalc':
5685 if self.options['lhapdf']:
5686 ld_path = misc.Popen([self.options['lhapdf'], '--libdir'],
5687 stdout=subprocess.PIPE).communicate()[0]
5688 ld_path = ld_path.replace('\n','')
5689 if 'LD_LIBRARY_PATH' not in os.environ:
5690 os.environ['LD_LIBRARY_PATH'] = ld_path
5691 elif not os.environ['LD_LIBRARY_PATH']:
5692 os.environ['LD_LIBRARY_PATH'] = ld_path
5693 elif ld_path not in os.environ['LD_LIBRARY_PATH']:
5694 os.environ['LD_LIBRARY_PATH'] += ';%s' % ld_path
5695 if self.options['lhapdf'] != 'lhapdf-config':
5696 if misc.which('lhapdf-config') != os.path.realpath(self.options['lhapdf']):
5697 os.environ['PATH'] = '%s:%s' % (os.path.realpath(self.options['lhapdf']),os.environ['PATH'])
5698 else:
5699 raise self.InvalidCmd('lhapdf is required to compile/use SysCalc. Specify his path or install it via install lhapdf6')
5700 if self.options['cpp_compiler']:
5701 make_flags.append('CXX=%s' % self.options['cpp_compiler'])
5702
5703
5704 if logger.level <= logging.INFO:
5705 devnull = open(os.devnull,'w')
5706 try:
5707 misc.call(['make', 'clean'], stdout=devnull, stderr=-2)
5708 except Exception:
5709 pass
5710 if name == 'pythia-pgs':
5711
5712 status = misc.call(['make'], cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
5713 if name in ['golem95','QCDLoop','PJFry']:
5714 status = misc.call(['make','install'],
5715 cwd = os.path.join(MG5DIR, name))
5716 else:
5717 status = misc.call(['make']+make_flags, cwd = os.path.join(MG5DIR, name))
5718 else:
5719 try:
5720 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
5721 except Exception:
5722 pass
5723 if name == 'pythia-pgs':
5724
5725 status = self.compile(mode='', cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
5726 if name in ['golem95','QCDLoop','PJFry']:
5727 status = misc.compile(['install'], mode='',
5728 cwd = os.path.join(MG5DIR, name))
5729 else:
5730 status = self.compile(make_flags, mode='',
5731 cwd = os.path.join(MG5DIR, name))
5732
5733 if not status:
5734 logger.info('Compilation succeeded')
5735 else:
5736
5737 if name == 'pythia-pgs':
5738 to_comment = ['libraries/PGS4/src/stdhep-dir/mcfio/arch_mcfio',
5739 'libraries/PGS4/src/stdhep-dir/src/stdhep_Arch']
5740 for f in to_comment:
5741 f = pjoin(MG5DIR, name, *f.split('/'))
5742 text = "".join(l for l in open(f) if 'fno-second-underscore' not in l)
5743 fsock = open(f,'w').write(text)
5744 try:
5745 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
5746 except Exception:
5747 pass
5748 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
5749 if not status:
5750 logger.info('Compilation succeeded')
5751 else:
5752 logger.warning('Error detected during the compilation. Please check the compilation error and run make manually.')
5753
5754
5755
5756 if args[0] == 'MadAnalysis':
5757 try:
5758 os.system('rm -rf td')
5759 os.mkdir(pjoin(MG5DIR, 'td'))
5760 except Exception, error:
5761 print error
5762 pass
5763
5764 if sys.platform == "darwin":
5765 logger.info('Downloading TD for Mac')
5766 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td_mac_intel.tar.gz'
5767 misc.call(['curl', target, '-otd.tgz'],
5768 cwd=pjoin(MG5DIR,'td'))
5769 misc.call(['tar', '-xzpvf', 'td.tgz'],
5770 cwd=pjoin(MG5DIR,'td'))
5771 files.mv(MG5DIR + '/td/td_mac_intel',MG5DIR+'/td/td')
5772 else:
5773 if sys.maxsize > 2**32:
5774 logger.info('Downloading TD for Linux 64 bit')
5775 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td64/td'
5776 logger.warning('''td program (needed by MadAnalysis) is not compile for 64 bit computer.
5777 In 99% of the case, this is perfectly fine. If you do not have plot, please follow
5778 instruction in https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/TopDrawer .''')
5779 else:
5780 logger.info('Downloading TD for Linux 32 bit')
5781 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td'
5782 misc.call(['wget', target], cwd=pjoin(MG5DIR,'td'))
5783 os.chmod(pjoin(MG5DIR,'td','td'), 0775)
5784 self.options['td_path'] = pjoin(MG5DIR,'td')
5785
5786 if not misc.which('gs'):
5787 logger.warning('''gosthscript not install on your system. This is not required to run MA.
5788 but this prevent to create jpg files and therefore to have the plots in the html output.''')
5789 if sys.platform == "darwin":
5790 logger.warning('''You can download this program at the following link:
5791 http://www.macupdate.com/app/mac/9980/gpl-ghostscript''')
5792
5793 if args[0] == 'Delphes2':
5794 data = open(pjoin(MG5DIR, 'Delphes','data','DetectorCard.dat')).read()
5795 data = data.replace('data/', 'DELPHESDIR/data/')
5796 out = open(pjoin(MG5DIR, 'Template','Common', 'Cards', 'delphes_card_default.dat'), 'w')
5797 out.write(data)
5798 if args[0] == 'Delphes3':
5799 if os.path.exists(pjoin(MG5DIR, 'Delphes','cards')):
5800 card_dir = pjoin(MG5DIR, 'Delphes','cards')
5801 else:
5802 card_dir = pjoin(MG5DIR, 'Delphes','examples')
5803 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
5804 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_default.dat'))
5805 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
5806 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_CMS.dat'))
5807 files.cp(pjoin(card_dir,'delphes_card_ATLAS.tcl'),
5808 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_ATLAS.dat'))
5809
5810
5811
5812 options_name = {'Delphes': 'delphes_path',
5813 'Delphes2': 'delphes_path',
5814 'Delphes3': 'delphes_path',
5815 'ExRootAnalysis': 'exrootanalysis_path',
5816 'MadAnalysis': 'madanalysis_path',
5817 'SysCalc': 'syscalc_path',
5818 'pythia-pgs':'pythia-pgs_path',
5819 'Golem95': 'golem',
5820 'PJFry': 'pjfry'}
5821
5822 if args[0] in options_name:
5823 opt = options_name[args[0]]
5824 if opt=='golem':
5825 self.options[opt] = pjoin(MG5DIR,name,'lib')
5826 self.exec_cmd('save options')
5827 elif opt=='pjfry':
5828 self.options[opt] = pjoin(MG5DIR,'PJFry','lib')
5829 self.exec_cmd('save options')
5830 elif self.options[opt] != self.options_configuration[opt]:
5831 self.options[opt] = self.options_configuration[opt]
5832 self.exec_cmd('save options')
5833
5834
5835
5837 """ check if the current version of mg5 is up-to-date.
5838 and allow user to install the latest version of MG5 """
5839
5840 def apply_patch(filetext):
5841 """function to apply the patch"""
5842 text = filetext.read()
5843 pattern = re.compile(r'''=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
5844
5845 for orig, new in pattern.findall(text):
5846 shutil.copytree(pjoin(MG5DIR, orig), pjoin(MG5DIR, 'UPDATE_TMP'))
5847 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
5848 for i, name in enumerate(full_path):
5849 path = os.path.sep.join(full_path[:i+1])
5850 if path and not os.path.isdir(path):
5851 os.mkdir(path)
5852 shutil.copytree(pjoin(MG5DIR, 'UPDATE_TMP'), pjoin(MG5DIR, new))
5853 shutil.rmtree(pjoin(MG5DIR, 'UPDATE_TMP'))
5854
5855 pattern = re.compile(r'''=== renamed file \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
5856
5857 for orig, new in pattern.findall(text):
5858 print 'move %s to %s' % (orig, new)
5859 try:
5860 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
5861 except IOError:
5862 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
5863 for i, name in enumerate(full_path):
5864 path = os.path.sep.join(full_path[:i+1])
5865 if path and not os.path.isdir(path):
5866 os.mkdir(path)
5867 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
5868
5869 pattern = re.compile(r'''^=== added file \'(?P<new>[^\']*)\'''',re.M)
5870 all_add = pattern.findall(text)
5871
5872
5873 pattern=re.compile(r'''=== removed file \'(?P<new>[^\']*)\'(?=.*=== added file \'(?P=new)\')''',re.S)
5874 print 'this step can take a few minuts. please be patient'
5875 all_rm_add = pattern.findall(text)
5876
5877 for new in all_add:
5878 if new in all_rm_add:
5879 continue
5880 if os.path.isfile(pjoin(MG5DIR, new)):
5881 os.remove(pjoin(MG5DIR, new))
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893 p= subprocess.Popen(['patch', '-p1'], stdin=subprocess.PIPE,
5894 cwd=MG5DIR)
5895 p.communicate(text)
5896
5897
5898
5899
5900
5901 pattern=re.compile('''=== modified file \'(?P<new>[^\']*)\'[^\n]*\n\-\-\- old/(?P<old>\S*)[^\n]*\n\+\+\+ new/(?P=new)''',re.S)
5902 for match in pattern.findall(text):
5903 new = pjoin(MG5DIR, match[0])
5904 old = pjoin(MG5DIR, match[1])
5905 if new == old:
5906 continue
5907 elif os.path.exists(old):
5908 if not os.path.exists(os.path.dirname(new)):
5909 split = new.split('/')
5910 for i in range(1,len(split)):
5911 path = '/'.join(split[:i])
5912 if not os.path.exists(path):
5913 print 'mkdir', path
5914 os.mkdir(path)
5915 files.cp(old,new)
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936 for path in misc.glob('*', pjoin(MG5DIR, 'bin')):
5937 misc.call(['chmod', '+x', path])
5938 for path in misc.glob(pjoin('*','bin','*'), pjoin(MG5DIR, 'Template')):
5939 misc.call(['chmod', '+x', path])
5940 for path in misc.glob(pjoin('*','bin','internal','*'), pjoin(MG5DIR, 'Template')):
5941 misc.call(['chmod', '+x', path])
5942 for path in misc.glob(pjoin('*','*', '*.py'), pjoin(MG5DIR, 'Template')):
5943 misc.call(['chmod', '+x', path])
5944 for path in misc.glob(pjoin('*','*','*.sh'), pjoin(MG5DIR, 'Template')):
5945 misc.call(['chmod', '+x', path])
5946
5947
5948 pattern=re.compile('''^=== touch (file|directory) \'(?P<new>[^\']*)\'''',re.M)
5949 for match in pattern.findall(text):
5950 if match[0] == 'file':
5951 new = os.path.dirname(pjoin(MG5DIR, match[1]))
5952 else:
5953 new = pjoin(MG5DIR, match[1])
5954 if not os.path.exists(new):
5955 split = new.split('/')
5956 for i in range(1,len(split)+1):
5957 path = '/'.join(split[:i])
5958 if path and not os.path.exists(path):
5959 print 'mkdir', path
5960 os.mkdir(path)
5961 if match[0] == 'file':
5962 print 'touch ', pjoin(MG5DIR, match[1])
5963 misc.call(['touch', pjoin(MG5DIR, match[1])])
5964
5965 pattern=re.compile('''^=== link file \'(?P<new>[^\']*)\' \'(?P<old>[^\']*)\'''', re.M)
5966 for new, old in pattern.findall(text):
5967 if not os.path.exists(pjoin(MG5DIR, new)):
5968 files.ln(old, os.path.dirname(new), os.path.basename(new))
5969
5970
5971 if os.path.isfile(pjoin(MG5DIR,'vendor','CutTools','includects','libcts.a')):
5972 misc.compile(cwd=pjoin(MG5DIR,'vendor','CutTools'))
5973 if os.path.isfile(pjoin(MG5DIR,'vendor','IREGI','src','libiregi.a')):
5974 misc.compile(cwd=pjoin(MG5DIR,'vendor','IREGI','src'))
5975
5976
5977 pattern = re.compile("""^Binary files old/(\S*).*and new/(\S*).*$""", re.M)
5978 if pattern.search(text):
5979 return True
5980 else:
5981 return False
5982
5983
5984 mode = [arg.split('=',1)[1] for arg in args if arg.startswith('--mode=')]
5985 if mode:
5986 mode = mode[-1]
5987 else:
5988 mode = "userrequest"
5989 force = any([arg=='-f' for arg in args])
5990 timeout = [arg.split('=',1)[1] for arg in args if arg.startswith('--timeout=')]
5991 if timeout:
5992 try:
5993 timeout = int(timeout[-1])
5994 except ValueError:
5995 raise self.InvalidCmd('%s: invalid argument for timeout (integer expected)'%timeout[-1])
5996 else:
5997 timeout = self.options['timeout']
5998 input_path = [arg.split('=',1)[1] for arg in args if arg.startswith('--input=')]
5999
6000 if input_path:
6001 fsock = open(input_path[0])
6002 need_binary = apply_patch(fsock)
6003 logger.info('manual patch apply. Please test your version.')
6004 if need_binary:
6005 logger.warning('Note that some files need to be loaded separately!')
6006 sys.exit(0)
6007
6008 options = ['y','n','on_exit']
6009 if mode == 'mg5_start':
6010 timeout = 2
6011 default = 'n'
6012 update_delay = self.options['auto_update'] * 24 * 3600
6013 if update_delay == 0:
6014 return
6015 elif mode == 'mg5_end':
6016 timeout = 5
6017 default = 'n'
6018 update_delay = self.options['auto_update'] * 24 * 3600
6019 if update_delay == 0:
6020 return
6021 options.remove('on_exit')
6022 elif mode == "userrequest":
6023 default = 'y'
6024 update_delay = 0
6025 else:
6026 raise self.InvalidCmd('Unknown mode for command install update')
6027
6028 if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')) or \
6029 os.path.exists(os.path.join(MG5DIR,'.bzr')):
6030 error_text = """This version of MG5 doesn\'t support auto-update. Common reasons are:
6031 1) This version was loaded via bazaar (use bzr pull to update instead).
6032 2) This version is a beta release of MG5."""
6033 if mode == 'userrequest':
6034 raise self.ConfigurationError(error_text)
6035 return
6036
6037 if not misc.which('patch'):
6038 error_text = """Not able to find program \'patch\'. Please reload a clean version
6039 or install that program and retry."""
6040 if mode == 'userrequest':
6041 raise self.ConfigurationError(error_text)
6042 return
6043
6044
6045
6046 data = {}
6047 for line in open(os.path.join(MG5DIR,'input','.autoupdate')):
6048 if not line.strip():
6049 continue
6050 sline = line.split()
6051 data[sline[0]] = int(sline[1])
6052
6053
6054 if 'version_nb' not in data:
6055 if mode == 'userrequest':
6056 error_text = 'This version of MG5 doesn\'t support auto-update. (Invalid information)'
6057 raise self.ConfigurationError(error_text)
6058 return
6059 elif 'last_check' not in data:
6060 data['last_check'] = time.time()
6061
6062
6063 if time.time() - data['last_check'] < update_delay:
6064 return
6065
6066 logger.info('Checking if MG5 is up-to-date... (takes up to %ss)' % timeout)
6067 class TimeOutError(Exception): pass
6068
6069 def handle_alarm(signum, frame):
6070 raise TimeOutError
6071
6072 signal.signal(signal.SIGALRM, handle_alarm)
6073 signal.alarm(timeout)
6074 to_update = 0
6075 try:
6076 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/mg5amc_build_nb')
6077 signal.alarm(0)
6078 web_version = int(filetext.read().strip())
6079 except (TimeOutError, ValueError, IOError):
6080 signal.alarm(0)
6081 print 'failed to connect server'
6082 if mode == 'mg5_end':
6083
6084 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6085 fsock.write("version_nb %s\n" % data['version_nb'])
6086 fsock.write("last_check %s\n" % \
6087 int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1))
6088 fsock.close()
6089 return
6090
6091 if web_version == data['version_nb']:
6092 logger.info('No new version of MG5 available')
6093
6094 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6095 fsock.write("version_nb %s\n" % data['version_nb'])
6096 fsock.write("last_check %s\n" % int(time.time()))
6097 fsock.close()
6098 return
6099 elif data['version_nb'] > web_version:
6100 logger_stderr.info('impossible to update: local %s web %s' % (data['version_nb'], web_version))
6101 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6102 fsock.write("version_nb %s\n" % data['version_nb'])
6103 fsock.write("last_check %s\n" % int(time.time()))
6104 fsock.close()
6105 return
6106 else:
6107 if not force:
6108 answer = self.ask('New Version of MG5 available! Do you want to update your current version?',
6109 default, options)
6110 else:
6111 answer = default
6112
6113
6114 if answer == 'y':
6115 logger.info('start updating code')
6116 fail = 0
6117 for i in range(data['version_nb'], web_version):
6118 try:
6119 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/patch/build%s.patch' %(i+1))
6120
6121 except Exception:
6122 print 'fail to load patch to build #%s' % (i+1)
6123 fail = i
6124 break
6125 need_binary = apply_patch(filetext)
6126 if need_binary:
6127 path = "http://madgraph.phys.ucl.ac.be/binary/binary_file%s.tgz" %(i+1)
6128 name = "extra_file%i" % (i+1)
6129 if sys.platform == "darwin":
6130 misc.call(['curl', path, '-o%s.tgz' % name], cwd=MG5DIR)
6131 else:
6132 misc.call(['wget', path, '--output-document=%s.tgz'% name], cwd=MG5DIR)
6133
6134 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
6135 stdout=open(os.devnull, 'w'))
6136
6137 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6138 if not fail:
6139 fsock.write("version_nb %s\n" % web_version)
6140 else:
6141 fsock.write("version_nb %s\n" % fail)
6142 fsock.write("last_check %s\n" % int(time.time()))
6143 fsock.close()
6144
6145
6146 logger.info('Checking current version. (type ctrl-c to bypass the check)')
6147 subprocess.call([os.path.join('tests','test_manager.py')],
6148 cwd=MG5DIR)
6149 print 'new version installed, please relaunch mg5'
6150 sys.exit(0)
6151 elif answer == 'n':
6152
6153 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
6154 fsock.write("version_nb %s\n" % data['version_nb'])
6155 fsock.write("last_check %s\n" % int(time.time()))
6156 fsock.close()
6157 logger.info('Update bypassed.')
6158 logger.info('The next check for a new version will be performed in %s days' \
6159 % abs(self.options['auto_update']))
6160 logger.info('In order to change this delay. Enter the command:')
6161 logger.info('set auto_update X')
6162 logger.info('Putting X to zero will prevent this check at anytime.')
6163 logger.info('You can upgrade your version at any time by typing:')
6164 logger.info('install update')
6165 else:
6166
6167
6168 self.options['auto_update'] = -1 * self.options['auto_update']
6169
6170
6171
6173 """ assign all configuration variable from file
6174 ./input/mg5_configuration.txt. assign to default if not define """
6175
6176 if not self.options:
6177 self.options = dict(self.options_configuration)
6178 self.options.update(self.options_madgraph)
6179 self.options.update(self.options_madevent)
6180
6181 if not config_path:
6182 if os.environ.has_key('MADGRAPH_BASE'):
6183 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
6184 self.set_configuration(config_path, final=False)
6185 if 'HOME' in os.environ:
6186 config_path = pjoin(os.environ['HOME'],'.mg5',
6187 'mg5_configuration.txt')
6188 if os.path.exists(config_path):
6189 self.set_configuration(config_path, final=False)
6190 config_path = os.path.relpath(pjoin(MG5DIR,'input',
6191 'mg5_configuration.txt'))
6192 return self.set_configuration(config_path, final)
6193
6194 if not os.path.exists(config_path):
6195 files.cp(pjoin(MG5DIR,'input','.mg5_configuration_default.txt'), config_path)
6196 config_file = open(config_path)
6197
6198
6199 logger.info('load MG5 configuration from %s ' % config_file.name)
6200 for line in config_file:
6201 if '#' in line:
6202 line = line.split('#',1)[0]
6203 line = line.replace('\n','').replace('\r\n','')
6204 try:
6205 name, value = line.split('=')
6206 except ValueError:
6207 pass
6208 else:
6209 name = name.strip()
6210 value = value.strip()
6211 if name != 'mg5_path':
6212 self.options[name] = value
6213 if value.lower() == "none" or value=="":
6214 self.options[name] = None
6215
6216 self.options['stdout_level'] = logging.getLogger('madgraph').level
6217 if not final:
6218 return self.options
6219
6220
6221
6222
6223 for key in self.options:
6224 if key in ['pythia8_path', 'hwpp_path', 'thepeg_path', 'hepmc_path',
6225 'mg5amc_py8_interface_path']:
6226 if self.options[key] in ['None', None]:
6227 self.options[key] = None
6228 continue
6229 path = self.options[key]
6230
6231 if key == 'pythia8_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Pythia8', 'Pythia.h')):
6232 if not os.path.isfile(pjoin(path, 'include', 'Pythia8', 'Pythia.h')):
6233 self.options['pythia8_path'] = None
6234 else:
6235 continue
6236
6237 if key == 'mg5amc_py8_interface_path' and not os.path.isfile(pjoin(MG5DIR, path, 'MG5aMC_PY8_interface')):
6238 if not os.path.isfile(pjoin(path, 'MG5aMC_PY8_interface')):
6239 self.options['pythia8_path'] = None
6240 else:
6241 continue
6242
6243
6244 elif key == 'hwpp_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
6245 if not os.path.isfile(pjoin(path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
6246 self.options['hwpp_path'] = None
6247 else:
6248 continue
6249
6250 elif key == 'thepeg_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
6251 if not os.path.isfile(pjoin(path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
6252 self.options['thepeg_path'] = None
6253 else:
6254 continue
6255
6256 elif key == 'hepmc_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'HEPEVT_Wrapper.h')):
6257 if not os.path.isfile(pjoin(path, 'include', 'HEPEVT_Wrapper.h')):
6258 self.options['hepmc_path'] = None
6259 else:
6260 continue
6261
6262 elif key in ['pjfry','golem','samurai']:
6263 if isinstance(self.options[key],str) and self.options[key].lower() == 'auto':
6264
6265 program = misc.which_lib('lib%s.a'%key)
6266 if program != None:
6267 fpath, _ = os.path.split(program)
6268 logger.info('Using %s library in %s' % (key,fpath))
6269 self.options[key]=fpath
6270 else:
6271
6272 local_install = {'pjfry':'PJFRY', 'golem':'golem95',
6273 'samurai':'samurai'}
6274 if os.path.isfile(pjoin(MG5DIR,local_install[key],'lib', 'lib%s.a' % key)):
6275 self.options[key]=pjoin(MG5DIR,local_install[key],'lib')
6276 else:
6277 self.options[key]=None
6278
6279 if key=='samurai' and \
6280 isinstance(self.options[key],str) and \
6281 self.options[key].lower() != 'auto':
6282 if os.path.isfile(pjoin(self.options[key],os.pardir,'AUTHORS')):
6283 try:
6284 version = open(pjoin(self.options[key],os.pardir,
6285 'VERSION'),'r').read()
6286 except IOError:
6287 version = None
6288 if version is None:
6289 self.options[key] = None
6290 logger.info('--------')
6291 logger.info(
6292 """The version of 'samurai' automatically detected seems too old to be compatible
6293 with MG5aMC and it will be turned off. Ask the authors for the latest version if
6294 you want to use samurai.
6295 If you want to enforce its use as-it-is, then specify directly its library folder
6296 in the MG5aMC option 'samurai' (instead of leaving it to its default 'auto').""")
6297 logger.info('--------')
6298
6299 elif key.endswith('path'):
6300 pass
6301 elif key in ['run_mode', 'auto_update']:
6302 self.options[key] = int(self.options[key])
6303 elif key in ['cluster_type','automatic_html_opening']:
6304 pass
6305 elif key in ['notification_center']:
6306 if self.options[key] in ['False', 'True']:
6307 self.allow_notification_center = eval(self.options[key])
6308 self.options[key] = self.allow_notification_center
6309 elif key not in ['text_editor','eps_viewer','web_browser', 'stdout_level']:
6310
6311 try:
6312 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
6313 except MadGraph5Error, error:
6314 print error
6315 logger.warning("Option %s from config file not understood" \
6316 % key)
6317 else:
6318 if key in self.options_madgraph:
6319 self.history.append('set %s %s' % (key, self.options[key]))
6320
6321
6322
6323
6324
6325
6326 launch_ext.open_file.configure(self.options)
6327 return self.options
6328
6330 """Check if the files is in a valid export directory and assign it to
6331 export path if if is"""
6332
6333
6334 if self._export_dir:
6335 return
6336
6337 if os.path.exists(pjoin(os.getcwd(), 'Cards')):
6338 self._export_dir = os.getcwd()
6339 return
6340
6341 path_split = filepath.split(os.path.sep)
6342 if len(path_split) > 2 and path_split[-2] == 'Cards':
6343 self._export_dir = os.path.sep.join(path_split[:-2])
6344 return
6345
6347 """Main commands: Ask for editing the parameter and then
6348 Execute the code (madevent/standalone/...)
6349 """
6350
6351
6352 current_options = dict([(name, self.options[name]) for name in self.options_madgraph])
6353 start_cwd = os.getcwd()
6354
6355 args = self.split_arg(line)
6356
6357 (options, args) = _launch_parser.parse_args(args)
6358 self.check_launch(args, options)
6359 options = options.__dict__
6360
6361
6362 if args[0].startswith('standalone'):
6363 if os.path.isfile(os.path.join(os.getcwd(),args[1],'Cards',\
6364 'MadLoopParams.dat')) and not os.path.isfile(os.path.join(\
6365 os.getcwd(),args[1],'SubProcesses','check_poles.f')):
6366 ext_program = launch_ext.MadLoopLauncher(self, args[1], \
6367 options=self.options, **options)
6368 else:
6369 ext_program = launch_ext.SALauncher(self, args[1], \
6370 options=self.options, **options)
6371 elif args[0] == 'madevent':
6372 if options['interactive']:
6373
6374 if isinstance(self, cmd.CmdShell):
6375 ME = madevent_interface.MadEventCmdShell(me_dir=args[1], options=self.options)
6376 else:
6377 ME = madevent_interface.MadEventCmd(me_dir=args[1],options=self.options)
6378 ME.pass_in_web_mode()
6379 stop = self.define_child_cmd_interface(ME)
6380 return stop
6381
6382
6383 if not self._generate_info:
6384
6385
6386 info = open(pjoin(args[1],'SubProcesses','procdef_mg5.dat')).read()
6387 generate_info = info.split('# Begin PROCESS',1)[1].split('\n')[1]
6388 generate_info = generate_info.split('#')[0]
6389 else:
6390 generate_info = self._generate_info
6391
6392 if len(generate_info.split('>')[0].strip().split())>1:
6393 ext_program = launch_ext.MELauncher(args[1], self,
6394 shell = isinstance(self, cmd.CmdShell),
6395 options=self.options,**options)
6396 else:
6397
6398 ext_program = launch_ext.MELauncher(args[1], self, unit='GeV',
6399 shell = isinstance(self, cmd.CmdShell),
6400 options=self.options,**options)
6401
6402 elif args[0] == 'pythia8':
6403 ext_program = launch_ext.Pythia8Launcher( args[1], self, **options)
6404
6405 elif args[0] == 'aMC@NLO':
6406 if options['interactive']:
6407 if isinstance(self, cmd.CmdShell):
6408 ME = amcatnlo_run.aMCatNLOCmdShell(me_dir=args[1], options=self.options)
6409 else:
6410 ME = amcatnlo_run.aMCatNLOCmd(me_dir=args[1],options=self.options)
6411 ME.pass_in_web_mode()
6412
6413 config_line = [l for l in self.history if l.strip().startswith('set')]
6414 for line in config_line:
6415 ME.exec_cmd(line)
6416 stop = self.define_child_cmd_interface(ME)
6417 return stop
6418 ext_program = launch_ext.aMCatNLOLauncher( args[1], self,
6419 shell = isinstance(self, cmd.CmdShell),
6420 **options)
6421 elif args[0] == 'madweight':
6422 import madgraph.interface.madweight_interface as madweight_interface
6423 if options['interactive']:
6424 if isinstance(self, cmd.CmdShell):
6425 MW = madweight_interface.MadWeightCmdShell(me_dir=args[1], options=self.options)
6426 else:
6427 MW = madweight_interface.MadWeightCmd(me_dir=args[1],options=self.options)
6428
6429 config_line = [l for l in self.history if l.strip().startswith('set')]
6430 for line in config_line:
6431 MW.exec_cmd(line)
6432 stop = self.define_child_cmd_interface(MW)
6433 return stop
6434 ext_program = launch_ext.MWLauncher( self, args[1],
6435 shell = isinstance(self, cmd.CmdShell),
6436 options=self.options,**options)
6437 else:
6438 os.chdir(start_cwd)
6439 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
6440
6441
6442 ext_program.run()
6443 os.chdir(start_cwd)
6444
6445 for key, value in current_options.items():
6446 self.options[key] = value
6447
6513
6514
6516 """create a restriction card in a interactive way"""
6517
6518 args = self.split_arg(line)
6519 self.check_customize_model(args)
6520
6521 model_path = self._curr_model.get('modelpath')
6522 if not os.path.exists(pjoin(model_path,'build_restrict.py')):
6523 raise self.InvalidCmd('''Model not compatible with this option.''')
6524
6525
6526 self._curr_model = import_ufo.import_model(model_path, restrict=False)
6527
6528
6529 out_path = StringIO.StringIO()
6530 param_writer.ParamCardWriter(self._curr_model, out_path)
6531
6532 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
6533
6534
6535 all_categories = self.ask('','0',[], ask_class=AskforCustomize)
6536 put_to_one = []
6537
6538 for block in param_card:
6539 value_dict = {}
6540 for param in param_card[block]:
6541 value = param.value
6542 if value == 0:
6543 param.value = 0.000001e-99
6544 elif value == 1:
6545 if block != 'qnumbers':
6546 put_to_one.append((block,param.lhacode))
6547 param.value = random.random()
6548 elif abs(value) in value_dict:
6549 param.value += value_dict[abs(value)] * 1e-4 * param.value
6550 value_dict[abs(value)] += 1
6551 else:
6552 value_dict[abs(value)] = 1
6553
6554 for category in all_categories:
6555 for options in category:
6556 if not options.status:
6557 continue
6558 param = param_card[options.lhablock].get(options.lhaid)
6559 param.value = options.value
6560
6561 logger.info('Loading the resulting model')
6562
6563 self._curr_model = import_ufo.RestrictModel(self._curr_model)
6564 model_name = self._curr_model.get('name')
6565 if model_name == 'mssm':
6566 keep_external=True
6567 else:
6568 keep_external=False
6569 self._curr_model.restrict_model(param_card,keep_external=keep_external)
6570
6571 if args:
6572 name = args[0].split('=',1)[1]
6573 path = pjoin(model_path,'restrict_%s.dat' % name)
6574 logger.info('Save restriction file as %s' % path)
6575 param_card.write(path)
6576 self._curr_model['name'] += '-%s' % name
6577
6578
6579 if put_to_one:
6580 out_path = StringIO.StringIO()
6581 param_writer.ParamCardWriter(self._curr_model, out_path)
6582
6583 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
6584
6585 for (block, lhacode) in put_to_one:
6586 misc.sprint(block, lhacode)
6587 try:
6588 param_card[block].get(lhacode).value = 1
6589 except:
6590 pass
6591 self._curr_model.set_parameters_and_couplings(param_card)
6592
6593 if args:
6594 name = args[0].split('=',1)[1]
6595 path = pjoin(model_path,'paramcard_%s.dat' % name)
6596 logger.info('Save default card file as %s' % path)
6597 param_card.write(path)
6598
6599 - def do_save(self, line, check=True, to_keep={}, log=True):
6600 """Not in help: Save information to file"""
6601
6602 args = self.split_arg(line)
6603
6604 if check:
6605 self.check_save(args)
6606
6607 if args[0] == 'model':
6608 if self._curr_model:
6609
6610 if save_load_object.save_to_file(args[1], self._curr_model):
6611 logger.info('Saved model to file %s' % args[1])
6612 else:
6613 raise self.InvalidCmd('No model to save!')
6614 elif args[0] == 'processes':
6615 if self._curr_amps:
6616 if save_load_object.save_to_file(args[1], self._curr_amps):
6617 logger.info('Saved processes to file %s' % args[1])
6618 else:
6619 raise self.InvalidCmd('No processes to save!')
6620
6621 elif args[0] == 'options':
6622
6623 to_define = {}
6624 for key, default in self.options_configuration.items():
6625 if self.options_configuration[key] != self.options[key] and not self.options_configuration[key] is None:
6626 to_define[key] = self.options[key]
6627
6628 if not '--auto' in args:
6629 for key, default in self.options_madevent.items():
6630 if self.options_madevent[key] != self.options[key] != None:
6631 if '_path' in key and os.path.basename(self.options[key]) == 'None':
6632 continue
6633 to_define[key] = self.options[key]
6634 elif key == 'cluster_queue' and self.options[key] is None:
6635 to_define[key] = self.options[key]
6636
6637 if '--all' in args:
6638 for key, default in self.options_madgraph.items():
6639 if self.options_madgraph[key] != self.options[key] != None and \
6640 key != 'stdout_level':
6641 to_define[key] = self.options[key]
6642 elif not '--auto' in args:
6643 for key, default in self.options_madgraph.items():
6644 if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level':
6645 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
6646 % (key,self.options_madgraph[key]) )
6647 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
6648 if len(args) >1 and not args[1].startswith('--'):
6649 filepath = args[1]
6650 else:
6651 filepath = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
6652 basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt')
6653 basedir = MG5DIR
6654
6655 if to_keep:
6656 to_define = to_keep
6657 self.write_configuration(filepath, basefile, basedir, to_define)
6658
6659
6660 - def do_set(self, line, log=True, model_reload=True):
6661 """Set an option, which will be default for coming generations/outputs.
6662 """
6663
6664
6665
6666 args = self.split_arg(line)
6667
6668
6669 self.check_set(args)
6670
6671 if args[0] == 'ignore_six_quark_processes':
6672 if args[1] == 'False':
6673 self.options[args[0]] = False
6674 return
6675 self.options[args[0]] = list(set([abs(p) for p in \
6676 self._multiparticles[args[1]]\
6677 if self._curr_model.get_particle(p).\
6678 is_fermion() and \
6679 self._curr_model.get_particle(abs(p)).\
6680 get('color') == 3]))
6681 if log:
6682 logger.info('Ignore processes with >= 6 quarks (%s)' % \
6683 ",".join([\
6684 self._curr_model.get_particle(q).get('name') \
6685 for q in self.options[args[0]]]))
6686
6687 elif args[0] == 'group_subprocesses':
6688 if args[1] not in ['Auto', 'NLO']:
6689 self.options[args[0]] = eval(args[1])
6690 else:
6691 self.options[args[0]] = args[1]
6692 if log:
6693 logger.info('Set group_subprocesses to %s' % \
6694 str(self.options[args[0]]))
6695 logger.info('Note that you need to regenerate all processes')
6696 self._curr_amps = diagram_generation.AmplitudeList()
6697 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6698
6699 elif args[0] == "stdout_level":
6700 if args[1].isdigit():
6701 level = int(args[1])
6702 else:
6703 level = eval('logging.' + args[1])
6704 logging.root.setLevel(level)
6705 logging.getLogger('madgraph').setLevel(level)
6706 logging.getLogger('madevent').setLevel(level)
6707 if log:
6708 logger.info('set output information to level: %s' % level)
6709 elif args[0].lower() == "ewscheme":
6710 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." %\
6711 (self._curr_model.get('name'), args[1]))
6712 logger.info("Importing a model will restore the default scheme")
6713 self._curr_model.change_electroweak_mode(args[1])
6714 elif args[0] == "complex_mass_scheme":
6715 old = self.options[args[0]]
6716 self.options[args[0]] = eval(args[1])
6717 aloha.complex_mass = eval(args[1])
6718 aloha_lib.KERNEL.clean()
6719 if self.options[args[0]]:
6720 if old:
6721 if log:
6722 logger.info('Complex mass already activated.')
6723 return
6724 if log:
6725 logger.info('Activate complex mass scheme.')
6726 else:
6727 if not old:
6728 if log:
6729 logger.info('Complex mass already desactivated.')
6730 return
6731 if log:
6732 logger.info('Desactivate complex mass scheme.')
6733 if not self._curr_model:
6734 return
6735 self.exec_cmd('import model %s' % self._curr_model.get('name'))
6736
6737 elif args[0] == "gauge":
6738
6739 if not self._curr_model:
6740 if args[1] == 'unitary':
6741 aloha.unitary_gauge = True
6742 else:
6743 aloha.unitary_gauge = False
6744 aloha_lib.KERNEL.clean()
6745 self.options[args[0]] = args[1]
6746 if log: logger.info('Passing to gauge %s.' % args[1])
6747 return
6748
6749
6750 able_to_mod = True
6751 if args[1] == 'unitary':
6752 if 0 in self._curr_model.get('gauge'):
6753 aloha.unitary_gauge = True
6754 else:
6755 able_to_mod = False
6756 if log: logger.warning('Note that unitary gauge is not allowed for your current model %s' \
6757 % self._curr_model.get('name'))
6758 else:
6759 if 1 in self._curr_model.get('gauge'):
6760 aloha.unitary_gauge = False
6761 else:
6762 able_to_mod = False
6763 if log: logger.warning('Note that Feynman gauge is not allowed for your current model %s' \
6764 % self._curr_model.get('name'))
6765 self.options[args[0]] = args[1]
6766
6767 if able_to_mod and log and args[0] == 'gauge' and \
6768 args[1] == 'unitary' and not self.options['gauge']=='unitary' and \
6769 isinstance(self._curr_model,loop_base_objects.LoopModel) and \
6770 not self._curr_model['perturbation_couplings'] in [[],['QCD']]:
6771 logger.warning('You will only be able to do tree level'+\
6772 ' and QCD corrections in the unitary gauge.')
6773
6774
6775 model_name = self._curr_model.get('modelpath+restriction')
6776 self._curr_model = None
6777 self._curr_amps = diagram_generation.AmplitudeList()
6778 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6779 self._curr_fortran_model = None
6780 self._curr_cpp_model = None
6781 self._curr_exporter = None
6782 self._done_export = False
6783 import_ufo._import_once = []
6784 logger.info('Passing to gauge %s.' % args[1])
6785
6786 if able_to_mod:
6787
6788
6789
6790 MadGraphCmd.do_import(self,'model %s' %model_name, force=True)
6791 elif log:
6792 logger.info('Note that you have to reload the model')
6793
6794 elif args[0] == 'fortran_compiler':
6795 if args[1] != 'None':
6796 if log:
6797 logger.info('set fortran compiler to %s' % args[1])
6798 self.options['fortran_compiler'] = args[1]
6799 else:
6800 self.options['fortran_compiler'] = None
6801 elif args[0] == 'f2py_compiler':
6802 if args[1] != 'None':
6803 if log:
6804 logger.info('set f2py compiler to %s' % args[1])
6805 self.options['f2py_compiler'] = args[1]
6806 else:
6807 self.options['f2py_compiler'] = None
6808
6809 elif args[0] == 'loop_optimized_output':
6810 if log:
6811 logger.info('set loop optimized output to %s' % args[1])
6812 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6813 self.options[args[0]] = args[1]
6814 if not self.options['loop_optimized_output'] and \
6815 self.options['loop_color_flows']:
6816 logger.warning("Turning off option 'loop_color_flows'"+\
6817 " since it is not available for non-optimized loop output.")
6818 self.do_set('loop_color_flows False',log=False)
6819 elif args[0] == 'loop_color_flows':
6820 if log:
6821 logger.info('set loop color flows to %s' % args[1])
6822 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6823 self.options[args[0]] = args[1]
6824 if self.options['loop_color_flows'] and \
6825 not self.options['loop_optimized_output']:
6826 logger.warning("Turning on option 'loop_optimized'"+\
6827 " needed for loop color flow computation.")
6828 self.do_set('loop_optimized_output True',False)
6829
6830 elif args[0] == 'fastjet':
6831 try:
6832 p = subprocess.Popen([args[1], '--version'], stdout=subprocess.PIPE,
6833 stderr=subprocess.PIPE)
6834 output, error = p.communicate()
6835 res = 0
6836 except Exception:
6837 res = 1
6838
6839 if res != 0 or error:
6840 logger.info('%s does not seem to correspond to a valid fastjet-config ' % args[1] + \
6841 'executable (v3+). We will use fjcore instead.\n Please set the \'fastjet\'' + \
6842 'variable to the full (absolute) /PATH/TO/fastjet-config (including fastjet-config).' +
6843 '\n MG5_aMC> set fastjet /PATH/TO/fastjet-config\n')
6844 self.options[args[0]] = None
6845 self.history.pop()
6846 elif int(output.split('.')[0]) < 3:
6847 logger.warning('%s is not ' % args[1] + \
6848 'v3 or greater. Please install FastJet v3+.')
6849 self.options[args[0]] = None
6850 self.history.pop()
6851 else:
6852 logger.info('set fastjet to %s' % args[1])
6853 self.options[args[0]] = args[1]
6854
6855 elif args[0] in ['pjfry','golem','samurai','ninja'] and \
6856 not (args[0]=='ninja' and args[1]=='./HEPTools/lib'):
6857 if args[1] in ['None',"''",'""']:
6858 self.options[args[0]] = None
6859 else:
6860 program = misc.which_lib(os.path.join(args[1],'lib%s.a'%args[0]))
6861 if program!=None:
6862 res = 0
6863 logger.info('set %s to %s' % (args[0],args[1]))
6864 self.options[args[0]] = args[1]
6865 else:
6866 res = 1
6867
6868 if res != 0 :
6869 logger.warning('%s does not seem to correspond to a valid %s lib ' % (args[1],args[0]) + \
6870 '. Please enter the full PATH/TO/%s/lib .\n'%args[0] + \
6871 'You will NOT be able to run %s otherwise.\n'%args[0])
6872
6873 elif args[0] == 'lhapdf':
6874 try:
6875 res = misc.call([args[1], '--version'], stdout=subprocess.PIPE,
6876 stderr=subprocess.PIPE)
6877 logger.info('set lhapdf to %s' % args[1])
6878 self.options[args[0]] = args[1]
6879 except Exception:
6880 res = 1
6881 if res != 0:
6882 logger.info('%s does not seem to correspond to a valid lhapdf-config ' % args[1] + \
6883 'executable. \nPlease set the \'lhapdf\' variable to the (absolute) ' + \
6884 '/PATH/TO/lhapdf-config (including lhapdf-config).\n' + \
6885 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n' + \
6886 ' MG5_aMC> set lhapdf /PATH/TO/lhapdf-config\n')
6887
6888 elif args[0] in ['timeout', 'auto_update', 'cluster_nb_retry',
6889 'cluster_retry_wait', 'cluster_size', 'max_npoint_for_channel']:
6890 self.options[args[0]] = int(args[1])
6891
6892 elif args[0] in ['cluster_local_path']:
6893 self.options[args[0]] = args[1].strip()
6894
6895 elif args[0] == 'cluster_status_update':
6896 if '(' in args[1]:
6897 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
6898 data = data.replace('(','').replace(')','').replace(',',' ').split()
6899 first, second = data[:2]
6900 else:
6901 first, second = args[1:3]
6902
6903 self.options[args[0]] = (int(first), int(second))
6904
6905 elif args[0] == 'OLP':
6906
6907
6908 self._curr_amps = diagram_generation.AmplitudeList()
6909 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6910 self._curr_exporter = None
6911 self.options[args[0]] = args[1]
6912
6913 elif args[0] =='output_dependencies':
6914 self.options[args[0]] = args[1]
6915 elif args[0] =='notification_center':
6916 if args[1] in ['None','True','False']:
6917 self.options[args[0]] = eval(args[1])
6918 self.allow_notification_center = self.options[args[0]]
6919 else:
6920 raise self.InvalidCmd('expected bool for notification_center')
6921 elif args[0] in ['cluster_queue']:
6922 self.options[args[0]] = args[1].strip()
6923 elif args[0] in self.options:
6924 if args[1] in ['None','True','False']:
6925 self.options[args[0]] = eval(args[1])
6926 else:
6927 self.options[args[0]] = args[1]
6928
6929 - def post_set(self, stop, line):
6930 """Check if we need to save this in the option file"""
6931
6932 args = self.split_arg(line)
6933
6934 try:
6935 self.check_set(args, log=False)
6936 except Exception:
6937 return stop
6938
6939 if args[0] in self.options_configuration and '--no_save' not in args:
6940 self.exec_cmd('save options --auto', log=False)
6941 elif args[0] in self.options_madevent:
6942 if not '--no_save' in line:
6943 logger.info('This option will be the default in any output that you are going to create in this session.')
6944 logger.info('In order to keep this changes permanent please run \'save options\'')
6945 else:
6946
6947 if not self.history or self.history[-1].split() != line.split():
6948 self.history.append('set %s' % line)
6949 self.avoid_history_duplicate('set %s' % args[0], ['define', 'set'])
6950 return stop
6951
6961
6963 """Main commands: Initialize a new Template or reinitialize one"""
6964
6965 args = self.split_arg(line)
6966
6967 self.check_output(args)
6968
6969
6970 noclean = '-noclean' in args
6971 force = '-f' in args
6972 nojpeg = '-nojpeg' in args
6973 flaglist = []
6974
6975 if '--postpone_model' in args:
6976 flaglist.append('store_model')
6977
6978 main_file_name = ""
6979 try:
6980 main_file_name = args[args.index('-name') + 1]
6981 except Exception:
6982 pass
6983
6984
6985
6986
6987
6988 if self._export_format == 'aloha':
6989
6990 format = [d[9:] for d in args if d.startswith('--format=')]
6991 if not format:
6992 format = 'Fortran'
6993 else:
6994 format = format[-1]
6995
6996 output = [d for d in args if d.startswith('--output=')]
6997 if not output:
6998 output = import_ufo.find_ufo_path(self._curr_model['name'])
6999 output = pjoin(output, format)
7000 if not os.path.isdir(output):
7001 os.mkdir(output)
7002 else:
7003 output = output[-1]
7004 if not os.path.isdir(output):
7005 raise self.InvalidCmd('%s is not a valid directory' % output)
7006 logger.info('creating routines in directory %s ' % output)
7007
7008 names = [d for d in args if not d.startswith('-')]
7009 wanted_lorentz = aloha_fct.guess_routine_from_name(names)
7010
7011 aloha_model = create_aloha.AbstractALOHAModel(self._curr_model.get('name'))
7012 aloha_model.add_Lorentz_object(self._curr_model.get('lorentz'))
7013 if wanted_lorentz:
7014 aloha_model.compute_subset(wanted_lorentz)
7015 else:
7016 aloha_model.compute_all(save=False)
7017 aloha_model.write(output, format)
7018 return
7019
7020
7021
7022
7023
7024
7025
7026
7027 config = {}
7028 config['madevent'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7029 config['matrix'] = {'check': False, 'exporter': 'v4', 'output':'dir'}
7030 config['standalone'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7031 config['standalone_msF'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7032 config['standalone_msP'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7033 config['standalone_rw'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
7034 config['standalone_cpp'] = {'check': False, 'exporter': 'cpp', 'output': 'Template'}
7035 config['pythia8'] = {'check': False, 'exporter': 'cpp', 'output':'dir'}
7036 config['matchbox_cpp'] = {'check': True, 'exporter': 'cpp', 'output': 'Template'}
7037 config['matchbox'] = {'check': True, 'exporter': 'v4', 'output': 'Template'}
7038 config['madweight'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
7039
7040 options = config[self._export_format]
7041
7042 if os.path.realpath(self._export_dir) == os.getcwd():
7043 if len(args) == 0:
7044 i=0
7045 while 1:
7046 if os.path.exists('Pythia8_proc_%i' %i):
7047 i+=1
7048 else:
7049 break
7050 os.mkdir('Pythia8_proc_%i' %i)
7051 self._export_dir = pjoin(self._export_dir, 'Pythia8_proc_%i' %i)
7052 logger.info('Create output in %s' % self._export_dir)
7053 elif not args[0] in ['.', '-f']:
7054 raise self.InvalidCmd, 'Wrong path directory to create in local directory use \'.\''
7055 elif not noclean and os.path.isdir(self._export_dir) and options['check']:
7056 if not force:
7057
7058 logger.info('INFO: directory %s already exists.' % self._export_dir)
7059 logger.info('If you continue this directory will be deleted and replaced.')
7060 answer = self.ask('Do you want to continue?', 'y', ['y','n'])
7061 else:
7062 answer = 'y'
7063 if answer != 'y':
7064 raise self.InvalidCmd('Stopped by user request')
7065 else:
7066 shutil.rmtree(self._export_dir)
7067
7068
7069
7070 if self.options['group_subprocesses'] in [True, False]:
7071 group_processes = self.options['group_subprocesses']
7072 elif self.options['group_subprocesses'] == 'Auto':
7073
7074 group_processes = True
7075
7076
7077
7078
7079 if self._curr_amps[0].get_ninitial() == 1 and \
7080 len(self._curr_amps)>1:
7081 processes = [amp.get('process') for amp in self._curr_amps]
7082 if len(set(proc.get('id') for proc in processes))!=len(processes):
7083
7084 if any(proc['perturbation_couplings'] != [] for proc in
7085 processes) and self._export_format == 'madevent':
7086 logger.warning("""
7087 || The loop-induced decay process you have specified contains several
7088 || subprocesses and, in order to be able to compute individual branching ratios,
7089 || MG5_aMC will *not* group them. Integration channels will also be considered
7090 || for each diagrams and as a result integration will be inefficient.
7091 || It is therefore recommended to perform this simulation by setting the MG5_aMC
7092 || option 'group_subprocesses' to 'True' (before the output of the process).
7093 || Notice that when doing so, processes for which one still wishes to compute
7094 || branching ratios independently can be specified using the syntax:
7095 || -> add process <proc_def>
7096 """)
7097 group_processes = False
7098
7099
7100 if options['exporter'] == 'v4':
7101 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
7102 group_subprocesses=group_processes)
7103 if options['output'] == 'Template':
7104 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name'))
7105 if options['exporter'] == 'cpp' and options['output'] == 'Template':
7106 export_cpp.setup_cpp_standalone_dir(self._export_dir, self._curr_model)
7107
7108 if options['output'] == 'dir' and not os.path.isdir(self._export_dir):
7109 os.makedirs(self._export_dir)
7110
7111
7112 self._done_export = False
7113
7114 if self._export_format == "madevent":
7115
7116
7117 if self.options['max_npoint_for_channel']:
7118 base_objects.Vertex.max_n_loop_for_multichanneling = self.options['max_npoint_for_channel']
7119 else:
7120 base_objects.Vertex.max_n_loop_for_multichanneling = 3
7121
7122
7123 self.export(nojpeg, main_file_name, group_processes, args)
7124
7125
7126 self.finalize(nojpeg, flaglist=flaglist)
7127
7128
7129 self._done_export = (self._export_dir, self._export_format)
7130
7131
7132 self._export_dir = None
7133
7134
7135 - def export(self, nojpeg = False, main_file_name = "", group_processes=True,
7136 args=[]):
7137 """Export a generated amplitude to file."""
7138
7139 version = [arg[10:] for arg in args if arg.startswith('--version=')]
7140 if version:
7141 version = version[-1]
7142 else:
7143 version = ''
7144
7145 def generate_matrix_elements(self, group_processes=True):
7146 """Helper function to generate the matrix elements before
7147 exporting. Uses the main function argument 'group_processes' to decide
7148 whether to use group_subprocess or not. (it has been set in do_output to
7149 the appropriate value if the MG5 option 'group_subprocesses' was set
7150 to 'Auto'."""
7151
7152 if self._export_format in ['standalone_msP', 'standalone_msF', 'standalone_mw']:
7153 to_distinguish = []
7154 for part in self._curr_model.get('particles'):
7155 if part.get('name') in args and part.get('antiname') in args and\
7156 part.get('name') != part.get('antiname'):
7157 to_distinguish.append(abs(part.get('pdg_code')))
7158
7159
7160 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \
7161 a1.get_number_of_diagrams())
7162
7163 cpu_time1 = time.time()
7164 ndiags = 0
7165 if not self._curr_matrix_elements.get_matrix_elements():
7166 if group_processes:
7167 cpu_time1 = time.time()
7168 dc_amps = diagram_generation.DecayChainAmplitudeList(\
7169 [amp for amp in self._curr_amps if isinstance(amp, \
7170 diagram_generation.DecayChainAmplitude)])
7171 non_dc_amps = diagram_generation.AmplitudeList(\
7172 [amp for amp in self._curr_amps if not \
7173 isinstance(amp, \
7174 diagram_generation.DecayChainAmplitude)])
7175 subproc_groups = group_subprocs.SubProcessGroupList()
7176 matrix_elements_opts = {'optimized_output':
7177 self.options['loop_optimized_output']}
7178 if non_dc_amps:
7179 subproc_groups.extend(\
7180 group_subprocs.SubProcessGroup.group_amplitudes(\
7181 non_dc_amps, self._export_format,
7182 matrix_elements_opts=matrix_elements_opts))
7183
7184 if dc_amps:
7185 dc_subproc_group = \
7186 group_subprocs.DecayChainSubProcessGroup.\
7187 group_amplitudes(dc_amps, self._export_format,
7188 matrix_elements_opts=matrix_elements_opts)
7189 subproc_groups.extend(dc_subproc_group.\
7190 generate_helas_decay_chain_subproc_groups())
7191
7192 ndiags = sum([len(m.get('diagrams')) for m in \
7193 subproc_groups.get_matrix_elements()])
7194 self._curr_matrix_elements = subproc_groups
7195
7196 uid = 0
7197 for group in subproc_groups:
7198 uid += 1
7199 for me in group.get('matrix_elements'):
7200 me.get('processes')[0].set('uid', uid)
7201 else:
7202 mode = {}
7203 if self._export_format in [ 'standalone_msP' ,
7204 'standalone_msF', 'standalone_rw']:
7205 mode['mode'] = 'MadSpin'
7206
7207
7208 if isinstance(self._curr_amps[0],
7209 loop_diagram_generation.LoopAmplitude):
7210 mode['optimized_output']=self.options['loop_optimized_output']
7211 HelasMultiProcessClass = loop_helas_objects.LoopHelasProcess
7212 compute_loop_nc = True
7213 else:
7214 HelasMultiProcessClass = helas_objects.HelasMultiProcess
7215 compute_loop_nc = False
7216
7217 self._curr_matrix_elements = HelasMultiProcessClass(
7218 self._curr_amps, compute_loop_nc=compute_loop_nc,
7219 matrix_element_opts=mode)
7220
7221 ndiags = sum([len(me.get('diagrams')) for \
7222 me in self._curr_matrix_elements.\
7223 get_matrix_elements()])
7224
7225 uid = 0
7226 for me in self._curr_matrix_elements.get_matrix_elements()[:]:
7227 uid += 1
7228 me.get('processes')[0].set('uid', uid)
7229
7230 cpu_time2 = time.time()
7231
7232
7233 return ndiags, cpu_time2 - cpu_time1
7234
7235
7236
7237 ndiags, cpu_time = generate_matrix_elements(self,group_processes)
7238
7239 calls = 0
7240
7241 path = self._export_dir
7242 if self._export_format in ['standalone_cpp', 'madevent', 'standalone',
7243 'standalone_msP', 'standalone_msF', 'standalone_rw',
7244 'matchbox_cpp', 'madweight', 'matchbox']:
7245 path = pjoin(path, 'SubProcesses')
7246
7247 cpu_time1 = time.time()
7248
7249
7250
7251
7252
7253 if self._export_format == 'madevent':
7254 calls += self._curr_exporter.export_processes(self._curr_matrix_elements,
7255 self._curr_fortran_model)
7256
7257
7258 card_path = pjoin(path, os.path.pardir, 'SubProcesses', \
7259 'procdef_mg5.dat')
7260 if self._generate_info:
7261 self._curr_exporter.write_procdef_mg5(card_path,
7262 self._curr_model['name'],
7263 self._generate_info)
7264 try:
7265 cmd.Cmd.onecmd(self, 'history .')
7266 except Exception:
7267 misc.sprint('command history fails.', 10)
7268 pass
7269
7270
7271 if self._export_format == 'pythia8':
7272
7273 process_names = []
7274 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
7275 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
7276 exporter = export_cpp.generate_process_files_pythia8(\
7277 me_group.get('matrix_elements'), self._curr_cpp_model,
7278 process_string = me_group.get('name'),
7279 process_number = group_number, path = path,
7280 version = version)
7281 process_names.append(exporter.process_name)
7282 else:
7283 exporter = export_cpp.generate_process_files_pythia8(\
7284 self._curr_matrix_elements, self._curr_cpp_model,
7285 process_string = self._generate_info, path = path)
7286 process_names.append(exporter.process_file_name)
7287
7288
7289 model_name, model_path = exporter.convert_model_to_pythia8(\
7290 self._curr_model, self._export_dir)
7291
7292
7293 filename, make_filename = \
7294 export_cpp.generate_example_file_pythia8(path,
7295 model_path,
7296 process_names,
7297 exporter,
7298 main_file_name)
7299
7300
7301 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
7302
7303
7304 if self._export_format == 'madweight':
7305
7306 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
7307
7308 self._curr_matrix_elements = self._curr_matrix_elements.split_lepton_grouping()
7309
7310 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
7311 calls = calls + \
7312 self._curr_exporter.generate_subprocess_directory_v4(\
7313 me_group, self._curr_fortran_model,
7314 group_number)
7315 else:
7316 for me_number, me in \
7317 enumerate(self._curr_matrix_elements.get_matrix_elements()):
7318 calls = calls + \
7319 self._curr_exporter.generate_subprocess_directory_v4(\
7320 me, self._curr_fortran_model, me_number)
7321
7322
7323 if self._export_format in ['standalone', 'standalone_msP',
7324 'standalone_msF', 'standalone_rw', 'matchbox']:
7325 for me in matrix_elements[:]:
7326 new_calls = self._curr_exporter.generate_subprocess_directory_v4(\
7327 me, self._curr_fortran_model)
7328 if not new_calls:
7329 matrix_elements.remove(me)
7330 calls = calls + new_calls
7331
7332
7333 if self._export_format == 'matrix':
7334 for me in matrix_elements:
7335 filename = pjoin(path, 'matrix_' + \
7336 me.get('processes')[0].shell_string() + ".f")
7337 if os.path.isfile(filename):
7338 logger.warning("Overwriting existing file %s" % filename)
7339 else:
7340 logger.info("Creating new file %s" % filename)
7341 calls = calls + self._curr_exporter.write_matrix_element_v4(\
7342 writers.FortranWriter(filename),\
7343 me, self._curr_fortran_model)
7344
7345
7346 if self._export_format in ['standalone_cpp', 'matchbox_cpp']:
7347 for me in matrix_elements:
7348 export_cpp.generate_subprocess_directory_standalone_cpp(\
7349 me, self._curr_cpp_model,
7350 path = path,
7351 format=self._export_format)
7352
7353 cpu_time2 = time.time() - cpu_time1
7354
7355 logger.info(("Generated helas calls for %d subprocesses " + \
7356 "(%d diagrams) in %0.3f s") % \
7357 (len(matrix_elements),
7358 ndiags, cpu_time))
7359
7360 if calls:
7361 if "cpu_time2" in locals():
7362 logger.info("Wrote files for %d helas calls in %0.3f s" % \
7363 (calls, cpu_time2))
7364 else:
7365 logger.info("Wrote files for %d helas calls" % \
7366 (calls))
7367
7368 if self._export_format == 'pythia8':
7369 logger.info("- All necessary files for Pythia 8 generated.")
7370 logger.info("- Run \"launch\" and select %s.cc," % filename)
7371 logger.info(" or go to %s/examples and run" % path)
7372 logger.info(" make -f %s" % make_filename)
7373 logger.info(" (with process_name replaced by process name).")
7374 logger.info(" You can then run ./%s to produce events for the process" % \
7375 filename)
7376
7377
7378
7379
7380 self._curr_amps = diagram_generation.AmplitudeList(\
7381 [me.get('base_amplitude') for me in \
7382 matrix_elements])
7383
7384 - def finalize(self, nojpeg, online = False, flaglist=[]):
7385 """Make the html output, write proc_card_mg5.dat and create
7386 madevent.tar.gz for a MadEvent directory"""
7387
7388 compiler_dict = {'fortran': self.options['fortran_compiler'],
7389 'cpp': self.options['cpp_compiler'],
7390 'f2py': self.options['f2py_compiler']}
7391
7392
7393 if self._export_format in ['madevent', 'standalone', 'standalone_msP',
7394 'standalone_msF', 'standalone_rw', 'NLO', 'madweight',
7395 'matchbox']:
7396
7397
7398 if self._model_v4_path:
7399 logger.info('Copy %s model files to directory %s' % \
7400 (os.path.basename(self._model_v4_path), self._export_dir))
7401 self._curr_exporter.export_model_files(self._model_v4_path)
7402 self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS'))
7403 else:
7404 logger.info('Export UFO model to MG4 format')
7405
7406
7407
7408 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
7409 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
7410
7411
7412 if hasattr(self, 'previous_lorentz'):
7413 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz))
7414 wanted_couplings = list(set(self.previous_couplings + wanted_couplings))
7415 del self.previous_lorentz
7416 del self.previous_couplings
7417 if 'store_model' in flaglist:
7418 self.previous_lorentz = wanted_lorentz
7419 self.previous_couplings = wanted_couplings
7420 else:
7421 self._curr_exporter.convert_model_to_mg4(self._curr_model,
7422 wanted_lorentz,
7423 wanted_couplings)
7424 if self._export_format in ['standalone_cpp', 'matchbox_cpp']:
7425 logger.info('Export UFO model to C++ format')
7426
7427
7428
7429 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
7430 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
7431 export_cpp.convert_model_to_cpp(self._curr_model,
7432 pjoin(self._export_dir),
7433 wanted_lorentz,
7434 wanted_couplings)
7435 export_cpp.make_model_cpp(self._export_dir)
7436
7437
7438 elif self._export_format in ['NLO']:
7439
7440 devnull = os.open(os.devnull, os.O_RDWR)
7441 try:
7442 res = misc.call([self.options['lhapdf'], '--version'], \
7443 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
7444 except Exception:
7445 res = 1
7446 if res != 0:
7447 logger.info('The value for lhapdf in the current configuration does not ' + \
7448 'correspond to a valid executable.\nPlease set it correctly either in ' + \
7449 'input/mg5_configuration or with "set lhapdf /path/to/lhapdf-config" ' + \
7450 'and regenrate the process. \nTo avoid regeneration, edit the ' + \
7451 ('%s/Cards/amcatnlo_configuration.txt file.\n' % self._export_dir ) + \
7452 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n')
7453
7454
7455
7456 self._curr_exporter.finalize_fks_directory( \
7457 self._curr_matrix_elements,
7458 self.history,
7459 not nojpeg,
7460 online,
7461 compiler_dict,
7462 output_dependencies = self.options['output_dependencies'],
7463 MG5DIR = MG5DIR)
7464
7465
7466 filename = os.path.join(self._export_dir, 'Cards', 'amcatnlo_configuration.txt')
7467 opts_to_keep = ['lhapdf', 'fastjet', 'pythia8_path', 'hwpp_path', 'thepeg_path',
7468 'hepmc_path']
7469 to_keep = {}
7470 for opt in opts_to_keep:
7471 if self.options[opt]:
7472 to_keep[opt] = self.options[opt]
7473 self.do_save('options %s' % filename.replace(' ', '\ '), check=False, \
7474 to_keep = to_keep)
7475
7476 elif self._export_format in ['madevent', 'madweight']:
7477
7478 filename = os.path.join(self._export_dir, 'Cards', 'me5_configuration.txt')
7479 self.do_save('options %s' % filename.replace(' ', '\ '), check=False,
7480 to_keep={'mg5_path':MG5DIR})
7481
7482 if self._export_format in ['madevent', 'standalone', 'standalone_msP', 'standalone_msF',
7483 'standalone_rw', 'madweight', 'matchbox']:
7484
7485 self._curr_exporter.finalize_v4_directory( \
7486 self._curr_matrix_elements,
7487 self.history,
7488 not nojpeg,
7489 online,
7490 compiler_dict)
7491
7492 if self._export_format in ['madevent', 'standalone', 'standalone_cpp','madweight', 'matchbox']:
7493 logger.info('Output to directory ' + self._export_dir + ' done.')
7494
7495 if self._export_format in ['madevent', 'NLO']:
7496 logger.info('Type \"launch\" to generate events from this process, or see')
7497 logger.info(self._export_dir + '/README')
7498 logger.info('Run \"open index.html\" to see more information about this process.')
7499
7501 """ propose some usefull possible action """
7502
7503 super(MadGraphCmd,self).do_help(line)
7504
7505 if line:
7506 return
7507
7508 if len(self.history) == 0:
7509 last_action_2 = 'mg5_start'
7510 last_action = 'mg5_start'
7511 else:
7512 args = self.history[-1].split()
7513 last_action = args[0]
7514 if len(args)>1:
7515 last_action_2 = '%s %s' % (last_action, args[1])
7516 else:
7517 last_action_2 = 'none'
7518
7519
7520
7521
7523 """Documented commands:Generate amplitudes for decay width calculation, with fixed
7524 number of final particles (called level)
7525 syntax; compute_widths particle [other particles] [--options=]
7526
7527 - particle/other particles can also be multiparticle name (can also be
7528 pid of the particle)
7529
7530 --body_decay=X [default=4.0025] allow to choose the precision.
7531 if X is an integer: compute all X body decay
7532 if X is a float <1: compute up to the time that total error < X
7533 if X is a float >1: stops at the first condition.
7534
7535 --path=X. Use a given file for the param_card. (default UFO built-in)
7536
7537 special argument:
7538 - skip_2body: allow to not consider those decay (use FR)
7539 - model: use the model pass in argument.
7540
7541 """
7542
7543
7544
7545 self.change_principal_cmd('MadGraph')
7546 if '--nlo' not in line:
7547 warning_text = """Please note that the automatic computation of the width is
7548 only valid in narrow-width approximation and at tree-level."""
7549 logger.warning(warning_text)
7550
7551 if not model:
7552 modelname = self._curr_model.get('modelpath+restriction')
7553 with misc.MuteLogger(['madgraph'], ['INFO']):
7554 model = import_ufo.import_model(modelname, decay=True)
7555 else:
7556 self._curr_model = model
7557 self._curr_fortran_model = \
7558 helas_call_writers.FortranUFOHelasCallWriter(self._curr_model)
7559 if not isinstance(model, model_reader.ModelReader):
7560 model = model_reader.ModelReader(model)
7561
7562 if '--nlo' in line:
7563
7564 self.compute_widths_SMWidth(line, model=model)
7565 return
7566
7567
7568 particles, opts = self.check_compute_widths(self.split_arg(line))
7569
7570 if opts['path']:
7571 correct = True
7572 param_card = check_param_card.ParamCard(opts['path'])
7573 for param in param_card['decay']:
7574 if param.value == "auto":
7575 param.value = 1
7576 param.format = 'float'
7577 correct = False
7578 if not correct:
7579 if opts['output']:
7580 param_card.write(opts['output'])
7581 opts['path'] = opts['output']
7582 else:
7583 param_card.write(opts['path'])
7584
7585 data = model.set_parameters_and_couplings(opts['path'])
7586
7587
7588 if do2body:
7589 skip_2body = True
7590 decay_info = {}
7591 for pid in particles:
7592 particle = model.get_particle(pid)
7593 if not hasattr(particle, 'partial_widths'):
7594 skip_2body = False
7595 break
7596 elif not decay_info:
7597 logger_mg.info('Get two body decay from FeynRules formula')
7598 decay_info[pid] = []
7599 mass = abs(eval(str(particle.get('mass')), data).real)
7600 data = model.set_parameters_and_couplings(opts['path'], scale= mass)
7601 total = 0
7602
7603 for mode, expr in particle.partial_widths.items():
7604 tmp_mass = mass
7605 for p in mode:
7606 try:
7607 value_mass = eval(str(p.mass), data)
7608 except Exception:
7609
7610
7611 value_mass = eval(str(model.get_particle(p.pdg_code).get('mass')), data)
7612 tmp_mass -= abs(value_mass)
7613 if tmp_mass <=0:
7614 continue
7615
7616 decay_to = [p.get('pdg_code') for p in mode]
7617 value = eval(expr,{'cmath':cmath},data).real
7618 if -1e-10 < value < 0:
7619 value = 0
7620 if -1e-5 < value < 0:
7621 logger.warning('Partial width for %s > %s negative: %s automatically set to zero' %
7622 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value))
7623 value = 0
7624 elif value < 0:
7625 raise Exception, 'Partial width for %s > %s negative: %s' % \
7626 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value)
7627 elif value < 0.1 and particle['color'] !=1:
7628 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
7629 % (particle.get('name'), value, decay_to))
7630 value = 0
7631
7632 decay_info[particle.get('pdg_code')].append([decay_to, value])
7633 total += value
7634 else:
7635 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
7636 opts['path'], opts['output'])
7637 if float(opts['body_decay']) == 2:
7638 return
7639 else:
7640 skip_2body = True
7641
7642
7643
7644
7645 self.do_decay_diagram('%s %s' % (' '.join([`id` for id in particles]),
7646 ' '.join('--%s=%s' % (key,value)
7647 for key,value in opts.items()
7648 if key not in ['precision_channel'])
7649 ), skip_2body=skip_2body)
7650
7651 if self._curr_amps:
7652 logger.info('Pass to numerical integration for computing the widths:')
7653 else:
7654 logger.info('No need for N body-decay (N>2). Results are in %s' % opts['output'])
7655
7656
7657
7658 return
7659
7660
7661 with misc.TMP_directory(dir=os.getcwd()) as path:
7662 decay_dir = pjoin(path,'temp_decay')
7663 logger_mg.info('More info in temporary files:\n %s/index.html' % (decay_dir))
7664 with misc.MuteLogger(['madgraph','ALOHA','cmdprint','madevent'], [40,40,40,40]):
7665 self.exec_cmd('output %s -f' % decay_dir)
7666
7667 if os.path.exists(opts['output']):
7668 files.cp(opts['output'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
7669 else:
7670 files.cp(opts['path'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
7671 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
7672 check_param_card.convert_to_slha1(pjoin(decay_dir, 'Cards', 'param_card.dat'))
7673
7674 me_cmd = madevent_interface.MadEventCmd(decay_dir)
7675
7676 me_cmd.model_name = self._curr_model['name']
7677 me_cmd.options['automatic_html_opening'] = False
7678
7679 me_opts=[('accuracy', opts['precision_channel']),
7680 ('points', 1000),
7681 ('iterations',9)]
7682 me_cmd.exec_cmd('survey decay -f %s' % (
7683 " ".join(['--%s=%s' % val for val in me_opts])),
7684 postcmd=False)
7685 me_cmd.exec_cmd('combine_events', postcmd=False)
7686
7687 me_cmd.collect_decay_widths()
7688 me_cmd.do_quit('')
7689
7690 del me_cmd
7691
7692 param = check_param_card.ParamCard(pjoin(decay_dir, 'Events', 'decay','param_card.dat'))
7693
7694 for pid in particles:
7695 width = param['decay'].get((pid,)).value
7696 particle = self._curr_model.get_particle(pid)
7697
7698
7699
7700
7701
7702
7703 if not pid in param['decay'].decay_table:
7704 continue
7705 if pid not in decay_info:
7706 decay_info[pid] = []
7707 for BR in param['decay'].decay_table[pid]:
7708 if len(BR.lhacode) == 3 and skip_2body:
7709 continue
7710 if BR.value * width <0.1 and particle['color'] !=1:
7711 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
7712 % (particle.get('name'), BR.value * width, BR.lhacode[1:]))
7713
7714 continue
7715
7716 decay_info[pid].append([BR.lhacode[1:], BR.value * width])
7717
7718 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
7719 opts['path'], opts['output'])
7720
7721 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
7722 check_param_card.convert_to_slha1(opts['output'])
7723 return
7724
7725
7726
7727
7729 """Compute widths with SMWidth.
7730 """
7731
7732
7733 particles, opts = self.check_compute_widths(self.split_arg(line))
7734
7735 if opts['path']:
7736 correct = True
7737 param_card = check_param_card.ParamCard(opts['path'])
7738 for param in param_card['decay']:
7739 if param.value == "auto":
7740 param.value = 1
7741 param.format = 'float'
7742 correct = False
7743 if not correct:
7744 if opts['output']:
7745 param_card.write(opts['output'])
7746 opts['path'] = opts['output']
7747 else:
7748 param_card.write(opts['path'])
7749
7750 if not model:
7751 model_path = self._curr_model.get('modelpath')
7752 model_name = self._curr_model.get('name')
7753 currmodel = self._curr_model
7754 else:
7755 model_path = model.get('modelpath')
7756 model_name = model.get('name')
7757 currmodel = model
7758
7759 if not os.path.exists(pjoin(model_path, 'SMWidth')):
7760 raise self.InvalidCmd, "Model %s is not valid for computing NLO width with SMWidth"%model_name
7761
7762
7763 externparam = [(param.lhablock.lower(),param.name.lower()) for param \
7764 in currmodel.get('parameters')[('external',)]]
7765
7766 if ('sminputs','aewm1') in externparam:
7767
7768 arg2 = "1"
7769 elif ('sminputs','mdl_gf') in externparam or ('sminputs','gf') in externparam:
7770
7771 arg2 = "2"
7772 else:
7773 raise Exception, "Do not know the EW scheme in the model %s"%model_name
7774
7775
7776 if not os.path.exists(pjoin(model_path, 'SMWidth','smwidth')):
7777 logger.info('Compiling SMWidth. This has to be done only once and'+\
7778 ' can take a couple of minutes.','$MG:color:BLACK')
7779 current = misc.detect_current_compiler(pjoin(model_path, 'SMWidth',
7780 'makefile_MW5'))
7781 new = 'gfortran' if self.options_configuration['fortran_compiler'] is None else \
7782 self.options_configuration['fortran_compiler']
7783 if current != new:
7784 misc.mod_compilator(pjoin(model_path, 'SMWidth'), new, current)
7785 misc.mod_compilator(pjoin(model_path, 'SMWidth','oneloop'), new, current)
7786 misc.mod_compilator(pjoin(model_path, 'SMWidth','hdecay'), new, current)
7787 misc.compile(cwd=pjoin(model_path, 'SMWidth'))
7788
7789
7790 identpath=" "
7791 carddir=os.path.dirname(opts['path'])
7792 if 'ident_card.dat' in os.listdir(carddir):
7793 identpath=pjoin(carddir,'ident_card.dat')
7794
7795 output,error = misc.Popen(['./smwidth',opts['path'],identpath,arg2],
7796 stdout=subprocess.PIPE,
7797 stdin=subprocess.PIPE,
7798 cwd=pjoin(model_path, 'SMWidth')).communicate()
7799 pattern = re.compile(r''' decay\s+(\+?\-?\d+)\s+(\+?\-?\d+\.\d+E\+?\-?\d+)''',re.I)
7800 width_list = pattern.findall(output)
7801 width_dict = {}
7802 for pid,width in width_list:
7803 width_dict[int(pid)] = float(width)
7804
7805 for pid in particles:
7806 if not pid in width_dict:
7807 width = 0
7808 else:
7809 width = width_dict[pid]
7810 param = param_card['decay'].get((pid,))
7811 param.value = width
7812 param.format = 'float'
7813 if pid not in param_card['decay'].decay_table:
7814 continue
7815 del param_card['decay'].decay_table[pid]
7816
7817 if opts['output']:
7818 param_card.write(opts['output'])
7819 logger.info('Results are written in %s' % opts['output'])
7820 else:
7821 param_card.write(opts['path'])
7822 logger.info('Results are written in %s' % opts['path'])
7823 return
7824
7825
7827 """Not in help: Generate amplitudes for decay width calculation, with fixed
7828 number of final particles (called level)
7829 syntax; decay_diagram part_name level param_path
7830 args; part_name level param_path
7831 part_name = name of the particle you want to calculate width
7832 level = a.) when level is int,
7833 it means the max number of decay products
7834 b.) when level is float,
7835 it means the required precision for width.
7836 param_path = path for param_card
7837 (this is necessary to determine whether a channel is onshell or not)
7838 e.g. calculate width for higgs up to 2-body decays.
7839 calculate_width h 2 [path]
7840 N.B. param_card must be given so that the program knows which channel
7841 is on shell and which is not.
7842
7843 special argument:
7844 - skip_2body: allow to not consider those decay (use FR)
7845 - model: use the model pass in argument.
7846 """
7847
7848 if model:
7849 self._curr_model = model
7850
7851 args = self.split_arg(line)
7852
7853 particles, args = self.check_decay_diagram(args)
7854
7855 pids = particles
7856 level = float(args['body_decay'])
7857 param_card_path = args['path']
7858 min_br = float(args['min_br'])
7859
7860
7861 self._curr_amps = diagram_generation.AmplitudeList()
7862
7863 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
7864
7865 self._done_export = False
7866
7867 self._export_format = None
7868
7869
7870
7871 if not model:
7872 self._curr_decaymodel = decay_objects.DecayModel(self._curr_model,
7873 True)
7874 self._curr_decaymodel.read_param_card(param_card_path)
7875 else:
7876 self._curr_decaymodel = model
7877 model = self._curr_decaymodel
7878
7879 if isinstance(pids, int):
7880 pids = [pids]
7881
7882 first =True
7883 for part_nb,pid in enumerate(pids):
7884 part = self._curr_decaymodel.get_particle(pid)
7885 if part.get('width').lower() == 'zero':
7886 continue
7887 logger_mg.info('get decay diagram for %s' % part['name'])
7888
7889 if level // 1 == level and level >1:
7890 level = int(level)
7891 self._curr_decaymodel.find_channels(part, level, min_br)
7892 if not skip_2body:
7893 amp = part.get_amplitudes(2)
7894 if amp:
7895 self._curr_amps.extend(amp)
7896
7897 for l in range(3, level+1):
7898 amp = part.get_amplitudes(l)
7899 if amp:
7900 self._curr_amps.extend(amp)
7901 else:
7902 max_level = level // 1
7903 if max_level < 2:
7904 max_level = 999
7905 precision = level % 1
7906 if first:
7907 model.find_all_channels(2,generate_abstract=False)
7908 first = False
7909 if not skip_2body:
7910 amp = part.get_amplitudes(2)
7911 if amp:
7912 self._curr_amps.extend(amp)
7913 clevel = 2
7914 while part.get('apx_decaywidth_err').real > precision:
7915 clevel += 1
7916 if clevel > max_level:
7917 logger_mg.info(' stop to %s body-decay. approximate error: %s' %
7918 (max_level, part.get('apx_decaywidth_err')) )
7919 break
7920 if clevel > 3:
7921 logger_mg.info(' current estimated error: %s go to %s-body decay:' %\
7922 (part.get('apx_decaywidth_err'), clevel))
7923 part.find_channels_nextlevel(model, min_br)
7924
7925 amp = part.get_amplitudes(clevel)
7926 if amp:
7927 self._curr_amps.extend(amp)
7928 part.update_decay_attributes(False, True, True, model)
7929
7930
7931
7932 if len(self._curr_amps) > 0:
7933 process = self._curr_amps[0]['process'].nice_string()
7934
7935 self._generate_info = process[9:]
7936
7937 else:
7938 logger.info("No decay is found")
7939
7941 """Temporary parser"""
7942
7943
7944
7945
7946
7947 _draw_usage = "draw FILEPATH [options]\n" + \
7948 "-- draw the diagrams in eps format\n" + \
7949 " Files will be FILEPATH/diagrams_\"process_string\".eps \n" + \
7950 " Example: draw plot_dir . \n"
7951 _draw_parser = misc.OptionParser(usage=_draw_usage)
7952 _draw_parser.add_option("", "--horizontal", default=False,
7953 action='store_true', help="force S-channel to be horizontal")
7954 _draw_parser.add_option("", "--external", default=0, type='float',
7955 help="authorizes external particles to end at top or " + \
7956 "bottom of diagram. If bigger than zero this tune the " + \
7957 "length of those line.")
7958 _draw_parser.add_option("", "--max_size", default=1.5, type='float',
7959 help="this forbids external line bigger than max_size")
7960 _draw_parser.add_option("", "--non_propagating", default=True, \
7961 dest="contract_non_propagating", action='store_false',
7962 help="avoid contractions of non propagating lines")
7963 _draw_parser.add_option("", "--add_gap", default=0, type='float', \
7964 help="set the x-distance between external particles")
7965
7966
7967 _launch_usage = "launch [DIRPATH] [options]\n" + \
7968 "-- execute the madevent/standalone/standalone_cpp/pythia8/NLO output present in DIRPATH\n" + \
7969 " By default DIRPATH is the latest created directory \n" + \
7970 " (for pythia8, it should be the Pythia 8 main directory) \n" + \
7971 " Example: launch PROC_sm_1 --name=run2 \n" + \
7972 " Example: launch ../pythia8 \n"
7973 _launch_parser = misc.OptionParser(usage=_launch_usage)
7974 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
7975 help="Use the card present in the directory in order to launch the different program")
7976 _launch_parser.add_option("-n", "--name", default='', type='str',
7977 help="Provide a name to the run (for madevent run)")
7978 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
7979 help="submit the job on the cluster")
7980 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
7981 help="submit the job on multicore core")
7982
7983 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
7984 help="Use Interactive Console [if available]")
7985 _launch_parser.add_option("-s", "--laststep", default='',
7986 help="last program run in MadEvent run. [auto|parton|pythia|pgs|delphes]")
7987 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true',
7988 help="Run the reweight module (reweighting by different model parameter")
7989 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true',
7990 help="Run the madspin package")
7996 """A class for asking a question where in addition you can have the
7997 set command define and modifying the param_card/run_card correctly"""
7998
7999 - def __init__(self, question, allow_arg=[], default=None,
8000 mother_interface=None, *arg, **opt):
8001
8002 model_path = mother_interface._curr_model.get('modelpath')
8003
8004 ufo_model = ufomodels.load_model(model_path)
8005 self.all_categories = ufo_model.build_restrict.all_categories
8006
8007 question = self.get_question()
8008
8009
8010 allow_arg = ['0']
8011 self.name2options = {}
8012 for category in self.all_categories:
8013 for options in category:
8014 if not options.first:
8015 continue
8016 self.name2options[str(len(allow_arg))] = options
8017 self.name2options[options.name.replace(' ','')] = options
8018 allow_arg.append(len(allow_arg))
8019 allow_arg.append('done')
8020
8021 cmd.SmartQuestion.__init__(self, question, allow_arg, default, mother_interface)
8022
8023
8024
8026 """Default action if line is not recognized"""
8027
8028 line = line.strip()
8029 args = line.split()
8030 if line == '' and self.default_value is not None:
8031 self.value = self.default_value
8032
8033 elif hasattr(self, 'do_%s' % args[0]):
8034 self.do_set(' '.join(args[1:]))
8035 elif line.strip() != '0' and line.strip() != 'done' and \
8036 str(line) != 'EOF' and line.strip() in self.allow_arg:
8037 option = self.name2options[line.strip()]
8038 option.status = not option.status
8039 self.value = 'repeat'
8040 else:
8041 self.value = line
8042
8043 return self.all_categories
8044
8045 - def reask(self, reprint_opt=True):
8050
8052 """ """
8053 self.value = 'repeat'
8054
8055 args = line.split()
8056 if args[0] not in self.name2options:
8057 logger.warning('Invalid set command. %s not recognize options. Valid options are: \n %s' %
8058 (args[0], ', '.join(self.name2options.keys()) ))
8059 return
8060 elif len(args) != 2:
8061 logger.warning('Invalid set command. Not correct number of argument')
8062 return
8063
8064
8065 if args[1] in ['True','1','.true.','T',1,True,'true','TRUE']:
8066 self.name2options[args[0]].status = True
8067 elif args[1] in ['False','0','.false.','F',0,False,'false','FALSE']:
8068 self.name2options[args[0]].status = False
8069 else:
8070 logger.warning('%s is not True/False. Didn\'t do anything.' % args[1])
8071
8072
8073
8075 """define the current question."""
8076 question = ''
8077 i=0
8078 for category in self.all_categories:
8079 question += category.name + ':\n'
8080 for options in category:
8081 if not options.first:
8082 continue
8083 i+=1
8084 question += ' %s: %s [%s]\n' % (i, options.name,
8085 options.display(options.status))
8086 question += 'Enter a number to change it\'s status or press enter to validate.\n'
8087 question += 'For scripting this function, please type: \'help\''
8088 return question
8089
8090
8092 """ Complete the set command"""
8093 signal.alarm(0)
8094 args = self.split_arg(line[0:begidx])
8095
8096 if len(args) == 1:
8097 possibilities = [x for x in self.name2options if not x.isdigit()]
8098 return self.list_completion(text, possibilities, line)
8099 else:
8100 return self.list_completion(text,['True', 'False'], line)
8101
8102
8104 '''help message'''
8105
8106 print 'This allows you to optimize your model to your needs.'
8107 print 'Enter the number associate to the possible restriction/add-on'
8108 print ' to change the status of this restriction/add-on.'
8109 print ''
8110 print 'In order to allow scripting of this function you can use the '
8111 print 'function \'set\'. This function takes two argument:'
8112 print 'set NAME VALUE'
8113 print ' NAME is the description of the option where you remove all spaces'
8114 print ' VALUE is either True or False'
8115 print ' Example: For the question'
8116 print ''' sm customization:
8117 1: diagonal ckm [True]
8118 2: c mass = 0 [True]
8119 3: b mass = 0 [False]
8120 4: tau mass = 0 [False]
8121 5: muon mass = 0 [True]
8122 6: electron mass = 0 [True]
8123 Enter a number to change it's status or press enter to validate.'''
8124 print ''' you can answer by'''
8125 print ' set diagonalckm False'
8126 print ' set taumass=0 True'
8127
8131
8132
8133
8134
8135
8136
8137
8138 if __name__ == '__main__':
8139
8140 run_option = sys.argv
8141 if len(run_option) > 1:
8142
8143 input_file = open(run_option[1], 'rU')
8144 cmd_line = MadGraphCmd(stdin=input_file)
8145 cmd_line.use_rawinput = False
8146 cmd_line.cmdloop()
8147 else:
8148
8149 MadGraphCmd().cmdloop()
8150