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