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