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_mg = logging.getLogger('madgraph')
104 logger_stderr = logging.getLogger('fatalerror')
105 logger_tuto = logging.getLogger('tutorial')
106
107 logger_tuto_nlo = logging.getLogger('tutorial_aMCatNLO')
108
109
110 logger_tuto_madloop = logging.getLogger('tutorial_MadLoop')
116 """Particularisation of the cmd command for MG5"""
117
118
119 next_possibility = {
120 'start': ['import model ModelName', 'import command PATH',
121 'import proc_v4 PATH', 'tutorial'],
122 'import model' : ['generate PROCESS','define MULTIPART PART1 PART2 ...',
123 'display particles', 'display interactions'],
124 'define': ['define MULTIPART PART1 PART2 ...', 'generate PROCESS',
125 'display multiparticles'],
126 'generate': ['add process PROCESS','output [OUTPUT_TYPE] [PATH]','display diagrams'],
127 'add process':['output [OUTPUT_TYPE] [PATH]', 'display processes'],
128 'output':['launch','open index.html','history PATH', 'exit'],
129 'display': ['generate PROCESS', 'add process PROCESS', 'output [OUTPUT_TYPE] [PATH]'],
130 'import proc_v4' : ['launch','exit'],
131 'launch': ['open index.html','exit'],
132 'tutorial': ['generate PROCESS', 'import model MODEL', 'help TOPIC']
133 }
134
135 debug_output = 'MG5_debug'
136 error_debug = 'Please report this bug on https://bugs.launchpad.net/madgraph5\n'
137 error_debug += 'More information is found in \'%(debug)s\'.\n'
138 error_debug += 'Please attach this file to your report.'
139
140 config_debug = 'If you need help with this issue please contact us on https://answers.launchpad.net/madgraph5\n'
141
142 keyboard_stop_msg = """stopping all operation
143 in order to quit mg5 please enter exit"""
144
145
146 InvalidCmd = madgraph.InvalidCmd
147 ConfigurationError = MadGraph5Error
148
150 """Init history and line continuation"""
151
152
153
154 info = misc.get_pkg_info()
155 info_line = ""
156
157 if info.has_key('version') and info.has_key('date'):
158 len_version = len(info['version'])
159 len_date = len(info['date'])
160 if len_version + len_date < 30:
161 info_line = "#* VERSION %s %s %s *\n" % \
162 (info['version'],
163 (30 - len_version - len_date) * ' ',
164 info['date'])
165
166 if os.path.exists(pjoin(MG5DIR, '.bzr')):
167 proc = subprocess.Popen(['bzr', 'nick'], stdout=subprocess.PIPE)
168 bzrname,_ = proc.communicate()
169 proc = subprocess.Popen(['bzr', 'revno'], stdout=subprocess.PIPE)
170 bzrversion,_ = proc.communicate()
171 bzrname, bzrversion = bzrname.strip(), bzrversion.strip()
172 len_name = len(bzrname)
173 len_version = len(bzrversion)
174 info_line += "#* BZR %s %s %s *\n" % \
175 (bzrname,
176 (34 - len_name - len_version) * ' ',
177 bzrversion)
178
179
180
181 self.history_header = banner_module.ProcCard.history_header % {'info_line': info_line}
182 banner_module.ProcCard.history_header = self.history_header
183
184 if info_line:
185 info_line = info_line.replace("#*","*")
186
187
188
189 logger.info(\
190 "************************************************************\n" + \
191 "* *\n" + \
192 "* W E L C O M E to *\n" + \
193 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \
194 "* *\n" + \
195 "* *\n" + \
196 "* * * *\n" + \
197 "* * * * * *\n" + \
198 "* * * * * 5 * * * * *\n" + \
199 "* * * * * *\n" + \
200 "* * * *\n" + \
201 "* *\n" + \
202 info_line + \
203 "* *\n" + \
204 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
205 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
206 "* and *\n" + \
207 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \
208 "* *\n" + \
209 "* Type 'help' for in-line help. *\n" + \
210 "* Type 'tutorial' to learn how MG5 works *\n" + \
211 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \
212 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \
213 "* *\n" + \
214 "************************************************************")
215
216 cmd.Cmd.__init__(self, *arg, **opt)
217
218 self.history = banner_module.ProcCard()
219
220
222 """Default action if line is not recognized"""
223
224
225 log=True
226 if line.startswith('p') or line.startswith('e'):
227 logger.warning("Command %s not recognized. Did you mean \'generate %s\'?. Please try again" %
228 (line.split()[0], line))
229 log=False
230 return super(CmdExtended,self).default(line, log=log)
231
232 - def postcmd(self,stop, line):
233 """ finishing a command
234 This looks if the command add a special post part.
235 This looks if we have to write an additional text for the tutorial."""
236
237 stop = super(CmdExtended, self).postcmd(stop, line)
238
239 if stop == False:
240 return False
241
242 args=line.split()
243
244 if len(args)==0:
245 return stop
246
247
248
249
250 if len(args)==1:
251 command=args[0]
252 else:
253 command = args[0]+'_'+args[1].split('.')[0]
254
255 try:
256 logger_tuto.info(getattr(tutorial_text, command).replace('\n','\n\t'))
257 except Exception:
258 try:
259 logger_tuto.info(getattr(tutorial_text, args[0]).replace('\n','\n\t'))
260 except Exception:
261 pass
262
263 try:
264 logger_tuto_nlo.info(getattr(tutorial_text_nlo, command).replace('\n','\n\t'))
265 except Exception:
266 try:
267 logger_tuto_nlo.info(getattr(tutorial_text_nlo, args[0]).replace('\n','\n\t'))
268 except Exception:
269 pass
270
271 try:
272 logger_tuto_madloop.info(getattr(tutorial_text_madloop, command).replace('\n','\n\t'))
273 except Exception:
274 try:
275 logger_tuto_madloop.info(getattr(tutorial_text_madloop, args[0]).replace('\n','\n\t'))
276 except Exception:
277 pass
278
279 return stop
280
281
283 """return the history header"""
284 return self.history_header % misc.get_time_info()
285
290 """ The Series of help routine for the MadGraphCmd"""
291
293 logger.info("syntax: save %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
294 logger.info("-- save information as file FILENAME",'$MG:color:BLACK')
295 logger.info(" FILENAME is optional for saving 'options'.")
296 logger.info(' By default it uses ./input/mg5_configuration.txt')
297 logger.info(' If you put "global" for FILENAME it will use ~/.mg5/mg5_configuration.txt')
298 logger.info(' If this files exists, it is uses by all MG5 on the system but continues')
299 logger.info(' to read the local options files.')
300
302 logger.info("syntax: load %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
303 logger.info("-- load information from file FILENAME",'$MG:color:BLACK')
304
306 logger.info("syntax: import " + "|".join(self._import_formats) + \
307 " FILENAME",'$MG:color:BLUE')
308 logger.info("-- imports file(s) in various formats",'$MG:color:GREEN')
309 logger.info("")
310 logger.info(" import model MODEL[-RESTRICTION] [OPTIONS]:",'$MG:color:BLACK')
311 logger.info(" Import a UFO model.")
312 logger.info(" MODEL should be a valid UFO model name")
313 logger.info(" Model restrictions are specified by MODEL-RESTRICTION")
314 logger.info(" with the file restrict_RESTRICTION.dat in the model dir.")
315 logger.info(" By default, restrict_default.dat is used.")
316 logger.info(" Specify model_name-full to get unrestricted model.")
317 logger.info(" '--modelname' keeps the original particle names for the model")
318 logger.info("")
319 logger.info(" import model_v4 MODEL [--modelname] :",'$MG:color:BLACK')
320 logger.info(" Import an MG4 model.")
321 logger.info(" Model should be the name of the model")
322 logger.info(" or the path to theMG4 model directory")
323 logger.info(" '--modelname' keeps the original particle names for the model")
324 logger.info("")
325 logger.info(" import proc_v4 [PATH] :",'$MG:color:BLACK')
326 logger.info(" Execute MG5 based on a proc_card.dat in MG4 format.")
327 logger.info(" Path to the proc_card is optional if you are in a")
328 logger.info(" madevent directory")
329 logger.info("")
330 logger.info(" import command PATH :",'$MG:color:BLACK')
331 logger.info(" Execute the list of command in the file at PATH")
332 logger.info("")
333 logger.info(" import banner PATH [--no_launch]:",'$MG:color:BLACK')
334 logger.info(" Rerun the exact same run define in the valid banner.")
335
337 logger.info("syntax: install " + "|".join(self._install_opts),'$MG:color:BLUE')
338 logger.info("-- Download the last version of the program and install it")
339 logger.info(" locally in the current MadGraph5_aMC@NLO version. In order to have")
340 logger.info(" a successful installation, you will need to have an up-to-date")
341 logger.info(" F77 and/or C and Root compiler.")
342 logger.info(" ")
343 logger.info(" \"install update\"",'$MG:color:BLACK')
344 logger.info(" check if your MG5 installation is the latest one.")
345 logger.info(" If not it load the difference between your current version and the latest one,")
346 logger.info(" and apply it to the code. Two options are available for this command:")
347 logger.info(" -f: didn't ask for confirmation if it founds an update.")
348 logger.info(" --timeout=: Change the maximum time allowed to reach the server.")
349
351 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLUE')
352 logger.info("-- display a the status of various internal state variables")
353 logger.info(" for particles/interactions you can specify the name or id of the")
354 logger.info(" particles/interactions to receive more details information.")
355 logger.info(" Example: display particles e+.",'$MG:color:GREEN')
356 logger.info(" > For \"checks\", can specify only to see failed checks.")
357 logger.info(" > For \"diagrams\", you can specify where the file will be written.")
358 logger.info(" Example: display diagrams ./",'$MG:color:GREEN')
359
360
362 """help for launch command"""
363
364
365
366 logger.info("syntax: launch <dir_path> <options>",'$MG:color:BLUE')
367 logger.info("-- execute the aMC@NLO/madevent/standalone/pythia8 output present in dir_path",'$MG:color:BLACK')
368 logger.info("By default, dir_path points to the last created directory.")
369 logger.info("(for pythia8, it should be the Pythia 8 main directory)")
370 logger.info("")
371 logger.info("Launch on madevent/pythia8/standalone outputs:",'$MG:color:BLACK')
372 logger.info(" o Example: launch PROC_sm_1 --name=run2",'$MG:color:GREEN')
373 logger.info(" o Example: launch ../pythia8",'$MG:color:GREEN')
374 logger.info(" > Options:")
375 logger.info(" -h, --help show this help message and exit")
376 logger.info(" -f, --force Use the card present in the directory in order")
377 logger.info(" to launch the different program")
378 logger.info(" -n NAME, --name=NAME Provide a name to the run (for madevent run)")
379 logger.info(" -c, --cluster submit the job on the cluster")
380 logger.info(" -m, --multicore submit the job on multicore core")
381 logger.info(" -i, --interactive Use Interactive Console [if available]")
382 logger.info(" -s LASTSTEP, --laststep=LASTSTEP")
383 logger.info(" last program run in MadEvent run.")
384 logger.info(" [auto|parton|pythia|pgs|delphes]")
385 logger.info("")
386 logger.info("Launch on MadLoop standalone output:",'$MG:color:BLACK')
387 logger.info(" o Example: launch PROC_loop_sm_1 -f",'$MG:color:GREEN')
388 logger.info(" > Simple check of a single Phase-space points.")
389 logger.info(" > You will be asked whether you want to edit the MadLoop ")
390 logger.info(" and model param card as well as the PS point, unless ")
391 logger.info(" the -f option is specified. All other options are ")
392 logger.info(" irrelevant for this kind of launch.")
393 logger.info("")
394 logger.info("Launch on aMC@NLO output:",'$MG:color:BLACK')
395 logger.info(" > launch <dir_path> <mode> <options>",'$MG:color:BLUE')
396 logger.info(" o Example: launch MyProc aMC@NLO -f -p",'$MG:color:GREEN')
397
399 logger.info("syntax: tutorial [" + "|".join(self._tutorial_opts) + "]",'$MG:color:BLUE')
400 logger.info("-- start/stop the MG5 tutorial mode (or stop any other mode)")
401 logger.info("-- aMCatNLO: start aMC@NLO tutorial mode")
402 logger.info("-- MadLoop: start MadLoop tutorial mode")
403
405 logger.info("syntax: open FILE ",'$MG:color:BLUE')
406 logger.info("-- open a file with the appropriate editor.",'$MG:color:BLACK')
407 logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
408 logger.info(' the path to the last created/used directory is used')
409 logger.info(' The program used to open those files can be chosen in the')
410 logger.info(' configuration file ./input/mg5_configuration.txt')
411
413 logger.info("syntax: customize_model --save=NAME",'$MG:color:BLUE')
414 logger.info("-- Open an invite where you options to tweak the model.",'$MG:color:BLACK')
415 logger.info(" If you specify the option --save=NAME, this tweak will be")
416 logger.info(" available for future import with the command 'import model XXXX-NAME'")
417
419 logger.info("syntax: output [" + "|".join(self._export_formats) + \
420 "] [path|.|auto] [options]",'$MG:color:BLUE')
421 logger.info("-- Output any generated process(es) to file.",'$MG:color:BLACK')
422 logger.info(" Default mode is madevent. Default path is \'.\' or auto.")
423 logger.info(" mode:",'$MG:color:BLACK')
424 logger.info(" - For MadLoop and aMC@NLO runs, there is only one mode and")
425 logger.info(" it is set by default.")
426 logger.info(" - If mode is madevent, create a MadEvent process directory.")
427 logger.info(" - If mode is standalone, create a Standalone directory")
428 logger.info(" - If mode is matrix, output the matrix.f files for all")
429 logger.info(" generated processes in directory \"path\".")
430 logger.info(" - If mode is standalone_cpp, create a standalone C++")
431 logger.info(" directory in \"path\".")
432 logger.info(" - If mode is pythia8, output all files needed to generate")
433 logger.info(" the processes using Pythia 8. The files are written in")
434 logger.info(" the Pythia 8 directory (default).")
435 logger.info(" NOTE: The Pythia 8 directory is set in the ./input/mg5_configuration.txt")
436 logger.info(" - If mode is aloha: Special syntax output:")
437 logger.info(" syntax: aloha [ROUTINE] [--options]" )
438 logger.info(" valid options for aloha output are:")
439 logger.info(" --format=Fortran|Python|Cpp : defining the output language")
440 logger.info(" --output= : defining output directory")
441 logger.info(" path: The path of the process directory.",'$MG:color:BLACK')
442 logger.info(" If you put '.' as path, your pwd will be used.")
443 logger.info(" If you put 'auto', an automatic directory PROC_XX_n will be created.")
444 logger.info(" options:",'$MG:color:BLACK')
445 logger.info(" -f: force cleaning of the directory if it already exists")
446 logger.info(" -d: specify other MG/ME directory")
447 logger.info(" -noclean: no cleaning performed in \"path\".")
448 logger.info(" -nojpeg: no jpeg diagrams will be generated.")
449 logger.info(" -name: the postfix of the main file in pythia8 mode.")
450 logger.info(" Examples:",'$MG:color:GREEN')
451 logger.info(" output",'$MG:color:GREEN')
452 logger.info(" output standalone MYRUN -f",'$MG:color:GREEN')
453 logger.info(" output pythia8 ../pythia8/ -name qcdprocs",'$MG:color:GREEN')
454
456 logger.info("syntax: check [" + "|".join(self._check_opts) + "] [param_card] process_definition [--energy=] [--split_orders=] [--reduction=]",'$MG:color:BLUE')
457 logger.info("-- check a process or set of processes.",'$MG:color:BLACK')
458 logger.info("General options:",'$MG:color:BLACK')
459 logger.info("o full:",'$MG:color:GREEN')
460 logger.info(" Perform all four checks described below:")
461 logger.info(" permutation, brs, gauge and lorentz_invariance.")
462 logger.info("o permutation:",'$MG:color:GREEN')
463 logger.info(" Check that the model and MG5 are working properly")
464 logger.info(" by generating permutations of the process and checking")
465 logger.info(" that the resulting matrix elements give the same value.")
466 logger.info("o gauge:",'$MG:color:GREEN')
467 logger.info(" Check that processes with massless gauge bosons are")
468 logger.info(" gauge invariant (comparing Feynman and unitary gauges)")
469 logger.info(" This check if for now not available for loop processes.")
470 logger.info("o brs:",'$MG:color:GREEN')
471 logger.info(" Check that the Ward identities are satisfied if the ")
472 logger.info(" process has at least one massless gauge boson as an")
473 logger.info(" external particle.")
474 logger.info("o lorentz_invariance:",'$MG:color:GREEN')
475 logger.info(" Check that the amplitude is lorentz invariant by")
476 logger.info(" comparing the amplitiude in different frames")
477 logger.info("Comments",'$MG:color:GREEN')
478 logger.info(" > If param_card is given, that param_card is used ")
479 logger.info(" instead of the default values for the model.")
480 logger.info(" If that file is an (LHE) event file. The param_card of the banner")
481 logger.info(" is used and the first event compatible with the requested process")
482 logger.info(" is used for the computation of the square matrix elements")
483 logger.info(" > \"--energy=\" allows to change the default value of sqrt(S).")
484 logger.info(" > Except for the 'gauge' test, all checks above are also")
485 logger.info(" available for loop processes with ML5 ('virt=' mode)")
486 logger.info("Example: check full p p > j j",'$MG:color:GREEN')
487 logger.info("Options for loop processes only:",'$MG:color:BLACK')
488 logger.info("o timing:",'$MG:color:GREEN')
489 logger.info(" Generate and output a process and returns detailed")
490 logger.info(" information about the code and a timing benchmark.")
491 logger.info("o stability:",'$MG:color:GREEN')
492 logger.info(" Generate and output a process and returns detailed")
493 logger.info(" statistics about the numerical stability of the code.")
494 logger.info("o profile:",'$MG:color:GREEN')
495 logger.info(" Performs both the timing and stability analysis at once")
496 logger.info(" and outputs the result in a log file without prompting")
497 logger.info(" it to the user.")
498 logger.info("Comments",'$MG:color:GREEN')
499 logger.info(" > These checks are only available for ML5 ('virt=' mode)")
500 logger.info(" > For the 'profile' and 'stability' checks, you can chose")
501 logger.info(" how many PS points should be used for the statistic by")
502 logger.info(" specifying it as an integer just before the [param_card]")
503 logger.info(" optional argument.")
504 logger.info(" > Notice multiparticle labels cannot be used with these checks.")
505 logger.info(" > \"--reduction=\" allows to change what reduction methods should be used.")
506 logger.info(" > \"--split_orders=\" allows to change what specific combination of coupling orders to consider.")
507 logger.info(" > For process syntax, please see help generate.")
508 logger.info(" > In order to save the directory generated or the reuse an existing one")
509 logger.info(" previously generated with the check command, one can add the '-reuse' ")
510 logger.info(" keyword just after the specification of the type of check desired.")
511 logger.info("Example: check profile g g > t t~ [virt=QCD]",'$MG:color:GREEN')
512
513
515
516 logger.info("-- generate diagrams for a given process",'$MG:color:BLUE')
517 logger.info("General leading-order syntax:",'$MG:color:BLACK')
518 logger.info(" o generate INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2^2=ORDER2 @N")
519 logger.info(" o Example: generate l+ vl > w+ > l+ vl a $ z / a h QED=3 QCD=0 @1",'$MG:color:GREEN')
520 logger.info(" > Alternative required s-channels can be separated by \"|\":")
521 logger.info(" b b~ > W+ W- | H+ H- > ta+ vt ta- vt~")
522 logger.info(" > If no coupling orders are given, MG5 will try to determine")
523 logger.info(" orders to ensure maximum number of QCD vertices.")
524 logger.info(" > Desired coupling orders combination can be specified directly for")
525 logger.info(" the squared matrix element by appending '^2' to the coupling name.")
526 logger.info(" For example, 'p p > j j QED^2==2 QCD^==2' selects the QED-QCD")
527 logger.info(" interference terms only. The other two operators '<=' and '>' are")
528 logger.info(" supported. Finally, a negative value COUP^2==-I refers to the")
529 logger.info(" N^(-I+1)LO term in the expansion of the COUP order.")
530 logger.info(" > To generate a second process use the \"add process\" command")
531 logger.info("Decay chain syntax:",'$MG:color:BLACK')
532 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
533 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')
534 logger.info(" > Note that identical particles will all be decayed.")
535 logger.info("Loop processes syntax:",'$MG:color:BLACK')
536 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
537 logger.info(" o Example: generate p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
538 logger.info(" > Notice that in this format, decay chains are not allowed.")
539 logger.info(" > The LoopOrder(s) defined specify the kind of loops to consider (only QCD for now).")
540 logger.info(" > The coupling restrictions before '[' restrict the orders of born *amplitudes*.")
541 logger.info(" So that in the example above QCD=2 restricts the born amplitude to have at")
542 logger.info(" most QCD=2 and loop amplitudes at most QCD=2+2 (because QCD loops are considered)")
543 logger.info(" > The coupling restrictions after ']' restrict the orders of the matrix element, ")
544 logger.info(" namely the squared amplitudes. In the example above QCD=6 correspond to born")
545 logger.info(" amplitudes with QCD=2 squared against loop amplitudes with QCD=4, adding up to 6.")
546 logger.info(" > The optional <NLO_mode=> can be any of the following ('all=' by default if absent):")
547 logger.info(" all= : Generate all the real-emission and loop diagrams, ready for aMC@NLO runs.")
548 logger.info(" virt= : Generate only the loop diagrams, read for MadLoop standalone checks/runs.")
549 logger.info(" real= : Generate only the real-emission diagrams, for use with alternative OLP. ")
550 logger.info(" > For processes without born amplitudes (i.e. loop-induced like g g > z), please use ")
551 logger.info(" the 'virt=' NLO mode. aMC@NLO cannot integrate these processes, but standalone MadLoop5")
552 logger.info(" can still handle these.")
553
555 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
556 logger.info(" OR merge two model",'$MG:color:BLUE')
557 logger.info('')
558 logger.info("-- generate diagrams for a process and add to existing processes",'$MG:color:BLUE')
559 logger.info("General leading-order syntax:",'$MG:color:BLACK')
560 logger.info(" o add process INITIAL STATE > REQ S-CHANNEL > FINAL STATE $ EXCL S-CHANNEL / FORBIDDEN PARTICLES COUP1=ORDER1 COUP2=ORDER2 @N")
561 logger.info(" o Example: add process l+ vl > w+ > l+ vl a $ z / a h QED=3 QCD=0 @1",'$MG:color:GREEN')
562 logger.info(" > Alternative required s-channels can be separated by \"|\":")
563 logger.info(" b b~ > W+ W- | H+ H- > ta+ vt ta- vt~")
564 logger.info(" > If no coupling orders are given, MG5 will try to determine")
565 logger.info(" orders to ensure maximum number of QCD vertices.")
566 logger.info(" > Note that if there are more than one non-QCD coupling type,")
567 logger.info(" coupling orders need to be specified by hand.")
568 logger.info("Decay chain syntax:",'$MG:color:BLACK')
569 logger.info(" o core process, decay1, (decay2, (decay2', ...)), ... etc")
570 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')
571 logger.info(" > Note that identical particles will all be decayed.")
572 logger.info("Loop processes syntax:",'$MG:color:BLACK')
573 logger.info(" o core process [ <NLO_mode=> LoopOrder1 LoopOrder2 ... ] SQUAREDCOUPi=ORDERi")
574 logger.info(" o Example: add process p p > t~ t QED=0 QCD=2 [ all= QCD ] QCD=6",'$MG:color:GREEN')
575 logger.info(" > Notice that in this format, decay chains are not allowed.")
576 logger.info(" > The LoopOrder(s) defined specify the kind of loops to consider (only QCD for now).")
577 logger.info(" > The coupling restrictions before '[' restrict the orders of born *amplitudes*.")
578 logger.info(" So that in the example above QCD=2 restricts the born amplitude to have at")
579 logger.info(" most QCD=2 and loop amplitudes at most QCD=2+2 (because QCD loops are considered)")
580 logger.info(" > The coupling restrictions after ']' restrict the orders of the matrix element, ")
581 logger.info(" namely the squared amplitudes. In the example above QCD=6 correspond to born")
582 logger.info(" amplitudes with QCD=2 squared against loop amplitudes with QCD=4, adding up to 6.")
583 logger.info(" > The optional <NLO_mode=> can be any of the following ('all=' by default if absent):")
584 logger.info(" all= : Generate all the real-emission and loop diagrams, ready for aMC@NLO runs.")
585 logger.info(" virt= : Generate only the loop diagrams, read for MadLoop standalone checks/runs.")
586 logger.info(" real= : Generate only the real-emission diagrams, for use with alternative OLP. ")
587 logger.info(" > For processes without born amplitudes (i.e. loop-induced like g g > z), please use ")
588 logger.info(" the 'virt=' NLO mode. aMC@NLO cannot integrate these processes, but standalone MadLoop5")
589 logger.info(" can still handle these.")
590
591 logger.info("-- merge two model to create a new one", '$MG:color:BLUE')
592 logger.info("syntax:",'$MG:color:BLACK')
593 logger.info(" o add model MODELNAME [OPTIONS]")
594 logger.info(" o Example: add model taudecay",'$MG:color:GREEN')
595 logger.info(" > Merge the two model in a single one. If that same merge was done before.")
596 logger.info(" > Just reload the previous merge. (WARNING: This doesn't check if those model are modified)")
597 logger.info(" > Options:")
598 logger.info(" --output= : Specify the name of the directory where the merge is done.")
599 logger.info(" This allow to do \"import NAME\" to load that merge.")
600 logger.info(" --recreate : Force to recreated the merge model even if the merge model directory already exists.")
601
603 logger.info("syntax: calculate_width PART [other particles] [OPTIONS]")
604 logger.info(" Computes the width and partial width for a set of particles")
605 logger.info(" Returns a valid param_card with this information.")
606 logger.info(" ")
607 logger.info(" PART: name of the particle you want to calculate width")
608 logger.info(" you can enter either the name or pdg code.\n")
609 logger.info(" Various options:\n")
610 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
611 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
612 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
613 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
614 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
615 logger.info(" default: 4.0025")
616 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
617 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
618 logger.info(" --precision_channel=X: requested numerical precision for each channel")
619 logger.info(" default: 0.01")
620 logger.info(" --path=X: path for param_card")
621 logger.info(" default: take value from the model")
622 logger.info(" --output=X: path where to write the resulting card. ")
623 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
624 logger.info(" --nlo: Compute NLO width [if the model support it]")
625 logger.info("")
626 logger.info(" example: calculate_width h --body_decay=2 --output=./param_card")
627
629 logger.info("syntax: decay_diagram PART [other particles] [OPTIONS]")
630 logger.info(" Returns the amplitude required for the computation of the widths")
631 logger.info(" ")
632 logger.info(" PART: name of the particle you want to calculate width")
633 logger.info(" you can enter either the name or pdg code.\n")
634 logger.info(" Various options:\n")
635 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
636 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
637 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
638 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
639 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
640 logger.info(" default: 4.0025")
641 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
642 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
643 logger.info(" --precision_channel=X: requested numerical precision for each channel")
644 logger.info(" default: 0.01")
645 logger.info(" --path=X: path for param_card")
646 logger.info(" default: take value from the model")
647 logger.info(" --output=X: path where to write the resulting card. ")
648 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
649 logger.info("")
650 logger.info(" example: calculate_width h --body_decay=2 --output=./param_card")
651
653 logger.info("-- define a multiparticle",'$MG:color:BLUE')
654 logger.info("Syntax: define multipart_name [=] part_name_list")
655 logger.info("Example: define p = g u u~ c c~ d d~ s s~ b b~",'$MG:color:GREEN')
656 logger.info("Special syntax: Use | for OR (used for required s-channels)")
657 logger.info("Special syntax: Use / to remove particles. Example: define q = p / g")
658
660 logger.info("-- set options for generation or output.",'$MG:color:BLUE')
661 logger.info("syntax: set <option_name> <option_value>",'$MG:color:BLACK')
662 logger.info("Possible options are: ")
663 for opts in [self._set_options[i*3:(i+1)*3] for i in \
664 range((len(self._set_options)//4)+1)]:
665 logger.info("%s"%(','.join(opts)),'$MG:color:GREEN')
666 logger.info("Details of each option:")
667 logger.info("group_subprocesses True/False/Auto: ",'$MG:color:GREEN')
668 logger.info(" > (default Auto) Smart grouping of subprocesses into ")
669 logger.info(" directories, mirroring of initial states, and ")
670 logger.info(" combination of integration channels.")
671 logger.info(" > Example: p p > j j j w+ gives 5 directories and 184 channels",'$MG:color:BLACK')
672 logger.info(" (cf. 65 directories and 1048 channels for regular output)",'$MG:color:BLACK')
673 logger.info(" > Auto means False for decay computation and True for collisions.")
674 logger.info("ignore_six_quark_processes multi_part_label",'$MG:color:GREEN')
675 logger.info(" > (default none) ignore processes with at least 6 of any")
676 logger.info(" of the quarks given in multi_part_label.")
677 logger.info(" > These processes give negligible contribution to the")
678 logger.info(" cross section but have subprocesses/channels.")
679 logger.info("stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL",'$MG:color:GREEN')
680 logger.info(" > change the default level for printed information")
681 logger.info("fortran_compiler NAME",'$MG:color:GREEN')
682 logger.info(" > (default None) Force a specific fortran compiler.")
683 logger.info(" If None, it tries first g77 and if not present gfortran")
684 logger.info(" but loop output use gfortran.")
685 logger.info("loop_optimized_output True|False",'$MG:color:GREEN')
686 logger.info(" > Exploits the open loop thechnique for considerable")
687 logger.info(" improvement.")
688 logger.info(" > CP relations among helicites are detected and the helicity")
689 logger.info(" filter has more potential.")
690 logger.info("loop_color_flows True|False",'$MG:color:GREEN')
691 logger.info(" > Only relevant for the loop optimized output.")
692 logger.info(" > Reduces the loop diagrams at the amplitude level")
693 logger.info(" rendering possible the computation of the loop amplitude")
694 logger.info(" for a fixed color flow or color configuration.")
695 logger.info(" > This option can considerably slow down the loop ME")
696 logger.info(" computation time, especially when summing over all color")
697 logger.info(" and helicity configuration, hence turned off by default.")
698 logger.info("gauge unitary|Feynman",'$MG:color:GREEN')
699 logger.info(" > (default unitary) choose the gauge of the non QCD part.")
700 logger.info(" > For loop processes, only Feynman gauge is employable.")
701 logger.info("complex_mass_scheme True|False",'$MG:color:GREEN')
702 logger.info(" > (default False) Set complex mass scheme.")
703 logger.info(" > Complex mass scheme is not yet supported for loop processes.")
704 logger.info("timeout VALUE",'$MG:color:GREEN')
705 logger.info(" > (default 20) Seconds allowed to answer questions.")
706 logger.info(" > Note that pressing tab always stops the timer.")
707 logger.info("cluster_temp_path PATH",'$MG:color:GREEN')
708 logger.info(" > (default None) [Used in Madevent Output]")
709 logger.info(" > Allow to perform the run in PATH directory")
710 logger.info(" > This allow to not run on the central disk. ")
711 logger.info(" > This is not used by condor cluster (since condor has")
712 logger.info(" its own way to prevent it).")
713 logger.info("OLP ProgramName",'$MG:color:GREEN')
714 logger.info(" > (default 'MadLoop') [Used for virtual generation]")
715 logger.info(" > Chooses what One-Loop Program to use for the virtual")
716 logger.info(" > matrix element generation via the BLAH accord.")
717 logger.info("output_dependencies <mode>",'$MG:color:GREEN')
718 logger.info(" > (default 'external') [Use for NLO outputs]")
719 logger.info(" > Choses how the external dependences (such as CutTools)")
720 logger.info(" > of NLO outputs are handled. Possible values are:")
721 logger.info(" o external: Some of the libraries the output depends")
722 logger.info(" on are links to their installation in MG5 root dir.")
723 logger.info(" o internal: All libraries the output depends on are")
724 logger.info(" copied and compiled locally in the output directory.")
725 logger.info(" o environment_paths: The location of all libraries the ")
726 logger.info(" output depends on should be found in your env. paths.")
727
739 """ The Series of help routine for the MadGraphCmd"""
740
742 """a class for read/write errors"""
743
745 """check the validity of line
746 syntax: add process PROCESS | add model MODELNAME
747 """
748
749 if len(args) < 2:
750 self.help_add()
751 raise self.InvalidCmd('\"add\" requires at least two arguments')
752
753 if args[0] not in ['model', 'process']:
754 raise self.InvalidCmd('\"add\" requires the argument \"process\" or \"model\"')
755
756 if args[0] == 'process':
757 return self.check_generate(args)
758
759 if args[0] == 'model':
760 pass
761
762
764 """check the validity of line
765 syntax: define multipart_name [ part_name_list ]
766 """
767
768 if len(args) < 2:
769 self.help_define()
770 raise self.InvalidCmd('\"define\" command requires at least two arguments')
771
772 if args[1] == '=':
773 del args[1]
774 if len(args) < 2:
775 self.help_define()
776 raise self.InvalidCmd('\"define\" command requires at least one particles name after \"=\"')
777
778 if '=' in args:
779 self.help_define()
780 raise self.InvalidCmd('\"define\" command requires symbols \"=\" at the second position')
781
782 if not self._curr_model:
783 logger.info('No model currently active. Try with the Standard Model')
784 self.do_import('model sm')
785
786 if self._curr_model['particles'].find_name(args[0]):
787 raise self.InvalidCmd("label %s is a particle name in this model\n\
788 Please retry with another name." % args[0])
789
791 """check the validity of line
792 syntax: display XXXXX
793 """
794
795 if len(args) < 1:
796 self.help_display()
797 raise self.InvalidCmd, 'display requires an argument specifying what to display'
798 if args[0] not in self._display_opts:
799 self.help_display()
800 raise self.InvalidCmd, 'Invalid arguments for display command: %s' % args[0]
801
802 if not self._curr_model:
803 raise self.InvalidCmd("No model currently active, please import a model!")
804
805
806 if (args[0] in ['processes', 'diagrams'] and not self._curr_amps and not self._fks_multi_proc):
807 raise self.InvalidCmd("No process generated, please generate a process!")
808 if args[0] == 'checks' and not self._comparisons:
809 raise self.InvalidCmd("No check results to display.")
810
811 if args[0] == 'variable' and len(args) !=2:
812 raise self.InvalidCmd('variable need a variable name')
813
814
816 """check the validity of line
817 syntax: draw DIRPATH [option=value]
818 """
819
820 if len(args) < 1:
821 args.append('/tmp')
822
823 if not self._curr_amps:
824 raise self.InvalidCmd("No process generated, please generate a process!")
825
826 if not os.path.isdir(args[0]):
827 raise self.InvalidCmd( "%s is not a valid directory for export file" % args[0])
828
830 """check the validity of args"""
831
832 if not self._curr_model:
833 raise self.InvalidCmd("No model currently active, please import a model!")
834
835 if self._model_v4_path:
836 raise self.InvalidCmd(\
837 "\"check\" not possible for v4 models")
838
839 if len(args) < 2:
840 self.help_check()
841 raise self.InvalidCmd("\"check\" requires a process.")
842
843 if args[0] not in self._check_opts:
844 args.insert(0, 'full')
845
846 param_card = None
847 if args[0] not in ['stability','profile','timing'] and os.path.isfile(args[1]):
848 param_card = args.pop(1)
849
850 if len(args)>1:
851 if args[1] != "-reuse":
852 args.insert(1, '-no_reuse')
853 else:
854 args.append('-no_reuse')
855
856 if args[0] in ['timing'] and os.path.isfile(args[2]):
857 param_card = args.pop(2)
858 misc.sprint(param_card)
859 if args[0] in ['stability', 'profile'] and len(args)>1:
860
861
862
863 try:
864 int(args[2])
865 except ValueError:
866 args.insert(2, '100')
867
868 if args[0] in ['stability', 'profile'] and os.path.isfile(args[3]):
869 param_card = args.pop(3)
870
871 if any([',' in elem for elem in args]):
872 raise self.InvalidCmd('Decay chains not allowed in check')
873
874 user_options = {'--energy':'1000','--split_orders':'-1',
875 '--reduction':'1|2|3|4'}
876 for arg in args[:]:
877 if arg.startswith('--') and '=' in arg:
878 key, value = arg.split('=')
879 if key not in user_options:
880 raise self.InvalidCmd, "unknown option %s" % key
881 user_options[key] = value
882 args.remove(arg)
883
884 self.check_process_format(" ".join(args[1:]))
885
886 for option, value in user_options.items():
887 args.append('%s=%s'%(option,value))
888
889 return param_card
890
915
916
955
956
969
970
971
1017
1018
1019
1021 """check that the install command is valid"""
1022
1023 if len(args) < 1:
1024 self.help_install()
1025 raise self.InvalidCmd('install command require at least one argument')
1026
1027 if args[0] not in self._install_opts:
1028 if not args[0].startswith('td'):
1029 self.help_install()
1030 raise self.InvalidCmd('Not recognize program %s ' % args[0])
1031
1032 if args[0] in ["ExRootAnalysis", "Delphes", "Delphes2"]:
1033 if not misc.which('root'):
1034 raise self.InvalidCmd(
1035 '''In order to install ExRootAnalysis, you need to install Root on your computer first.
1036 please follow information on http://root.cern.ch/drupal/content/downloading-root''')
1037 if 'ROOTSYS' not in os.environ:
1038 raise self.InvalidCmd(
1039 '''The environment variable ROOTSYS is not configured.
1040 You can set it by adding the following lines in your .bashrc [.bash_profile for mac]:
1041 export ROOTSYS=%s
1042 export PATH=$PATH:$ROOTSYS/bin
1043 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib
1044 export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$ROOTSYS/lib
1045 This will take effect only in a NEW terminal
1046 ''' % os.path.realpath(pjoin(misc.which('root'), \
1047 os.path.pardir, os.path.pardir)))
1048
1049
1051 """check the validity of the line"""
1052
1053
1054 if not( 0 <= int(options.cluster) <= 2):
1055 return self.InvalidCmd, 'cluster mode should be between 0 and 2'
1056
1057 if not args:
1058 if self._done_export:
1059 mode = self.find_output_type(self._done_export[0])
1060
1061 if not self._done_export[1].startswith(mode):
1062 print mode, self._done_export[1]
1063 raise self.InvalidCmd, \
1064 '%s not valid directory for launch' % self._done_export[0]
1065 args.append(self._done_export[1])
1066 args.append(self._done_export[0])
1067 return
1068 else:
1069 logger.warning('output command missing, run it automatically (with default argument)')
1070 self.do_output('')
1071 logger.warning('output done: running launch')
1072 return self.check_launch(args, options)
1073
1074 if len(args) != 1:
1075 self.help_launch()
1076 return self.InvalidCmd, 'Invalid Syntax: Too many argument'
1077
1078
1079 if os.path.isdir(args[0]):
1080 path = os.path.realpath(args[0])
1081 elif os.path.isdir(pjoin(MG5DIR,args[0])):
1082 path = pjoin(MG5DIR,args[0])
1083 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])):
1084 path = pjoin(MG4DIR,args[0])
1085 else:
1086 raise self.InvalidCmd, '%s is not a valid directory' % args[0]
1087
1088 mode = self.find_output_type(path)
1089
1090 args[0] = mode
1091 args.append(path)
1092
1093 self._done_export = [path, mode]
1094
1095
1097 """ identify the import type of a given path
1098 valid output: model/model_v4/proc_v4/command"""
1099
1100 possibility = [pjoin(MG5DIR,'models',path), \
1101 pjoin(MG5DIR,'models',path+'_v4'), path]
1102 if '-' in path:
1103 name = path.rsplit('-',1)[0]
1104 possibility = [pjoin(MG5DIR,'models',name), name] + possibility
1105
1106 for name in possibility:
1107 if os.path.isdir(name):
1108 if os.path.exists(pjoin(name,'particles.py')):
1109 return 'model'
1110 elif os.path.exists(pjoin(name,'particles.dat')):
1111 return 'model_v4'
1112
1113
1114 if os.path.isfile(path):
1115 text = open(path).read()
1116 pat = re.compile('(Begin process|<MGVERSION>)', re.I)
1117 matches = pat.findall(text)
1118 if not matches:
1119 return 'command'
1120 elif len(matches) > 1:
1121 return 'banner'
1122 elif matches[0].lower() == 'begin process':
1123 return 'proc_v4'
1124 else:
1125 return 'banner'
1126 else:
1127 return 'proc_v4'
1128
1129
1130
1131
1133 """ identify the type of output of a given directory:
1134 valid output: madevent/standalone/standalone_cpp"""
1135
1136 card_path = pjoin(path,'Cards')
1137 bin_path = pjoin(path,'bin')
1138 src_path = pjoin(path,'src')
1139 include_path = pjoin(path,'include')
1140 subproc_path = pjoin(path,'SubProcesses')
1141 mw_path = pjoin(path,'Source','MadWeight')
1142
1143 if os.path.isfile(pjoin(include_path, 'Pythia.h')):
1144 return 'pythia8'
1145 elif not os.path.isdir(os.path.join(path, 'SubProcesses')):
1146 raise self.InvalidCmd, '%s : Not a valid directory' % path
1147
1148 if os.path.isdir(src_path):
1149 return 'standalone_cpp'
1150 elif os.path.isdir(mw_path):
1151 return 'madweight'
1152 elif os.path.isfile(pjoin(bin_path,'madevent')):
1153 return 'madevent'
1154 elif os.path.isfile(pjoin(bin_path,'aMCatNLO')):
1155 return 'aMC@NLO'
1156 elif os.path.isdir(card_path):
1157 return 'standalone'
1158
1159 raise self.InvalidCmd, '%s : Not a valid directory' % path
1160
1167
1169 """check the validity of the line"""
1170
1171
1172 if len(args) >1 :
1173 self.help_customize_model()
1174 raise self.InvalidCmd('No argument expected for this command')
1175
1176 if len(args):
1177 if not args[0].startswith('--save='):
1178 self.help_customize_model()
1179 raise self.InvalidCmd('Wrong argument for this command')
1180 if '-' in args[0][6:]:
1181 raise self.InvalidCmd('The name given in save options can\'t contain \'-\' symbol.')
1182
1183 if self._model_v4_path:
1184 raise self.InvalidCmd('Restriction of Model is not supported by v4 model.')
1185
1186
1188 """ check the validity of the line"""
1189
1190 if len(args) == 0:
1191 args.append('options')
1192
1193 if args[0] not in self._save_opts and args[0] != 'global':
1194 self.help_save()
1195 raise self.InvalidCmd('wrong \"save\" format')
1196 elif args[0] == 'global':
1197 args.insert(0, 'options')
1198
1199 if args[0] != 'options' and len(args) != 2:
1200 self.help_save()
1201 raise self.InvalidCmd('wrong \"save\" format')
1202 elif args[0] != 'options' and len(args) == 2:
1203 basename = os.path.dirname(args[1])
1204 if not os.path.exists(basename):
1205 raise self.InvalidCmd('%s is not a valid path, please retry' % \
1206 args[1])
1207
1208 if args[0] == 'options':
1209 has_path = None
1210 for arg in args[1:]:
1211 if arg in ['--auto', '--all']:
1212 continue
1213 elif arg.startswith('--'):
1214 raise self.InvalidCmd('unknow command for \'save options\'')
1215 elif arg == 'global':
1216 if os.environ.has_key('HOME'):
1217 args.remove('global')
1218 args.insert(1,pjoin(os.environ['HOME'],'.mg5','mg5_configuration.txt'))
1219 has_path = True
1220 else:
1221 basename = os.path.dirname(arg)
1222 if not os.path.exists(basename):
1223 raise self.InvalidCmd('%s is not a valid path, please retry' % \
1224 arg)
1225 elif has_path:
1226 raise self.InvalidCmd('only one path is allowed')
1227 else:
1228 args.remove(arg)
1229 args.insert(1, arg)
1230 has_path = True
1231 if not has_path:
1232 args.insert(1, pjoin(MG5DIR,'input','mg5_configuration.txt'))
1233
1234
1236 """ check the validity of the line"""
1237
1238 if len(args) == 1 and args[0] in ['complex_mass_scheme',\
1239 'loop_optimized_output',\
1240 'loop_color_flows']:
1241 args.append('True')
1242
1243 if len(args) > 2 and '=' == args[1]:
1244 args.pop(1)
1245
1246 if len(args) < 2:
1247 self.help_set()
1248 raise self.InvalidCmd('set needs an option and an argument')
1249
1250 if args[1] == 'default':
1251 if args[0] in self.options_configuration:
1252 default = self.options_configuration[args[0]]
1253 elif args[0] in self.options_madgraph:
1254 default = self.options_madgraph[args[0]]
1255 elif args[0] in self.options_madevent:
1256 default = self.options_madevent[args[0]]
1257 else:
1258 raise self.InvalidCmd('%s doesn\'t have a valid default value' % args[0])
1259 if log:
1260 logger.info('Pass parameter %s to it\'s default value: %s' %
1261 (args[0], default))
1262 args[1] = str(default)
1263
1264 if args[0] not in self._set_options:
1265 if not args[0] in self.options and not args[0] in self.options:
1266 self.help_set()
1267 raise self.InvalidCmd('Possible options for set are %s' % \
1268 self._set_options)
1269
1270 if args[0] in ['group_subprocesses']:
1271 if args[1] not in ['False', 'True', 'Auto']:
1272 raise self.InvalidCmd('%s needs argument False, True or Auto' % \
1273 args[0])
1274 if args[0] in ['ignore_six_quark_processes']:
1275 if args[1] not in self._multiparticles.keys() and args[1] != 'False':
1276 raise self.InvalidCmd('ignore_six_quark_processes needs ' + \
1277 'a multiparticle name as argument')
1278
1279 if args[0] in ['stdout_level']:
1280 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] and \
1281 not args[1].isdigit():
1282 raise self.InvalidCmd('output_level needs ' + \
1283 'a valid level')
1284
1285 if args[0] in ['timeout', 'max_npoint_for_channel']:
1286 if not args[1].isdigit():
1287 raise self.InvalidCmd('%s values should be a integer' % args[0])
1288
1289 if args[0] in ['loop_optimized_output', 'loop_color_flows']:
1290 try:
1291 args[1] = banner_module.ConfigFile.format_variable(args[1], bool, args[0])
1292 except Exception:
1293 raise self.InvalidCmd('%s needs argument True or False'%args[0])
1294
1295 if args[0] in ['gauge']:
1296 if args[1] not in ['unitary','Feynman']:
1297 raise self.InvalidCmd('gauge needs argument unitary or Feynman.')
1298
1299 if args[0] in ['timeout']:
1300 if not args[1].isdigit():
1301 raise self.InvalidCmd('timeout values should be a integer')
1302
1303 if args[0] in ['OLP']:
1304 if args[1] not in MadGraphCmd._OLP_supported:
1305 raise self.InvalidCmd('OLP value should be one of %s'\
1306 %str(MadGraphCmd._OLP_supported))
1307
1308 if args[0].lower() in ['ewscheme']:
1309 if not self._curr_model:
1310 raise self.InvalidCmd("ewscheme acts on the current model please load one first.")
1311 if args[1] not in ['external']:
1312 raise self.InvalidCmd('Only valid ewscheme is "external". To restore default, please re-import the model.')
1313
1314 if args[0] in ['output_dependencies']:
1315 if args[1] not in MadGraphCmd._output_dependencies_supported:
1316 raise self.InvalidCmd('output_dependencies value should be one of %s'\
1317 %str(MadGraphCmd._output_dependencies_supported))
1318
1320 """ check the validity of the line """
1321
1322 if len(args) != 1:
1323 self.help_open()
1324 raise self.InvalidCmd('OPEN command requires exactly one argument')
1325
1326 if args[0].startswith('./'):
1327 if not os.path.isfile(args[0]):
1328 raise self.InvalidCmd('%s: not such file' % args[0])
1329 return True
1330
1331
1332 if not self._done_export:
1333 if not os.path.isfile(args[0]):
1334 self.help_open()
1335 raise self.InvalidCmd('No command \"output\" or \"launch\" used. Impossible to associate this name to a file')
1336 else:
1337 return True
1338
1339 path = self._done_export[0]
1340 if os.path.isfile(pjoin(path,args[0])):
1341 args[0] = pjoin(path,args[0])
1342 elif os.path.isfile(pjoin(path,'Cards',args[0])):
1343 args[0] = pjoin(path,'Cards',args[0])
1344 elif os.path.isfile(pjoin(path,'HTML',args[0])):
1345 args[0] = pjoin(path,'HTML',args[0])
1346
1347 elif '_card.dat' in args[0]:
1348 name = args[0].replace('_card.dat','_card_default.dat')
1349 if os.path.isfile(pjoin(path,'Cards', name)):
1350 files.cp(path + '/Cards/' + name, path + '/Cards/'+ args[0])
1351 args[0] = pjoin(path,'Cards', args[0])
1352 else:
1353 raise self.InvalidCmd('No default path for this file')
1354 elif not os.path.isfile(args[0]):
1355 raise self.InvalidCmd('No default path for this file')
1356
1357
1359 """ check the validity of the line"""
1360
1361
1362 if args and args[0] in self._export_formats:
1363 self._export_format = args.pop(0)
1364 else:
1365 self._export_format = default
1366
1367 if not self._curr_model:
1368 text = 'No model found. Please import a model first and then retry.'
1369 raise self.InvalidCmd(text)
1370
1371 if self._model_v4_path and \
1372 (self._export_format not in self._v4_export_formats):
1373 text = " The Model imported (MG4 format) does not contain enough\n "
1374 text += " information for this type of output. In order to create\n"
1375 text += " output for " + args[0] + ", you have to use a UFO model.\n"
1376 text += " Those model can be imported with MG5> import model NAME."
1377 logger.warning(text)
1378 raise self.InvalidCmd('')
1379
1380 if self._export_format == 'aloha':
1381 return
1382
1383
1384 if not self._curr_amps:
1385 text = 'No processes generated. Please generate a process first.'
1386 raise self.InvalidCmd(text)
1387
1388 if args and args[0][0] != '-':
1389
1390 path = args.pop(0)
1391 forbiden_chars = ['>','<',';','&']
1392 for char in forbiden_chars:
1393 if char in path:
1394 raise self.InvalidCmd('%s is not allowed in the output path' % char)
1395
1396 if path == 'auto' and self._export_format in \
1397 ['madevent', 'standalone', 'standalone_cpp', 'matchbox_cpp', 'madweight',
1398 'matchbox']:
1399 self.get_default_path()
1400 if '-noclean' not in args and os.path.exists(self._export_dir):
1401 args.append('-noclean')
1402 elif path != 'auto':
1403 self._export_dir = path
1404 elif path == 'auto':
1405 if self.options['pythia8_path']:
1406 self._export_dir = self.options['pythia8_path']
1407 else:
1408 self._export_dir = '.'
1409 else:
1410 if self._export_format != 'pythia8':
1411
1412 self.get_default_path()
1413 if '-noclean' not in args and os.path.exists(self._export_dir):
1414 args.append('-noclean')
1415
1416 else:
1417 if self.options['pythia8_path']:
1418 self._export_dir = self.options['pythia8_path']
1419 else:
1420 self._export_dir = '.'
1421
1422 self._export_dir = os.path.realpath(self._export_dir)
1423
1424
1426 """ check and format calculate decay width:
1427 Expected format: NAME [other names] [--options]
1428 # fill the options if not present.
1429 # NAME can be either (anti-)particle name, multiparticle, pid
1430 """
1431
1432 if len(args)<1:
1433 self.help_compute_widths()
1434 raise self.InvalidCmd('''compute_widths requires at least the name of one particle.
1435 If you want to compute the width of all particles, type \'compute_widths all\'''')
1436
1437 particles = set()
1438 options = {'path':None, 'output':None,
1439 'min_br':None, 'body_decay':4.0025, 'precision_channel':0.01,
1440 'nlo':False}
1441
1442
1443 for i,arg in enumerate(args):
1444 if arg.startswith('--'):
1445 if arg.startswith('--nlo'):
1446 options['nlo'] =True
1447 continue
1448 elif not '=' in arg:
1449 raise self.InvalidCmd('Options required an equal (and then the value)')
1450 arg, value = arg.split('=')
1451 if arg[2:] not in options:
1452 raise self.InvalidCmd('%s not valid options' % arg)
1453 options[arg[2:]] = value
1454 continue
1455
1456 if arg.isdigit():
1457 p = self._curr_model.get_particle(int(arg))
1458 if not p:
1459 raise self.InvalidCmd('Model doesn\'t have pid %s for any particle' % arg)
1460 particles.add(abs(int(arg)))
1461 elif arg in self._multiparticles:
1462 particles.update([abs(id) for id in self._multiparticles[args[0]]])
1463 else:
1464 if not self._curr_model['case_sensitive']:
1465 arg = arg.lower()
1466 for p in self._curr_model['particles']:
1467 if p['name'] == arg or p['antiname'] == arg:
1468 particles.add(abs(p.get_pdg_code()))
1469 break
1470 else:
1471 if arg == 'all':
1472
1473 particles.update([abs(p.get_pdg_code())
1474 for p in self._curr_model['particles']])
1475 else:
1476 raise self.InvalidCmd('%s invalid particle name' % arg)
1477
1478 if options['path'] and not os.path.isfile(options['path']):
1479
1480 if os.path.exists(pjoin(MG5DIR, options['path'])):
1481 options['path'] = pjoin(MG5DIR, options['path'])
1482 elif self._model_v4_path and os.path.exists(pjoin(self._model_v4_path, options['path'])):
1483 options['path'] = pjoin(self._curr_model_v4_path, options['path'])
1484 elif os.path.exists(pjoin(self._curr_model.path, options['path'])):
1485 options['path'] = pjoin(self._curr_model.path, options['path'])
1486
1487 if os.path.isdir(options['path']) and os.path.isfile(pjoin(options['path'], 'param_card.dat')):
1488 options['path'] = pjoin(options['path'], 'param_card.dat')
1489 elif not os.path.isfile(options['path']):
1490 raise self.InvalidCmd('%s is not a valid path' % args[2])
1491
1492 if madevent_interface.MadEventCmd.detect_card_type(options['path']) != 'param_card.dat':
1493 raise self.InvalidCmd('%s should be a path to a param_card' % options['path'])
1494
1495 if not options['path']:
1496 param_card_text = self._curr_model.write_param_card()
1497 if not options['output']:
1498 dirpath = self._curr_model.get('modelpath')
1499 options['path'] = pjoin(dirpath, 'param_card.dat')
1500 else:
1501 options['path'] = options['output']
1502 ff = open(options['path'],'w')
1503 ff.write(param_card_text)
1504 ff.close()
1505 if not options['output']:
1506 options['output'] = options['path']
1507
1508 if not options['min_br']:
1509 options['min_br'] = (float(options['body_decay']) % 1) / 5
1510 return particles, options
1511
1512
1513 check_decay_diagram = check_compute_widths
1514
1516 """Set self._export_dir to the default (\'auto\') path"""
1517
1518 if self._export_format in ['madevent', 'standalone']:
1519
1520
1521 if 'TemplateVersion.txt' in os.listdir('.'):
1522
1523 self._export_dir = os.path.realpath('.')
1524 return
1525 elif 'TemplateVersion.txt' in os.listdir('..'):
1526
1527 self._export_dir = os.path.realpath('..')
1528 return
1529 elif self.stdin != sys.stdin:
1530
1531 input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
1532 print "Not standard stdin, use input path"
1533 if input_path[-2] == 'Cards':
1534 self._export_dir = os.path.sep.join(input_path[:-2])
1535 if 'TemplateVersion.txt' in self._export_dir:
1536 return
1537
1538
1539 if self._export_format == 'NLO':
1540 name_dir = lambda i: 'PROCNLO_%s_%s' % \
1541 (self._curr_model['name'], i)
1542 auto_path = lambda i: pjoin(self.writing_dir,
1543 name_dir(i))
1544 elif self._export_format.startswith('madevent'):
1545 name_dir = lambda i: 'PROC_%s_%s' % \
1546 (self._curr_model['name'], i)
1547 auto_path = lambda i: pjoin(self.writing_dir,
1548 name_dir(i))
1549 elif self._export_format.startswith('standalone'):
1550 name_dir = lambda i: 'PROC_SA_%s_%s' % \
1551 (self._curr_model['name'], i)
1552 auto_path = lambda i: pjoin(self.writing_dir,
1553 name_dir(i))
1554 elif self._export_format == 'madweight':
1555 name_dir = lambda i: 'PROC_MW_%s_%s' % \
1556 (self._curr_model['name'], i)
1557 auto_path = lambda i: pjoin(self.writing_dir,
1558 name_dir(i))
1559 elif self._export_format == 'standalone_cpp':
1560 name_dir = lambda i: 'PROC_SA_CPP_%s_%s' % \
1561 (self._curr_model['name'], i)
1562 auto_path = lambda i: pjoin(self.writing_dir,
1563 name_dir(i))
1564 elif self._export_format in ['matchbox_cpp', 'matchbox']:
1565 name_dir = lambda i: 'PROC_MATCHBOX_%s_%s' % \
1566 (self._curr_model['name'], i)
1567 auto_path = lambda i: pjoin(self.writing_dir,
1568 name_dir(i))
1569 elif self._export_format == 'pythia8':
1570 if self.options['pythia8_path']:
1571 self._export_dir = self.options['pythia8_path']
1572 else:
1573 self._export_dir = '.'
1574 return
1575 else:
1576 self._export_dir = '.'
1577 return
1578 for i in range(500):
1579 if os.path.isdir(auto_path(i)):
1580 continue
1581 else:
1582 self._export_dir = auto_path(i)
1583 break
1584 if not self._export_dir:
1585 raise self.InvalidCmd('Can\'t use auto path,' + \
1586 'more than 500 dirs already')
1587
1593 """ Check the validity of input line for web entry
1594 (no explicit path authorized)"""
1595
1597 """class for WebRestriction"""
1598
1600 """check the validity of line
1601 syntax: draw FILEPATH [option=value]
1602 """
1603 raise self.WebRestriction('direct call to draw is forbidden on the web')
1604
1612
1614 """ Not authorize for the Web"""
1615
1616 raise self.WebRestriction('Check call is forbidden on the web')
1617
1618 - def check_history(self, args):
1619 """check the validity of line
1620 No Path authorize for the Web"""
1621
1622 CheckValidForCmd.check_history(self, args)
1623
1624 if len(args) == 2 and args[1] not in ['.', 'clean']:
1625 raise self.WebRestriction('Path can\'t be specify on the web.')
1626
1627
1643
1645 """ No possibility to install new software on the web """
1646 if args == ['update','--mode=mg5_start']:
1647 return
1648
1649 raise self.WebRestriction('Impossible to install program on the cluster')
1650
1652 """ check the validity of the line
1653 No Path authorize for the Web"""
1654
1655 CheckValidForCmd.check_load(self, args)
1656
1657 if len(args) == 2:
1658 if args[0] != 'model':
1659 raise self.WebRestriction('only model can be loaded online')
1660 if 'model.pkl' not in args[1]:
1661 raise self.WebRestriction('not valid pkl file: wrong name')
1662 if not os.path.realpath(args[1]).startswith(pjoin(MG4DIR, \
1663 'Models')):
1664 raise self.WebRestriction('Wrong path to load model')
1665
1667 """ not authorize on web"""
1668 raise self.WebRestriction('\"save\" command not authorize online')
1669
1671 """ not authorize on web"""
1672 raise self.WebRestriction('\"open\" command not authorize online')
1673
1675 """ check the validity of the line"""
1676
1677
1678 CheckValidForCmd.check_output(self, args, default=default)
1679 args[:] = ['.', '-f']
1680
1681 self._export_dir = os.path.realpath(os.getcwd())
1682
1683 if 'madevent' != self._export_format:
1684 raise self.WebRestriction, 'only available output format is madevent (at current stage)'
1685
1690 """ The Series of help routine for the MadGraphCmd"""
1691
1693 """ complete the nlo settings within square brackets. It uses the
1694 allowed_loop_mode for the proposed mode if specified, otherwise, it
1695 uses self._nlo_modes_for_completion"""
1696
1697
1698
1699
1700 nlo_modes = allowed_loop_mode if not allowed_loop_mode is None else \
1701 self._nlo_modes_for_completion
1702 if isinstance(self._curr_model,loop_base_objects.LoopModel):
1703 pert_couplings_allowed = self._curr_model['perturbation_couplings']
1704 else:
1705 pert_couplings_allowed = []
1706 if self._curr_model.get('name').startswith('sm'):
1707 pert_couplings_allowed = pert_couplings_allowed + ['QCD']
1708
1709 loop_specs = line[line.index('[')+1:]
1710 try:
1711 loop_orders = loop_specs[loop_specs.index('=')+1:]
1712 except ValueError:
1713 loop_orders = loop_specs
1714 possibilities = []
1715 possible_orders = [order for order in pert_couplings_allowed if \
1716 order not in loop_orders]
1717
1718
1719 single_completion = ''
1720 if len(nlo_modes)==1:
1721 single_completion = '%s= '%nlo_modes[0]
1722 if len(possible_orders)==1:
1723 single_completion = single_completion + possible_orders[0] + ' ] '
1724
1725 if text.endswith('['):
1726 if single_completion != '':
1727 return self.list_completion(text, ['[ '+single_completion])
1728 else:
1729 return self.list_completion(text,['[ '])
1730
1731 if text.endswith('='):
1732 return self.list_completion(text,[' '])
1733
1734 if args[-1]=='[':
1735 possibilities = possibilities + ['%s= '%mode for mode in nlo_modes]
1736 if single_completion != '':
1737 return self.list_completion(text, [single_completion])
1738 else:
1739 if len(possible_orders)==1:
1740 return self.list_completion(text, [poss+' %s ] '%\
1741 possible_orders[0] for poss in possibilities])
1742 return self.list_completion(text, possibilities)
1743
1744 if len(possible_orders)==1:
1745 possibilities.append(possible_orders[0]+' ] ')
1746 else:
1747 possibilities.extend(possible_orders)
1748 if any([(order in loop_orders) for order in pert_couplings_allowed]):
1749 possibilities.append(']')
1750 return self.list_completion(text, possibilities)
1751
1752 - def model_completion(self, text, process, line, categories = True, \
1753 allowed_loop_mode = None):
1754 """ complete the line with model information. If categories is True,
1755 it will use completion with categories. If allowed_loop_mode is
1756 specified, it will only complete with these loop modes."""
1757
1758
1759
1760 args = self.split_arg(process)
1761 if len(args) > 2 and '>' in line and '[' in line and not ']' in line:
1762 return self.nlo_completion(args,text,line, allowed_loop_mode = \
1763 allowed_loop_mode)
1764
1765 while ',' in process:
1766 process = process[process.index(',')+1:]
1767 args = self.split_arg(process)
1768 couplings = []
1769
1770
1771 if len(args) > 1 and args[-1]=='@':
1772 return
1773
1774
1775
1776 if isinstance(self._curr_model,loop_base_objects.LoopModel):
1777 pert_couplings_allowed = self._curr_model['perturbation_couplings']
1778 else:
1779 pert_couplings_allowed = []
1780 if self._curr_model.get('name').startswith('sm'):
1781 pert_couplings_allowed = pert_couplings_allowed + ['QCD']
1782
1783
1784 particles = list(set(self._particle_names + self._multiparticles.keys()))
1785 n_part_entered = len([1 for a in args if a in particles])
1786
1787
1788 if n_part_entered == 2 and args[-1] != '>':
1789 return self.list_completion(text, '>')
1790
1791
1792 syntax = []
1793 couplings = []
1794 if len(args) > 0 and args[-1] != '>' and n_part_entered > 0:
1795 syntax.append('>')
1796 if '>' in args and args.index('>') < len(args) - 1:
1797 couplings.extend(sum([[c+"=",c+'^2'] for c in \
1798 self._couplings+['WEIGHTED']],[]))
1799 syntax.extend(['@','$','/','>',','])
1800 if '[' not in line and ',' not in line and len(pert_couplings_allowed)>0:
1801 syntax.append('[')
1802
1803
1804
1805 if '[' in line:
1806 syntax = []
1807 particles = []
1808
1809 couplings.append('@')
1810
1811 if not categories:
1812
1813
1814
1815
1816
1817 return self.list_completion(text, particles+syntax+couplings)
1818 else:
1819
1820 poss_particles = self.list_completion(text, particles)
1821 poss_syntax = self.list_completion(text, syntax)
1822 poss_couplings = self.list_completion(text, couplings)
1823 possibilities = {}
1824 if poss_particles != []: possibilities['Particles']=poss_particles
1825 if poss_syntax != []: possibilities['Syntax']=poss_syntax
1826 if poss_couplings != []: possibilities['Coupling orders']=poss_couplings
1827 if len(possibilities.keys())==1:
1828 return self.list_completion(text, possibilities.values()[0])
1829 else:
1830 return self.deal_multiple_categories(possibilities)
1831
1833 "Complete the generate command"
1834
1835
1836
1837 args = self.split_arg(line[0:begidx])
1838
1839 valid_sqso_operators=['==','<=','>']
1840 if any(line.endswith('^2 %s '%op) for op in valid_sqso_operators):
1841 return
1842 if args[-1].endswith('^2'):
1843 return self.list_completion(text,valid_sqso_operators)
1844 match_op = [o for o in valid_sqso_operators if o.startswith(args[-1])]
1845 if args[-2].endswith('^2') and len(match_op)>0:
1846 if args[-1] in valid_sqso_operators:
1847 return self.list_completion(text,' ')
1848 if len(match_op)==1:
1849 return self.list_completion(text,[match_op[0][len(args[-1]):]])
1850 else:
1851 return self.list_completion(text,match_op)
1852
1853 if len(args) > 2 and args[-1] == '@' or ( args[-1].endswith('=') and \
1854 (not '[' in line or ('[' in line and ']' in line))):
1855 return
1856
1857 try:
1858 return self.model_completion(text, ' '.join(args[1:]),line)
1859 except Exception as error:
1860 print error
1861
1862
1863
1864
1865
1866
1867
1868
1869
1871 "Complete the compute_widths command"
1872
1873 args = self.split_arg(line[0:begidx])
1874
1875 if args[-1] in ['--path=', '--output=']:
1876 completion = {'path': self.path_completion(text)}
1877 elif line[begidx-1] == os.path.sep:
1878 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)])
1879 if current_dir.startswith('--path='):
1880 current_dir = current_dir[7:]
1881 if current_dir.startswith('--output='):
1882 current_dir = current_dir[9:]
1883 completion = {'path': self.path_completion(text, current_dir)}
1884 else:
1885 completion = {}
1886 completion['options'] = self.list_completion(text,
1887 ['--path=', '--output=', '--min_br=0.\$',
1888 '--precision_channel=0.\$', '--body_decay=', '--nlo'])
1889 completion['particles'] = self.model_completion(text, '', line)
1890
1891 return self.deal_multiple_categories(completion)
1892
1893 complete_decay_diagram = complete_compute_widths
1894
1896 "Complete the add command"
1897
1898 args = self.split_arg(line[0:begidx])
1899
1900
1901 if len(args) == 1:
1902 return self.list_completion(text, self._add_opts)
1903
1904 if args[1] == 'process':
1905 return self.complete_generate(text, " ".join(args[1:]), begidx, endidx)
1906
1907 elif args[1] == 'model':
1908 completion_categories = self.complete_import(text, line, begidx, endidx,
1909 allow_restrict=False, treat_completion=False)
1910 completion_categories['options'] = self.list_completion(text,['--modelname=','--recreate'])
1911 return self.deal_multiple_categories(completion_categories)
1912
1914 "Complete the customize_model command"
1915
1916 args = self.split_arg(line[0:begidx])
1917
1918
1919 if len(args) == 1:
1920 return self.list_completion(text, ['--save='])
1921
1922
1924 "Complete the check command"
1925
1926 out = {}
1927 args = self.split_arg(line[0:begidx])
1928
1929
1930 if len(args) == 1:
1931 return self.list_completion(text, self._check_opts)
1932
1933
1934 if args[-1].endswith(os.path.sep):
1935 return self.path_completion(text, pjoin(*[a for a in args \
1936 if a.endswith(os.path.sep)]))
1937
1938 model_comp = self.model_completion(text, ' '.join(args[2:]),line,
1939 categories = True, allowed_loop_mode=['virt'])
1940
1941 model_comp_and_path = self.deal_multiple_categories(\
1942 {'Process completion': self.model_completion(text, ' '.join(args[2:]),
1943 line, categories = False, allowed_loop_mode=['virt']),
1944 'Param_card.dat path completion:':self.path_completion(text),
1945 'options': self.list_completion(text, ['--energy='])})
1946
1947 if len(args) == 2:
1948 return model_comp_and_path
1949 elif len(args) == 3:
1950 try:
1951 int(args[2])
1952 except ValueError:
1953 return model_comp
1954 else:
1955 return model_comp_and_path
1956 elif len(args) > 3:
1957 return model_comp
1958
1959
1966
1968 """Complete particle information"""
1969 return self.model_completion(text, line[6:],line)
1970
1984
1986 "Complete the draw command"
1987
1988 args = self.split_arg(line[0:begidx])
1989
1990
1991 if args[-1].endswith(os.path.sep):
1992 return self.path_completion(text,
1993 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
1994 only_dirs = True)
1995
1996 if len(args) == 1:
1997 return self.path_completion(text, '.', only_dirs = True)
1998
1999
2000
2001 if len(args) >= 2:
2002 opt = ['horizontal', 'external=', 'max_size=', 'add_gap=',
2003 'non_propagating', '--']
2004 return self.list_completion(text, opt)
2005
2007 """ complete the launch command"""
2008 args = self.split_arg(line[0:begidx])
2009
2010
2011 if args[-1].endswith(os.path.sep):
2012 return self.path_completion(text,
2013 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2014 only_dirs = True)
2015
2016 if len(args) == 1:
2017 out = {'Path from ./': self.path_completion(text, '.', only_dirs = True)}
2018 if MG5DIR != os.path.realpath('.'):
2019 out['Path from %s' % MG5DIR] = self.path_completion(text,
2020 MG5DIR, only_dirs = True, relative=False)
2021 if MG4DIR and MG4DIR != os.path.realpath('.') and MG4DIR != MG5DIR:
2022 out['Path from %s' % MG4DIR] = self.path_completion(text,
2023 MG4DIR, only_dirs = True, relative=False)
2024
2025
2026
2027 if len(args) >= 2:
2028 out={}
2029
2030 if line[0:begidx].endswith('--laststep='):
2031 opt = ['parton', 'pythia', 'pgs','delphes','auto']
2032 out['Options'] = self.list_completion(text, opt, line)
2033 else:
2034 opt = ['--cluster', '--multicore', '-i', '--name=', '-f','-m', '-n',
2035 '-p','--parton','--interactive', '--laststep=parton', '--laststep=pythia',
2036 '--laststep=pgs', '--laststep=delphes','--laststep=auto']
2037 out['Options'] = self.list_completion(text, opt, line)
2038
2039
2040 return self.deal_multiple_categories(out)
2041
2060
2079
2080 @cmd.debug()
2082 """ complete the open command """
2083
2084 args = self.split_arg(line[0:begidx])
2085
2086
2087 if os.path.sep in args[-1] + text:
2088 return self.path_completion(text,
2089 pjoin(*[a for a in args if \
2090 a.endswith(os.path.sep)]))
2091
2092 possibility = []
2093 if self._done_export:
2094 path = self._done_export[0]
2095 possibility = ['index.html']
2096 if os.path.isfile(pjoin(path,'README')):
2097 possibility.append('README')
2098 if os.path.isdir(pjoin(path,'Cards')):
2099 possibility += [f for f in os.listdir(pjoin(path,'Cards'))
2100 if f.endswith('.dat')]
2101 if os.path.isdir(pjoin(path,'HTML')):
2102 possibility += [f for f in os.listdir(pjoin(path,'HTML'))
2103 if f.endswith('.html') and 'default' not in f]
2104 else:
2105 possibility.extend(['./','../'])
2106 if os.path.exists('MG5_debug'):
2107 possibility.append('MG5_debug')
2108 if os.path.exists('ME5_debug'):
2109 possibility.append('ME5_debug')
2110
2111 return self.list_completion(text, possibility)
2112
2113 @cmd.debug()
2114 - def complete_output(self, text, line, begidx, endidx,
2115 possible_options = ['f', 'noclean', 'nojpeg'],
2116 possible_options_full = ['-f', '-noclean', '-nojpeg']):
2117 "Complete the output command"
2118
2119 possible_format = self._export_formats
2120
2121 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2122 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2123 'mg5', 'DECAY', 'EventConverter', 'Models',
2124 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha',
2125 'matchbox', 'matchbox_cpp', 'tests']
2126
2127
2128 args = self.split_arg(line[0:begidx])
2129 if len(args) >= 1:
2130 if len(args) > 1 and args[1] == 'aloha':
2131 try:
2132 return self.aloha_complete_output(text, line, begidx, endidx)
2133 except Exception, error:
2134 print error
2135
2136 if args[-1].endswith(os.path.sep):
2137 return [name for name in self.path_completion(text,
2138 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2139 only_dirs = True) if name not in forbidden_names]
2140
2141 if args[-1][0] == '-' or len(args) > 1 and args[-2] == '-':
2142 return self.list_completion(text, possible_options)
2143 if len(args) > 2:
2144 return self.list_completion(text, possible_options_full)
2145
2146 if len(args) == 1:
2147 format = possible_format + ['.' + os.path.sep, '..' + os.path.sep, 'auto']
2148 return self.list_completion(text, format)
2149
2150
2151 content = [name for name in self.path_completion(text, '.', only_dirs = True) \
2152 if name not in forbidden_names]
2153 content += ['auto']
2154 return self.list_completion(text, content)
2155
2157 "Complete the output aloha command"
2158 args = self.split_arg(line[0:begidx])
2159 completion_categories = {}
2160
2161 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS',
2162 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
2163 'mg5', 'DECAY', 'EventConverter', 'Models',
2164 'ExRootAnalysis', 'Transfer_Fct', 'aloha',
2165 'apidoc','vendor']
2166
2167
2168
2169 options = ['--format=Fortran', '--format=Python','--format=gpu','--format=CPP','--output=']
2170 options = self.list_completion(text, options)
2171 if options:
2172 completion_categories['options'] = options
2173
2174 if args[-1] == '--output=' or args[-1].endswith(os.path.sep):
2175
2176 completion_categories['path'] = [name for name in self.path_completion(text,
2177 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2178 only_dirs = True) if name not in forbidden_names]
2179
2180 else:
2181 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
2182 wf_opt = []
2183 amp_opt = []
2184 opt_conjg = []
2185 for lor in ufomodel.all_lorentz:
2186 amp_opt.append('%s_0' % lor.name)
2187 for i in range(len(lor.spins)):
2188 wf_opt.append('%s_%i' % (lor.name,i+1))
2189 if i % 2 == 0 and lor.spins[i] == 2:
2190 opt_conjg.append('%sC%i_%i' % (lor.name,i //2 +1,i+1))
2191 completion_categories['amplitude routines'] = self.list_completion(text, amp_opt)
2192 completion_categories['Wavefunctions routines'] = self.list_completion(text, wf_opt)
2193 completion_categories['conjugate_routines'] = self.list_completion(text, opt_conjg)
2194
2195 return self.deal_multiple_categories(completion_categories)
2196
2198 "Complete the set command"
2199 args = self.split_arg(line[0:begidx])
2200
2201
2202 if len(args) == 1:
2203 opts = list(set(self.options.keys() + self._set_options))
2204 return self.list_completion(text, opts)
2205
2206 if len(args) == 2:
2207 if args[1] in ['group_subprocesses', 'complex_mass_scheme',\
2208 'loop_optimized_output', 'loop_color_flows']:
2209 return self.list_completion(text, ['False', 'True', 'default'])
2210 elif args[1] in ['ignore_six_quark_processes']:
2211 return self.list_completion(text, self._multiparticles.keys())
2212 elif args[1].lower() == 'ewscheme':
2213 return self.list_completion(text, ["external"])
2214 elif args[1] == 'gauge':
2215 return self.list_completion(text, ['unitary', 'Feynman','default'])
2216 elif args[1] == 'OLP':
2217 return self.list_completion(text, MadGraphCmd._OLP_supported)
2218 elif args[1] == 'output_dependencies':
2219 return self.list_completion(text,
2220 MadGraphCmd._output_dependencies_supported)
2221 elif args[1] == 'stdout_level':
2222 return self.list_completion(text, ['DEBUG','INFO','WARNING','ERROR',
2223 'CRITICAL','default'])
2224 elif args[1] == 'fortran_compiler':
2225 return self.list_completion(text, ['f77','g77','gfortran','default'])
2226 elif args[1] == 'cpp_compiler':
2227 return self.list_completion(text, ['g++', 'c++', 'clang', 'default'])
2228 elif args[1] == 'nb_core':
2229 return self.list_completion(text, [str(i) for i in range(100)] + ['default'] )
2230 elif args[1] == 'run_mode':
2231 return self.list_completion(text, [str(i) for i in range(3)] + ['default'])
2232 elif args[1] == 'cluster_type':
2233 return self.list_completion(text, cluster.from_name.keys() + ['default'])
2234 elif args[1] == 'cluster_queue':
2235 return []
2236 elif args[1] == 'automatic_html_opening':
2237 return self.list_completion(text, ['False', 'True', 'default'])
2238 else:
2239
2240 second_set = [name for name in self.path_completion(text, '.', only_dirs = True)]
2241 return self.list_completion(text, second_set + ['default'])
2242 elif len(args) >2 and args[-1].endswith(os.path.sep):
2243 return self.path_completion(text,
2244 pjoin(*[a for a in args if a.endswith(os.path.sep)]),
2245 only_dirs = True)
2246
2247 - def complete_import(self, text, line, begidx, endidx, allow_restrict=True,
2248 treat_completion=True):
2249 "Complete the import command"
2250
2251 args=self.split_arg(line[0:begidx])
2252
2253
2254 if len(args) == 1:
2255 opt = self.list_completion(text, self._import_formats)
2256 if opt:
2257 return opt
2258 mode = 'all'
2259 elif args[1] in self._import_formats:
2260 mode = args[1]
2261 else:
2262 args.insert(1, 'all')
2263 mode = 'all'
2264
2265
2266 completion_categories = {}
2267
2268 if mode in ['model', 'all'] and '-' in text:
2269
2270 path = '-'.join([part for part in text.split('-')[:-1]])
2271
2272
2273 all_name = self.find_restrict_card(path, no_restrict=False)
2274 all_name += self.find_restrict_card(path, no_restrict=False,
2275 base_dir=pjoin(MG5DIR,'models'))
2276
2277
2278 all_name = [name+' ' for name in all_name if name.startswith(text)
2279 and name.strip() != text]
2280
2281
2282 if all_name:
2283 completion_categories['Restricted model'] = all_name
2284
2285
2286 if os.path.sep in args[-1]:
2287 if mode.startswith('model') or mode == 'all':
2288
2289 try:
2290 cur_path = pjoin(*[a for a in args \
2291 if a.endswith(os.path.sep)])
2292 except Exception:
2293 pass
2294 else:
2295 all_dir = self.path_completion(text, cur_path, only_dirs = True)
2296 if mode in ['model_v4','all']:
2297 completion_categories['Path Completion'] = all_dir
2298
2299 new = []
2300 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2301 for name in all_dir]
2302 if data:
2303 completion_categories['Path Completion'] = all_dir + new
2304 else:
2305 try:
2306 cur_path = pjoin(*[a for a in args \
2307 if a.endswith(os.path.sep)])
2308 except Exception:
2309 pass
2310 else:
2311 all_path = self.path_completion(text, cur_path)
2312 if mode == 'all':
2313 new = []
2314 data = [new.__iadd__(self.find_restrict_card(name, base_dir=cur_path))
2315 for name in all_path]
2316 if data:
2317 completion_categories['Path Completion'] = data[0]
2318 else:
2319 completion_categories['Path Completion'] = all_path
2320
2321
2322 if (len(args) == 2):
2323 is_model = True
2324 if mode == 'model':
2325 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py'))
2326 mod_name = lambda name: name
2327 elif mode == 'model_v4':
2328 file_cond = lambda p : (os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat'))
2329 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat')))
2330 mod_name = lambda name :(name[-3:] != '_v4' and name or name[:-3])
2331 elif mode == 'all':
2332 mod_name = lambda name: name
2333 file_cond = lambda p : os.path.exists(pjoin(MG5DIR,'models',p,'particles.py')) \
2334 or os.path.exists(pjoin(MG5DIR,'models',p,'particles.dat')) \
2335 or os.path.exists(pjoin(self._mgme_dir,'Models',p,'particles.dat'))
2336 else:
2337 cur_path = pjoin(*[a for a in args \
2338 if a.endswith(os.path.sep)])
2339 all_path = self.path_completion(text, cur_path)
2340 completion_categories['model name'] = all_path
2341 is_model = False
2342
2343 if is_model:
2344 model_list = [mod_name(name) for name in \
2345 self.path_completion(text,
2346 pjoin(MG5DIR,'models'),
2347 only_dirs = True) \
2348 if file_cond(name)]
2349
2350 if mode == 'model_v4':
2351 completion_categories['model name'] = model_list
2352 elif allow_restrict:
2353
2354 all_name = []
2355 for model_name in model_list:
2356 all_name += self.find_restrict_card(model_name,
2357 base_dir=pjoin(MG5DIR,'models'))
2358 else:
2359 all_name = model_list
2360
2361 if mode == 'all':
2362 cur_path = pjoin(*[a for a in args \
2363 if a.endswith(os.path.sep)])
2364 all_path = self.path_completion(text, cur_path)
2365 completion_categories['model name'] = all_path + all_name
2366 elif mode == 'model':
2367 completion_categories['model name'] = all_name
2368
2369
2370 if mode == 'all' and len(args)>1:
2371 mode = self.find_import_type(args[2])
2372
2373 if len(args) >= 3 and mode.startswith('model') and not '-modelname' in line:
2374 if not text and not completion_categories:
2375 return ['--modelname']
2376 elif not (os.path.sep in args[-1] and line[-1] != ' '):
2377 completion_categories['options'] = self.list_completion(text, ['--modelname','-modelname','--noprefix'])
2378 if len(args) >= 3 and mode.startswith('banner') and not '--no_launch' in line:
2379 completion_categories['options'] = self.list_completion(text, ['--no_launch'])
2380
2381 if treat_completion:
2382 return self.deal_multiple_categories(completion_categories)
2383 else:
2384
2385 return completion_categories
2386
2387
2389 """find the restriction file associate to a given model"""
2390
2391
2392 if no_restrict:
2393 output = [model_name]
2394 else:
2395 output = []
2396
2397
2398 if not os.path.exists(pjoin(base_dir, model_name, 'couplings.py')):
2399
2400 return output
2401
2402 if model_name.endswith(os.path.sep):
2403 model_name = model_name[:-1]
2404
2405
2406 if os.path.exists(pjoin(base_dir, model_name, 'restrict_default.dat')):
2407 output.append('%s-full' % model_name)
2408
2409
2410 for name in os.listdir(pjoin(base_dir, model_name)):
2411 if name.startswith('restrict_') and not name.endswith('default.dat') \
2412 and name.endswith('.dat'):
2413 tag = name[9:-4]
2414 while model_name.endswith(os.path.sep):
2415 model_name = model_name[:-1]
2416 output.append('%s-%s' % (model_name, tag))
2417
2418
2419 return output
2420
2431
2432
2433
2434
2435 -class MadGraphCmd(HelpToCmd, CheckValidForCmd, CompleteForCmd, CmdExtended):
2436 """The command line processor of MadGraph"""
2437
2438 writing_dir = '.'
2439
2440
2441 _display_opts = ['particles', 'interactions', 'processes', 'diagrams',
2442 'diagrams_text', 'multiparticles', 'couplings', 'lorentz',
2443 'checks', 'parameters', 'options', 'coupling_order','variable']
2444 _add_opts = ['process', 'model']
2445 _save_opts = ['model', 'processes', 'options']
2446 _tutorial_opts = ['aMCatNLO', 'stop', 'MadLoop', 'MadGraph5']
2447 _switch_opts = ['mg5','aMC@NLO','ML5']
2448 _check_opts = ['full', 'timing', 'stability', 'profile', 'permutation',
2449 'gauge','lorentz', 'brs']
2450 _import_formats = ['model_v4', 'model', 'proc_v4', 'command', 'banner']
2451 _install_opts = ['pythia-pgs', 'Delphes', 'MadAnalysis', 'ExRootAnalysis',
2452 'update', 'Delphes2', 'SysCalc', 'Golem95']
2453 _v4_export_formats = ['madevent', 'standalone', 'standalone_msP','standalone_msF',
2454 'matrix', 'standalone_rw', 'madweight']
2455 _export_formats = _v4_export_formats + ['standalone_cpp', 'pythia8', 'aloha',
2456 'matchbox_cpp', 'matchbox']
2457 _set_options = ['group_subprocesses',
2458 'ignore_six_quark_processes',
2459 'stdout_level',
2460 'fortran_compiler',
2461 'cpp_compiler',
2462 'loop_optimized_output',
2463 'complex_mass_scheme',
2464 'gauge',
2465 'EWscheme',
2466 'max_npoint_for_channel']
2467 _valid_nlo_modes = ['all','real','virt','sqrvirt','tree','noborn','LOonly']
2468 _valid_sqso_types = ['==','<=','=','>']
2469 _valid_amp_so_types = ['=','<=']
2470 _OLP_supported = ['MadLoop', 'GoSam']
2471 _output_dependencies_supported = ['external', 'internal','environment_paths']
2472
2473
2474
2475 options_configuration = {'pythia8_path': './pythia8',
2476 'hwpp_path': './herwigPP',
2477 'thepeg_path': './thepeg',
2478 'hepmc_path': './hepmc',
2479 'madanalysis_path': './MadAnalysis',
2480 'pythia-pgs_path':'./pythia-pgs',
2481 'td_path':'./td',
2482 'delphes_path':'./Delphes',
2483 'exrootanalysis_path':'./ExRootAnalysis',
2484 'syscalc_path': './SysCalc',
2485 'timeout': 60,
2486 'web_browser':None,
2487 'eps_viewer':None,
2488 'text_editor':None,
2489 'fortran_compiler':None,
2490 'f2py_compiler':None,
2491 'cpp_compiler':None,
2492 'auto_update':7,
2493 'cluster_type': 'condor',
2494 'cluster_temp_path': None,
2495 'cluster_queue': None,
2496 'cluster_status_update': (600, 30),
2497 'fastjet':'fastjet-config',
2498 'pjfry':'auto',
2499 'golem':'auto',
2500 'lhapdf':'lhapdf-config',
2501 'applgrid':'applgrid-config',
2502 'amcfast':'amcfast-config',
2503 'cluster_temp_path':None,
2504 'cluster_local_path': '/cvmfs/cp3.uclouvain.be/madgraph/',
2505 'OLP': 'MadLoop',
2506 'cluster_nb_retry':1,
2507 'cluster_retry_wait':300,
2508 'cluster_size':100,
2509 'output_dependencies':'external'
2510 }
2511
2512 options_madgraph= {'group_subprocesses': 'Auto',
2513 'ignore_six_quark_processes': False,
2514 'complex_mass_scheme': False,
2515 'gauge':'unitary',
2516 'stdout_level':None,
2517 'loop_optimized_output':True,
2518 'loop_color_flows':False,
2519 'max_npoint_for_channel': 0
2520 }
2521
2522 options_madevent = {'automatic_html_opening':True,
2523 'run_mode':2,
2524 'nb_core': None
2525 }
2526
2527
2528
2529 _curr_model = None
2530 _curr_amps = diagram_generation.AmplitudeList()
2531 _curr_matrix_elements = helas_objects.HelasMultiProcess()
2532 _curr_fortran_model = None
2533 _curr_cpp_model = None
2534 _curr_exporter = None
2535 _done_export = False
2536 _curr_decaymodel = None
2537
2538 helporder = ['Main commands', 'Documented commands']
2539
2540
2554
2555
2556 - def __init__(self, mgme_dir = '', *completekey, **stdin):
2557 """ add a tracker of the history """
2558
2559 CmdExtended.__init__(self, *completekey, **stdin)
2560
2561
2562 if mgme_dir:
2563 if os.path.isdir(pjoin(mgme_dir, 'Template')):
2564 self._mgme_dir = mgme_dir
2565 logger.info('Setting MG/ME directory to %s' % mgme_dir)
2566 else:
2567 logger.warning('Warning: Directory %s not valid MG/ME directory' % \
2568 mgme_dir)
2569 self._mgme_dir = MG4DIR
2570
2571
2572 self._multiparticles = {}
2573 self.options = {}
2574 self._generate_info = ""
2575 self._model_v4_path = None
2576 self._export_dir = None
2577 self._export_format = 'madevent'
2578 self._mgme_dir = MG4DIR
2579 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
2580 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
2581 self._comparisons = None
2582 self._nlo_modes_for_completion = ['all','virt','real','LOonly']
2583
2584
2585 self.set_configuration()
2586
2605
2619
2620
2621
2623 """Generate an amplitude for a given process and add to
2624 existing amplitudes
2625 or merge two model
2626 """
2627
2628 args = self.split_arg(line)
2629
2630
2631 warning_duplicate = True
2632 if '--no_warning=duplicate' in args:
2633 warning_duplicate = False
2634 args.remove('--no_warning=duplicate')
2635
2636
2637 self.check_add(args)
2638
2639 if args[0] == 'model':
2640 return self.add_model(args[1:])
2641
2642
2643
2644 if args[-1].startswith('--optimize'):
2645 optimize = True
2646 args.pop()
2647 else:
2648 optimize = False
2649
2650 if args[0] == 'process':
2651
2652 line = ' '.join(args[1:])
2653
2654
2655 if not self._generate_info:
2656 self._generate_info = line
2657
2658
2659 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
2660
2661
2662 if ',' in line:
2663 if ']' in line or '[' in line:
2664 error_msg=\
2665 """The '[' and ']' syntax cannot be used in cunjunction with decay chains.
2666 This implies that with decay chains:
2667 > Squared coupling order limitations are not available.
2668 > Loop corrections cannot be considered."""
2669 raise MadGraph5Error(error_msg)
2670 else:
2671 myprocdef, line = self.extract_decay_chain_process(line)
2672
2673
2674
2675 if myprocdef.are_decays_perturbed():
2676 raise MadGraph5Error("Decay processes cannot be perturbed.")
2677
2678
2679
2680 if myprocdef.decays_have_squared_orders() or \
2681 myprocdef['squared_orders']!={}:
2682 raise MadGraph5Error("Decay processes cannot specify "+\
2683 "squared orders constraints.")
2684 if myprocdef.are_negative_orders_present():
2685 raise MadGraph5Error("Decay processes cannot include negative"+\
2686 " coupling orders constraints.")
2687 else:
2688 myprocdef = self.extract_process(line)
2689
2690
2691 if not myprocdef:
2692 raise self.InvalidCmd("Empty or wrong format process, please try again.")
2693
2694
2695 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
2696 myprocdef.get_ninitial():
2697 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
2698
2699
2700
2701 if len([1 for val in myprocdef.get('orders').values()+\
2702 myprocdef.get('squared_orders').values() if val<0])>1:
2703 raise MadGraph5Error("Negative coupling order constraints"+\
2704 " can only be given on one type of coupling and either on"+\
2705 " squared orders or amplitude orders, not both.")
2706
2707 cpu_time1 = time.time()
2708
2709
2710 if self.options['group_subprocesses'] == 'Auto':
2711 collect_mirror_procs = True
2712 else:
2713 collect_mirror_procs = self.options['group_subprocesses']
2714 ignore_six_quark_processes = \
2715 self.options['ignore_six_quark_processes'] if \
2716 "ignore_six_quark_processes" in self.options \
2717 else []
2718
2719 myproc = diagram_generation.MultiProcess(myprocdef,
2720 collect_mirror_procs = collect_mirror_procs,
2721 ignore_six_quark_processes = ignore_six_quark_processes,
2722 optimize=optimize)
2723
2724
2725 for amp in myproc.get('amplitudes'):
2726 if amp not in self._curr_amps:
2727 self._curr_amps.append(amp)
2728 elif warning_duplicate:
2729 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
2730 amp.nice_string_processes()
2731
2732
2733 self._done_export = False
2734
2735 cpu_time2 = time.time()
2736
2737 nprocs = len(myproc.get('amplitudes'))
2738 ndiags = sum([amp.get_number_of_diagrams() for \
2739 amp in myproc.get('amplitudes')])
2740 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
2741 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
2742 ndiags = sum([amp.get_number_of_diagrams() for \
2743 amp in self._curr_amps])
2744 logger.info("Total: %i processes with %i diagrams" % \
2745 (len(self._curr_amps), ndiags))
2746
2748 """merge two model"""
2749
2750 model_path = args[0]
2751 recreate = ('--recreate' in args)
2752 output_dir = [a.split('=',1)[1] for a in args if a.startswith('--output')]
2753 if output_dir:
2754 output_dir = output_dir[0]
2755 recreate = True
2756 restrict_name = ''
2757 else:
2758 name = os.path.basename(self._curr_model.get('modelpath'))
2759 restrict_name = self._curr_model.get('restrict_name')
2760 output_dir = pjoin(MG5DIR, 'models', '%s__%s' % (name,
2761 os.path.basename(model_path)))
2762
2763 if os.path.exists(output_dir):
2764 if recreate:
2765 shutil.rmtree(output_dir)
2766 else:
2767 logger.info('Model already created! Loading it from %s' % output_dir)
2768 oldmodel = self._curr_model.get('modelpath')
2769 new_model_name = output_dir
2770 if restrict_name:
2771 new_model_name = '%s-%s' % (output_dir, restrict_name)
2772 try:
2773 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
2774 printcmd=False, precmd=True, postcmd=True)
2775 except Exception, error:
2776 logger.debug('fail to load model %s with error:\n %s' % (output_dir, error))
2777 logger.warning('Fail to load the model. Restore previous model')
2778 self.exec_cmd('import model %s' % oldmodel, errorhandling=False,
2779 printcmd=False, precmd=True, postcmd=True)
2780 raise Exception('Invalid Model! Please retry with the option \'--recreate\'.')
2781 else:
2782 return
2783
2784
2785 import models.usermod as usermod
2786 base_model = usermod.UFOModel(self._curr_model.get('modelpath'))
2787
2788 identify = dict(tuple(a.split('=')) for a in args if '=' in a)
2789 base_model.add_model(path=model_path, identify_particles=identify)
2790 base_model.write(output_dir)
2791
2792 new_model_name = output_dir
2793 if restrict_name:
2794 new_model_name = '%s-%s' % (output_dir, restrict_name)
2795 self.exec_cmd('import model %s' % new_model_name, errorhandling=False,
2796 printcmd=False, precmd=True, postcmd=True)
2797
2798
2799
2836
2837
2839 """Display current internal status"""
2840
2841 args = self.split_arg(line)
2842
2843 self.check_display(args)
2844
2845 if args[0] == 'diagrams':
2846 self.draw(' '.join(args[1:]))
2847
2848 if args[0] == 'particles' and len(args) == 1:
2849 propagating_particle = []
2850 nb_unpropagating = 0
2851 for particle in self._curr_model['particles']:
2852 if particle.get('propagating'):
2853 propagating_particle.append(particle)
2854 else:
2855 nb_unpropagating += 1
2856
2857 print "Current model contains %i particles:" % \
2858 len(propagating_particle)
2859 part_antipart = [part for part in propagating_particle \
2860 if not part['self_antipart']]
2861 part_self = [part for part in propagating_particle \
2862 if part['self_antipart']]
2863 for part in part_antipart:
2864 print part['name'] + '/' + part['antiname'],
2865 print ''
2866 for part in part_self:
2867 print part['name'],
2868 print ''
2869 if nb_unpropagating:
2870 print 'In addition of %s un-physical particle mediating new interactions.' \
2871 % nb_unpropagating
2872
2873 elif args[0] == 'particles':
2874 for arg in args[1:]:
2875 if arg.isdigit() or (arg[0] == '-' and arg[1:].isdigit()):
2876 particle = self._curr_model.get_particle(abs(int(arg)))
2877 else:
2878 particle = self._curr_model['particles'].find_name(arg)
2879 if not particle:
2880 raise self.InvalidCmd, 'no particle %s in current model' % arg
2881
2882 print "Particle %s has the following properties:" % particle.get_name()
2883 print str(particle)
2884
2885 elif args[0] == 'interactions' and len(args) == 1:
2886 text = "Current model contains %i interactions\n" % \
2887 len(self._curr_model['interactions'])
2888 for i, inter in enumerate(self._curr_model['interactions']):
2889 text += str(i+1) + ':'
2890 for part in inter['particles']:
2891 if part['is_part']:
2892 text += part['name']
2893 else:
2894 text += part['antiname']
2895 text += " "
2896 text += " ".join(order + '=' + str(inter['orders'][order]) \
2897 for order in inter['orders'])
2898 text += '\n'
2899 pydoc.pager(text)
2900
2901 elif args[0] == 'interactions' and len(args)==2 and args[1].isdigit():
2902 for arg in args[1:]:
2903 if int(arg) > len(self._curr_model['interactions']):
2904 raise self.InvalidCmd, 'no interaction %s in current model' % arg
2905 if int(arg) == 0:
2906 print 'Special interactions which identify two particles'
2907 else:
2908 print "Interactions %s has the following property:" % arg
2909 print self._curr_model['interactions'][int(arg)-1]
2910
2911 elif args[0] == 'interactions':
2912 request_part = args[1:]
2913 text = ''
2914 for i, inter in enumerate(self._curr_model['interactions']):
2915 present_part = [part['is_part'] and part['name'] or part['antiname']
2916 for part in inter['particles']
2917 if (part['is_part'] and part['name'] in request_part) or
2918 (not part['is_part'] and part['antiname'] in request_part)]
2919 if len(present_part) < len(request_part):
2920 continue
2921
2922 if set(present_part) != set(request_part):
2923 continue
2924
2925 if len(request_part) > len(set(request_part)):
2926 for p in request_part:
2927 if request_part.count(p) > present_part.count(p):
2928 continue
2929
2930 name = str(i+1) + ' : '
2931 for part in inter['particles']:
2932 if part['is_part']:
2933 name += part['name']
2934 else:
2935 name += part['antiname']
2936 name += " "
2937 text += "\nInteractions %s has the following property:\n" % name
2938 text += str(self._curr_model['interactions'][i])
2939
2940 text += '\n'
2941 print name
2942 if text =='':
2943 text += 'No matching for any interactions'
2944 pydoc.pager(text)
2945
2946
2947 elif args[0] == 'parameters' and len(args) == 1:
2948 text = "Current model contains %i parameters\n" % \
2949 sum([len(part) for part in
2950 self._curr_model['parameters'].values()])
2951 keys = self._curr_model['parameters'].keys()
2952 def key_sort(x, y):
2953 if ('external',) == x:
2954 return -1
2955 elif ('external',) == y:
2956 return +1
2957 elif len(x) < len(y):
2958 return -1
2959 else:
2960 return 1
2961 keys.sort(key_sort)
2962 for key in keys:
2963 item = self._curr_model['parameters'][key]
2964 text += '\nparameter type: %s\n' % str(key)
2965 for value in item:
2966 if hasattr(value, 'expr'):
2967 if value.value is not None:
2968 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
2969 else:
2970 text+= ' %s = %s\n' % (value.name, value.expr)
2971 else:
2972 if value.value is not None:
2973 text+= ' %s = %s\n' % (value.name, value.value)
2974 else:
2975 text+= ' %s \n' % (value.name)
2976 pydoc.pager(text)
2977
2978 elif args[0] == 'processes':
2979 for amp in self._curr_amps:
2980 print amp.nice_string_processes()
2981
2982 elif args[0] == 'diagrams_text':
2983 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
2984 pydoc.pager(text)
2985
2986 elif args[0] == 'multiparticles':
2987 print 'Multiparticle labels:'
2988 for key in self._multiparticles:
2989 print self.multiparticle_string(key)
2990
2991 elif args[0] == 'coupling_order':
2992 hierarchy = self._curr_model['order_hierarchy'].items()
2993
2994 def order(first, second):
2995 if first[1] < second[1]:
2996 return -1
2997 else:
2998 return 1
2999 hierarchy.sort(order)
3000 for order in hierarchy:
3001 print ' %s : weight = %s' % order
3002
3003 elif args[0] == 'couplings' and len(args) == 1:
3004 if self._model_v4_path:
3005 print 'No couplings information available in V4 model'
3006 return
3007 text = ''
3008 text = "Current model contains %i couplings\n" % \
3009 sum([len(part) for part in
3010 self._curr_model['couplings'].values()])
3011 keys = self._curr_model['couplings'].keys()
3012 def key_sort(x, y):
3013 if ('external',) == x:
3014 return -1
3015 elif ('external',) == y:
3016 return +1
3017 elif len(x) < len(y):
3018 return -1
3019 else:
3020 return 1
3021 keys.sort(key_sort)
3022 for key in keys:
3023 item = self._curr_model['couplings'][key]
3024 text += '\ncouplings type: %s\n' % str(key)
3025 for value in item:
3026 if value.value is not None:
3027 text+= ' %s = %s = %s\n' % (value.name, value.expr ,value.value)
3028 else:
3029 text+= ' %s = %s\n' % (value.name, value.expr)
3030
3031 pydoc.pager(text)
3032
3033 elif args[0] == 'couplings':
3034 if self._model_v4_path:
3035 print 'No couplings information available in V4 model'
3036 return
3037
3038 try:
3039 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3040 print 'Note that this is the UFO informations.'
3041 print ' "display couplings" present the actual definition'
3042 print 'prints the current states of mode'
3043 print eval('ufomodel.couplings.%s.nice_string()'%args[1])
3044 except Exception:
3045 raise self.InvalidCmd, 'no couplings %s in current model' % args[1]
3046
3047 elif args[0] == 'lorentz':
3048 if self._model_v4_path:
3049 print 'No lorentz information available in V4 model'
3050 return
3051 elif len(args) == 1:
3052 raise self.InvalidCmd,\
3053 'display lorentz require an argument: the name of the lorentz structure.'
3054 return
3055 try:
3056 ufomodel = ufomodels.load_model(self._curr_model.get('name'))
3057 print eval('ufomodel.lorentz.%s.nice_string()'%args[1])
3058 except Exception:
3059 raise self.InvalidCmd, 'no lorentz %s in current model' % args[1]
3060
3061 elif args[0] == 'checks':
3062 comparisons = self._comparisons[0]
3063 if len(args) > 1 and args[1] == 'failed':
3064 comparisons = [c for c in comparisons if not c['passed']]
3065 outstr = "Process check results:"
3066 for comp in comparisons:
3067 outstr += "\n%s:" % comp['process'].nice_string()
3068 outstr += "\n Phase space point: (px py pz E)"
3069 for i, p in enumerate(comp['momenta']):
3070 outstr += "\n%2s %+.9e %+.9e %+.9e %+.9e" % tuple([i] + p)
3071 outstr += "\n Permutation values:"
3072 outstr += "\n " + str(comp['values'])
3073 if comp['passed']:
3074 outstr += "\n Process passed (rel. difference %.9e)" % \
3075 comp['difference']
3076 else:
3077 outstr += "\n Process failed (rel. difference %.9e)" % \
3078 comp['difference']
3079
3080 used_aloha = sorted(self._comparisons[1])
3081 outstr += "\nChecked ALOHA routines:"
3082 for aloha in used_aloha:
3083 aloha_str = aloha[0]
3084 if aloha[1]:
3085 aloha_str += 'C' + 'C'.join([str(ia) for ia in aloha[1]])
3086 aloha_str += "_%d" % aloha[2]
3087 outstr += "\n" + aloha_str
3088
3089 pydoc.pager(outstr)
3090
3091 elif args[0] == 'options':
3092 outstr = " MadGraph5_aMC@NLO Options \n"
3093 outstr += " ---------------- \n"
3094 keys = self.options_madgraph.keys()
3095 keys.sort()
3096 for key in keys:
3097 default = self.options_madgraph[key]
3098 value = self.options[key]
3099 if value == default:
3100 outstr += " %25s \t:\t%s\n" % (key,value)
3101 else:
3102 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3103 outstr += "\n"
3104 outstr += " MadEvent Options \n"
3105 outstr += " ---------------- \n"
3106 keys = self.options_madevent.keys()
3107 keys.sort()
3108 for key in keys:
3109 default = self.options_madevent[key]
3110 value = self.options[key]
3111 if value == default:
3112 outstr += " %25s \t:\t%s\n" % (key,value)
3113 else:
3114 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3115 outstr += "\n"
3116 outstr += " Configuration Options \n"
3117 outstr += " --------------------- \n"
3118 keys = self.options_configuration.keys()
3119 keys.sort()
3120 for key in keys:
3121 default = self.options_configuration[key]
3122 value = self.options[key]
3123 if value == default:
3124 outstr += " %25s \t:\t%s\n" % (key,value)
3125 else:
3126 outstr += " %25s \t:\t%s (user set)\n" % (key,value)
3127
3128 output.write(outstr)
3129 elif args[0] in ["variable"]:
3130 super(MadGraphCmd, self).do_display(line, output)
3131
3132
3133 - def multiparticle_string(self, key):
3134 """Returns a nicely formatted string for the multiparticle"""
3135
3136 if self._multiparticles[key] and \
3137 isinstance(self._multiparticles[key][0], list):
3138 return "%s = %s" % (key, "|".join([" ".join([self._curr_model.\
3139 get('particle_dict')[part_id].get_name() \
3140 for part_id in id_list]) \
3141 for id_list in self._multiparticles[key]]))
3142 else:
3143 return "%s = %s" % (key, " ".join([self._curr_model.\
3144 get('particle_dict')[part_id].get_name() \
3145 for part_id in self._multiparticles[key]]))
3146
3172
3173
3174
3175 - def draw(self, line,selection='all',type=''):
3231
3232
3234 """Check a given process or set of processes"""
3235
3236 args = self.split_arg(line)
3237
3238 param_card = self.check_check(args)
3239 options= {'events':None}
3240 if param_card and 'banner' == madevent_interface.MadEventCmd.detect_card_type(param_card):
3241 logger.info("Will use the param_card contained in the banner and the events associated")
3242 import madgraph.various.banner as banner
3243 options['events'] = param_card
3244 mybanner = banner.Banner(param_card)
3245 param_card = mybanner.charge_card('param_card')
3246
3247 aloha_lib.KERNEL.clean()
3248
3249 gauge = str(self.options['gauge'])
3250 options['reuse'] = args[1]=="-reuse"
3251 args = args[:1]+args[2:]
3252
3253
3254 if args[0] in ['stability', 'profile']:
3255 options['npoints'] = int(args[1])
3256 args = args[:1]+args[2:]
3257
3258 MLoptions={}
3259 i=-1
3260 while args[i].startswith('--'):
3261 option = args[i].split('=')
3262 if option[0] =='--energy':
3263 options['energy']=float(option[1])
3264 elif option[0]=='--split_orders':
3265 options['split_orders']=int(option[1])
3266 elif option[0]=='--reduction':
3267 MLoptions['MLReductionLib']=[int(ir) for ir in option[1].split('|')]
3268 i=i-1
3269 args = args[:i+1]
3270
3271 proc_line = " ".join(args[1:])
3272 myprocdef = self.extract_process(proc_line)
3273
3274
3275
3276 output_path = os.getcwd()
3277
3278
3279 if not myprocdef:
3280 raise self.InvalidCmd("Empty or wrong format process, please try again.")
3281
3282 if args[0] in ['timing','stability', 'profile'] and not \
3283 myprocdef.get('perturbation_couplings'):
3284 raise self.InvalidCmd("Only loop processes can have their "+
3285 " timings or stability checked.")
3286
3287 if args[0]=='gauge' and \
3288 not myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3289 raise self.InvalidCmd(
3290 """Feynman vs unitary gauge comparisons can only be done if there are no loop
3291 propagators affected by this gauge. Typically, either processes at tree level
3292 or including only QCD perturbations can be considered here.""")
3293
3294 if args[0]=='gauge' and len(self._curr_model.get('gauge')) < 2:
3295 raise self.InvalidCmd("The current model does not allow for both "+\
3296 "Feynman and unitary gauge.")
3297
3298
3299 loggers = [logging.getLogger('madgraph.diagram_generation'),
3300 logging.getLogger('madgraph.loop_diagram_generation'),
3301 logging.getLogger('ALOHA'),
3302 logging.getLogger('madgraph.helas_objects'),
3303 logging.getLogger('madgraph.loop_exporter'),
3304 logging.getLogger('madgraph.export_v4'),
3305 logging.getLogger('cmdprint'),
3306 logging.getLogger('madgraph.model'),
3307 logging.getLogger('madgraph.base_objects')]
3308 old_levels = [log.level for log in loggers]
3309 for log in loggers:
3310 log.setLevel(logging.WARNING)
3311
3312
3313 cpu_time1 = time.time()
3314
3315
3316
3317
3318
3319
3320
3321 if myprocdef.get('perturbation_couplings')==[]:
3322 aloha.loop_mode = False
3323
3324 comparisons = []
3325 gauge_result = []
3326 gauge_result_no_brs = []
3327 lorentz_result =[]
3328 nb_processes = 0
3329 timings = []
3330 stability = []
3331 profile_time = []
3332 profile_stab = []
3333
3334 if "_cuttools_dir" in dir(self):
3335 CT_dir = self._cuttools_dir
3336 else:
3337 CT_dir =""
3338 if "MLReductionLib" in MLoptions:
3339 if 1 in MLoptions["MLReductionLib"]:
3340 MLoptions["MLReductionLib"].remove(1)
3341
3342 TIR_dir={}
3343 if "_iregi_dir" in dir(self):
3344 TIR_dir['iregi_dir']=self._iregi_dir
3345 else:
3346 if "MLReductionLib" in MLoptions:
3347 if 3 in MLoptions["MLReductionLib"]:
3348 logger.warning('IREGI not available on your system; it will be skipped.')
3349 MLoptions["MLReductionLib"].remove(3)
3350
3351 if 'pjfry' in self.options and isinstance(self.options['pjfry'],str):
3352 TIR_dir['pjfry_dir']=self.options['pjfry']
3353 else:
3354 if "MLReductionLib" in MLoptions:
3355 if 2 in MLoptions["MLReductionLib"]:
3356 logger.info('PJFRY not available on your system; it will be skipped.')
3357 MLoptions["MLReductionLib"].remove(2)
3358
3359 if 'golem' in self.options and isinstance(self.options['golem'],str):
3360 TIR_dir['golem_dir']=self.options['golem']
3361 else:
3362 if "MLReductionLib" in MLoptions:
3363 if 4 in MLoptions["MLReductionLib"]:
3364 logger.info('GOLEM not available on your system; it will be skipped.')
3365 MLoptions["MLReductionLib"].remove(4)
3366
3367 if args[0] in ['timing']:
3368 timings = process_checks.check_timing(myprocdef,
3369 param_card = param_card,
3370 cuttools=CT_dir,
3371 tir=TIR_dir,
3372 options = options,
3373 cmd = self,
3374 output_path = output_path,
3375 MLOptions = MLoptions
3376 )
3377
3378 if args[0] in ['stability']:
3379 stability=process_checks.check_stability(myprocdef,
3380 param_card = param_card,
3381 cuttools=CT_dir,
3382 tir=TIR_dir,
3383 options = options,
3384 output_path = output_path,
3385 cmd = self,
3386 MLOptions = MLoptions)
3387
3388 if args[0] in ['profile']:
3389
3390
3391 profile_time, profile_stab = process_checks.check_profile(myprocdef,
3392 param_card = param_card,
3393 cuttools=CT_dir,
3394 tir=TIR_dir,
3395 options = options,
3396 MLOptions = MLoptions,
3397 output_path = output_path,
3398 cmd = self)
3399
3400 if args[0] in ['gauge', 'full'] and \
3401 len(self._curr_model.get('gauge')) == 2 and\
3402 myprocdef.get('perturbation_couplings') in [[],['QCD']]:
3403
3404 line = " ".join(args[1:])
3405 myprocdef = self.extract_process(line)
3406 if gauge == 'unitary':
3407 myprocdef_unit = myprocdef
3408 self.do_set('gauge Feynman', log=False)
3409 myprocdef_feyn = self.extract_process(line)
3410 else:
3411 myprocdef_feyn = myprocdef
3412 self.do_set('gauge unitary', log=False)
3413 myprocdef_unit = self.extract_process(line)
3414
3415 nb_part_unit = len(myprocdef_unit.get('model').get('particles'))
3416 nb_part_feyn = len(myprocdef_feyn.get('model').get('particles'))
3417 if nb_part_feyn == nb_part_unit:
3418 logger.error('No Goldstone present for this check!!')
3419 gauge_result_no_brs = process_checks.check_unitary_feynman(
3420 myprocdef_unit, myprocdef_feyn,
3421 param_card = param_card,
3422 options=options,
3423 cuttools=CT_dir,
3424 tir=TIR_dir,
3425 reuse = options['reuse'],
3426 output_path = output_path,
3427 cmd = self)
3428
3429
3430 self.do_set('gauge %s' % gauge, log=False)
3431 nb_processes += len(gauge_result_no_brs)
3432
3433 if args[0] in ['permutation', 'full']:
3434 comparisons = process_checks.check_processes(myprocdef,
3435 param_card = param_card,
3436 quick = True,
3437 cuttools=CT_dir,
3438 tir=TIR_dir,
3439 reuse = options['reuse'],
3440 cmd = self,
3441 output_path = output_path,
3442 options=options)
3443 nb_processes += len(comparisons[0])
3444
3445 if args[0] in ['lorentz', 'full']:
3446 myprocdeff = copy.copy(myprocdef)
3447 lorentz_result = process_checks.check_lorentz(myprocdeff,
3448 param_card = param_card,
3449 cuttools=CT_dir,
3450 tir=TIR_dir,
3451 reuse = options['reuse'],
3452 cmd = self,
3453 output_path = output_path,
3454 options=options)
3455 nb_processes += len(lorentz_result)
3456
3457 if args[0] in ['brs', 'full']:
3458 gauge_result = process_checks.check_gauge(myprocdef,
3459 param_card = param_card,
3460 cuttools=CT_dir,
3461 tir=TIR_dir,
3462 reuse = options['reuse'],
3463 cmd = self,
3464 output_path = output_path,
3465 options=options)
3466 nb_processes += len(gauge_result)
3467
3468 cpu_time2 = time.time()
3469 logger.info("%i checked performed in %0.3f s" \
3470 % (nb_processes,
3471 (cpu_time2 - cpu_time1)))
3472
3473 if args[0] not in ['timing','stability', 'profile']:
3474 if self.options['complex_mass_scheme']:
3475 text = "Note that Complex mass scheme gives gauge/lorentz invariant\n"
3476 text+= "results only for stable particles in final states.\n\n"
3477 elif not myprocdef.get('perturbation_couplings'):
3478 text = "Note That all width have been set to zero for those checks\n\n"
3479 else:
3480 text = "\n"
3481 else:
3482 text ="\n"
3483
3484 if timings:
3485 text += 'Timing result for the '+('optimized' if \
3486 self.options['loop_optimized_output'] else 'default')+' output:\n'
3487
3488 text += process_checks.output_timings(myprocdef, timings)
3489 if stability:
3490 text += 'Stability result for the '+('optimized' if \
3491 self.options['loop_optimized_output'] else 'default')+' output:\n'
3492 text += process_checks.output_stability(stability,output_path)
3493
3494 if profile_time and profile_stab:
3495 text += 'Timing result '+('optimized' if \
3496 self.options['loop_optimized_output'] else 'default')+':\n'
3497 text += process_checks.output_profile(myprocdef, profile_stab,
3498 profile_time, output_path, options['reuse']) + '\n'
3499 if lorentz_result:
3500 text += 'Lorentz invariance results:\n'
3501 text += process_checks.output_lorentz_inv(lorentz_result) + '\n'
3502 if gauge_result:
3503 text += 'Gauge results:\n'
3504 text += process_checks.output_gauge(gauge_result) + '\n'
3505 if gauge_result_no_brs:
3506 text += 'Gauge results (switching between Unitary/Feynman):\n'
3507 text += process_checks.output_unitary_feynman(gauge_result_no_brs) + '\n'
3508
3509 if comparisons and len(comparisons[0])>0:
3510 text += 'Process permutation results:\n'
3511 text += process_checks.output_comparisons(comparisons[0]) + '\n'
3512 self._comparisons = comparisons
3513
3514
3515 if len(text.split('\n'))>20 and not '-reuse' in line and text!='':
3516 if 'test_manager' not in sys.argv[0]:
3517 pydoc.pager(text)
3518
3519
3520 for i, log in enumerate(loggers):
3521 log.setLevel(old_levels[i])
3522
3523
3524
3525 if len(text.split('\n'))<=20 or options['reuse']:
3526
3527 logging.getLogger('madgraph.check_cmd').info(text)
3528 else:
3529 logging.getLogger('madgraph.check_cmd').debug(text)
3530
3531
3532 process_checks.clean_added_globals(process_checks.ADDED_GLOBAL)
3533 if not options['reuse']:
3534 process_checks.clean_up(self._mgme_dir)
3535
3536
3556
3558 """Extract a process definition from a string. Returns
3559 a ProcessDefinition."""
3560
3561
3562 if not len(re.findall('>\D', line)) in [1,2]:
3563 self.do_help('generate')
3564 raise self.InvalidCmd('Wrong use of \">\" special character.')
3565
3566
3567
3568
3569 space_before = re.compile(r"(?P<carac>\S)(?P<tag>[\\[\\]/\,\\$\\>|])(?P<carac2>\S)")
3570 line = space_before.sub(r'\g<carac> \g<tag> \g<carac2>', line)
3571
3572
3573
3574
3575
3576
3577 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
3578 proc_number_re = proc_number_pattern.match(line)
3579 if proc_number_re:
3580 proc_number = int(proc_number_re.group(2))
3581 line = proc_number_re.group(1) + \
3582 proc_number_re.group(3)
3583
3584
3585
3586
3587 squared_order_pattern = re.compile(\
3588 "^(?P<before>.+>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
3589 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*$")
3590 squared_order_re = squared_order_pattern.match(line)
3591 squared_orders = {}
3592
3593
3594
3595
3596 split_orders = []
3597 while squared_order_re:
3598 type = squared_order_re.group('type')
3599 if type not in self._valid_sqso_types:
3600 raise self.InvalidCmd, "Type of squared order constraint '%s'"\
3601 %type+" is not supported."
3602 squared_orders[squared_order_re.group('name')] = \
3603 (int(squared_order_re.group('value')),type)
3604 line = squared_order_re.group('before')
3605 squared_order_re = squared_order_pattern.match(line)
3606
3607
3608 perturbation_couplings_pattern = \
3609 re.compile("^(?P<proc>.+>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*"+\
3610 "(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
3611 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
3612 perturbation_couplings = ""
3613 LoopOption= 'tree'
3614 HasBorn= True
3615 if perturbation_couplings_re:
3616 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
3617 option=perturbation_couplings_re.group("option")
3618 if option:
3619 if option in self._valid_nlo_modes:
3620 LoopOption=option
3621 if option=='sqrvirt':
3622 LoopOption='virt'
3623 HasBorn=False
3624 elif option=='noborn':
3625 HasBorn=False
3626 else:
3627 raise self.InvalidCmd, "NLO mode %s is not valid. "%option+\
3628 "Valid modes are %s. "%str(self._valid_nlo_modes)
3629 else:
3630 LoopOption='all'
3631
3632 line = perturbation_couplings_re.group("proc")+\
3633 perturbation_couplings_re.group("rest")
3634
3635
3636
3637
3638 orders = {}
3639 if not perturbation_couplings_re:
3640 new_squared_orders = {}
3641 for order in squared_orders.keys():
3642 if order.endswith('^2'):
3643 new_squared_orders[order[:-2]]=squared_orders[order]
3644 else:
3645 if squared_orders[order][1] not in self._valid_amp_so_types:
3646 raise self.InvalidCmd, \
3647 "Amplitude order constraints can only be of type %s"%\
3648 (', '.join(self._valid_amp_so_types))+\
3649 ", not '%s'."%squared_orders[order][1]
3650 orders[order]=squared_orders[order][0]
3651 squared_orders=new_squared_orders
3652 else:
3653
3654
3655 new_squared_orders = {}
3656 for order in squared_orders.keys():
3657 new_squared_orders[order[:-2] if order.endswith('^2') else order]=\
3658 squared_orders[order]
3659 squared_orders=new_squared_orders
3660
3661
3662
3663 order_pattern = re.compile(\
3664 "^(?P<before>.+>.+)\s+(?P<name>(\w|(\^2))+)\s*(?P<type>"+\
3665 "(=|(<=)|(==)|(===)|(!=)|(>=)|<|>))\s*(?P<value>-?\d+)\s*$")
3666 order_re = order_pattern.match(line)
3667 while order_re:
3668 type = order_re.group('type')
3669 if order_re.group('name').endswith('^2'):
3670 if type not in self._valid_sqso_types:
3671 raise self.InvalidCmd, "Type of squared order "+\
3672 "constraint '%s'"%type+" is not supported."
3673 squared_orders[order_re.group('name')[:-2]] = \
3674 (int(order_re.group('value')),type)
3675 else:
3676 if type not in self._valid_amp_so_types:
3677 raise self.InvalidCmd, \
3678 "Amplitude order constraints can only be of type %s"%\
3679 (', '.join(self._valid_amp_so_types))+", not '%s'."%type
3680
3681 orders[order_re.group('name')] = \
3682 int(order_re.group('value'))
3683 line = order_re.group('before')
3684 order_re = order_pattern.match(line)
3685
3686
3687
3688
3689
3690
3691 if orders=={} and squared_orders!={}:
3692 for order in squared_orders.keys():
3693 if squared_orders[order][0]>=0 and squared_orders[order][1]!='>':
3694 orders[order]=squared_orders[order][0]
3695 else:
3696 orders[order]=99
3697
3698 if not self._curr_model['case_sensitive']:
3699
3700 line = line.lower()
3701
3702
3703 slash = line.find("/")
3704 dollar = line.find("$")
3705 forbidden_particles = ""
3706 if slash > 0:
3707 if dollar > slash:
3708 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)(\$.*)$", line)
3709 else:
3710 forbidden_particles_re = re.match("^(.+)\s*/\s*(.+\s*)$", line)
3711 if forbidden_particles_re:
3712 forbidden_particles = forbidden_particles_re.group(2)
3713 line = forbidden_particles_re.group(1)
3714 if len(forbidden_particles_re.groups()) > 2:
3715 line = line + forbidden_particles_re.group(3)
3716
3717
3718 forbidden_schannels_re = re.match("^(.+)\s*\$\s*\$\s*(.+)\s*$", line)
3719 forbidden_schannels = ""
3720 if forbidden_schannels_re:
3721 forbidden_schannels = forbidden_schannels_re.group(2)
3722 line = forbidden_schannels_re.group(1)
3723
3724
3725 forbidden_onsh_schannels_re = re.match("^(.+)\s*\$\s*(.+)\s*$", line)
3726 forbidden_onsh_schannels = ""
3727 if forbidden_onsh_schannels_re:
3728 forbidden_onsh_schannels = forbidden_onsh_schannels_re.group(2)
3729 line = forbidden_onsh_schannels_re.group(1)
3730
3731
3732 required_schannels_re = re.match("^(.+?)>(.+?)>(.+)$", line)
3733 required_schannels = ""
3734 if required_schannels_re:
3735 required_schannels = required_schannels_re.group(2)
3736 line = required_schannels_re.group(1) + ">" + \
3737 required_schannels_re.group(3)
3738
3739 args = self.split_arg(line)
3740
3741 myleglist = base_objects.MultiLegList()
3742 state = False
3743
3744
3745 for part_name in args:
3746 if part_name == '>':
3747 if not myleglist:
3748 raise self.InvalidCmd, "No final state particles"
3749 state = True
3750 continue
3751
3752 mylegids = []
3753 if part_name in self._multiparticles:
3754 if isinstance(self._multiparticles[part_name][0], list):
3755 raise self.InvalidCmd,\
3756 "Multiparticle %s is or-multiparticle" % part_name + \
3757 " which can be used only for required s-channels"
3758 mylegids.extend(self._multiparticles[part_name])
3759 elif part_name.isdigit() or part_name.startswith('-') and part_name[1:].isdigit():
3760 if int(part_name) in self._curr_model.get('particle_dict'):
3761 mylegids.append(int(part_name))
3762 else:
3763 raise self.InvalidCmd, \
3764 "No pdg_code %s in model" % part_name
3765 else:
3766 mypart = self._curr_model['particles'].get_copy(part_name)
3767 if mypart:
3768 mylegids.append(mypart.get_pdg_code())
3769
3770 if mylegids:
3771 myleglist.append(base_objects.MultiLeg({'ids':mylegids,
3772 'state':state}))
3773 else:
3774 raise self.InvalidCmd, \
3775 "No particle %s in model" % part_name
3776
3777 if filter(lambda leg: leg.get('state') == True, myleglist):
3778
3779
3780 perturbation_couplings_list = perturbation_couplings.split()
3781 if perturbation_couplings_list==['']:
3782 perturbation_couplings_list=[]
3783
3784
3785 split_orders=list(set(perturbation_couplings_list+squared_orders.keys()))
3786 try:
3787 split_orders.sort(key=lambda elem: 0 if elem=='WEIGHTED' else
3788 self._curr_model['order_hierarchy'][elem])
3789 except KeyError:
3790 raise self.InvalidCmd, "The loaded model does not defined a "+\
3791 " coupling order hierarchy for these couplings: %s"%\
3792 str([so for so in split_orders if so!='WEIGHTED' and so not
3793 in self._curr_model['order_hierarchy'].keys()])
3794
3795
3796
3797
3798 if LoopOption=='tree':
3799 perturbation_couplings_list = []
3800 if perturbation_couplings_list and LoopOption not in ['real', 'LOonly']:
3801 if not isinstance(self._curr_model,loop_base_objects.LoopModel):
3802 raise self.InvalidCmd(\
3803 "The current model does not allow for loop computations.")
3804 else:
3805 for pert_order in perturbation_couplings_list:
3806 if pert_order not in self._curr_model['perturbation_couplings']:
3807 raise self.InvalidCmd(\
3808 "Perturbation order %s is not among" % pert_order + \
3809 " the perturbation orders allowed for by the loop model.")
3810 if not self.options['loop_optimized_output'] and \
3811 LoopOption not in ['tree','real'] and split_orders!=[]:
3812 logger.warning('The default output mode (loop_optimized_output'+\
3813 ' = False) does not support evaluations for given powers of'+\
3814 ' coupling orders. MadLoop output will therefore not be'+\
3815 ' able to provide such quantities.')
3816 split_orders = []
3817
3818
3819 forbidden_particle_ids = \
3820 self.extract_particle_ids(forbidden_particles)
3821 if forbidden_particle_ids and \
3822 isinstance(forbidden_particle_ids[0], list):
3823 raise self.InvalidCmd(\
3824 "Multiparticle %s is or-multiparticle" % part_name + \
3825 " which can be used only for required s-channels")
3826 forbidden_onsh_schannel_ids = \
3827 self.extract_particle_ids(forbidden_onsh_schannels)
3828 forbidden_schannel_ids = \
3829 self.extract_particle_ids(forbidden_schannels)
3830 if forbidden_onsh_schannel_ids and \
3831 isinstance(forbidden_onsh_schannel_ids[0], list):
3832 raise self.InvalidCmd,\
3833 "Multiparticle %s is or-multiparticle" % part_name + \
3834 " which can be used only for required s-channels"
3835 if forbidden_schannel_ids and \
3836 isinstance(forbidden_schannel_ids[0], list):
3837 raise self.InvalidCmd,\
3838 "Multiparticle %s is or-multiparticle" % part_name + \
3839 " which can be used only for required s-channels"
3840 required_schannel_ids = \
3841 self.extract_particle_ids(required_schannels)
3842 if required_schannel_ids and not \
3843 isinstance(required_schannel_ids[0], list):
3844 required_schannel_ids = [required_schannel_ids]
3845
3846 sqorders_values = dict([(k,v[0]) for k, v in squared_orders.items()])
3847 if len([1 for sqo_v in sqorders_values.values() if sqo_v<0])>1:
3848 raise self.InvalidCmd(
3849 "At most one negative squared order constraint can be specified.")
3850
3851 sqorders_types = dict([(k,v[1]) for k, v in squared_orders.items()])
3852
3853 return \
3854 base_objects.ProcessDefinition({'legs': myleglist,
3855 'model': self._curr_model,
3856 'id': proc_number,
3857 'orders': orders,
3858 'squared_orders':sqorders_values,
3859 'sqorders_types':sqorders_types,
3860 'forbidden_particles': forbidden_particle_ids,
3861 'forbidden_onsh_s_channels': forbidden_onsh_schannel_ids,
3862 'forbidden_s_channels': forbidden_schannel_ids,
3863 'required_s_channels': required_schannel_ids,
3864 'overall_orders': overall_orders,
3865 'perturbation_couplings': perturbation_couplings_list,
3866 'has_born':HasBorn,
3867 'NLO_mode':LoopOption,
3868 'split_orders':split_orders
3869 })
3870
3871
3872
3874 """ Routine to create the MultiProcess for the loop-induced case"""
3875
3876 args = self.split_arg(line)
3877
3878 warning_duplicate = True
3879 if '--no_warning=duplicate' in args:
3880 warning_duplicate = False
3881 args.remove('--no_warning=duplicate')
3882
3883
3884 self.check_add(args)
3885 if args[0] == 'process':
3886 args = args[1:]
3887
3888
3889
3890 if args[-1].startswith('--optimize'):
3891 optimize = True
3892 args.pop()
3893 else:
3894 optimize = False
3895
3896
3897 if not myprocdef:
3898 myprocdef = self.extract_process(' '.join(args))
3899
3900 myprocdef.set('NLO_mode', 'noborn')
3901
3902
3903 if not self._generate_info:
3904 self._generate_info = line
3905
3906
3907
3908
3909
3910
3911
3912 if self._curr_amps and self._curr_amps[0].get_ninitial() != \
3913 myprocdef.get_ninitial():
3914 raise self.InvalidCmd("Can not mix processes with different number of initial states.")
3915
3916 if self._curr_amps and (not isinstance(self._curr_amps[0], loop_diagram_generation.LoopAmplitude) or \
3917 self._curr_amps[0]['has_born']):
3918 raise self.InvalidCmd("Can not mix loop induced process with not loop induced process")
3919
3920
3921
3922 if len([1 for val in myprocdef.get('orders').values()+\
3923 myprocdef.get('squared_orders').values() if val<0])>1:
3924 raise MadGraph5Error("Negative coupling order constraints"+\
3925 " can only be given on one type of coupling and either on"+\
3926 " squared orders or amplitude orders, not both.")
3927
3928 cpu_time1 = time.time()
3929
3930
3931 if self.options['group_subprocesses'] == 'Auto':
3932 collect_mirror_procs = True
3933 else:
3934 collect_mirror_procs = self.options['group_subprocesses']
3935 ignore_six_quark_processes = \
3936 self.options['ignore_six_quark_processes'] if \
3937 "ignore_six_quark_processes" in self.options \
3938 else []
3939
3940
3941
3942 myproc = loop_diagram_generation.LoopInducedMultiProcess(myprocdef,
3943 collect_mirror_procs = collect_mirror_procs,
3944 ignore_six_quark_processes = ignore_six_quark_processes,
3945 optimize=optimize)
3946
3947 for amp in myproc.get('amplitudes'):
3948 if amp not in self._curr_amps:
3949 self._curr_amps.append(amp)
3950 if amp['has_born']:
3951 raise Exception
3952 elif warning_duplicate:
3953 raise self.InvalidCmd, "Duplicate process %s found. Please check your processes." % \
3954 amp.nice_string_processes()
3955
3956
3957 self._done_export = False
3958
3959 cpu_time2 = time.time()
3960
3961 nprocs = len(myproc.get('amplitudes'))
3962 ndiags = sum([amp.get_number_of_diagrams() for \
3963 amp in myproc.get('amplitudes')])
3964 logger.info("%i processes with %i diagrams generated in %0.3f s" % \
3965 (nprocs, ndiags, (cpu_time2 - cpu_time1)))
3966 ndiags = sum([amp.get_number_of_diagrams() for \
3967 amp in self._curr_amps])
3968 logger.info("Total: %i processes with %i diagrams" % \
3969 (len(self._curr_amps), ndiags))
3970
3971 @staticmethod
3973 """Takes a valid process and return
3974 a tuple (core_process, options). This removes
3975 - any NLO specifications.
3976 - any options
3977 [Used by MadSpin]
3978 """
3979
3980
3981
3982 line=procline
3983 pos1=line.find("[")
3984 if pos1>0:
3985 pos2=line.find("]")
3986 if pos2 >pos1:
3987 line=line[:pos1]+line[pos2+1:]
3988
3989
3990
3991
3992 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*(.*)$")
3993 proc_number_re = proc_number_pattern.match(line)
3994 if proc_number_re:
3995 line = proc_number_re.group(1) + proc_number_re.group(3)
3996
3997
3998 pos=1000
3999
4000 order_pattern = re.compile("^(.+)\s+(\w+)\s*=\s*(\d+)\s*$")
4001 order_re = order_pattern.match(line)
4002 if (order_re):
4003 pos_order=line.find(order_re.group(2))
4004 if pos_order>0 and pos_order < pos : pos=pos_order
4005
4006
4007 slash = line.find("/")
4008 if slash > 0 and slash < pos: pos=slash
4009 dollar = line.find("$")
4010 if dollar > 0 and dollar < pos: pos=dollar
4011
4012 if pos<1000:
4013 proc_option=line[pos:]
4014 line=line[:pos]
4015 else:
4016 proc_option=""
4017
4018 return line, proc_option
4019
4021 """Takes a valid process and return
4022 a set of id of final states particles. [Used by MadSpin]
4023 """
4024
4025 if not self._curr_model['case_sensitive']:
4026 procline = procline.lower()
4027 pids = self._curr_model.get('name2pdg')
4028
4029
4030
4031
4032
4033
4034
4035 if ',' in procline:
4036 core, decay = procline.split(',', 1)
4037 core_final = self.get_final_part(core)
4038
4039
4040 all_decays = decay.split(',')
4041 nb_level, tmp_decay = 0, ''
4042 decays = []
4043
4044 for one_decay in all_decays:
4045 if '(' in one_decay:
4046 nb_level += 1
4047 if ')' in one_decay:
4048 nb_level -= 1
4049
4050 if nb_level:
4051 if tmp_decay:
4052 tmp_decay += ', %s' % one_decay
4053 else:
4054 tmp_decay = one_decay
4055 elif tmp_decay:
4056 final = '%s,%s' % (tmp_decay, one_decay)
4057 final = final.strip()
4058 assert final[0] == '(' and final[-1] == ')'
4059 final = final[1:-1]
4060 decays.append(final)
4061 tmp_decay = ''
4062 else:
4063 decays.append(one_decay)
4064
4065 for one_decay in decays:
4066 first = one_decay.split('>',1)[0].strip()
4067 if first in pids:
4068 pid = set([pids[first]])
4069 elif first in self._multiparticles:
4070 pid = set(self._multiparticles[first])
4071 else:
4072 raise Exception, 'invalid particle name: %s. ' % first
4073 core_final.difference_update(pid)
4074 core_final.update(self.get_final_part(one_decay))
4075
4076 return core_final
4077
4078
4079 final = set()
4080 final_states = re.search(r'> ([^\/\$\=\@>]*)(\[|\s\S+\=|\$|\/|\@|$)', procline)
4081 particles = final_states.groups()[0]
4082 for particle in particles.split():
4083 if particle in pids:
4084 final.add(pids[particle])
4085 elif particle in self._multiparticles:
4086 final.update(set(self._multiparticles[particle]))
4087 return final
4088
4089 - def extract_particle_ids(self, args):
4090 """Extract particle ids from a list of particle names. If
4091 there are | in the list, this corresponds to an or-list, which
4092 is represented as a list of id lists. An or-list is used to
4093 allow multiple required s-channel propagators to be specified
4094 (e.g. Z/gamma)."""
4095
4096 if isinstance(args, basestring):
4097 args.replace("|", " | ")
4098 args = self.split_arg(args)
4099 all_ids = []
4100 ids=[]
4101 for part_name in args:
4102 mypart = self._curr_model['particles'].get_copy(part_name)
4103 if mypart:
4104 ids.append([mypart.get_pdg_code()])
4105 elif part_name in self._multiparticles:
4106 ids.append(self._multiparticles[part_name])
4107 elif part_name == "|":
4108
4109 if ids:
4110 all_ids.append(ids)
4111 ids = []
4112 elif part_name.isdigit() or (part_name.startswith('-') and part_name[1:].isdigit()):
4113 ids.append([int(part_name)])
4114 else:
4115 raise self.InvalidCmd("No particle %s in model" % part_name)
4116 all_ids.append(ids)
4117
4118
4119 res_lists = []
4120 for i, id_list in enumerate(all_ids):
4121 res_lists.extend(diagram_generation.expand_list_list(id_list))
4122
4123 for ilist, idlist in enumerate(res_lists):
4124 set_dict = {}
4125 res_lists[ilist] = [set_dict.setdefault(i,i) for i in idlist \
4126 if i not in set_dict]
4127
4128 if len(res_lists) == 1:
4129 res_lists = res_lists[0]
4130
4131 return res_lists
4132
4134 """Optimize the order of particles in a pdg list, so that
4135 similar particles are next to each other. Sort according to:
4136 1. pdg > 0, 2. spin, 3. color, 4. mass > 0"""
4137
4138 if not pdg_list:
4139 return
4140 if not isinstance(pdg_list[0], int):
4141 return
4142
4143 model = self._curr_model
4144 pdg_list.sort(key = lambda i: i < 0)
4145 pdg_list.sort(key = lambda i: model.get_particle(i).is_fermion())
4146 pdg_list.sort(key = lambda i: model.get_particle(i).get('color'),
4147 reverse = True)
4148 pdg_list.sort(key = lambda i: \
4149 model.get_particle(i).get('mass').lower() != 'zero')
4150
4152 """Recursively extract a decay chain process definition from a
4153 string. Returns a ProcessDefinition."""
4154
4155
4156 proc_number_pattern = re.compile("^(.+)@\s*(\d+)\s*((\w+\s*=\s*\d+\s*)*)$")
4157 proc_number_re = proc_number_pattern.match(line)
4158 proc_number = 0
4159 overall_orders = {}
4160 if proc_number_re:
4161 proc_number = int(proc_number_re.group(2))
4162 line = proc_number_re.group(1)
4163 if proc_number_re.group(3):
4164 order_pattern = re.compile("^(.*?)\s*(\w+)\s*=\s*(\d+)\s*$")
4165 order_line = proc_number_re.group(3)
4166 order_re = order_pattern.match(order_line)
4167 while order_re:
4168 overall_orders[order_re.group(2)] = int(order_re.group(3))
4169 order_line = order_re.group(1)
4170 order_re = order_pattern.match(order_line)
4171 logger.info(line)
4172
4173 index_comma = line.find(",")
4174 index_par = line.find(")")
4175 min_index = index_comma
4176 if index_par > -1 and (index_par < min_index or min_index == -1):
4177 min_index = index_par
4178
4179 if min_index > -1:
4180 core_process = self.extract_process(line[:min_index], proc_number,
4181 overall_orders)
4182 else:
4183 core_process = self.extract_process(line, proc_number,
4184 overall_orders)
4185
4186
4187
4188 while index_comma > -1:
4189 line = line[index_comma + 1:]
4190 if not line.strip():
4191 break
4192 index_par = line.find(')')
4193
4194 if line.lstrip()[0] == '(' and index_par !=-1 and \
4195 not ',' in line[:index_par]:
4196 par_start = line.find('(')
4197 line = '%s %s' % (line[par_start+1:index_par], line[index_par+1:])
4198 index_par = line.find(')')
4199 if line.lstrip()[0] == '(':
4200
4201
4202 line = line.lstrip()[1:]
4203
4204 decay_process, line = \
4205 self.extract_decay_chain_process(line,
4206 level_down=True)
4207 index_comma = line.find(",")
4208 index_par = line.find(')')
4209 else:
4210 index_comma = line.find(",")
4211 min_index = index_comma
4212 if index_par > -1 and \
4213 (index_par < min_index or min_index == -1):
4214 min_index = index_par
4215 if min_index > -1:
4216 decay_process = self.extract_process(line[:min_index])
4217 else:
4218 decay_process = self.extract_process(line)
4219
4220 core_process.get('decay_chains').append(decay_process)
4221
4222 if level_down:
4223 if index_par == -1:
4224 raise self.InvalidCmd, \
4225 "Missing ending parenthesis for decay process"
4226
4227 if index_par < index_comma:
4228 line = line[index_par + 1:]
4229 level_down = False
4230 break
4231
4232 if level_down:
4233 index_par = line.find(')')
4234 if index_par == -1:
4235 raise self.InvalidCmd, \
4236 "Missing ending parenthesis for decay process"
4237 line = line[index_par + 1:]
4238
4239
4240
4241 return core_process, line
4242
4243
4244
4246 """Main commands: Import files with external formats"""
4247
4248 args = self.split_arg(line)
4249
4250 self.check_import(args)
4251 if args[0].startswith('model'):
4252 self._model_v4_path = None
4253
4254 self._curr_amps = diagram_generation.AmplitudeList()
4255 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
4256
4257 if args[0].endswith('_v4'):
4258 self._curr_model, self._model_v4_path = \
4259 import_v4.import_model(args[1], self._mgme_dir)
4260 self._curr_fortran_model = \
4261 helas_call_writers.FortranHelasCallWriter(\
4262 self._curr_model)
4263 else:
4264
4265 if (args[1].startswith('loop_qcd_qed_sm') or\
4266 args[1].split('/')[-1].startswith('loop_qcd_qed_sm')) and\
4267 self.options['gauge']!='Feynman':
4268 logger.info('Switching to Feynman gauge because '+\
4269 'it is the only one supported by the model loop_qcd_qed_sm.')
4270 self._curr_model = None
4271 self.do_set('gauge Feynman',log=False)
4272 prefix = not '--noprefix' in args
4273 if prefix:
4274 aloha.aloha_prefix='mdl_'
4275 else:
4276 aloha.aloha_prefix=''
4277
4278 try:
4279 self._curr_model = import_ufo.import_model(args[1], prefix=prefix)
4280 except import_ufo.UFOImportError, error:
4281 if 'not a valid UFO model' in str(error):
4282 logger_stderr.warning('WARNING: %s' % error)
4283 logger_stderr.warning('Try to recover by running '+\
4284 'automatically `import model_v4 %s` instead.'% args[1])
4285 self.exec_cmd('import model_v4 %s ' % args[1], precmd=True)
4286 return
4287 if self.options['complex_mass_scheme']:
4288 self._curr_model.change_mass_to_complex_scheme()
4289 if hasattr(self._curr_model, 'set_parameters_and_couplings'):
4290 self._curr_model.set_parameters_and_couplings()
4291 if self.options['gauge']=='unitary':
4292 if not force and isinstance(self._curr_model,\
4293 loop_base_objects.LoopModel) and \
4294 self._curr_model.get('perturbation_couplings') not in \
4295 [[],['QCD']]:
4296 if 1 not in self._curr_model.get('gauge') :
4297 logger_stderr.warning('This model does not allow Feynman '+\
4298 'gauge. You will only be able to do tree level '+\
4299 'QCD loop cmputations with it.')
4300 else:
4301 logger.info('Change to the gauge to Feynman because '+\
4302 'this loop model allows for more than just tree level'+\
4303 ' and QCD perturbations.')
4304 self.do_set('gauge Feynman', log=False)
4305 return
4306 if 0 not in self._curr_model.get('gauge') :
4307 logger_stderr.warning('Change the gauge to Feynman since '+\
4308 'the model does not allow unitary gauge')
4309 self.do_set('gauge Feynman', log=False)
4310 return
4311 else:
4312 if 1 not in self._curr_model.get('gauge') :
4313 logger_stderr.warning('Change the gauge to unitary since the'+\
4314 ' model does not allow Feynman gauge.'+\
4315 ' Please re-import the model')
4316 self._curr_model = None
4317 self.do_set('gauge unitary', log= False)
4318 return
4319
4320 self._curr_fortran_model = \
4321 helas_call_writers.FortranUFOHelasCallWriter(\
4322 self._curr_model)
4323 self._curr_cpp_model = \
4324 helas_call_writers.CPPUFOHelasCallWriter(\
4325 self._curr_model)
4326
4327 if '-modelname' not in args:
4328 self._curr_model.pass_particles_name_in_mg_default()
4329
4330
4331 self.process_model()
4332
4333 self._curr_amps = diagram_generation.AmplitudeList()
4334 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
4335 process_checks.store_aloha = []
4336
4337 elif args[0] == 'command':
4338
4339 if not os.path.isfile(args[1]):
4340 raise self.InvalidCmd("Path %s is not a valid pathname" % args[1])
4341 else:
4342
4343
4344 self.check_for_export_dir(args[1])
4345
4346 self.import_command_file(args[1])
4347
4348 elif args[0] == 'banner':
4349 type = madevent_interface.MadEventCmd.detect_card_type(args[1])
4350 if type != 'banner':
4351 raise self.InvalidCmd, 'The File should be a valid banner'
4352 ban = banner_module.Banner(args[1])
4353
4354 if 'mg5proccard' in ban:
4355 for line in ban['mg5proccard'].split('\n'):
4356 if line.startswith('#') or line.startswith('<'):
4357 continue
4358 self.exec_cmd(line)
4359 else:
4360 raise self.InvalidCmd, 'Only MG5 banner are supported'
4361
4362 if not self._done_export:
4363 self.exec_cmd('output . -f')
4364
4365 ban.split(self._done_export[0])
4366 logger.info('All Cards from the banner have been place in directory %s' % pjoin(self._done_export[0], 'Cards'))
4367 if '--no_launch' not in args:
4368 self.exec_cmd('launch')
4369
4370 elif args[0] == 'proc_v4':
4371
4372 if len(args) == 1 and self._export_dir:
4373 proc_card = pjoin(self._export_dir, 'Cards', \
4374 'proc_card.dat')
4375 elif len(args) == 2:
4376 proc_card = args[1]
4377
4378
4379 self.check_for_export_dir(os.path.realpath(proc_card))
4380 else:
4381 raise MadGraph5Error('No default directory in output')
4382
4383
4384
4385 self.import_mg4_proc_card(proc_card)
4386
4388 """ For simple decay chain: remove diagram that are not in the BR.
4389 param_card should be a ParamCard instance."""
4390
4391 assert isinstance(param_card, check_param_card.ParamCard)
4392
4393
4394 amplitudes = diagram_generation.AmplitudeList()
4395 for amp in self._curr_amps:
4396 amplitudes.extend(amp.get_amplitudes())
4397
4398 to_remove = []
4399 for amp in amplitudes:
4400 mother = [l.get('id') for l in amp['process'].get('legs') \
4401 if not l.get('state')]
4402 if 1 == len(mother):
4403 decay_table = param_card['decay'].decay_table[abs(mother[0])]
4404
4405 child = [l.get('id') for l in amp['process'].get('legs') \
4406 if l.get('state')]
4407 if not mother[0] > 0:
4408 child = [x if self._curr_model.get_particle(x)['self_antipart']
4409 else -x for x in child]
4410 child.sort()
4411 child.insert(0, len(child))
4412
4413 if tuple(child) not in decay_table.keys():
4414 to_remove.append(amp)
4415
4416 def remove_amp(amps):
4417 for amp in amps[:]:
4418 if amp in to_remove:
4419 amps.remove(amp)
4420 if isinstance(amp, diagram_generation.DecayChainAmplitude):
4421 remove_amp(amp.get('decay_chains'))
4422 for decay in amp.get('decay_chains'):
4423 remove_amp(decay.get('amplitudes'))
4424 remove_amp(self._curr_amps)
4425
4426
4435
4437 """Set variables _particle_names and _couplings for tab
4438 completion, define multiparticles"""
4439
4440
4441 self._particle_names = [p.get('name') for p in self._curr_model.get('particles')\
4442 if p.get('propagating')] + \
4443 [p.get('antiname') for p in self._curr_model.get('particles') \
4444 if p.get('propagating')]
4445
4446 self._couplings = list(set(sum([i.get('orders').keys() for i in \
4447 self._curr_model.get('interactions')], [])))
4448
4449 self.add_default_multiparticles()
4450
4451
4453 """ read a V4 proc card, convert it and run it in mg5"""
4454
4455
4456 if self.history and self.history[-1].startswith('import proc_v4'):
4457 self.history[-1] = '#%s' % self.history[-1]
4458
4459
4460 reader = files.read_from_file(filepath, import_v4.read_proc_card_v4)
4461 if not reader:
4462 raise self.InvalidCmd('\"%s\" is not a valid path' % filepath)
4463
4464 if self._mgme_dir:
4465
4466 self.exec_cmd("# Import the model %s" % reader.model, precmd=True)
4467 line = self.exec_cmd('import model_v4 %s -modelname' % \
4468 (reader.model), precmd=True)
4469 else:
4470 logging.error('No MG_ME installation detected')
4471 return
4472
4473
4474
4475 lines = reader.extract_command_lines(self._curr_model)
4476 for line in lines:
4477 self.exec_cmd(line, precmd=True)
4478
4479 return
4480
4482 """ add default particle from file interface.multiparticles_default.txt
4483 """
4484
4485 defined_multiparticles = self._multiparticles.keys()
4486 removed_multiparticles = []
4487
4488
4489 for key in self._multiparticles.keys():
4490 try:
4491 for part in self._multiparticles[key]:
4492 self._curr_model.get('particle_dict')[part]
4493 except Exception:
4494 del self._multiparticles[key]
4495 defined_multiparticles.remove(key)
4496 removed_multiparticles.append(key)
4497
4498
4499 for line in open(pjoin(MG5DIR, 'input', \
4500 'multiparticles_default.txt')):
4501 if line.startswith('#'):
4502 continue
4503 try:
4504 if not self._curr_model['case_sensitive']:
4505 multipart_name = line.lower().split()[0]
4506 else:
4507 multipart_name = line.split()[0]
4508 if multipart_name not in self._multiparticles:
4509
4510 self.exec_cmd('define %s' % line, printcmd=False, precmd=True)
4511 except self.InvalidCmd, why:
4512 logger_stderr.warning('impossible to set default multiparticles %s because %s' %
4513 (line.split()[0],why))
4514
4515 scheme = "old"
4516 for qcd_container in ['p', 'j']:
4517 if qcd_container not in self._multiparticles:
4518 continue
4519 multi = self._multiparticles[qcd_container]
4520 b = self._curr_model.get_particle(5)
4521 if not b:
4522 break
4523
4524 if 5 in multi:
4525 if b['mass'] != 'ZERO':
4526 multi.remove(5)
4527 multi.remove(-5)
4528 scheme = 4
4529 elif b['mass'] == 'ZERO':
4530 multi.append(5)
4531 multi.append(-5)
4532 scheme = 5
4533
4534 if scheme in [4,5]:
4535 logger.warning("Pass the definition of \'j\' and \'p\' to %s flavour scheme." % scheme)
4536 for container in ['p', 'j']:
4537 if container in defined_multiparticles:
4538 defined_multiparticles.remove(container)
4539
4540
4541
4542 if defined_multiparticles:
4543 if 'all' in defined_multiparticles:
4544 defined_multiparticles.remove('all')
4545 logger.info("Kept definitions of multiparticles %s unchanged" % \
4546 " / ".join(defined_multiparticles))
4547
4548 for removed_part in removed_multiparticles:
4549 if removed_part in self._multiparticles:
4550 removed_multiparticles.remove(removed_part)
4551
4552 if removed_multiparticles:
4553 logger.info("Removed obsolete multiparticles %s" % \
4554 " / ".join(removed_multiparticles))
4555
4556
4557 line = []
4558 for part in self._curr_model.get('particles'):
4559 line.append('%s %s' % (part.get('name'), part.get('antiname')))
4560 line = 'all =' + ' '.join(line)
4561 self.do_define(line)
4562
4564 """Install optional package from the MG suite."""
4565
4566 args = self.split_arg(line)
4567
4568 self.check_install(args)
4569
4570 if sys.platform == "darwin":
4571 program = "curl"
4572 else:
4573 program = "wget"
4574
4575
4576 if args[0] == 'update':
4577 self.install_update(args, wget=program)
4578 return
4579
4580
4581 import urllib
4582 path = {}
4583
4584 data_path = ['http://madgraph.phys.ucl.ac.be/package_info.dat',
4585 'http://madgraph.hep.uiuc.edu/package_info.dat']
4586 r = random.randint(0,1)
4587 r = [r, (1-r)]
4588 for index in r:
4589 cluster_path = data_path[index]
4590 try:
4591 data = urllib.urlopen(cluster_path)
4592 except Exception:
4593 continue
4594 break
4595 else:
4596 raise MadGraph5Error, '''Impossible to connect any of us servers.
4597 Please check your internet connection or retry later'''
4598
4599 for line in data:
4600 split = line.split()
4601 path[split[0]] = split[1]
4602
4603
4604 if args[0] == 'Delphes':
4605 args[0] = 'Delphes3'
4606
4607 name = {'td_mac': 'td', 'td_linux':'td', 'Delphes2':'Delphes',
4608 'Delphes3':'Delphes', 'pythia-pgs':'pythia-pgs',
4609 'ExRootAnalysis': 'ExRootAnalysis','MadAnalysis':'MadAnalysis',
4610 'SysCalc':'SysCalc', 'Golem95': 'golem95'}
4611 name = name[args[0]]
4612
4613
4614 if args[0] in ['Delphes2', 'pythia-pgs']:
4615 logger.warning("Please Note that this package is NOT maintained anymore by their author(s).\n"+\
4616 " You should consider using an up-to-date version of the code.")
4617
4618 try:
4619 os.system('rm -rf %s' % pjoin(MG5DIR, name))
4620 except Exception:
4621 pass
4622
4623
4624 logger.info('Downloading %s' % path[args[0]])
4625 if sys.platform == "darwin":
4626 misc.call(['curl', path[args[0]], '-o%s.tgz' % name], cwd=MG5DIR)
4627 else:
4628 misc.call(['wget', path[args[0]], '--output-document=%s.tgz'% name], cwd=MG5DIR)
4629
4630
4631 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
4632 stdout=open(os.devnull, 'w'))
4633
4634 if returncode:
4635 raise MadGraph5Error, 'Fail to download correctly the File. Stop'
4636
4637
4638
4639 if not os.path.exists(pjoin(MG5DIR, name)):
4640 created_name = [n for n in os.listdir(MG5DIR) if n.startswith(name)
4641 and not n.endswith('gz')]
4642 if not created_name:
4643 raise MadGraph5Error, 'The file was not loaded correctly. Stop'
4644 else:
4645 created_name = created_name[0]
4646 files.mv(pjoin(MG5DIR, created_name), pjoin(MG5DIR, name))
4647
4648
4649 logger.info('compile %s. This might takes a while.' % name)
4650
4651
4652 if args[0] == "pythia-pgs" and sys.maxsize > 2**32:
4653 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
4654 text = open(path).read()
4655 text = text.replace('MBITS=32','MBITS=64')
4656 open(path, 'w').writelines(text)
4657 if not os.path.exists(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib')):
4658 os.mkdir(pjoin(MG5DIR, 'pythia-pgs', 'libraries','pylib','lib'))
4659
4660
4661
4662 if 'FC' not in os.environ or not os.environ['FC']:
4663 if self.options['fortran_compiler'] and self.options['fortran_compiler'] != 'None':
4664 compiler = self.options['fortran_compiler']
4665 elif misc.which('gfortran'):
4666 compiler = 'gfortran'
4667 elif misc.which('g77'):
4668 compiler = 'g77'
4669 else:
4670 raise self.InvalidCmd('Require g77 or Gfortran compiler')
4671
4672 path = None
4673 base_compiler= ['FC=g77','FC=gfortran']
4674 if args[0] == "pythia-pgs":
4675 path = os.path.join(MG5DIR, 'pythia-pgs', 'src', 'make_opts')
4676 elif args[0] == 'MadAnalysis':
4677 path = os.path.join(MG5DIR, 'MadAnalysis', 'makefile')
4678 if path:
4679 text = open(path).read()
4680 for base in base_compiler:
4681 text = text.replace(base,'FC=%s' % compiler)
4682 open(path, 'w').writelines(text)
4683 os.environ['FC'] = compiler
4684
4685
4686 if name == 'golem95':
4687
4688 ld_path = misc.Popen(['./configure',
4689 '--prefix=%s'%str(pjoin(MG5DIR, name)),'FC=%s'%os.environ['FC']],
4690 cwd=pjoin(MG5DIR,'golem95'),stdout=subprocess.PIPE).communicate()[0]
4691
4692
4693 if name == 'SysCalc':
4694 if self.options['lhapdf']:
4695 ld_path = misc.Popen([self.options['lhapdf'], '--libdir'],
4696 stdout=subprocess.PIPE).communicate()[0]
4697 ld_path = ld_path.replace('\n','')
4698 if 'LD_LIBRARY_PATH' not in os.environ:
4699 os.environ['LD_LIBRARY_PATH'] = ld_path
4700 elif not os.environ['LD_LIBRARY_PATH']:
4701 os.environ['LD_LIBRARY_PATH'] = ld_path
4702 elif ld_path not in os.environ['LD_LIBRARY_PATH']:
4703 os.environ['LD_LIBRARY_PATH'] += ';%s' % ld_path
4704 if self.options['lhapdf'] != 'lhapdf-config':
4705 if misc.which('lhapdf-config') != os.path.realpath(self.options['lhapdf']):
4706 os.environ['PATH'] = '%s:%s' % (os.path.realpath(self.options['lhapdf']),os.environ['PATH'])
4707 else:
4708 raise self.InvalidCmd('lhapdf is required to compile/use SysCalc')
4709
4710 if logger.level <= logging.INFO:
4711 devnull = open(os.devnull,'w')
4712 try:
4713 misc.call(['make', 'clean'], stdout=devnull, stderr=-2)
4714 except Exception:
4715 pass
4716 if name == 'pythia-pgs':
4717
4718 status = misc.call(['make'], cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
4719 if name == 'golem95':
4720 status = misc.call(['make','install'],
4721 cwd = os.path.join(MG5DIR, name))
4722 else:
4723 status = misc.call(['make'], cwd = os.path.join(MG5DIR, name))
4724 else:
4725 try:
4726 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
4727 except Exception:
4728 pass
4729 if name == 'pythia-pgs':
4730
4731 status = self.compile(mode='', cwd = pjoin(MG5DIR, name, 'libraries', 'pylib'))
4732 if name == 'golem95':
4733 status = misc.compile(['install'], mode='',
4734 cwd = os.path.join(MG5DIR, name))
4735 else:
4736 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
4737
4738 if not status:
4739 logger.info('Compilation succeeded')
4740 else:
4741
4742 if name == 'pythia-pgs':
4743 to_comment = ['libraries/PGS4/src/stdhep-dir/mcfio/arch_mcfio',
4744 'libraries/PGS4/src/stdhep-dir/src/stdhep_Arch']
4745 for f in to_comment:
4746 f = pjoin(MG5DIR, name, *f.split('/'))
4747 text = "".join(l for l in open(f) if 'fno-second-underscore' not in l)
4748 fsock = open(f,'w').write(text)
4749 try:
4750 misc.compile(['clean'], mode='', cwd = os.path.join(MG5DIR, name))
4751 except Exception:
4752 pass
4753 status = self.compile(mode='', cwd = os.path.join(MG5DIR, name))
4754 if not status:
4755 logger.info('Compilation succeeded')
4756 else:
4757 logger.warning('Error detected during the compilation. Please check the compilation error and run make manually.')
4758
4759
4760
4761 if args[0] == 'MadAnalysis':
4762 try:
4763 os.system('rm -rf td')
4764 os.mkdir(pjoin(MG5DIR, 'td'))
4765 except Exception, error:
4766 print error
4767 pass
4768
4769 if sys.platform == "darwin":
4770 logger.info('Downloading TD for Mac')
4771 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td_mac_intel.tar.gz'
4772 misc.call(['curl', target, '-otd.tgz'],
4773 cwd=pjoin(MG5DIR,'td'))
4774 misc.call(['tar', '-xzpvf', 'td.tgz'],
4775 cwd=pjoin(MG5DIR,'td'))
4776 files.mv(MG5DIR + '/td/td_mac_intel',MG5DIR+'/td/td')
4777 else:
4778 if sys.maxsize > 2**32:
4779 logger.info('Downloading TD for Linux 64 bit')
4780 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td64/td'
4781 logger.warning('''td program (needed by MadAnalysis) is not compile for 64 bit computer.
4782 In 99% of the case, this is perfectly fine. If you do not have plot, please follow
4783 instruction in https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/TopDrawer .''')
4784 else:
4785 logger.info('Downloading TD for Linux 32 bit')
4786 target = 'http://madgraph.phys.ucl.ac.be/Downloads/td'
4787 misc.call(['wget', target], cwd=pjoin(MG5DIR,'td'))
4788 os.chmod(pjoin(MG5DIR,'td','td'), 0775)
4789 self.options['td_path'] = pjoin(MG5DIR,'td')
4790
4791 if not misc.which('gs'):
4792 logger.warning('''gosthscript not install on your system. This is not required to run MA.
4793 but this prevent to create jpg files and therefore to have the plots in the html output.''')
4794 if sys.platform == "darwin":
4795 logger.warning('''You can download this program at the following link:
4796 http://www.macupdate.com/app/mac/9980/gpl-ghostscript''')
4797
4798 if args[0] == 'Delphes2':
4799 data = open(pjoin(MG5DIR, 'Delphes','data','DetectorCard.dat')).read()
4800 data = data.replace('data/', 'DELPHESDIR/data/')
4801 out = open(pjoin(MG5DIR, 'Template','Common', 'Cards', 'delphes_card_default.dat'), 'w')
4802 out.write(data)
4803 if args[0] == 'Delphes3':
4804 if os.path.exists(pjoin(MG5DIR, 'Delphes','cards')):
4805 card_dir = pjoin(MG5DIR, 'Delphes','cards')
4806 else:
4807 card_dir = pjoin(MG5DIR, 'Delphes','examples')
4808 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
4809 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_default.dat'))
4810 files.cp(pjoin(card_dir,'delphes_card_CMS.tcl'),
4811 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_CMS.dat'))
4812 files.cp(pjoin(card_dir,'delphes_card_ATLAS.tcl'),
4813 pjoin(MG5DIR,'Template', 'Common', 'Cards', 'delphes_card_ATLAS.dat'))
4814
4815
4816
4817 options_name = {'Delphes': 'delphes_path',
4818 'Delphes2': 'delphes_path',
4819 'Delphes3': 'delphes_path',
4820 'ExRootAnalysis': 'exrootanalysis_path',
4821 'MadAnalysis': 'madanalysis_path',
4822 'SysCalc': 'syscalc_path',
4823 'pythia-pgs':'pythia-pgs_path',
4824 'Golem95': 'golem'}
4825
4826 if args[0] in options_name:
4827 opt = options_name[args[0]]
4828 if opt=='golem':
4829 self.options[opt] = pjoin(MG5DIR,name,'lib')
4830 self.exec_cmd('save options')
4831 elif self.options[opt] != self.options_configuration[opt]:
4832 self.options[opt] = self.options_configuration[opt]
4833 self.exec_cmd('save options')
4834
4835
4836
4838 """ check if the current version of mg5 is up-to-date.
4839 and allow user to install the latest version of MG5 """
4840
4841 def apply_patch(filetext):
4842 """function to apply the patch"""
4843 text = filetext.read()
4844 pattern = re.compile(r'''=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
4845
4846 for orig, new in pattern.findall(text):
4847 shutil.copytree(pjoin(MG5DIR, orig), pjoin(MG5DIR, 'UPDATE_TMP'))
4848 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
4849 for i, name in enumerate(full_path):
4850 path = os.path.sep.join(full_path[:i+1])
4851 if path and not os.path.isdir(path):
4852 os.mkdir(path)
4853 shutil.copytree(pjoin(MG5DIR, 'UPDATE_TMP'), pjoin(MG5DIR, new))
4854 shutil.rmtree(pjoin(MG5DIR, 'UPDATE_TMP'))
4855
4856 pattern = re.compile(r'''=== renamed file \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
4857
4858 for orig, new in pattern.findall(text):
4859 print 'move %s to %s' % (orig, new)
4860 try:
4861 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
4862 except IOError:
4863 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
4864 for i, name in enumerate(full_path):
4865 path = os.path.sep.join(full_path[:i+1])
4866 if path and not os.path.isdir(path):
4867 os.mkdir(path)
4868 files.cp(pjoin(MG5DIR, orig), pjoin(MG5DIR, new), error=True)
4869
4870 pattern = re.compile(r'''^=== added file \'(?P<new>[^\']*)\'''',re.M)
4871 all_add = pattern.findall(text)
4872
4873
4874 pattern=re.compile(r'''=== removed file \'(?P<new>[^\']*)\'(?=.*=== added file \'(?P=new)\')''',re.S)
4875 print 'this step can take a few minuts. please be patient'
4876 all_rm_add = pattern.findall(text)
4877
4878 for new in all_add:
4879 if new in all_rm_add:
4880 continue
4881 if os.path.isfile(pjoin(MG5DIR, new)):
4882 os.remove(pjoin(MG5DIR, new))
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894 p= subprocess.Popen(['patch', '-p1'], stdin=subprocess.PIPE,
4895 cwd=MG5DIR)
4896 p.communicate(text)
4897
4898
4899
4900
4901
4902 pattern=re.compile('''=== modified file \'(?P<new>[^\']*)\'[^\n]*\n\-\-\- old/(?P<old>\S*)[^\n]*\n\+\+\+ new/(?P=new)''',re.S)
4903 for match in pattern.findall(text):
4904 new = pjoin(MG5DIR, match[0])
4905 old = pjoin(MG5DIR, match[1])
4906 if new == old:
4907 continue
4908 elif os.path.exists(old):
4909 if not os.path.exists(os.path.dirname(new)):
4910 split = new.split('/')
4911 for i in range(1,len(split)):
4912 path = '/'.join(split[:i])
4913 if not os.path.exists(path):
4914 print 'mkdir', path
4915 os.mkdir(path)
4916 files.cp(old,new)
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937 for path in glob.glob(pjoin(MG5DIR, 'bin','*')):
4938 misc.call(['chmod', '+x', path])
4939 for path in glob.glob(pjoin(MG5DIR, 'Template','*','bin','*')):
4940 misc.call(['chmod', '+x', path])
4941 for path in glob.glob(pjoin(MG5DIR, 'Template','*','bin','internal','*')):
4942 misc.call(['chmod', '+x', path])
4943 for path in glob.glob(pjoin(MG5DIR, 'Template','*','*', '*.py')):
4944 misc.call(['chmod', '+x', path])
4945 for path in glob.glob(pjoin(MG5DIR, 'Template','*','*','*.sh')):
4946 misc.call(['chmod', '+x', path])
4947
4948
4949 pattern=re.compile('''^=== touch (file|directory) \'(?P<new>[^\']*)\'''',re.M)
4950 for match in pattern.findall(text):
4951 if match[0] == 'file':
4952 new = os.path.dirname(pjoin(MG5DIR, match[1]))
4953 else:
4954 new = pjoin(MG5DIR, match[1])
4955 if not os.path.exists(new):
4956 split = new.split('/')
4957 for i in range(1,len(split)+1):
4958 path = '/'.join(split[:i])
4959 if path and not os.path.exists(path):
4960 print 'mkdir', path
4961 os.mkdir(path)
4962 if match[0] == 'file':
4963 print 'touch ', pjoin(MG5DIR, match[1])
4964 misc.call(['touch', pjoin(MG5DIR, match[1])])
4965
4966 pattern=re.compile('''^=== link file \'(?P<new>[^\']*)\' \'(?P<old>[^\']*)\'''', re.M)
4967 for new, old in pattern.findall(text):
4968 if not os.path.exists(pjoin(MG5DIR, new)):
4969 files.ln(old, os.path.dirname(new), os.path.basename(new))
4970
4971
4972 if os.path.isfile(pjoin(MG5DIR,'vendor','CutTools','includects','libcts.a')):
4973 misc.compile(cwd=pjoin(MG5DIR,'vendor','CutTools'))
4974 if os.path.isfile(pjoin(MG5DIR,'vendor','IREGI','src','libiregi.a')):
4975 misc.compile(cwd=pjoin(MG5DIR,'vendor','IREGI','src'))
4976
4977
4978 pattern = re.compile("""^Binary files old/(\S*).*and new/(\S*).*$""", re.M)
4979 if pattern.search(text):
4980 return True
4981 else:
4982 return False
4983
4984
4985 mode = [arg.split('=',1)[1] for arg in args if arg.startswith('--mode=')]
4986 if mode:
4987 mode = mode[-1]
4988 else:
4989 mode = "userrequest"
4990 force = any([arg=='-f' for arg in args])
4991 timeout = [arg.split('=',1)[1] for arg in args if arg.startswith('--timeout=')]
4992 if timeout:
4993 try:
4994 timeout = int(timeout[-1])
4995 except ValueError:
4996 raise self.InvalidCmd('%s: invalid argument for timeout (integer expected)'%timeout[-1])
4997 else:
4998 timeout = self.options['timeout']
4999 input_path = [arg.split('=',1)[1] for arg in args if arg.startswith('--input=')]
5000
5001 if input_path:
5002 fsock = open(input_path[0])
5003 need_binary = apply_patch(fsock)
5004 logger.info('manual patch apply. Please test your version.')
5005 if need_binary:
5006 logger.warning('Note that some files need to be loaded separately!')
5007 sys.exit(0)
5008
5009 options = ['y','n','on_exit']
5010 if mode == 'mg5_start':
5011 timeout = 2
5012 default = 'n'
5013 update_delay = self.options['auto_update'] * 24 * 3600
5014 if update_delay == 0:
5015 return
5016 elif mode == 'mg5_end':
5017 timeout = 5
5018 default = 'n'
5019 update_delay = self.options['auto_update'] * 24 * 3600
5020 if update_delay == 0:
5021 return
5022 options.remove('on_exit')
5023 elif mode == "userrequest":
5024 default = 'y'
5025 update_delay = 0
5026 else:
5027 raise self.InvalidCmd('Unknown mode for command install update')
5028
5029 if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')) or \
5030 os.path.exists(os.path.join(MG5DIR,'.bzr')):
5031 error_text = """This version of MG5 doesn\'t support auto-update. Common reasons are:
5032 1) This version was loaded via bazaar (use bzr pull to update instead).
5033 2) This version is a beta release of MG5."""
5034 if mode == 'userrequest':
5035 raise self.ConfigurationError(error_text)
5036 return
5037
5038 if not misc.which('patch'):
5039 error_text = """Not able to find program \'patch\'. Please reload a clean version
5040 or install that program and retry."""
5041 if mode == 'userrequest':
5042 raise self.ConfigurationError(error_text)
5043 return
5044
5045
5046
5047 data = {}
5048 for line in open(os.path.join(MG5DIR,'input','.autoupdate')):
5049 if not line.strip():
5050 continue
5051 sline = line.split()
5052 data[sline[0]] = int(sline[1])
5053
5054
5055 if 'version_nb' not in data:
5056 if mode == 'userrequest':
5057 error_text = 'This version of MG5 doesn\'t support auto-update. (Invalid information)'
5058 raise self.ConfigurationError(error_text)
5059 return
5060 elif 'last_check' not in data:
5061 data['last_check'] = time.time()
5062
5063
5064 if time.time() - data['last_check'] < update_delay:
5065 return
5066
5067 logger.info('Checking if MG5 is up-to-date... (takes up to %ss)' % timeout)
5068 class TimeOutError(Exception): pass
5069
5070 def handle_alarm(signum, frame):
5071 raise TimeOutError
5072
5073 signal.signal(signal.SIGALRM, handle_alarm)
5074 signal.alarm(timeout)
5075 to_update = 0
5076 try:
5077 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/mg5amc_build_nb')
5078 signal.alarm(0)
5079 web_version = int(filetext.read().strip())
5080 except (TimeOutError, ValueError, IOError):
5081 signal.alarm(0)
5082 print 'failed to connect server'
5083 if mode == 'mg5_end':
5084
5085 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
5086 fsock.write("version_nb %s\n" % data['version_nb'])
5087 fsock.write("last_check %s\n" % \
5088 int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1))
5089 fsock.close()
5090 return
5091
5092 if web_version == data['version_nb']:
5093 logger.info('No new version of MG5 available')
5094
5095 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
5096 fsock.write("version_nb %s\n" % data['version_nb'])
5097 fsock.write("last_check %s\n" % int(time.time()))
5098 fsock.close()
5099 return
5100 elif data['version_nb'] > web_version:
5101 logger_stderr.info('impossible to update: local %s web %s' % (data['version_nb'], web_version))
5102 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
5103 fsock.write("version_nb %s\n" % data['version_nb'])
5104 fsock.write("last_check %s\n" % int(time.time()))
5105 fsock.close()
5106 return
5107 else:
5108 if not force:
5109 answer = self.ask('New Version of MG5 available! Do you want to update your current version?',
5110 default, options)
5111 else:
5112 answer = default
5113
5114
5115 if answer == 'y':
5116 logger.info('start updating code')
5117 fail = 0
5118 for i in range(data['version_nb'], web_version):
5119 try:
5120 filetext = urllib.urlopen('http://madgraph.phys.ucl.ac.be/patch/build%s.patch' %(i+1))
5121
5122 except Exception:
5123 print 'fail to load patch to build #%s' % (i+1)
5124 fail = i
5125 break
5126 need_binary = apply_patch(filetext)
5127 if need_binary:
5128 path = "http://madgraph.phys.ucl.ac.be/binary/binary_file%s.tgz" %(i+1)
5129 name = "extra_file%i" % (i+1)
5130 if sys.platform == "darwin":
5131 misc.call(['curl', path, '-o%s.tgz' % name], cwd=MG5DIR)
5132 else:
5133 misc.call(['wget', path, '--output-document=%s.tgz'% name], cwd=MG5DIR)
5134
5135 returncode = misc.call(['tar', '-xzpf', '%s.tgz' % name], cwd=MG5DIR,
5136 stdout=open(os.devnull, 'w'))
5137
5138 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
5139 if not fail:
5140 fsock.write("version_nb %s\n" % web_version)
5141 else:
5142 fsock.write("version_nb %s\n" % fail)
5143 fsock.write("last_check %s\n" % int(time.time()))
5144 fsock.close()
5145 logger.info('Checking current version. (type ctrl-c to bypass the check)')
5146 subprocess.call([os.path.join('tests','test_manager.py')],
5147 cwd=MG5DIR)
5148
5149 print 'new version installed, please relaunch mg5'
5150 sys.exit(0)
5151 elif answer == 'n':
5152
5153 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
5154 fsock.write("version_nb %s\n" % data['version_nb'])
5155 fsock.write("last_check %s\n" % int(time.time()))
5156 fsock.close()
5157 logger.info('Update bypassed.')
5158 logger.info('The next check for a new version will be performed in %s days' \
5159 % abs(self.options['auto_update']))
5160 logger.info('In order to change this delay. Enter the command:')
5161 logger.info('set auto_update X')
5162 logger.info('Putting X to zero will prevent this check at anytime.')
5163 logger.info('You can upgrade your version at any time by typing:')
5164 logger.info('install update')
5165 else:
5166
5167
5168 self.options['auto_update'] = -1 * self.options['auto_update']
5169
5170
5171
5173 """ assign all configuration variable from file
5174 ./input/mg5_configuration.txt. assign to default if not define """
5175
5176 if not self.options:
5177 self.options = dict(self.options_configuration)
5178 self.options.update(self.options_madgraph)
5179 self.options.update(self.options_madevent)
5180
5181 if not config_path:
5182 if os.environ.has_key('MADGRAPH_BASE'):
5183 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
5184 self.set_configuration(config_path, final)
5185 return
5186 if 'HOME' in os.environ:
5187 config_path = pjoin(os.environ['HOME'],'.mg5',
5188 'mg5_configuration.txt')
5189 if os.path.exists(config_path):
5190 self.set_configuration(config_path, final=False)
5191 config_path = os.path.relpath(pjoin(MG5DIR,'input',
5192 'mg5_configuration.txt'))
5193 return self.set_configuration(config_path, final)
5194
5195 if not os.path.exists(config_path):
5196 files.cp(pjoin(MG5DIR,'input','.mg5_configuration_default.txt'), config_path)
5197 config_file = open(config_path)
5198
5199
5200 logger.info('load MG5 configuration from %s ' % config_file.name)
5201 for line in config_file:
5202 if '#' in line:
5203 line = line.split('#',1)[0]
5204 line = line.replace('\n','').replace('\r\n','')
5205 try:
5206 name, value = line.split('=')
5207 except ValueError:
5208 pass
5209 else:
5210 name = name.strip()
5211 value = value.strip()
5212 if name != 'mg5_path':
5213 self.options[name] = value
5214 if value.lower() == "none" or value=="":
5215 self.options[name] = None
5216
5217 self.options['stdout_level'] = logging.getLogger('madgraph').level
5218 if not final:
5219 return self.options
5220
5221
5222
5223
5224 for key in self.options:
5225 if key in ['pythia8_path', 'hwpp_path', 'thepeg_path', 'hepmc_path']:
5226 if self.options[key] in ['None', None]:
5227 self.options[key] = None
5228 continue
5229 path = self.options[key]
5230
5231 if key == 'pythia8_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Pythia8', 'Pythia.h')):
5232 if not os.path.isfile(pjoin(path, 'include', 'Pythia8', 'Pythia.h')):
5233 self.options['pythia8_path'] = None
5234 else:
5235 continue
5236
5237 elif key == 'hwpp_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
5238 if not os.path.isfile(pjoin(path, 'include', 'Herwig++', 'Analysis', 'BasicConsistency.hh')):
5239 self.options['hwpp_path'] = None
5240 else:
5241 continue
5242
5243 elif key == 'thepeg_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
5244 if not os.path.isfile(pjoin(path, 'include', 'ThePEG', 'ACDC', 'ACDCGenCell.h')):
5245 self.options['thepeg_path'] = None
5246 else:
5247 continue
5248
5249 elif key == 'hepmc_path' and not os.path.isfile(pjoin(MG5DIR, path, 'include', 'HEPEVT_Wrapper.h')):
5250 if not os.path.isfile(pjoin(path, 'include', 'HEPEVT_Wrapper.h')):
5251 self.options['hepmc_path'] = None
5252 else:
5253 continue
5254
5255 elif key in ['pjfry','golem']:
5256 if isinstance(self.options[key],str) and self.options[key].lower() == 'auto':
5257
5258 program = misc.which_lib('lib%s.a'%key)
5259 if program != None:
5260 fpath, fname = os.path.split(program)
5261 logger.info('Using %s library in %s'%(key,fpath))
5262 self.options[key]=fpath
5263 else:
5264
5265 local_install = {'pjfry':'PJFRY', 'golem':'golem95'}
5266 if os.path.isfile(pjoin(MG5DIR,local_install[key],'lib', 'lib%s.a' % key)):
5267 self.options[key]=pjoin(MG5DIR,local_install[key],'lib')
5268 else:
5269 self.options[key]=None
5270
5271 elif key.endswith('path'):
5272 pass
5273 elif key in ['run_mode', 'auto_update']:
5274 self.options[key] = int(self.options[key])
5275 elif key in ['cluster_type','automatic_html_opening']:
5276 pass
5277 elif key not in ['text_editor','eps_viewer','web_browser', 'stdout_level']:
5278
5279 try:
5280 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
5281 except MadGraph5Error, error:
5282 print error
5283 logger.warning("Option %s from config file not understood" \
5284 % key)
5285 else:
5286 if key in self.options_madgraph:
5287 self.history.append('set %s %s' % (key, self.options[key]))
5288
5289 launch_ext.open_file.configure(self.options)
5290 return self.options
5291
5293 """Check if the files is in a valid export directory and assign it to
5294 export path if if is"""
5295
5296
5297 if self._export_dir:
5298 return
5299
5300 if os.path.exists(pjoin(os.getcwd(), 'Cards')):
5301 self._export_dir = os.getcwd()
5302 return
5303
5304 path_split = filepath.split(os.path.sep)
5305 if len(path_split) > 2 and path_split[-2] == 'Cards':
5306 self._export_dir = os.path.sep.join(path_split[:-2])
5307 return
5308
5310 """Main commands: Ask for editing the parameter and then
5311 Execute the code (madevent/standalone/...)
5312 """
5313
5314
5315 current_options = dict([(name, self.options[name]) for name in self.options_madgraph])
5316 start_cwd = os.getcwd()
5317
5318 args = self.split_arg(line)
5319
5320 (options, args) = _launch_parser.parse_args(args)
5321 self.check_launch(args, options)
5322 options = options.__dict__
5323
5324
5325 if args[0].startswith('standalone'):
5326 if os.path.isfile(os.path.join(os.getcwd(),args[1],'Cards',\
5327 'MadLoopParams.dat')) and not os.path.isfile(os.path.join(\
5328 os.getcwd(),args[1],'SubProcesses','check_poles.f')):
5329 ext_program = launch_ext.MadLoopLauncher(self, args[1], \
5330 options=self.options, **options)
5331 else:
5332 ext_program = launch_ext.SALauncher(self, args[1], \
5333 options=self.options, **options)
5334 elif args[0] == 'madevent':
5335 if options['interactive']:
5336 if hasattr(self, 'do_shell'):
5337 ME = madevent_interface.MadEventCmdShell(me_dir=args[1], options=self.options)
5338 else:
5339 ME = madevent_interface.MadEventCmd(me_dir=args[1],options=self.options)
5340 ME.pass_in_web_mode()
5341 stop = self.define_child_cmd_interface(ME)
5342 return stop
5343
5344
5345 if not self._generate_info:
5346
5347
5348 info = open(pjoin(args[1],'SubProcesses','procdef_mg5.dat')).read()
5349 generate_info = info.split('# Begin PROCESS',1)[1].split('\n')[1]
5350 generate_info = generate_info.split('#')[0]
5351 else:
5352 generate_info = self._generate_info
5353
5354 if len(generate_info.split('>')[0].strip().split())>1:
5355 ext_program = launch_ext.MELauncher(args[1], self,
5356 shell = hasattr(self, 'do_shell'),
5357 options=self.options,**options)
5358 else:
5359
5360 ext_program = launch_ext.MELauncher(args[1], self, unit='GeV',
5361 shell = hasattr(self, 'do_shell'),
5362 options=self.options,**options)
5363
5364 elif args[0] == 'pythia8':
5365 ext_program = launch_ext.Pythia8Launcher( args[1], self, **options)
5366
5367 elif args[0] == 'aMC@NLO':
5368 if options['interactive']:
5369 if hasattr(self, 'do_shell'):
5370 ME = amcatnlo_run.aMCatNLOCmdShell(me_dir=args[1], options=self.options)
5371 else:
5372 ME = amcatnlo_run.aMCatNLOCmd(me_dir=args[1],options=self.options)
5373 ME.pass_in_web_mode()
5374
5375 config_line = [l for l in self.history if l.strip().startswith('set')]
5376 for line in config_line:
5377 ME.exec_cmd(line)
5378 stop = self.define_child_cmd_interface(ME)
5379 return stop
5380 ext_program = launch_ext.aMCatNLOLauncher( args[1], self, **options)
5381 elif args[0] == 'madweight':
5382 import madgraph.interface.madweight_interface as madweight_interface
5383 if options['interactive']:
5384 if hasattr(self, 'do_shell'):
5385 MW = madweight_interface.MadWeightCmdShell(me_dir=args[1], options=self.options)
5386 else:
5387 MW = madweight_interface.MadWeightCmd(me_dir=args[1],options=self.options)
5388
5389 config_line = [l for l in self.history if l.strip().startswith('set')]
5390 for line in config_line:
5391 MW.exec_cmd(line)
5392 stop = self.define_child_cmd_interface(MW)
5393 return stop
5394 ext_program = launch_ext.MWLauncher( self, args[1],
5395 shell = hasattr(self, 'do_shell'),
5396 options=self.options,**options)
5397 else:
5398 os.chdir(start_cwd)
5399 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
5400
5401
5402 ext_program.run()
5403 os.chdir(start_cwd)
5404
5405 for key, value in current_options.items():
5406 self.options[key] = value
5407
5473
5474
5476 """create a restriction card in a interactive way"""
5477
5478 args = self.split_arg(line)
5479 self.check_customize_model(args)
5480
5481 model_path = self._curr_model.get('modelpath')
5482 if not os.path.exists(pjoin(model_path,'build_restrict.py')):
5483 raise self.InvalidCmd('''Model not compatible with this option.''')
5484
5485
5486 self._curr_model = import_ufo.import_model(model_path, restrict=False)
5487
5488
5489 out_path = StringIO.StringIO()
5490 param_writer.ParamCardWriter(self._curr_model, out_path)
5491
5492 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
5493
5494
5495 all_categories = self.ask('','0',[], ask_class=AskforCustomize)
5496 put_to_one = []
5497
5498 for block in param_card:
5499 value_dict = {}
5500 for param in param_card[block]:
5501 value = param.value
5502 if value == 0:
5503 param.value = 0.000001e-99
5504 elif value == 1:
5505 if block != 'qnumbers':
5506 put_to_one.append((block,param.lhacode))
5507 param.value = random.random()
5508 elif abs(value) in value_dict:
5509 param.value += value_dict[abs(value)] * 1e-4 * param.value
5510 value_dict[abs(value)] += 1
5511 else:
5512 value_dict[abs(value)] = 1
5513
5514 for category in all_categories:
5515 for options in category:
5516 if not options.status:
5517 continue
5518 param = param_card[options.lhablock].get(options.lhaid)
5519 param.value = options.value
5520
5521 logger.info('Loading the resulting model')
5522
5523 self._curr_model = import_ufo.RestrictModel(self._curr_model)
5524 model_name = self._curr_model.get('name')
5525 if model_name == 'mssm':
5526 keep_external=True
5527 else:
5528 keep_external=False
5529 self._curr_model.restrict_model(param_card,keep_external=keep_external)
5530
5531 if args:
5532 name = args[0].split('=',1)[1]
5533 path = pjoin(model_path,'restrict_%s.dat' % name)
5534 logger.info('Save restriction file as %s' % path)
5535 param_card.write(path)
5536 self._curr_model['name'] += '-%s' % name
5537
5538
5539 if put_to_one:
5540 out_path = StringIO.StringIO()
5541 param_writer.ParamCardWriter(self._curr_model, out_path)
5542
5543 param_card = check_param_card.ParamCard(out_path.getvalue().split('\n'))
5544
5545 for (block, lhacode) in put_to_one:
5546 misc.sprint(block, lhacode)
5547 try:
5548 param_card[block].get(lhacode).value = 1
5549 except:
5550 pass
5551 self._curr_model.set_parameters_and_couplings(param_card)
5552
5553 if args:
5554 name = args[0].split('=',1)[1]
5555 path = pjoin(model_path,'paramcard_%s.dat' % name)
5556 logger.info('Save default card file as %s' % path)
5557 param_card.write(path)
5558
5559 - def do_save(self, line, check=True, to_keep={}, log=True):
5560 """Not in help: Save information to file"""
5561
5562 args = self.split_arg(line)
5563
5564 if check:
5565 self.check_save(args)
5566
5567 if args[0] == 'model':
5568 if self._curr_model:
5569
5570 if save_load_object.save_to_file(args[1], self._curr_model):
5571 logger.info('Saved model to file %s' % args[1])
5572 else:
5573 raise self.InvalidCmd('No model to save!')
5574 elif args[0] == 'processes':
5575 if self._curr_amps:
5576 if save_load_object.save_to_file(args[1], self._curr_amps):
5577 logger.info('Saved processes to file %s' % args[1])
5578 else:
5579 raise self.InvalidCmd('No processes to save!')
5580
5581 elif args[0] == 'options':
5582
5583 to_define = {}
5584 for key, default in self.options_configuration.items():
5585 if self.options_configuration[key] != self.options[key] != None:
5586 to_define[key] = self.options[key]
5587
5588 if not '--auto' in args:
5589 for key, default in self.options_madevent.items():
5590 if self.options_madevent[key] != self.options[key] != None:
5591 if '_path' in key and os.path.basename(self.options[key]) == 'None':
5592 continue
5593 to_define[key] = self.options[key]
5594 elif key == 'cluster_queue' and self.options[key] is None:
5595 to_define[key] = self.options[key]
5596
5597 if '--all' in args:
5598 for key, default in self.options_madgraph.items():
5599 if self.options_madgraph[key] != self.options[key] != None and \
5600 key != 'stdout_level':
5601 to_define[key] = self.options[key]
5602 elif not '--auto' in args:
5603 for key, default in self.options_madgraph.items():
5604 if self.options_madgraph[key] != self.options[key] != None and key != 'stdout_level':
5605 logger.info('The option %s is modified [%s] but will not be written in the configuration files.' \
5606 % (key,self.options_madgraph[key]) )
5607 logger.info('If you want to make this value the default for future session, you can run \'save options --all\'')
5608 if len(args) >1 and not args[1].startswith('--'):
5609 filepath = args[1]
5610 else:
5611 filepath = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
5612 basefile = pjoin(MG5DIR, 'input', '.mg5_configuration_default.txt')
5613 basedir = MG5DIR
5614
5615 if to_keep:
5616 to_define = to_keep
5617 self.write_configuration(filepath, basefile, basedir, to_define)
5618
5619
5620 - def do_set(self, line, log=True):
5621 """Set an option, which will be default for coming generations/outputs
5622 """
5623
5624
5625
5626 args = self.split_arg(line)
5627
5628
5629 self.check_set(args)
5630
5631 if args[0] == 'ignore_six_quark_processes':
5632 if args[1] == 'False':
5633 self.options[args[0]] = False
5634 return
5635 self.options[args[0]] = list(set([abs(p) for p in \
5636 self._multiparticles[args[1]]\
5637 if self._curr_model.get_particle(p).\
5638 is_fermion() and \
5639 self._curr_model.get_particle(abs(p)).\
5640 get('color') == 3]))
5641 if log:
5642 logger.info('Ignore processes with >= 6 quarks (%s)' % \
5643 ",".join([\
5644 self._curr_model.get_particle(q).get('name') \
5645 for q in self.options[args[0]]]))
5646
5647 elif args[0] == 'group_subprocesses':
5648 if args[1] not in ['Auto', 'NLO']:
5649 self.options[args[0]] = eval(args[1])
5650 else:
5651 self.options[args[0]] = args[1]
5652 if log:
5653 logger.info('Set group_subprocesses to %s' % \
5654 str(self.options[args[0]]))
5655 logger.info('Note that you need to regenerate all processes')
5656 self._curr_amps = diagram_generation.AmplitudeList()
5657 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5658
5659 elif args[0] == "stdout_level":
5660 if args[1].isdigit():
5661 level = int(args[1])
5662 else:
5663 level = eval('logging.' + args[1])
5664 logging.root.setLevel(level)
5665 logging.getLogger('madgraph').setLevel(level)
5666 logging.getLogger('madevent').setLevel(level)
5667 if log:
5668 logger.info('set output information to level: %s' % level)
5669 elif args[0].lower() == "ewscheme":
5670 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." %\
5671 (self._curr_model.get('name'), args[1]))
5672 logger.info("Importing a model will restore the default scheme")
5673 self._curr_model.change_electroweak_mode(args[1])
5674 elif args[0] == "complex_mass_scheme":
5675 old = self.options[args[0]]
5676 self.options[args[0]] = eval(args[1])
5677 aloha.complex_mass = eval(args[1])
5678 aloha_lib.KERNEL.clean()
5679 if not self._curr_model:
5680 pass
5681 elif self.options[args[0]]:
5682 if old:
5683 if log:
5684 logger.info('Complex mass already activated.')
5685 return
5686 if log:
5687 logger.info('Activate complex mass scheme.')
5688 self._curr_model.change_mass_to_complex_scheme()
5689 if hasattr(self._curr_model, 'set_parameters_and_couplings'):
5690 self._curr_model.set_parameters_and_couplings()
5691 else:
5692 if not old:
5693 if log:
5694 logger.info('Complex mass already desactivated.')
5695 return
5696 if log:
5697 logger.info('Desactivate complex mass scheme.')
5698 self.exec_cmd('import model %s' % self._curr_model.get('name'))
5699
5700 elif args[0] == "gauge":
5701
5702 if not self._curr_model:
5703 if args[1] == 'unitary':
5704 aloha.unitary_gauge = True
5705 else:
5706 aloha.unitary_gauge = False
5707 aloha_lib.KERNEL.clean()
5708 self.options[args[0]] = args[1]
5709 if log: logger.info('Passing to gauge %s.' % args[1])
5710 return
5711
5712
5713 able_to_mod = True
5714 if args[1] == 'unitary':
5715 if 0 in self._curr_model.get('gauge'):
5716 aloha.unitary_gauge = True
5717 else:
5718 able_to_mod = False
5719 if log: logger.warning('Note that unitary gauge is not allowed for your current model %s' \
5720 % self._curr_model.get('name'))
5721 else:
5722 if 1 in self._curr_model.get('gauge'):
5723 aloha.unitary_gauge = False
5724 else:
5725 able_to_mod = False
5726 if log: logger.warning('Note that Feynman gauge is not allowed for your current model %s' \
5727 % self._curr_model.get('name'))
5728 self.options[args[0]] = args[1]
5729
5730 if able_to_mod and log and args[0] == 'gauge' and \
5731 args[1] == 'unitary' and not self.options['gauge']=='unitary' and \
5732 isinstance(self._curr_model,loop_base_objects.LoopModel) and \
5733 not self._curr_model['perturbation_couplings'] in [[],['QCD']]:
5734 logger.warning('You will only be able to do tree level'+\
5735 ' and QCD corrections in the unitary gauge.')
5736
5737
5738 model_name = self._curr_model.get('modelpath+restriction')
5739 self._curr_model = None
5740 self._curr_amps = diagram_generation.AmplitudeList()
5741 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5742 self._curr_fortran_model = None
5743 self._curr_cpp_model = None
5744 self._curr_exporter = None
5745 self._done_export = False
5746 import_ufo._import_once = []
5747 logger.info('Passing to gauge %s.' % args[1])
5748
5749 if able_to_mod:
5750
5751
5752
5753 MadGraphCmd.do_import(self,'model %s' %model_name, force=True)
5754 elif log:
5755 logger.info('Note that you have to reload the model')
5756
5757 elif args[0] == 'fortran_compiler':
5758 if args[1] != 'None':
5759 if log:
5760 logger.info('set fortran compiler to %s' % args[1])
5761 self.options['fortran_compiler'] = args[1]
5762 else:
5763 self.options['fortran_compiler'] = None
5764 elif args[0] == 'f2py_compiler':
5765 if args[1] != 'None':
5766 if log:
5767 logger.info('set f2py compiler to %s' % args[1])
5768 self.options['f2py_compiler'] = args[1]
5769 else:
5770 self.options['f2py_compiler'] = None
5771
5772 elif args[0] == 'loop_optimized_output':
5773 if log:
5774 logger.info('set loop optimized output to %s' % args[1])
5775 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5776 self.options[args[0]] = args[1]
5777 if not self.options['loop_optimized_output'] and \
5778 self.options['loop_color_flows']:
5779 logger.warning("Turning off option 'loop_color_flows'"+\
5780 " since it is not available for non-optimized loop output.")
5781 self.do_set('loop_color_flows False',log=False)
5782 elif args[0] == 'loop_color_flows':
5783 if log:
5784 logger.info('set loop color flows to %s' % args[1])
5785 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5786 self.options[args[0]] = args[1]
5787 if self.options['loop_color_flows'] and \
5788 not self.options['loop_optimized_output']:
5789 logger.warning("Turning on option 'loop_optimized'"+\
5790 " needed for loop color flow computation.")
5791 self.do_set('loop_optimized_output True',False)
5792
5793 elif args[0] == 'fastjet':
5794 try:
5795 p = subprocess.Popen([args[1], '--version'], stdout=subprocess.PIPE,
5796 stderr=subprocess.PIPE)
5797 output, error = p.communicate()
5798 res = 0
5799 except Exception:
5800 res = 1
5801
5802 if res != 0 or error:
5803 logger.info('%s does not seem to correspond to a valid fastjet-config ' % args[1] + \
5804 'executable (v3+). We will use fjcore instead.\n Please set the \'fastjet\'' + \
5805 'variable to the full (absolute) /PATH/TO/fastjet-config (including fastjet-config).' +
5806 '\n MG5_aMC> set fastjet /PATH/TO/fastjet-config\n')
5807 self.options[args[0]] = None
5808 self.history.pop()
5809 elif int(output.split('.')[0]) < 3:
5810 logger.warning('%s is not ' % args[1] + \
5811 'v3 or greater. Please install FastJet v3+.')
5812 self.options[args[0]] = None
5813 self.history.pop()
5814 else:
5815 logger.info('set fastjet to %s' % args[1])
5816 self.options[args[0]] = args[1]
5817
5818 elif args[0] in ["pjfry","golem"]:
5819 program = misc.which_lib(os.path.join(args[1],"lib%s.a"%args[0]))
5820 if program!=None:
5821 res = 0
5822 logger.info('set %s to %s' % (args[0],args[1]))
5823 self.options[args[0]] = args[1]
5824 else:
5825 res = 1
5826
5827 if res != 0 :
5828 logger.warning('%s does not seem to correspond to a valid %s lib ' % (args[1],args[0]) + \
5829 '. Please enter the full PATH/TO/%s/lib .\n'%args[0] + \
5830 'You will NOT be able to run %s otherwise.\n'%args[0])
5831
5832 elif args[0] == 'lhapdf':
5833 try:
5834 res = misc.call([args[1], '--version'], stdout=subprocess.PIPE,
5835 stderr=subprocess.PIPE)
5836 logger.info('set lhapdf to %s' % args[1])
5837 self.options[args[0]] = args[1]
5838 except Exception:
5839 res = 1
5840 if res != 0:
5841 logger.info('%s does not seem to correspond to a valid lhapdf-config ' % args[1] + \
5842 'executable. \nPlease set the \'lhapdf\' variable to the (absolute) ' + \
5843 '/PATH/TO/lhapdf-config (including lhapdf-config).\n' + \
5844 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n' + \
5845 ' MG5_aMC> set lhapdf /PATH/TO/lhapdf-config\n')
5846
5847 elif args[0] in ['timeout', 'auto_update', 'cluster_nb_retry',
5848 'cluster_retry_wait', 'cluster_size', 'max_npoint_for_channel']:
5849 self.options[args[0]] = int(args[1])
5850
5851 elif args[0] in ['cluster_local_path']:
5852 self.options[args[0]] = args[1].strip()
5853
5854 elif args[0] == 'cluster_status_update':
5855 if '(' in args[1]:
5856 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
5857 data = data.replace('(','').replace(')','').replace(',',' ').split()
5858 first, second = data[:2]
5859 else:
5860 first, second = args[1:3]
5861
5862 self.options[args[0]] = (int(first), int(second))
5863
5864 elif args[0] == 'OLP':
5865
5866
5867 self._curr_amps = diagram_generation.AmplitudeList()
5868 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
5869 self._curr_exporter = None
5870 self.options[args[0]] = args[1]
5871
5872 elif args[0] =='output_dependencies':
5873 self.options[args[0]] = args[1]
5874
5875 elif args[0] in self.options:
5876 if args[1] in ['None','True','False']:
5877 self.options[args[0]] = eval(args[1])
5878 else:
5879 self.options[args[0]] = args[1]
5880
5881 - def post_set(self, stop, line):
5882 """Check if we need to save this in the option file"""
5883
5884 args = self.split_arg(line)
5885
5886 try:
5887 self.check_set(args, log=False)
5888 except Exception:
5889 return stop
5890
5891 if args[0] in self.options_configuration and '--no_save' not in args:
5892 self.exec_cmd('save options --auto', log=False)
5893 elif args[0] in self.options_madevent:
5894 if not '--no_save' in line:
5895 logger.info('This option will be the default in any output that you are going to create in this session.')
5896 logger.info('In order to keep this changes permanent please run \'save options\'')
5897 else:
5898
5899 if not self.history or self.history[-1].split() != line.split():
5900 self.history.append('set %s' % line)
5901 self.avoid_history_duplicate('set %s' % args[0], ['define', 'set'])
5902 return stop
5903
5913
5915 """Main commands: Initialize a new Template or reinitialize one"""
5916
5917 args = self.split_arg(line)
5918
5919 self.check_output(args)
5920
5921
5922 noclean = '-noclean' in args
5923 force = '-f' in args
5924 nojpeg = '-nojpeg' in args
5925 flaglist = []
5926 if '--postpone_model' in args:
5927 flaglist.append('store_model')
5928
5929 main_file_name = ""
5930 try:
5931 main_file_name = args[args.index('-name') + 1]
5932 except Exception:
5933 pass
5934
5935
5936
5937
5938
5939 if self._export_format == 'aloha':
5940
5941 format = [d[9:] for d in args if d.startswith('--format=')]
5942 if not format:
5943 format = 'Fortran'
5944 else:
5945 format = format[-1]
5946
5947 output = [d for d in args if d.startswith('--output=')]
5948 if not output:
5949 output = import_ufo.find_ufo_path(self._curr_model['name'])
5950 output = pjoin(output, format)
5951 if not os.path.isdir(output):
5952 os.mkdir(output)
5953 else:
5954 output = output[-1]
5955 if not os.path.isdir(output):
5956 raise self.InvalidCmd('%s is not a valid directory' % output)
5957 logger.info('creating routines in directory %s ' % output)
5958
5959 names = [d for d in args if not d.startswith('-')]
5960 wanted_lorentz = aloha_fct.guess_routine_from_name(names)
5961
5962 aloha_model = create_aloha.AbstractALOHAModel(self._curr_model.get('name'))
5963 aloha_model.add_Lorentz_object(self._curr_model.get('lorentz'))
5964 if wanted_lorentz:
5965 aloha_model.compute_subset(wanted_lorentz)
5966 else:
5967 aloha_model.compute_all(save=False)
5968 aloha_model.write(output, format)
5969 return
5970
5971
5972
5973
5974
5975
5976
5977
5978 config = {}
5979 config['madevent'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
5980 config['matrix'] = {'check': False, 'exporter': 'v4', 'output':'dir'}
5981 config['standalone'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
5982 config['standalone_msF'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
5983 config['standalone_msP'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
5984 config['standalone_rw'] = {'check': False, 'exporter': 'v4', 'output':'Template'}
5985 config['standalone_cpp'] = {'check': False, 'exporter': 'cpp', 'output': 'Template'}
5986 config['pythia8'] = {'check': False, 'exporter': 'cpp', 'output':'dir'}
5987 config['matchbox_cpp'] = {'check': True, 'exporter': 'cpp', 'output': 'Template'}
5988 config['matchbox'] = {'check': True, 'exporter': 'v4', 'output': 'Template'}
5989 config['madweight'] = {'check': True, 'exporter': 'v4', 'output':'Template'}
5990
5991 options = config[self._export_format]
5992
5993 if os.path.realpath(self._export_dir) == os.getcwd():
5994 if len(args) == 0:
5995 i=0
5996 while 1:
5997 if os.path.exists('Pythia8_proc_%i' %i):
5998 i+=1
5999 else:
6000 break
6001 os.mkdir('Pythia8_proc_%i' %i)
6002 self._export_dir = pjoin(self._export_dir, 'Pythia8_proc_%i' %i)
6003 logger.info('Create output in %s' % self._export_dir)
6004 elif not args[0] in ['.', '-f']:
6005 raise self.InvalidCmd, 'Wrong path directory to create in local directory use \'.\''
6006 elif not noclean and os.path.isdir(self._export_dir) and options['check']:
6007 if not force:
6008
6009 logger.info('INFO: directory %s already exists.' % self._export_dir)
6010 logger.info('If you continue this directory will be deleted and replaced.')
6011 answer = self.ask('Do you want to continue?', 'y', ['y','n'])
6012 else:
6013 answer = 'y'
6014 if answer != 'y':
6015 raise self.InvalidCmd('Stopped by user request')
6016 else:
6017 shutil.rmtree(self._export_dir)
6018
6019
6020
6021 if self.options['group_subprocesses'] in [True, False]:
6022 group_processes = self.options['group_subprocesses']
6023 elif self.options['group_subprocesses'] == 'Auto':
6024
6025 group_processes = True
6026
6027
6028
6029
6030 if self._curr_amps[0].get_ninitial() == 1 and \
6031 len(self._curr_amps)>1:
6032 processes = [amp.get('process') for amp in self._curr_amps]
6033 if len(set(proc.get('id') for proc in processes))!=len(processes):
6034
6035 if any(proc['perturbation_couplings'] != [] for proc in
6036 processes) and self._export_format == 'madevent':
6037 logger.warning("""
6038 || The loop-induced decay process you have specified contains several
6039 || subprocesses and, in order to be able to compute individual branching ratios,
6040 || MG5_aMC will *not* group them. Integration channels will also be considered
6041 || for each diagrams and as a result integration will be inefficient.
6042 || It is therefore recommended to perform this simulation by setting the MG5_aMC
6043 || option 'group_subprocesses' to 'True' (before the output of the process).
6044 || Notice that when doing so, processes for which one still wishes to compute
6045 || branching ratios independently can be specified using the syntax:
6046 || -> add process <proc_def>
6047 """)
6048 group_processes = False
6049
6050
6051 if options['exporter'] == 'v4':
6052 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
6053 group_subprocesses=group_processes)
6054 if options['output'] == 'Template':
6055 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name'))
6056 if options['exporter'] == 'cpp' and options['output'] == 'Template':
6057 export_cpp.setup_cpp_standalone_dir(self._export_dir, self._curr_model)
6058
6059 if options['output'] == 'dir' and not os.path.isdir(self._export_dir):
6060 os.makedirs(self._export_dir)
6061
6062
6063 self._done_export = False
6064
6065 if self._export_format == "madevent":
6066
6067
6068 if self.options['max_npoint_for_channel']:
6069 base_objects.Vertex.max_n_loop_for_multichanneling = self.options['max_npoint_for_channel']
6070 else:
6071 base_objects.Vertex.max_n_loop_for_multichanneling = 3
6072
6073
6074 self.export(nojpeg, main_file_name, group_processes, args)
6075
6076
6077 self.finalize(nojpeg, flaglist=flaglist)
6078
6079
6080 self._done_export = (self._export_dir, self._export_format)
6081
6082
6083 self._export_dir = None
6084
6085
6086 - def export(self, nojpeg = False, main_file_name = "", group_processes=True,
6087 args=[]):
6088 """Export a generated amplitude to file."""
6089
6090 def generate_matrix_elements(self, group_processes=True):
6091 """Helper function to generate the matrix elements before
6092 exporting. Uses the main function argument 'group_processes' to decide
6093 whether to use group_subprocess or not. (it has been set in do_output to
6094 the appropriate value if the MG5 option 'group_subprocesses' was set
6095 to 'Auto'."""
6096
6097 if self._export_format in ['standalone_msP', 'standalone_msF', 'standalone_mw']:
6098 to_distinguish = []
6099 for part in self._curr_model.get('particles'):
6100 if part.get('name') in args and part.get('antiname') in args and\
6101 part.get('name') != part.get('antiname'):
6102 to_distinguish.append(abs(part.get('pdg_code')))
6103
6104
6105 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \
6106 a1.get_number_of_diagrams())
6107
6108 cpu_time1 = time.time()
6109 ndiags = 0
6110 if not self._curr_matrix_elements.get_matrix_elements():
6111 if group_processes:
6112 cpu_time1 = time.time()
6113 dc_amps = diagram_generation.DecayChainAmplitudeList(\
6114 [amp for amp in self._curr_amps if isinstance(amp, \
6115 diagram_generation.DecayChainAmplitude)])
6116 non_dc_amps = diagram_generation.AmplitudeList(\
6117 [amp for amp in self._curr_amps if not \
6118 isinstance(amp, \
6119 diagram_generation.DecayChainAmplitude)])
6120 subproc_groups = group_subprocs.SubProcessGroupList()
6121 matrix_elements_opts = {'optimized_output':
6122 self.options['loop_optimized_output']}
6123 if non_dc_amps:
6124 subproc_groups.extend(\
6125 group_subprocs.SubProcessGroup.group_amplitudes(\
6126 non_dc_amps, self._export_format,
6127 matrix_elements_opts=matrix_elements_opts))
6128
6129 if dc_amps:
6130 dc_subproc_group = \
6131 group_subprocs.DecayChainSubProcessGroup.\
6132 group_amplitudes(dc_amps, self._export_format,
6133 matrix_elements_opts=matrix_elements_opts)
6134 subproc_groups.extend(dc_subproc_group.\
6135 generate_helas_decay_chain_subproc_groups())
6136
6137 ndiags = sum([len(m.get('diagrams')) for m in \
6138 subproc_groups.get_matrix_elements()])
6139 self._curr_matrix_elements = subproc_groups
6140
6141 uid = 0
6142 for group in subproc_groups:
6143 uid += 1
6144 for me in group.get('matrix_elements'):
6145 me.get('processes')[0].set('uid', uid)
6146 else:
6147 mode = {}
6148 if self._export_format in [ 'standalone_msP' ,
6149 'standalone_msF', 'standalone_rw']:
6150 mode['mode'] = 'MadSpin'
6151
6152
6153 if isinstance(self._curr_amps[0],
6154 loop_diagram_generation.LoopAmplitude):
6155 mode['optimized_output']=self.options['loop_optimized_output']
6156 HelasMultiProcessClass = loop_helas_objects.LoopHelasProcess
6157 compute_loop_nc = True
6158 else:
6159 HelasMultiProcessClass = helas_objects.HelasMultiProcess
6160 compute_loop_nc = False
6161
6162 self._curr_matrix_elements = HelasMultiProcessClass(
6163 self._curr_amps, compute_loop_nc=compute_loop_nc,
6164 matrix_element_opts=mode)
6165
6166 ndiags = sum([len(me.get('diagrams')) for \
6167 me in self._curr_matrix_elements.\
6168 get_matrix_elements()])
6169
6170 uid = 0
6171 for me in self._curr_matrix_elements.get_matrix_elements()[:]:
6172 uid += 1
6173 me.get('processes')[0].set('uid', uid)
6174
6175 cpu_time2 = time.time()
6176
6177
6178 return ndiags, cpu_time2 - cpu_time1
6179
6180
6181
6182 ndiags, cpu_time = generate_matrix_elements(self,group_processes)
6183
6184 calls = 0
6185
6186 path = self._export_dir
6187 if self._export_format in ['standalone_cpp', 'madevent', 'standalone',
6188 'standalone_msP', 'standalone_msF', 'standalone_rw',
6189 'matchbox_cpp', 'madweight', 'matchbox']:
6190 path = pjoin(path, 'SubProcesses')
6191
6192 cpu_time1 = time.time()
6193
6194
6195
6196
6197
6198 if self._export_format == 'madevent':
6199 calls += self._curr_exporter.export_processes(self._curr_matrix_elements,
6200 self._curr_fortran_model)
6201
6202
6203 card_path = pjoin(path, os.path.pardir, 'SubProcesses', \
6204 'procdef_mg5.dat')
6205 if self._generate_info:
6206 self._curr_exporter.write_procdef_mg5(card_path,
6207 self._curr_model['name'],
6208 self._generate_info)
6209 try:
6210 cmd.Cmd.onecmd(self, 'history .')
6211 except Exception:
6212 misc.sprint('command history fails.', 10)
6213 pass
6214
6215
6216 if self._export_format == 'pythia8':
6217
6218 process_names = []
6219 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
6220 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
6221 exporter = export_cpp.generate_process_files_pythia8(\
6222 me_group.get('matrix_elements'), self._curr_cpp_model,
6223 process_string = me_group.get('name'),
6224 process_number = group_number, path = path)
6225 process_names.append(exporter.process_name)
6226 else:
6227 exporter = export_cpp.generate_process_files_pythia8(\
6228 self._curr_matrix_elements, self._curr_cpp_model,
6229 process_string = self._generate_info, path = path)
6230 process_names.append(exporter.process_file_name)
6231
6232
6233 model_name, model_path = export_cpp.convert_model_to_pythia8(\
6234 self._curr_model, self._export_dir)
6235
6236
6237 filename, make_filename = \
6238 export_cpp.generate_example_file_pythia8(path,
6239 model_path,
6240 process_names,
6241 exporter,
6242 main_file_name)
6243
6244
6245 matrix_elements = self._curr_matrix_elements.get_matrix_elements()
6246
6247
6248 if self._export_format == 'madweight':
6249
6250 if isinstance(self._curr_matrix_elements, group_subprocs.SubProcessGroupList):
6251
6252 self._curr_matrix_elements = self._curr_matrix_elements.split_lepton_grouping()
6253
6254 for (group_number, me_group) in enumerate(self._curr_matrix_elements):
6255 calls = calls + \
6256 self._curr_exporter.generate_subprocess_directory_v4(\
6257 me_group, self._curr_fortran_model,
6258 group_number)
6259 else:
6260 for me_number, me in \
6261 enumerate(self._curr_matrix_elements.get_matrix_elements()):
6262 calls = calls + \
6263 self._curr_exporter.generate_subprocess_directory_v4(\
6264 me, self._curr_fortran_model, me_number)
6265
6266
6267 if self._export_format in ['standalone', 'standalone_msP',
6268 'standalone_msF', 'standalone_rw', 'matchbox']:
6269 for me in matrix_elements[:]:
6270 new_calls = self._curr_exporter.generate_subprocess_directory_v4(\
6271 me, self._curr_fortran_model)
6272 if not new_calls:
6273 matrix_elements.remove(me)
6274 calls = calls + new_calls
6275
6276
6277 if self._export_format == 'matrix':
6278 for me in matrix_elements:
6279 filename = pjoin(path, 'matrix_' + \
6280 me.get('processes')[0].shell_string() + ".f")
6281 if os.path.isfile(filename):
6282 logger.warning("Overwriting existing file %s" % filename)
6283 else:
6284 logger.info("Creating new file %s" % filename)
6285 calls = calls + self._curr_exporter.write_matrix_element_v4(\
6286 writers.FortranWriter(filename),\
6287 me, self._curr_fortran_model)
6288
6289
6290 if self._export_format in ['standalone_cpp', 'matchbox_cpp']:
6291 for me in matrix_elements:
6292 export_cpp.generate_subprocess_directory_standalone_cpp(\
6293 me, self._curr_cpp_model,
6294 path = path,
6295 format=self._export_format)
6296
6297 cpu_time2 = time.time() - cpu_time1
6298
6299 logger.info(("Generated helas calls for %d subprocesses " + \
6300 "(%d diagrams) in %0.3f s") % \
6301 (len(matrix_elements),
6302 ndiags, cpu_time))
6303
6304 if calls:
6305 if "cpu_time2" in locals():
6306 logger.info("Wrote files for %d helas calls in %0.3f s" % \
6307 (calls, cpu_time2))
6308 else:
6309 logger.info("Wrote files for %d helas calls" % \
6310 (calls))
6311
6312 if self._export_format == 'pythia8':
6313 logger.info("- All necessary files for Pythia 8 generated.")
6314 logger.info("- Run \"launch\" and select %s.cc," % filename)
6315 logger.info(" or go to %s/examples and run" % path)
6316 logger.info(" make -f %s" % make_filename)
6317 logger.info(" (with process_name replaced by process name).")
6318 logger.info(" You can then run ./%s to produce events for the process" % \
6319 filename)
6320
6321
6322
6323
6324 self._curr_amps = diagram_generation.AmplitudeList(\
6325 [me.get('base_amplitude') for me in \
6326 matrix_elements])
6327
6328 - def finalize(self, nojpeg, online = False, flaglist=[]):
6329 """Make the html output, write proc_card_mg5.dat and create
6330 madevent.tar.gz for a MadEvent directory"""
6331
6332 compiler_dict = {'fortran': self.options['fortran_compiler'],
6333 'cpp': self.options['cpp_compiler'],
6334 'f2py': self.options['f2py_compiler']}
6335
6336
6337 if self._export_format in ['madevent', 'standalone', 'standalone_msP',
6338 'standalone_msF', 'standalone_rw', 'NLO', 'madweight',
6339 'matchbox']:
6340
6341
6342 if self._model_v4_path:
6343 logger.info('Copy %s model files to directory %s' % \
6344 (os.path.basename(self._model_v4_path), self._export_dir))
6345 self._curr_exporter.export_model_files(self._model_v4_path)
6346 self._curr_exporter.export_helas(pjoin(self._mgme_dir,'HELAS'))
6347 else:
6348 logger.info('Export UFO model to MG4 format')
6349
6350
6351
6352 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
6353 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
6354
6355
6356 if hasattr(self, 'previous_lorentz'):
6357 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz))
6358 wanted_couplings = list(set(self.previous_couplings + wanted_couplings))
6359 del self.previous_lorentz
6360 del self.previous_couplings
6361 if 'store_model' in flaglist:
6362 self.previous_lorentz = wanted_lorentz
6363 self.previous_couplings = wanted_couplings
6364 else:
6365 self._curr_exporter.convert_model_to_mg4(self._curr_model,
6366 wanted_lorentz,
6367 wanted_couplings)
6368 if self._export_format in ['standalone_cpp', 'matchbox_cpp']:
6369 logger.info('Export UFO model to C++ format')
6370
6371
6372
6373 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
6374 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
6375 export_cpp.convert_model_to_cpp(self._curr_model,
6376 pjoin(self._export_dir),
6377 wanted_lorentz,
6378 wanted_couplings)
6379 export_cpp.make_model_cpp(self._export_dir)
6380
6381
6382 elif self._export_format in ['NLO']:
6383
6384 devnull = os.open(os.devnull, os.O_RDWR)
6385 try:
6386 res = misc.call([self.options['lhapdf'], '--version'], \
6387 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
6388 except Exception:
6389 res = 1
6390 if res != 0:
6391 logger.info('The value for lhapdf in the current configuration does not ' + \
6392 'correspond to a valid executable.\nPlease set it correctly either in ' + \
6393 'input/mg5_configuration or with "set lhapdf /path/to/lhapdf-config" ' + \
6394 'and regenrate the process. \nTo avoid regeneration, edit the ' + \
6395 ('%s/Cards/amcatnlo_configuration.txt file.\n' % self._export_dir ) + \
6396 'Note that you can still compile and run aMC@NLO with the built-in PDFs\n')
6397
6398
6399
6400 self._curr_exporter.finalize_fks_directory( \
6401 self._curr_matrix_elements,
6402 self.history,
6403 not nojpeg,
6404 online,
6405 compiler_dict,
6406 output_dependencies = self.options['output_dependencies'],
6407 MG5DIR = MG5DIR)
6408
6409
6410 filename = os.path.join(self._export_dir, 'Cards', 'amcatnlo_configuration.txt')
6411 opts_to_keep = ['lhapdf', 'fastjet', 'pythia8_path', 'hwpp_path', 'thepeg_path',
6412 'hepmc_path']
6413 to_keep = {}
6414 for opt in opts_to_keep:
6415 if self.options[opt]:
6416 to_keep[opt] = self.options[opt]
6417 self.do_save('options %s' % filename.replace(' ', '\ '), check=False, \
6418 to_keep = to_keep)
6419
6420 elif self._export_format in ['madevent', 'madweight']:
6421
6422 filename = os.path.join(self._export_dir, 'Cards', 'me5_configuration.txt')
6423 self.do_save('options %s' % filename.replace(' ', '\ '), check=False,
6424 to_keep={'mg5_path':MG5DIR})
6425
6426 if self._export_format in ['madevent', 'standalone', 'standalone_msP', 'standalone_msF',
6427 'standalone_rw', 'madweight', 'matchbox']:
6428
6429 self._curr_exporter.finalize_v4_directory( \
6430 self._curr_matrix_elements,
6431 self.history,
6432 not nojpeg,
6433 online,
6434 compiler_dict)
6435
6436 if self._export_format in ['madevent', 'standalone', 'standalone_cpp','madweight', 'matchbox']:
6437 logger.info('Output to directory ' + self._export_dir + ' done.')
6438
6439 if self._export_format in ['madevent', 'NLO']:
6440 logger.info('Type \"launch\" to generate events from this process, or see')
6441 logger.info(self._export_dir + '/README')
6442 logger.info('Run \"open index.html\" to see more information about this process.')
6443
6445 """ propose some usefull possible action """
6446
6447 super(MadGraphCmd,self).do_help(line)
6448
6449 if line:
6450 return
6451
6452 if len(self.history) == 0:
6453 last_action_2 = 'mg5_start'
6454 last_action = 'mg5_start'
6455 else:
6456 args = self.history[-1].split()
6457 last_action = args[0]
6458 if len(args)>1:
6459 last_action_2 = '%s %s' % (last_action, args[1])
6460 else:
6461 last_action_2 = 'none'
6462
6463
6464
6465
6467 """Documented commands:Generate amplitudes for decay width calculation, with fixed
6468 number of final particles (called level)
6469 syntax; compute_widths particle [other particles] [--options=]
6470
6471 - particle/other particles can also be multiparticle name (can also be
6472 pid of the particle)
6473
6474 --body_decay=X [default=4.0025] allow to choose the precision.
6475 if X is an integer: compute all X body decay
6476 if X is a float <1: compute up to the time that total error < X
6477 if X is a float >1: stops at the first condition.
6478
6479 --path=X. Use a given file for the param_card. (default UFO built-in)
6480
6481 special argument:
6482 - skip_2body: allow to not consider those decay (use FR)
6483 - model: use the model pass in argument.
6484
6485 """
6486
6487
6488
6489 self.change_principal_cmd('MadGraph')
6490 if '--nlo' not in line:
6491 warning_text = """Please note that the automatic computation of the width is
6492 only valid in narrow-width approximation and at tree-level."""
6493 logger.warning(warning_text)
6494
6495 if not model:
6496 modelname = self._curr_model.get('modelpath+restriction')
6497 with misc.MuteLogger(['madgraph'], ['INFO']):
6498 model = import_ufo.import_model(modelname, decay=True)
6499 else:
6500 self._curr_model = model
6501 self._curr_fortran_model = \
6502 helas_call_writers.FortranUFOHelasCallWriter(\
6503 self._curr_model)
6504 if not isinstance(model, model_reader.ModelReader):
6505 model = model_reader.ModelReader(model)
6506
6507 if '--nlo' in line:
6508
6509 self.compute_widths_SMWidth(line, model=model)
6510 return
6511
6512
6513 particles, opts = self.check_compute_widths(self.split_arg(line))
6514
6515 if opts['path']:
6516 correct = True
6517 param_card = check_param_card.ParamCard(opts['path'])
6518 for param in param_card['decay']:
6519 if param.value == "auto":
6520 param.value = 1
6521 param.format = 'float'
6522 correct = False
6523 if not correct:
6524 if opts['output']:
6525 param_card.write(opts['output'])
6526 opts['path'] = opts['output']
6527 else:
6528 param_card.write(opts['path'])
6529
6530 data = model.set_parameters_and_couplings(opts['path'])
6531
6532
6533 if do2body:
6534 skip_2body = True
6535 decay_info = {}
6536 for pid in particles:
6537 particle = model.get_particle(pid)
6538 if not hasattr(particle, 'partial_widths'):
6539 skip_2body = False
6540 break
6541 elif not decay_info:
6542 logger_mg.info('Get two body decay from FeynRules formula')
6543 decay_info[pid] = []
6544 mass = abs(eval(str(particle.get('mass')), data).real)
6545 data = model.set_parameters_and_couplings(opts['path'], scale= mass)
6546 total = 0
6547
6548 for mode, expr in particle.partial_widths.items():
6549 tmp_mass = mass
6550 for p in mode:
6551 try:
6552 value_mass = eval(str(p.mass), data)
6553 except Exception:
6554
6555
6556 value_mass = eval(str(model.get_particle(p.pdg_code).get('mass')), data)
6557 tmp_mass -= abs(value_mass)
6558 if tmp_mass <=0:
6559 continue
6560
6561 decay_to = [p.get('pdg_code') for p in mode]
6562 value = eval(expr,{'cmath':cmath},data).real
6563 if -1e-10 < value < 0:
6564 value = 0
6565 if -1e-5 < value < 0:
6566 logger.warning('Partial width for %s > %s negative: %s automatically set to zero' %
6567 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value))
6568 value = 0
6569 elif value < 0:
6570 raise Exception, 'Partial width for %s > %s negative: %s' % \
6571 (particle.get('name'), ' '.join([p.get('name') for p in mode]), value)
6572 decay_info[particle.get('pdg_code')].append([decay_to, value])
6573 total += value
6574 else:
6575 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
6576 opts['path'], opts['output'])
6577 if float(opts['body_decay']) == 2:
6578 return
6579 else:
6580 skip_2body = True
6581
6582
6583
6584
6585 self.do_decay_diagram('%s %s' % (' '.join([`id` for id in particles]),
6586 ' '.join('--%s=%s' % (key,value)
6587 for key,value in opts.items()
6588 if key not in ['precision_channel'])
6589 ), skip_2body=skip_2body)
6590
6591 if self._curr_amps:
6592 logger.info('Pass to numerical integration for computing the widths:')
6593 else:
6594 logger.info('No need for N body-decay (N>2). Results are in %s' % opts['output'])
6595 return
6596
6597
6598 with misc.TMP_directory(dir=os.getcwd()) as path:
6599 decay_dir = pjoin(path,'temp_decay')
6600 logger_mg.info('More info in temporary files:\n %s/index.html' % (decay_dir))
6601 with misc.MuteLogger(['madgraph','ALOHA','cmdprint','madevent'], [40,40,40,40]):
6602 self.exec_cmd('output %s -f' % decay_dir)
6603
6604 if os.path.exists(opts['output']):
6605 files.cp(opts['output'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
6606 else:
6607 files.cp(opts['path'], pjoin(decay_dir, 'Cards', 'param_card.dat'))
6608 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
6609 check_param_card.convert_to_slha1(pjoin(decay_dir, 'Cards', 'param_card.dat'))
6610
6611 me_cmd = madevent_interface.MadEventCmd(decay_dir)
6612
6613 me_cmd.model_name = self._curr_model['name']
6614 me_cmd.options['automatic_html_opening'] = False
6615
6616 me_opts=[('accuracy', opts['precision_channel']),
6617 ('points', 1000),
6618 ('iterations',9)]
6619 me_cmd.exec_cmd('survey decay -f %s' % (
6620 " ".join(['--%s=%s' % val for val in me_opts])),
6621 postcmd=False)
6622 me_cmd.exec_cmd('combine_events', postcmd=False)
6623
6624 me_cmd.collect_decay_widths()
6625 me_cmd.do_quit('')
6626
6627 del me_cmd
6628
6629 param = check_param_card.ParamCard(pjoin(decay_dir, 'Events', 'decay','param_card.dat'))
6630
6631 for pid in particles:
6632 width = param['decay'].get((pid,)).value
6633 particle = self._curr_model.get_particle(pid)
6634
6635
6636
6637
6638
6639
6640 if not pid in param['decay'].decay_table:
6641 continue
6642 if pid not in decay_info:
6643 decay_info[pid] = []
6644 for BR in param['decay'].decay_table[pid]:
6645 if len(BR.lhacode) == 3 and skip_2body:
6646 continue
6647 if BR.value * width <0.1 and particle['color'] !=1:
6648 logger.warning("partial width of particle %s lower than QCD scale:%s. Set it to zero. (%s)" \
6649 % (particle.get('name'), BR.value * width, BR.lhacode[1:]))
6650
6651 continue
6652
6653 decay_info[pid].append([BR.lhacode[1:], BR.value * width])
6654
6655 madevent_interface.MadEventCmd.update_width_in_param_card(decay_info,
6656 opts['path'], opts['output'])
6657
6658 if self._curr_model['name'] == 'mssm' or self._curr_model['name'].startswith('mssm-'):
6659 check_param_card.convert_to_slha1(opts['output'])
6660 return
6661
6662
6663
6664
6666 """Compute widths with SMWidth.
6667 """
6668
6669
6670 particles, opts = self.check_compute_widths(self.split_arg(line))
6671
6672 if opts['path']:
6673 correct = True
6674 param_card = check_param_card.ParamCard(opts['path'])
6675 for param in param_card['decay']:
6676 if param.value == "auto":
6677 param.value = 1
6678 param.format = 'float'
6679 correct = False
6680 if not correct:
6681 if opts['output']:
6682 param_card.write(opts['output'])
6683 opts['path'] = opts['output']
6684 else:
6685 param_card.write(opts['path'])
6686
6687 if not model:
6688 model_path = self._curr_model.get('modelpath')
6689 model_name = self._curr_model.get('name')
6690 currmodel = self._curr_model
6691 else:
6692 model_path = model.get('modelpath')
6693 model_name = model.get('name')
6694 currmodel = model
6695
6696 if not os.path.exists(pjoin(model_path, 'SMWidth')):
6697 raise self.InvalidCmd, "Model %s is not valid for computing NLO width with SMWidth"%model_name
6698
6699
6700 externparam = [(param.lhablock.lower(),param.name.lower()) for param \
6701 in currmodel.get('parameters')[('external',)]]
6702
6703 if ('sminputs','aewm1') in externparam:
6704
6705 arg2 = "1"
6706 elif ('sminputs','mdl_gf') in externparam or ('sminputs','gf') in externparam:
6707
6708 arg2 = "2"
6709 else:
6710 raise Exception, "Do not know the EW scheme in the model %s"%model_name
6711
6712
6713 if not os.path.exists(pjoin(model_path, 'SMWidth','smwidth')):
6714 logger.info('Compiling SMWidth. This has to be done only once and'+\
6715 ' can take a couple of minutes.','$MG:color:BLACK')
6716 current = misc.detect_current_compiler(pjoin(model_path, 'SMWidth',
6717 'makefile_MW5'))
6718 new = 'gfortran' if self.options_configuration['fortran_compiler'] is None else \
6719 self.options_configuration['fortran_compiler']
6720 if current != new:
6721 misc.mod_compilator(pjoin(model_path, 'SMWidth'), new, current)
6722 misc.mod_compilator(pjoin(model_path, 'SMWidth','oneloop'), new, current)
6723 misc.mod_compilator(pjoin(model_path, 'SMWidth','hdecay'), new, current)
6724 misc.compile(cwd=pjoin(model_path, 'SMWidth'))
6725
6726
6727 identpath=" "
6728 carddir=os.path.dirname(opts['path'])
6729 if 'ident_card.dat' in os.listdir(carddir):
6730 identpath=pjoin(carddir,'ident_card.dat')
6731
6732 output,error = misc.Popen(['./smwidth',opts['path'],identpath,arg2],
6733 stdout=subprocess.PIPE,
6734 stdin=subprocess.PIPE,
6735 cwd=pjoin(model_path, 'SMWidth')).communicate()
6736 pattern = re.compile(r''' decay\s+(\+?\-?\d+)\s+(\+?\-?\d+\.\d+E\+?\-?\d+)''',re.I)
6737 width_list = pattern.findall(output)
6738 width_dict = {}
6739 for pid,width in width_list:
6740 width_dict[int(pid)] = float(width)
6741
6742 for pid in particles:
6743 if not pid in width_dict:
6744 width = 0
6745 else:
6746 width = width_dict[pid]
6747 param = param_card['decay'].get((pid,))
6748 param.value = width
6749 param.format = 'float'
6750 if pid not in param_card['decay'].decay_table:
6751 continue
6752 del param_card['decay'].decay_table[pid]
6753
6754 if opts['output']:
6755 param_card.write(opts['output'])
6756 logger.info('Results are written in %s' % opts['output'])
6757 else:
6758 param_card.write(opts['path'])
6759 logger.info('Results are written in %s' % opts['path'])
6760 return
6761
6762
6764 """Not in help: Generate amplitudes for decay width calculation, with fixed
6765 number of final particles (called level)
6766 syntax; decay_diagram part_name level param_path
6767 args; part_name level param_path
6768 part_name = name of the particle you want to calculate width
6769 level = a.) when level is int,
6770 it means the max number of decay products
6771 b.) when level is float,
6772 it means the required precision for width.
6773 param_path = path for param_card
6774 (this is necessary to determine whether a channel is onshell or not)
6775 e.g. calculate width for higgs up to 2-body decays.
6776 calculate_width h 2 [path]
6777 N.B. param_card must be given so that the program knows which channel
6778 is on shell and which is not.
6779
6780 special argument:
6781 - skip_2body: allow to not consider those decay (use FR)
6782 - model: use the model pass in argument.
6783 """
6784
6785 if model:
6786 self._curr_model = model
6787
6788 args = self.split_arg(line)
6789
6790 particles, args = self.check_decay_diagram(args)
6791
6792 pids = particles
6793 level = float(args['body_decay'])
6794 param_card_path = args['path']
6795 min_br = float(args['min_br'])
6796
6797
6798 self._curr_amps = diagram_generation.AmplitudeList()
6799
6800 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
6801
6802 self._done_export = False
6803
6804 self._export_format = None
6805
6806
6807
6808 if not model:
6809 self._curr_decaymodel = decay_objects.DecayModel(self._curr_model,
6810 True)
6811 self._curr_decaymodel.read_param_card(param_card_path)
6812 else:
6813 self._curr_decaymodel = model
6814 model = self._curr_decaymodel
6815
6816 if isinstance(pids, int):
6817 pids = [pids]
6818
6819 first =True
6820 for part_nb,pid in enumerate(pids):
6821 part = self._curr_decaymodel.get_particle(pid)
6822 if part.get('width').lower() == 'zero':
6823 continue
6824 logger_mg.info('get decay diagram for %s' % part['name'])
6825
6826 if level // 1 == level and level >1:
6827 level = int(level)
6828 self._curr_decaymodel.find_channels(part, level, min_br)
6829 if not skip_2body:
6830 amp = part.get_amplitudes(2)
6831 if amp:
6832 self._curr_amps.extend(amp)
6833
6834 for l in range(3, level+1):
6835 amp = part.get_amplitudes(l)
6836 if amp:
6837 self._curr_amps.extend(amp)
6838 else:
6839 max_level = level // 1
6840 if max_level < 2:
6841 max_level = 999
6842 precision = level % 1
6843 if first:
6844 model.find_all_channels(2,generate_abstract=False)
6845 first = False
6846 if not skip_2body:
6847 amp = part.get_amplitudes(2)
6848 if amp:
6849 self._curr_amps.extend(amp)
6850 clevel = 2
6851 while part.get('apx_decaywidth_err').real > precision:
6852 clevel += 1
6853 if clevel > max_level:
6854 logger_mg.info(' stop to %s body-decay. approximate error: %s' %
6855 (max_level, part.get('apx_decaywidth_err')) )
6856 break
6857 if clevel > 3:
6858 logger_mg.info(' current estimated error: %s go to %s-body decay:' %\
6859 (part.get('apx_decaywidth_err'), clevel))
6860 part.find_channels_nextlevel(model, min_br)
6861
6862 amp = part.get_amplitudes(clevel)
6863 if amp:
6864 self._curr_amps.extend(amp)
6865 part.update_decay_attributes(False, True, True, model)
6866
6867
6868
6869 if len(self._curr_amps) > 0:
6870 process = self._curr_amps[0]['process'].nice_string()
6871
6872 self._generate_info = process[9:]
6873
6874 else:
6875 print "No decay is found"
6876
6878 """Temporary parser"""
6879
6880
6881
6882
6883
6884 _draw_usage = "draw FILEPATH [options]\n" + \
6885 "-- draw the diagrams in eps format\n" + \
6886 " Files will be FILEPATH/diagrams_\"process_string\".eps \n" + \
6887 " Example: draw plot_dir . \n"
6888 _draw_parser = misc.OptionParser(usage=_draw_usage)
6889 _draw_parser.add_option("", "--horizontal", default=False,
6890 action='store_true', help="force S-channel to be horizontal")
6891 _draw_parser.add_option("", "--external", default=0, type='float',
6892 help="authorizes external particles to end at top or " + \
6893 "bottom of diagram. If bigger than zero this tune the " + \
6894 "length of those line.")
6895 _draw_parser.add_option("", "--max_size", default=1.5, type='float',
6896 help="this forbids external line bigger than max_size")
6897 _draw_parser.add_option("", "--non_propagating", default=True, \
6898 dest="contract_non_propagating", action='store_false',
6899 help="avoid contractions of non propagating lines")
6900 _draw_parser.add_option("", "--add_gap", default=0, type='float', \
6901 help="set the x-distance between external particles")
6902
6903
6904 _launch_usage = "launch [DIRPATH] [options]\n" + \
6905 "-- execute the madevent/standalone/standalone_cpp/pythia8/NLO output present in DIRPATH\n" + \
6906 " By default DIRPATH is the latest created directory \n" + \
6907 " (for pythia8, it should be the Pythia 8 main directory) \n" + \
6908 " Example: launch PROC_sm_1 --name=run2 \n" + \
6909 " Example: launch ../pythia8 \n"
6910 _launch_parser = misc.OptionParser(usage=_launch_usage)
6911 _launch_parser.add_option("-f", "--force", default=False, action='store_true',
6912 help="Use the card present in the directory in order to launch the different program")
6913 _launch_parser.add_option("-n", "--name", default='', type='str',
6914 help="Provide a name to the run (for madevent run)")
6915 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true',
6916 help="submit the job on the cluster")
6917 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true',
6918 help="submit the job on multicore core")
6919
6920 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true',
6921 help="Use Interactive Console [if available]")
6922 _launch_parser.add_option("-s", "--laststep", default='',
6923 help="last program run in MadEvent run. [auto|parton|pythia|pgs|delphes]")
6924 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true',
6925 help="Run the reweight module (reweighting by different model parameter")
6926 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true',
6927 help="Run the madspin package")
6933 """A class for asking a question where in addition you can have the
6934 set command define and modifying the param_card/run_card correctly"""
6935
6936 - def __init__(self, question, allow_arg=[], default=None,
6937 mother_interface=None, *arg, **opt):
6938
6939 model_path = mother_interface._curr_model.get('modelpath')
6940
6941 ufo_model = ufomodels.load_model(model_path)
6942 self.all_categories = ufo_model.build_restrict.all_categories
6943
6944 question = self.get_question()
6945
6946
6947 allow_arg = ['0']
6948 self.name2options = {}
6949 for category in self.all_categories:
6950 for options in category:
6951 if not options.first:
6952 continue
6953 self.name2options[str(len(allow_arg))] = options
6954 self.name2options[options.name.replace(' ','')] = options
6955 allow_arg.append(len(allow_arg))
6956 allow_arg.append('done')
6957
6958 cmd.SmartQuestion.__init__(self, question, allow_arg, default, mother_interface)
6959
6960
6961
6963 """Default action if line is not recognized"""
6964
6965 line = line.strip()
6966 args = line.split()
6967 if line == '' and self.default_value is not None:
6968 self.value = self.default_value
6969
6970 elif hasattr(self, 'do_%s' % args[0]):
6971 self.do_set(' '.join(args[1:]))
6972 elif line.strip() != '0' and line.strip() != 'done' and \
6973 str(line) != 'EOF' and line.strip() in self.allow_arg:
6974 option = self.name2options[line.strip()]
6975 option.status = not option.status
6976 self.value = 'repeat'
6977 else:
6978 self.value = line
6979
6980 return self.all_categories
6981
6982 - def reask(self, reprint_opt=True):
6987
6989 """ """
6990 self.value = 'repeat'
6991
6992 args = line.split()
6993 if args[0] not in self.name2options:
6994 logger.warning('Invalid set command. %s not recognize options. Valid options are: \n %s' %
6995 (args[0], ', '.join(self.name2options.keys()) ))
6996 return
6997 elif len(args) != 2:
6998 logger.warning('Invalid set command. Not correct number of argument')
6999 return
7000
7001
7002 if args[1] in ['True','1','.true.','T',1,True,'true','TRUE']:
7003 self.name2options[args[0]].status = True
7004 elif args[1] in ['False','0','.false.','F',0,False,'false','FALSE']:
7005 self.name2options[args[0]].status = False
7006 else:
7007 logger.warning('%s is not True/False. Didn\'t do anything.' % args[1])
7008
7009
7010
7012 """define the current question."""
7013 question = ''
7014 i=0
7015 for category in self.all_categories:
7016 question += category.name + ':\n'
7017 for options in category:
7018 if not options.first:
7019 continue
7020 i+=1
7021 question += ' %s: %s [%s]\n' % (i, options.name,
7022 options.display(options.status))
7023 question += 'Enter a number to change it\'s status or press enter to validate.\n'
7024 question += 'For scripting this function, please type: \'help\''
7025 return question
7026
7027
7029 """ Complete the set command"""
7030 signal.alarm(0)
7031 args = self.split_arg(line[0:begidx])
7032
7033 if len(args) == 1:
7034 possibilities = [x for x in self.name2options if not x.isdigit()]
7035 return self.list_completion(text, possibilities, line)
7036 else:
7037 return self.list_completion(text,['True', 'False'], line)
7038
7039
7041 '''help message'''
7042
7043 print 'This allows you to optimize your model to your needs.'
7044 print 'Enter the number associate to the possible restriction/add-on'
7045 print ' to change the status of this restriction/add-on.'
7046 print ''
7047 print 'In order to allow scripting of this function you can use the '
7048 print 'function \'set\'. This function takes two argument:'
7049 print 'set NAME VALUE'
7050 print ' NAME is the description of the option where you remove all spaces'
7051 print ' VALUE is either True or False'
7052 print ' Example: For the question'
7053 print ''' sm customization:
7054 1: diagonal ckm [True]
7055 2: c mass = 0 [True]
7056 3: b mass = 0 [False]
7057 4: tau mass = 0 [False]
7058 5: muon mass = 0 [True]
7059 6: electron mass = 0 [True]
7060 Enter a number to change it's status or press enter to validate.'''
7061 print ''' you can answer by'''
7062 print ' set diagonalckm False'
7063 print ' set taumass=0 True'
7064
7068
7069
7070
7071
7072
7073
7074
7075 if __name__ == '__main__':
7076
7077 run_option = sys.argv
7078 if len(run_option) > 1:
7079
7080 input_file = open(run_option[1], 'rU')
7081 cmd_line = MadGraphCmd(stdin=input_file)
7082 cmd_line.use_rawinput = False
7083 cmd_line.cmdloop()
7084 else:
7085
7086 MadGraphCmd().cmdloop()
7087