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.
16 Uses the cmd package for command interpretation and tab completion.
17 """
18 from __future__ import division
19
20 import atexit
21 import cmath
22 import cmd
23 import glob
24 import logging
25 import math
26 import optparse
27 import os
28 import pydoc
29 import random
30 import re
31 import shutil
32 import signal
33 import stat
34 import subprocess
35 import sys
36 import time
37 import traceback
38
39
40 try:
41 import readline
42 GNU_SPLITTING = ('GNU' in readline.__doc__)
43 except:
44 GNU_SPLITTING = True
45
46 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
47 root_path = os.path.split(root_path)[0]
48 sys.path.insert(0, os.path.join(root_path,'bin'))
49
50
51 pjoin = os.path.join
52
53 logger = logging.getLogger('madgraph.stdout')
54 logger_stderr = logging.getLogger('madgraph.stderr')
55
56
57 try:
58 import madgraph
59 except ImportError:
60
61 import internal.extended_cmd as cmd
62 import internal.banner as banner_mod
63 import internal.shower_card as shower_card_mod
64 import internal.misc as misc
65 import internal.cluster as cluster
66 import internal.check_param_card as check_param_card
67 import internal.files as files
68 from internal import InvalidCmd, MadGraph5Error
69 MADEVENT=True
70 else:
71
72 import madgraph.interface.extended_cmd as cmd
73 import madgraph.various.banner as banner_mod
74 import madgraph.various.shower_card as shower_card_mod
75 import madgraph.various.misc as misc
76 import madgraph.iolibs.files as files
77 import madgraph.various.cluster as cluster
78 import models.check_param_card as check_param_card
79 from madgraph import InvalidCmd, MadGraph5Error, MG5DIR
80 MADEVENT=False
86 """ The Series of help routins in common between amcatnlo_run and
87 madevent interface"""
88
90 logger.info("syntax: treatcards [param|run] [--output_dir=] [--param_card=] [--run_card=]")
91 logger.info("-- create the .inc files containing the cards information." )
92
94 logger.info("syntax: set %s argument" % "|".join(self._set_options))
95 logger.info("-- set options")
96 logger.info(" stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL")
97 logger.info(" change the default level for printed information")
98 logger.info(" timeout VALUE")
99 logger.info(" (default 20) Seconds allowed to answer questions.")
100 logger.info(" Note that pressing tab always stops the timer.")
101 logger.info(" cluster_temp_path PATH")
102 logger.info(" (default None) Allow to perform the run in PATH directory")
103 logger.info(" This allow to not run on the central disk. This is not used")
104 logger.info(" by condor cluster (since condor has it's own way to prevent it).")
105
107 logger.info("syntax: help [RUN] [%s] [-f]" % '|'.join(self._plot_mode))
108 logger.info("-- create the plot for the RUN (current run by default)")
109 logger.info(" at the different stage of the event generation")
110 logger.info(" Note than more than one mode can be specified in the same command.")
111 logger.info(" This require to have MadAnalysis and td require. By default")
112 logger.info(" if those programs are installed correctly, the creation")
113 logger.info(" will be performed automaticaly during the event generation.")
114 logger.info(" -f options: answer all question by default.")
115
117 logger.info("syntax: compute_widths Particle [Particles] [OPTIONS]")
118 logger.info("-- Compute the widths for the particles specified.")
119 logger.info(" By default, this takes the current param_card and overwrites it.")
120 logger.info(" Precision allows to define when to include three/four/... body decays (LO).")
121 logger.info(" If this number is an integer then all N-body decay will be included.")
122 logger.info(" Various options:\n")
123 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
124 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
125 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
126 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
127 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
128 logger.info(" default: 4.0025")
129 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
130 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
131 logger.info(" --precision_channel=X: requested numerical precision for each channel")
132 logger.info(" default: 0.01")
133 logger.info(" --path=X: path for param_card")
134 logger.info(" default: take value from the model")
135 logger.info(" --output=X: path where to write the resulting card. ")
136 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
137 logger.info(" --nlo: Compute NLO width [if the model support it]")
138
139
141 logger.info("syntax: pythia [RUN] [--run_options]")
142 logger.info("-- run pythia on RUN (current one by default)")
143 self.run_options_help([('-f','answer all question by default'),
144 ('--tag=', 'define the tag for the pythia run'),
145 ('--no_default', 'not run if pythia_card not present')])
146
148 logger.info("syntax: pgs [RUN] [--run_options]")
149 logger.info("-- run pgs on RUN (current one by default)")
150 self.run_options_help([('-f','answer all question by default'),
151 ('--tag=', 'define the tag for the pgs run'),
152 ('--no_default', 'not run if pgs_card not present')])
153
155 logger.info("syntax: delphes [RUN] [--run_options]")
156 logger.info("-- run delphes on RUN (current one by default)")
157 self.run_options_help([('-f','answer all question by default'),
158 ('--tag=', 'define the tag for the delphes run'),
159 ('--no_default', 'not run if delphes_card not present')])
160
162 if not skip_syntax:
163 logger.info("syntax: decay_events [RUN]")
164 logger.info("This functionality allows for the decay of resonances")
165 logger.info("in a .lhe file, keeping track of the spin correlation effets.")
166 logger.info("BE AWARE OF THE CURRENT LIMITATIONS:")
167 logger.info(" (1) Only a succession of 2 body decay are currently allowed")
168
172 """ The Series of check routines in common between amcatnlo_run and
173 madevent interface"""
174
176 """ check the validity of the line"""
177
178 if len(args) < 2:
179 self.help_set()
180 raise self.InvalidCmd('set needs an option and an argument')
181
182 if args[0] not in self._set_options + self.options.keys():
183 self.help_set()
184 raise self.InvalidCmd('Possible options for set are %s' % \
185 self._set_options)
186
187 if args[0] in ['stdout_level']:
188 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \
189 and not args[1].isdigit():
190 raise self.InvalidCmd('output_level needs ' + \
191 'a valid level')
192
193 if args[0] in ['timeout']:
194 if not args[1].isdigit():
195 raise self.InvalidCmd('timeout values should be a integer')
196
198 """check that the model is loadable and check that the format is of the
199 type: PART PATH --output=PATH -f --precision=N
200 return the model.
201 """
202
203
204 if MADEVENT and not self.options['mg5_path']:
205 raise self.InvalidCmd, '''The automatic computations of widths requires that MG5 is installed on the system.
206 You can install it and set his path in ./Cards/me5_configuration.txt'''
207 elif MADEVENT:
208 sys.path.append(self.options['mg5_path'])
209 try:
210 import models.model_reader as model_reader
211 import models.import_ufo as import_ufo
212 except ImportError:
213 raise self.ConfigurationError, '''Can\'t load MG5.
214 The variable mg5_path should not be correctly configure.'''
215
216
217 ufo_path = pjoin(self.me_dir,'bin','internal', 'ufomodel')
218
219 if not MADEVENT:
220 modelname = self.find_model_name()
221
222
223
224 model = import_ufo.import_model(modelname, decay=True,
225 restrict=True)
226 if self.mother and self.mother.options['complex_mass_scheme']:
227 model.change_mass_to_complex_scheme()
228 else:
229 model = import_ufo.import_model(pjoin(
230 self.me_dir,'bin','internal', 'ufomodel'),decay=True)
231
232 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''')
233 if has_cms.search(open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')\
234 ).read()):
235 model.change_mass_to_complex_scheme()
236
237
238
239
240
241
242 if '-modelname' not in open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')).read():
243 model.pass_particles_name_in_mg_default()
244 model = model_reader.ModelReader(model)
245 particles_name = dict([(p.get('name'), p.get('pdg_code'))
246 for p in model.get('particles')])
247 particles_name.update(dict([(p.get('antiname'), p.get('pdg_code'))
248 for p in model.get('particles')]))
249
250 output = {'model': model, 'force': False, 'output': None,
251 'path':None, 'particles': set(), 'body_decay':4.0025,
252 'min_br':None, 'precision_channel':0.01}
253 for arg in args:
254 if arg.startswith('--output='):
255 output_path = arg.split('=',1)[1]
256 if not os.path.exists(output_path):
257 raise self.InvalidCmd, 'Invalid Path for the output. Please retry.'
258 if not os.path.isfile(output_path):
259 output_path = pjoin(output_path, 'param_card.dat')
260 output['output'] = output_path
261 elif arg == '-f':
262 output['force'] = True
263 elif os.path.isfile(arg):
264 ftype = self.detect_card_type(arg)
265 if ftype != 'param_card.dat':
266 raise self.InvalidCmd , '%s is not a valid param_card.' % arg
267 output['path'] = arg
268 elif arg.startswith('--path='):
269 arg = arg.split('=',1)[1]
270 ftype = self.detect_card_type(arg)
271 if ftype != 'param_card.dat':
272 raise self.InvalidCmd , '%s is not a valid param_card.' % arg
273 output['path'] = arg
274 elif arg.startswith('--'):
275 if "=" in arg:
276 name, value = arg.split('=',1)
277 try:
278 value = float(value)
279 except Exception:
280 raise self.InvalidCmd, '--%s requires integer or a float' % name
281 output[name[2:]] = float(value)
282 elif arg == "--nlo":
283 output["nlo"] = True
284 elif arg in particles_name:
285
286 output['particles'].add(particles_name[arg])
287 elif arg.isdigit() and int(arg) in particles_name.values():
288 output['particles'].add(eval(arg))
289 elif arg == 'all':
290 output['particles'] = set(['all'])
291 else:
292 self.help_compute_widths()
293 raise self.InvalidCmd, '%s is not a valid argument for compute_widths' % arg
294 if self.force:
295 output['force'] = True
296
297 if not output['particles']:
298 raise self.InvalidCmd, '''This routines requires at least one particle in order to compute
299 the related width'''
300
301 if output['output'] is None:
302 output['output'] = output['path']
303
304 return output
305
307 """ check the validity of the line """
308
309 if len(args) != 1:
310 self.help_open()
311 raise self.InvalidCmd('OPEN command requires exactly one argument')
312
313 if args[0].startswith('./'):
314 if not os.path.isfile(args[0]):
315 raise self.InvalidCmd('%s: not such file' % args[0])
316 return True
317
318
319 if not self.me_dir:
320 if not os.path.isfile(args[0]):
321 self.help_open()
322 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file')
323 else:
324 return True
325
326 path = self.me_dir
327 if os.path.isfile(os.path.join(path,args[0])):
328 args[0] = os.path.join(path,args[0])
329 elif os.path.isfile(os.path.join(path,'Cards',args[0])):
330 args[0] = os.path.join(path,'Cards',args[0])
331 elif os.path.isfile(os.path.join(path,'HTML',args[0])):
332 args[0] = os.path.join(path,'HTML',args[0])
333
334 elif '_card.dat' in args[0]:
335 name = args[0].replace('_card.dat','_card_default.dat')
336 if os.path.isfile(os.path.join(path,'Cards', name)):
337 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0]))
338 args[0] = os.path.join(path,'Cards', args[0])
339 else:
340 raise self.InvalidCmd('No default path for this file')
341 elif not os.path.isfile(args[0]):
342 raise self.InvalidCmd('No default path for this file')
343
345 """check that treatcards arguments are valid
346 [param|run|all] [--output_dir=] [--param_card=] [--run_card=]
347 """
348
349 opt = {'output_dir':pjoin(self.me_dir,'Source'),
350 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'),
351 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')}
352 mode = 'all'
353 for arg in args:
354 if arg.startswith('--') and '=' in arg:
355 key,value =arg[2:].split('=',1)
356 if not key in opt:
357 self.help_treatcards()
358 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \
359 % key)
360 if key in ['param_card', 'run_card']:
361 if os.path.isfile(value):
362 card_name = self.detect_card_type(value)
363 if card_name != key:
364 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
365 % (card_name, key))
366 opt[key] = value
367 elif os.path.isfile(pjoin(self.me_dir,value)):
368 card_name = self.detect_card_type(pjoin(self.me_dir,value))
369 if card_name != key:
370 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
371 % (card_name, key))
372 opt[key] = value
373 else:
374 raise self.InvalidCmd('No such file: %s ' % value)
375 elif key in ['output_dir']:
376 if os.path.isdir(value):
377 opt[key] = value
378 elif os.path.isdir(pjoin(self.me_dir,value)):
379 opt[key] = pjoin(self.me_dir, value)
380 else:
381 raise self.InvalidCmd('No such directory: %s' % value)
382 elif arg in ['MadLoop','param','run','all']:
383 mode = arg
384 else:
385 self.help_treatcards()
386 raise self.InvalidCmd('Unvalid argument %s' % arg)
387
388 return mode, opt
389
391 """Check the argument for decay_events command
392 syntax: decay_events [NAME]
393 Note that other option are already remove at this point
394 """
395
396 opts = []
397 if '-from_cards' in args:
398 args.remove('-from_cards')
399 opts.append('-from_cards')
400
401 if len(args) == 0:
402 if self.run_name:
403 args.insert(0, self.run_name)
404 elif self.results.lastrun:
405 args.insert(0, self.results.lastrun)
406 else:
407 raise self.InvalidCmd('No run name currently defined. Please add this information.')
408 return
409
410 if args[0] != self.run_name:
411 self.set_run_name(args[0])
412
413 args[0] = self.get_events_path(args[0])
414
415 args += opts
416
418 """Check the argument for decay_events command
419 syntax: decay_events [NAME]
420 Note that other option are already remove at this point
421 """
422
423 if len(args) == 0:
424 if self.run_name:
425 args.insert(0, self.run_name)
426 elif self.results.lastrun:
427 args.insert(0, self.results.lastrun)
428 else:
429 raise self.InvalidCmd('No run name currently defined. Please add this information.')
430 return
431
432 if args[0] and os.path.isfile(args[0]):
433 pass
434 else:
435 if args[0] != self.run_name:
436 self.set_run_name(args[0], allow_new_tag=False)
437
438 args[0] = self.get_events_path(args[0])
439
440
442 """Check the argument for decay_events command
443 syntax: decay_events [NAME]
444 Note that other option are already remove at this point
445 """
446
447
448 if self.mode == 'madevent':
449 possible_path = [
450 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe.gz'),
451 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe')]
452 else:
453 possible_path = [
454 pjoin(self.me_dir,'Events', run_name, 'events.lhe.gz'),
455 pjoin(self.me_dir,'Events', run_name, 'events.lhe')]
456
457 for path in possible_path:
458 if os.path.exists(path):
459 correct_path = path
460 break
461 else:
462 raise self.InvalidCmd('No events file corresponding to %s run. ' % run_name)
463 return correct_path
464
471
472
473
474
475 -class CommonRunCmd(HelpToCmd, CheckValidForCmd, cmd.Cmd):
476
477 debug_output = 'ME5_debug'
478 helporder = ['Main Commands', 'Documented commands', 'Require MG5 directory',
479 'Advanced commands']
480
481
482
483 options_configuration = {'pythia8_path': './pythia8',
484 'hwpp_path': './herwigPP',
485 'thepeg_path': './thepeg',
486 'hepmc_path': './hepmc',
487 'madanalysis_path': './MadAnalysis',
488 'pythia-pgs_path':'./pythia-pgs',
489 'td_path':'./td',
490 'delphes_path':'./Delphes',
491 'exrootanalysis_path':'./ExRootAnalysis',
492 'syscalc_path': './SysCalc',
493 'lhapdf': 'lhapdf-config',
494 'timeout': 60,
495 'web_browser':None,
496 'eps_viewer':None,
497 'text_editor':None,
498 'fortran_compiler':None,
499 'cpp_compiler': None,
500 'auto_update':7,
501 'cluster_type': 'condor',
502 'cluster_status_update': (600, 30),
503 'cluster_nb_retry':1,
504 'cluster_local_path': "/cvmfs/cp3.uclouvain.be/madgraph/",
505 'cluster_retry_wait':300}
506
507 options_madgraph= {'stdout_level':None}
508
509 options_madevent = {'automatic_html_opening':True,
510 'run_mode':2,
511 'cluster_queue':'madgraph',
512 'cluster_time':None,
513 'cluster_size':100,
514 'cluster_memory':None,
515 'nb_core': None,
516 'cluster_temp_path':None}
517
518
519 - def __init__(self, me_dir, options, *args, **opts):
520 """common"""
521
522 cmd.Cmd.__init__(self, *args, **opts)
523
524 if me_dir is None and MADEVENT:
525 me_dir = root_path
526
527 self.me_dir = me_dir
528 self.options = options
529
530
531 self.status = pjoin(self.me_dir, 'status')
532 self.error = pjoin(self.me_dir, 'error')
533 self.dirbin = pjoin(self.me_dir, 'bin', 'internal')
534
535
536 if os.path.exists(pjoin(me_dir,'RunWeb')):
537 message = '''Another instance of the program is currently running.
538 (for this exact same directory) Please wait that this is instance is
539 closed. If no instance is running, you can delete the file
540 %s and try again.''' % pjoin(me_dir,'RunWeb')
541 raise AlreadyRunning, message
542 else:
543 pid = os.getpid()
544 fsock = open(pjoin(me_dir,'RunWeb'),'w')
545 fsock.write(`pid`)
546 fsock.close()
547
548 misc.Popen([os.path.relpath(pjoin(self.dirbin, 'gen_cardhtml-pl'), me_dir)],
549 cwd=me_dir)
550
551 self.to_store = []
552 self.run_name = None
553 self.run_tag = None
554 self.banner = None
555
556 self.set_configuration()
557 self.configure_run_mode(self.options['run_mode'])
558
559
560 self.get_characteristics()
561
562 if not self.proc_characteristics['ninitial']:
563
564 nexternal = open(pjoin(self.me_dir,'Source','nexternal.inc')).read()
565 found = re.search("PARAMETER\s*\(NINCOMING=(\d)\)", nexternal)
566 self.ninitial = int(found.group(1))
567 else:
568 self.ninitial = self.proc_characteristics['ninitial']
569
570
571
605
606
608 """Advanced commands: create .inc files from param_card.dat/run_card.dat"""
609
610 keepwidth = False
611 if '--keepwidth' in line:
612 keepwidth = True
613 line = line.replace('--keepwidth', '')
614 args = self.split_arg(line)
615 mode, opt = self.check_treatcards(args)
616
617 if mode in ['run', 'all']:
618 if not hasattr(self, 'run_card'):
619 if amcatnlo:
620 run_card = banner_mod.RunCardNLO(opt['run_card'])
621 else:
622 run_card = banner_mod.RunCard(opt['run_card'])
623 else:
624 run_card = self.run_card
625
626 run_card.write_include_file(pjoin(opt['output_dir'],'run_card.inc'))
627
628 if mode in ['MadLoop', 'all']:
629 if os.path.exists(pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat')):
630 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir,
631 'Cards', 'MadLoopParams.dat'))
632
633 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses",
634 "MadLoopParams.dat"))
635
636 if mode in ['param', 'all']:
637 if os.path.exists(pjoin(self.me_dir, 'Source', 'MODEL', 'mp_coupl.inc')):
638 param_card = check_param_card.ParamCardMP(opt['param_card'])
639 else:
640 param_card = check_param_card.ParamCard(opt['param_card'])
641 outfile = pjoin(opt['output_dir'], 'param_card.inc')
642 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat')
643 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')):
644 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')
645 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')):
646 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
647 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')):
648 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w')
649 fsock.write(' ')
650 fsock.close()
651 return
652 else:
653 subprocess.call(['python', 'write_param_card.py'],
654 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'))
655 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
656
657
658 if amcatnlo and not keepwidth:
659
660 pids = self.get_pid_final_states()
661
662 if not MADEVENT and pjoin(self.me_dir,'bin','internal') not in sys.path:
663 sys.path.insert(0,pjoin(self.me_dir,'bin','internal'))
664
665
666
667 to_del = [name for name in sys.modules.keys()
668 if name.startswith('internal.ufomodel')
669 or name.startswith('ufomodel')]
670 for name in to_del:
671 del(sys.modules[name])
672
673 import ufomodel as ufomodel
674 zero = ufomodel.parameters.ZERO
675 no_width = [p for p in ufomodel.all_particles
676 if (str(p.pdg_code) in pids or str(-p.pdg_code) in pids)
677 and p.color != 1 and p.width != zero]
678 done = []
679 for part in no_width:
680 if abs(part.pdg_code) in done:
681 continue
682 done.append(abs(part.pdg_code))
683 param = param_card['decay'].get((part.pdg_code,))
684
685 if param.value != 0:
686 logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.'''
687 % part.name,'$MG:color:BLACK')
688 param.value = 0
689
690 param_card.write_inc_file(outfile, ident_card, default)
691
692
694 """ """
695 if not self.options['madanalysis_path']:
696 plot = False
697
698 self.ask_edit_card_static(cards, mode, plot, self.options['timeout'],
699 self.ask)
700
701 @staticmethod
704 if not ask:
705 ask = CommonRunCmd.ask
706
707 def path2name(path):
708 if '_card' in path:
709 return path.split('_card')[0]
710 elif path == 'delphes_trigger.dat':
711 return 'trigger'
712 elif path == 'input.lhco':
713 return 'lhco'
714 elif path == 'MadLoopParams.dat':
715 return 'MadLoopParams'
716 else:
717 raise Exception, 'Unknow cards name %s' % path
718
719
720
721 question = """Do you want to edit a card (press enter to bypass editing)?\n"""
722 possible_answer = ['0', 'done']
723 card = {0:'done'}
724
725 for i, card_name in enumerate(cards):
726 imode = path2name(card_name)
727 possible_answer.append(i+1)
728 possible_answer.append(imode)
729 question += ' %s / %-10s : %s\n' % (i+1, imode, card_name)
730 card[i+1] = imode
731 if plot:
732 question += ' 9 / %-10s : plot_card.dat\n' % 'plot'
733 possible_answer.append(9)
734 possible_answer.append('plot')
735 card[9] = 'plot'
736
737 if 'param_card.dat' in cards:
738
739 question += ' you can also\n'
740 question += ' - enter the path to a valid card or banner.\n'
741 question += ' - use the \'set\' command to modify a parameter directly.\n'
742 question += ' The set option works only for param_card and run_card.\n'
743 question += ' Type \'help set\' for more information on this command.\n'
744 question += ' - call an external program (ASperGE/MadWidth/...).\n'
745 question += ' Type \'help\' for the list of available command\n'
746 else:
747 question += ' you can also\n'
748 question += ' - enter the path to a valid card.\n'
749 if 'transfer_card.dat' in cards:
750 question += ' - use the \'change_tf\' command to set a transfer functions.\n'
751
752 out = 'to_run'
753 while out not in ['0', 'done']:
754 out = ask(question, '0', possible_answer, timeout=int(1.5*timeout),
755 path_msg='enter path', ask_class = AskforEditCard,
756 cards=cards, mode=mode, **opt)
757
758
759 @staticmethod
761 """detect the type of the card. Return value are
762 banner
763 param_card.dat
764 run_card.dat
765 pythia_card.dat
766 plot_card.dat
767 pgs_card.dat
768 delphes_card.dat
769 delphes_trigger.dat
770 shower_card.dat [aMCatNLO]
771 FO_analyse_card.dat [aMCatNLO]
772 madspin_card.dat [MS]
773 transfer_card.dat [MW]
774 madweight_card.dat [MW]
775 """
776
777 text = open(path).read(50000)
778 if text == '':
779 logger.warning('File %s is empty' % path)
780 return 'unknown'
781 text = re.findall('(<MGVersion>|ParticlePropagator|<mg5proccard>|CEN_max_tracker|#TRIGGER CARD|parameter set name|muon eta coverage|QES_over_ref|MSTP|b_stable|FO_ANALYSIS_FORMAT|MSTU|Begin Minpts|gridpack|ebeam1|block\s+mw_run|BLOCK|DECAY|launch|madspin|transfer_card\.dat|set)', text, re.I)
782 text = [t.lower() for t in text]
783 if '<mgversion>' in text or '<mg5proccard>' in text:
784 return 'banner'
785 elif 'particlepropagator' in text:
786 return 'delphes_card.dat'
787 elif 'cen_max_tracker' in text:
788 return 'delphes_card.dat'
789 elif '#trigger card' in text:
790 return 'delphes_trigger.dat'
791 elif 'parameter set name' in text:
792 return 'pgs_card.dat'
793 elif 'muon eta coverage' in text:
794 return 'pgs_card.dat'
795 elif 'mstp' in text and not 'b_stable' in text:
796 return 'pythia_card.dat'
797 elif 'begin minpts' in text:
798 return 'plot_card.dat'
799 elif ('gridpack' in text and 'ebeam1' in text) or \
800 ('qes_over_ref' in text and 'ebeam1' in text):
801 return 'run_card.dat'
802 elif any(t.endswith('mw_run') for t in text):
803 return 'madweight_card.dat'
804 elif 'transfer_card.dat' in text:
805 return 'transfer_card.dat'
806 elif 'block' in text and 'decay' in text:
807 return 'param_card.dat'
808 elif 'b_stable' in text:
809 return 'shower_card.dat'
810 elif 'fo_analysis_format' in text:
811 return 'FO_analyse_card.dat'
812 elif 'decay' in text and 'launch' in text and 'madspin' in text:
813 return 'madspin_card.dat'
814 elif 'launch' in text and 'set' in text:
815 return 'reweight_card.dat'
816 elif 'decay' in text and 'launch' in text:
817 return 'madspin_card.dat'
818 else:
819 return 'unknown'
820
821
822
824 """create automatically a tag"""
825
826 used_tags = [r['tag'] for r in self.results[self.run_name]]
827 i=0
828 while 1:
829 i+=1
830 if 'tag_%s' %i not in used_tags:
831 return 'tag_%s' % i
832
833
834
835 - def create_plot(self, mode='parton', event_path=None, output=None, tag=None):
836 """create the plot"""
837
838 madir = self.options['madanalysis_path']
839 if not tag:
840 tag = self.run_card['run_tag']
841 td = self.options['td_path']
842
843 if not madir or not td or \
844 not os.path.exists(pjoin(self.me_dir, 'Cards', 'plot_card.dat')):
845 return False
846
847 if 'ickkw' in self.run_card and int(self.run_card['ickkw']) and \
848 mode == 'Pythia':
849 self.update_status('Create matching plots for Pythia', level='pythia')
850
851 if not os.path.exists(pjoin(self.me_dir,'Events','events.tree')):
852 misc.gunzip(pjoin(self.me_dir,'Events',
853 self.run_name, '%s_pythia_events.tree.gz' % tag), keep=True,
854 stdout=pjoin(self.me_dir,'Events','events.tree'))
855 files.mv(pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'),
856 pjoin(self.me_dir,'Events','xsecs.tree'))
857
858
859 misc.call([self.dirbin+'/create_matching_plots.sh',
860 self.run_name, tag, madir],
861 stdout = os.open(os.devnull, os.O_RDWR),
862 cwd=pjoin(self.me_dir,'Events'))
863
864
865 misc.gzip(pjoin(self.me_dir,"Events","events.tree"),
866 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_events.tree.gz'))
867 files.mv(pjoin(self.me_dir,'Events','xsecs.tree'),
868 pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'))
869
870
871 if not event_path:
872 if mode == 'parton':
873 possibilities=[
874 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
875 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe.gz'),
876 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe'),
877 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')]
878 for event_path in possibilities:
879 if os.path.exists(event_path):
880 break
881 output = pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
882
883 elif mode == 'Pythia':
884 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe')
885 output = pjoin(self.me_dir, 'HTML',self.run_name,
886 'plots_pythia_%s.html' % tag)
887 elif mode == 'PGS':
888 event_path = pjoin(self.me_dir, 'Events', self.run_name,
889 '%s_pgs_events.lhco' % tag)
890 output = pjoin(self.me_dir, 'HTML',self.run_name,
891 'plots_pgs_%s.html' % tag)
892 elif mode == 'Delphes':
893 event_path = pjoin(self.me_dir, 'Events', self.run_name,'%s_delphes_events.lhco' % tag)
894 output = pjoin(self.me_dir, 'HTML',self.run_name,
895 'plots_delphes_%s.html' % tag)
896 elif mode == "shower":
897 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe')
898 output = pjoin(self.me_dir, 'HTML',self.run_name,
899 'plots_shower_%s.html' % tag)
900 if not self.options['pythia-pgs_path']:
901 return
902 else:
903 raise self.InvalidCmd, 'Invalid mode %s' % mode
904 elif mode == 'reweight' and not output:
905 output = pjoin(self.me_dir, 'HTML',self.run_name,
906 'plots_%s.html' % tag)
907
908 if not os.path.exists(event_path):
909 if os.path.exists(event_path+'.gz'):
910 misc.gunzip('%s.gz' % event_path)
911 else:
912 raise self.InvalidCmd, 'Events file %s does not exist' % event_path
913 elif event_path.endswith(".gz"):
914 misc.gunzip(event_path)
915 event_path = event_path[:-3]
916
917
918 self.update_status('Creating Plots for %s level' % mode, level = mode.lower())
919
920 mode = mode.lower()
921 if mode not in ['parton', 'reweight']:
922 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s_%s' % (mode.lower(),tag))
923 elif mode == 'parton':
924 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_parton')
925 else:
926 plot_dir =pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s' % (tag))
927
928 if not os.path.isdir(plot_dir):
929 os.makedirs(plot_dir)
930
931 files.ln(pjoin(self.me_dir, 'Cards','plot_card.dat'), plot_dir, 'ma_card.dat')
932
933 try:
934 proc = misc.Popen([os.path.join(madir, 'plot_events')],
935 stdout = open(pjoin(plot_dir, 'plot.log'),'w'),
936 stderr = subprocess.STDOUT,
937 stdin=subprocess.PIPE,
938 cwd=plot_dir)
939 proc.communicate('%s\n' % event_path)
940 del proc
941
942 misc.call(['%s/plot' % self.dirbin, madir, td],
943 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
944 stderr = subprocess.STDOUT,
945 cwd=plot_dir)
946
947 misc.call(['%s/plot_page-pl' % self.dirbin,
948 os.path.basename(plot_dir),
949 mode],
950 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
951 stderr = subprocess.STDOUT,
952 cwd=pjoin(self.me_dir, 'HTML', self.run_name))
953
954 shutil.move(pjoin(self.me_dir, 'HTML',self.run_name ,'plots.html'),
955 output)
956
957 logger.info("Plots for %s level generated, see %s" % \
958 (mode, output))
959 except OSError, error:
960 logger.error('fail to create plot: %s. Please check that MadAnalysis is correctly installed.' % error)
961
962 self.update_status('End Plots for %s level' % mode, level = mode.lower(),
963 makehtml=False)
964
965 return True
966
968 """Run hep2lhe on the file Events/pythia_events.hep"""
969
970 if not self.options['pythia-pgs_path']:
971 raise self.InvalidCmd, 'No pythia-pgs path defined'
972
973 pydir = pjoin(self.options['pythia-pgs_path'], 'src')
974 eradir = self.options['exrootanalysis_path']
975
976
977 if misc.is_executable(pjoin(pydir, 'hep2lhe')):
978 self.update_status('Creating shower LHE File (for plot)', level='pythia')
979
980 out = open(pjoin(self.me_dir,'Events','pythia_events.lhe'), 'w')
981
982 out.writelines('<!--\n')
983 out.writelines('# Warning! Never use this file for detector studies!\n')
984 out.writelines('-->\n<!--\n')
985 if banner_path:
986 out.writelines(open(banner_path).read().replace('<LesHouchesEvents version="1.0">',''))
987 out.writelines('\n-->\n')
988 out.close()
989
990 self.cluster.launch_and_wait(self.dirbin+'/run_hep2lhe',
991 argument= [pydir],
992 cwd=pjoin(self.me_dir,'Events'),
993 stdout=os.devnull)
994
995 logger.info('Warning! Never use this lhe file for detector studies!')
996
997 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHEFConverter')):
998 self.update_status('Creating Pythia LHE Root File', level='pythia')
999 try:
1000 misc.call([eradir+'/ExRootLHEFConverter',
1001 'pythia_events.lhe',
1002 pjoin(self.run_name, '%s_pythia_lhe_events.root' % self.run_tag)],
1003 cwd=pjoin(self.me_dir,'Events'))
1004 except Exception, error:
1005 misc.sprint('ExRootLHEFConverter fails', str(error),
1006 log=logger)
1007 pass
1008
1010 """Dummy routine, to be overwritten by daughter classes"""
1011
1012 pass
1013
1014
1016 """launch pgs"""
1017
1018 args = self.split_arg(line)
1019
1020 if '--no_default' in args:
1021 no_default = True
1022 args.remove('--no_default')
1023 else:
1024 no_default = False
1025
1026
1027
1028
1029
1030
1031 lock = self.check_pgs(args)
1032
1033
1034 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
1035 if no_default:
1036 logger.info('No pgs_card detected, so not run pgs')
1037 return
1038
1039 files.cp(pjoin(self.me_dir, 'Cards', 'pgs_card_default.dat'),
1040 pjoin(self.me_dir, 'Cards', 'pgs_card.dat'))
1041 logger.info('No pgs card found. Take the default one.')
1042
1043 if not (no_default or self.force):
1044 self.ask_edit_cards(['pgs_card.dat'])
1045
1046 self.update_status('prepare PGS run', level=None)
1047
1048 pgsdir = pjoin(self.options['pythia-pgs_path'], 'src')
1049 eradir = self.options['exrootanalysis_path']
1050 madir = self.options['madanalysis_path']
1051 td = self.options['td_path']
1052
1053
1054 if not misc.is_executable(pjoin(pgsdir, 'pgs')):
1055 logger.info('No PGS executable -- running make')
1056 misc.compile(cwd=pgsdir)
1057
1058 self.update_status('Running PGS', level='pgs')
1059
1060 tag = self.run_tag
1061
1062 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, self.run_tag))
1063 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
1064 self.banner.add(pjoin(self.me_dir, 'Cards','pgs_card.dat'))
1065 self.banner.write(banner_path)
1066 else:
1067 open(banner_path, 'w').close()
1068
1069
1070
1071
1072 if lock:
1073 lock.wait()
1074
1075 ff = open(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 'w')
1076 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
1077 text = open(banner_path).read()
1078 text = '#%s' % text.replace('\n','\n#')
1079 dico = self.results[self.run_name].get_current_info()
1080 text +='\n## Integrated weight (pb) : %.4g' % dico['cross']
1081 text +='\n## Number of Event : %s\n' % dico['nb_event']
1082 ff.writelines(text)
1083 ff.close()
1084
1085 try:
1086 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done'))
1087 except Exception:
1088 pass
1089
1090 pgs_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_pgs.log" % tag)
1091 self.cluster.launch_and_wait('../bin/internal/run_pgs',
1092 argument=[pgsdir], cwd=pjoin(self.me_dir,'Events'),
1093 stdout=pgs_log, stderr=subprocess.STDOUT)
1094
1095 if not os.path.exists(pjoin(self.me_dir, 'Events', 'pgs.done')):
1096 logger.error('Fail to create LHCO events')
1097 return
1098 else:
1099 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done'))
1100
1101 if os.path.getsize(banner_path) == os.path.getsize(pjoin(self.me_dir, 'Events','pgs_events.lhco')):
1102 misc.call(['cat pgs_uncleaned_events.lhco >> pgs_events.lhco'],
1103 cwd=pjoin(self.me_dir, 'Events'))
1104 os.remove(pjoin(self.me_dir, 'Events', 'pgs_uncleaned_events.lhco '))
1105
1106
1107 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHCOlympicsConverter')):
1108 self.update_status('Creating PGS Root File', level='pgs')
1109 try:
1110 misc.call([eradir+'/ExRootLHCOlympicsConverter',
1111 'pgs_events.lhco',pjoin('%s/%s_pgs_events.root' % (self.run_name, tag))],
1112 cwd=pjoin(self.me_dir, 'Events'))
1113 except Exception:
1114 logger.warning('fail to produce Root output [problem with ExRootAnalysis')
1115 if os.path.exists(pjoin(self.me_dir, 'Events', 'pgs_events.lhco')):
1116
1117 files.mv(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'),
1118 pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag))
1119 self.create_plot('PGS')
1120 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag))
1121
1122 self.update_status('finish', level='pgs', makehtml=False)
1123
1124
1126 """Require MG5 directory: Compute automatically the widths of a set
1127 of particles"""
1128
1129
1130
1131 args = self.split_arg(line)
1132 opts = self.check_compute_widths(args)
1133
1134 from madgraph.interface.master_interface import MasterCmd
1135 cmd = MasterCmd()
1136 self.define_child_cmd_interface(cmd, interface=False)
1137 cmd.exec_cmd('set automatic_html_opening False --no_save')
1138 if not opts['path']:
1139 opts['path'] = pjoin(self.me_dir, 'Cards', 'param_card.dat')
1140 if not opts['force'] :
1141 self.ask_edit_cards(['param_card'],[], plot=False)
1142
1143
1144 line = 'compute_widths %s %s' % \
1145 (' '.join([str(i) for i in opts['particles']]),
1146 ' '.join('--%s=%s' % (key,value) for (key,value) in opts.items()
1147 if key not in ['model', 'force', 'particles'] and value))
1148 cmd.exec_cmd(line, model=opts['model'])
1149 self.child = None
1150 del cmd
1151
1152
1154 """Not in help:Print the cross-section/ number of events for a given run"""
1155
1156 args = self.split_arg(line)
1157 options={'path':None, 'mode':'w', 'format':'full'}
1158 for arg in list(args):
1159 if arg.startswith('--') and '=' in arg:
1160 name,value=arg.split('=',1)
1161 name = name [2:]
1162 options[name] = value
1163 args.remove(arg)
1164
1165
1166 if len(args) > 0:
1167 run_name = args[0]
1168 else:
1169 for i, run_name in enumerate(self.results.order):
1170 for j, one_result in enumerate(self.results[run_name]):
1171 if i or j:
1172 options['mode'] = "a"
1173 if options['path']:
1174 self.print_results_in_file(one_result, options['path'], options['mode'], options['format'])
1175 else:
1176 self.print_results_in_shell(one_result)
1177 return
1178
1179 if run_name not in self.results:
1180 raise self.InvalidCmd('%s is not a valid run_name or it doesn\'t have any information' \
1181 % run_name)
1182
1183
1184 if len(args) == 2:
1185 tag = args[1]
1186 if tag.isdigit():
1187 tag = int(tag) - 1
1188 if len(self.results[run_name]) < tag:
1189 raise self.InvalidCmd('Only %s different tag available' % \
1190 len(self.results[run_name]))
1191 data = self.results[run_name][tag]
1192 else:
1193 data = self.results[run_name].return_tag(tag)
1194 else:
1195 data = self.results[run_name].return_tag(None)
1196
1197 if options['path']:
1198 self.print_results_in_file(data, options['path'], options['mode'], options['format'])
1199 else:
1200 self.print_results_in_shell(data)
1201
1202
1203
1205 """ run delphes and make associate root file/plot """
1206
1207 args = self.split_arg(line)
1208
1209 if '--no_default' in args:
1210 no_default = True
1211 args.remove('--no_default')
1212 else:
1213 no_default = False
1214
1215
1216
1217
1218
1219 lock = self.check_delphes(args)
1220 self.update_status('prepare delphes run', level=None)
1221
1222
1223 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
1224 delphes3 = False
1225 prog = '../bin/internal/run_delphes'
1226 else:
1227 delphes3 = True
1228 prog = '../bin/internal/run_delphes3'
1229
1230
1231
1232 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
1233 if no_default:
1234 logger.info('No delphes_card detected, so not run Delphes')
1235 return
1236
1237 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_card_default.dat'),
1238 pjoin(self.me_dir, 'Cards', 'delphes_card.dat'))
1239 logger.info('No delphes card found. Take the default one.')
1240 if not delphes3 and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')):
1241 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_trigger_default.dat'),
1242 pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat'))
1243 if not (no_default or self.force):
1244 if delphes3:
1245 self.ask_edit_cards(['delphes_card.dat'], args)
1246 else:
1247 self.ask_edit_cards(['delphes_card.dat', 'delphes_trigger.dat'], args)
1248
1249 self.update_status('Running Delphes', level=None)
1250
1251 if lock:
1252 lock.wait()
1253
1254
1255
1256 delphes_dir = self.options['delphes_path']
1257 tag = self.run_tag
1258 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
1259 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_card.dat'))
1260 if not delphes3:
1261 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_trigger.dat'))
1262 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)))
1263
1264 cross = self.results[self.run_name].get_current_info()['cross']
1265
1266 delphes_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_delphes.log" % tag)
1267 self.cluster.launch_and_wait(prog,
1268 argument= [delphes_dir, self.run_name, tag, str(cross)],
1269 stdout=delphes_log, stderr=subprocess.STDOUT,
1270 cwd=pjoin(self.me_dir,'Events'))
1271
1272 if not os.path.exists(pjoin(self.me_dir, 'Events',
1273 self.run_name, '%s_delphes_events.lhco' % tag)):
1274 logger.error('Fail to create LHCO events from DELPHES')
1275 return
1276
1277 if os.path.exists(pjoin(self.me_dir,'Events','delphes.root')):
1278 source = pjoin(self.me_dir,'Events','delphes.root')
1279 target = pjoin(self.me_dir,'Events', self.run_name, "%s_delphes_events.root" % tag)
1280 files.mv(source, target)
1281
1282
1283 madir = self.options['madanalysis_path']
1284 td = self.options['td_path']
1285
1286
1287 self.create_plot('Delphes')
1288
1289 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)):
1290 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag))
1291
1292
1293
1294 self.update_status('delphes done', level='delphes', makehtml=False)
1295
1296
1298 """Find the pid of all particles in the final states"""
1299 pids = set()
1300 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
1301 'subproc.mg'))]
1302 nb_init = self.ninitial
1303 pat = re.compile(r'''DATA \(IDUP\(I,\d+\),I=1,\d+\)/([\+\-\d,\s]*)/''', re.I)
1304 for Pdir in subproc:
1305 text = open(pjoin(self.me_dir, 'SubProcesses', Pdir, 'born_leshouche.inc')).read()
1306 group = pat.findall(text)
1307 for particles in group:
1308 particles = particles.split(',')
1309 pids.update(set(particles[nb_init:]))
1310
1311 return pids
1312
1313
1336
1337
1338 if hasattr(self, 'pdffile') and self.pdffile:
1339 return self.pdffile
1340 else:
1341 for line in open(pjoin(self.me_dir,'Source','PDF','pdf_list.txt')):
1342 data = line.split()
1343 if len(data) < 4:
1344 continue
1345 if data[1].lower() == self.run_card['pdlabel'].lower():
1346 self.pdffile = check_cluster(pjoin(self.me_dir, 'lib', 'Pdfdata', data[2]))
1347 return self.pdffile
1348 else:
1349
1350 path = pjoin(self.me_dir, 'lib', 'PDFsets')
1351 if os.path.exists(path):
1352 self.pdffile = path
1353 else:
1354 self.pdffile = " "
1355 return self.pdffile
1356
1358 """Not in help: exit """
1359
1360
1361 try:
1362 os.remove(pjoin(self.me_dir,'RunWeb'))
1363 except Exception, error:
1364 pass
1365
1366 try:
1367 self.store_result()
1368 except Exception:
1369
1370 pass
1371
1372 try:
1373 self.update_status('', level=None)
1374 except Exception, error:
1375 pass
1376 try:
1377 devnull = open(os.devnull, 'w')
1378 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir,
1379 stdout=devnull, stderr=devnull)
1380 except Exception:
1381 pass
1382 try:
1383 devnull.close()
1384 except Exception:
1385 pass
1386
1387 return super(CommonRunCmd, self).do_quit(line)
1388
1389
1390
1391 do_EOF = do_quit
1392 do_exit = do_quit
1393
1394
1404
1405
1406 - def do_set(self, line, log=True):
1407 """Set an option, which will be default for coming generations/outputs
1408 """
1409
1410
1411
1412 args = self.split_arg(line)
1413
1414 self.check_set(args)
1415
1416 if args[0] in self.options_configuration and '--no_save' not in args:
1417 self.do_save('options --auto')
1418
1419 if args[0] == "stdout_level":
1420 if args[1].isdigit():
1421 logging.root.setLevel(int(args[1]))
1422 logging.getLogger('madgraph').setLevel(int(args[1]))
1423 else:
1424 logging.root.setLevel(eval('logging.' + args[1]))
1425 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1]))
1426 if log: logger.info('set output information to level: %s' % args[1])
1427 elif args[0] == "fortran_compiler":
1428 if args[1] == 'None':
1429 args[1] = None
1430 self.options['fortran_compiler'] = args[1]
1431 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'fortran')
1432 if current != args[1] and args[1] != None:
1433 misc.mod_compilator(self.me_dir, args[1], current, 'gfortran')
1434 elif args[0] == "cpp_compiler":
1435 if args[1] == 'None':
1436 args[1] = None
1437 self.options['cpp_compiler'] = args[1]
1438 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'cpp')
1439 if current != args[1] and args[1] != None:
1440 misc.mod_compilator(self.me_dir, args[1], current, 'cpp')
1441 elif args[0] == "run_mode":
1442 if not args[1] in [0,1,2,'0','1','2']:
1443 raise self.InvalidCmd, 'run_mode should be 0, 1 or 2.'
1444 self.cluster_mode = int(args[1])
1445 self.options['run_mode'] = self.cluster_mode
1446 elif args[0] in ['cluster_type', 'cluster_queue', 'cluster_temp_path']:
1447 if args[1] == 'None':
1448 args[1] = None
1449 self.options[args[0]] = args[1]
1450
1451
1452 elif args[0] in ['cluster_nb_retry', 'cluster_retry_wait', 'cluster_size']:
1453 self.options[args[0]] = int(args[1])
1454
1455 elif args[0] == 'nb_core':
1456 if args[1] == 'None':
1457 import multiprocessing
1458 self.nb_core = multiprocessing.cpu_count()
1459 self.options['nb_core'] = self.nb_core
1460 return
1461 if not args[1].isdigit():
1462 raise self.InvalidCmd('nb_core should be a positive number')
1463 self.nb_core = int(args[1])
1464 self.options['nb_core'] = self.nb_core
1465 elif args[0] == 'timeout':
1466 self.options[args[0]] = int(args[1])
1467 elif args[0] == 'cluster_status_update':
1468 if '(' in args[1]:
1469 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
1470 data = data.replace('(','').replace(')','').replace(',',' ').split()
1471 first, second = data[:2]
1472 else:
1473 first, second = args[1:3]
1474
1475 self.options[args[0]] = (int(first), int(second))
1476 elif args[0] in self.options:
1477 if args[1] in ['None','True','False']:
1478 self.options[args[0]] = eval(args[1])
1479 elif args[0].endswith('path'):
1480 if os.path.exists(args[1]):
1481 self.options[args[0]] = args[1]
1482 elif os.path.exists(pjoin(self.me_dir, args[1])):
1483 self.options[args[0]] = pjoin(self.me_dir, args[1])
1484 else:
1485 raise self.InvalidCmd('Not a valid path: keep previous value: \'%s\'' % self.options[args[0]])
1486 else:
1487 self.options[args[0]] = args[1]
1488
1489 - def post_set(self, stop, line):
1490 """Check if we need to save this in the option file"""
1491 try:
1492 args = self.split_arg(line)
1493 if 'cluster' in args[0] or args[0] == 'run_mode':
1494 self.configure_run_mode(self.options['run_mode'])
1495
1496
1497
1498 self.check_set(args)
1499
1500 if args[0] in self.options_configuration and '--no_save' not in args:
1501 self.exec_cmd('save options --auto')
1502 elif args[0] in self.options_madevent:
1503 logger.info('This option will be the default in any output that you are going to create in this session.')
1504 logger.info('In order to keep this changes permanent please run \'save options\'')
1505 return stop
1506 except self.InvalidCmd:
1507 return stop
1508
1535
1536
1538 """Check that all the width are define in the param_card.
1539 If some width are set on 'Auto', call the computation tools."""
1540
1541 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
1542 text = open(path).read()
1543 pdg_info = pattern.findall(text)
1544 if pdg_info:
1545 if run:
1546 logger.info('Computing the width set on auto in the param_card.dat')
1547 has_nlo = any(nlo.lower()=="@nlo" for _,nlo in pdg_info)
1548 pdg = [pdg for pdg,nlo in pdg_info]
1549 if not has_nlo:
1550 self.do_compute_widths('%s %s' % (' '.join(pdg), path))
1551 else:
1552 self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path))
1553 else:
1554 logger.info('''Some width are on Auto in the card.
1555 Those will be computed as soon as you have finish the edition of the cards.
1556 If you want to force the computation right now and being able to re-edit
1557 the cards afterwards, you can type \"compute_wdiths\".''')
1558
1559
1561 """If a ME run is currently running add a link in the html output"""
1562
1563
1564
1565 if hasattr(self, 'results') and hasattr(self.results, 'current') and\
1566 self.results.current and 'run_name' in self.results.current and \
1567 hasattr(self, 'me_dir'):
1568 name = self.results.current['run_name']
1569 tag = self.results.current['tag']
1570 self.debug_output = pjoin(self.me_dir, '%s_%s_debug.log' % (name,tag))
1571 if errortype:
1572 self.results.current.debug = errortype
1573 else:
1574 self.results.current.debug = self.debug_output
1575
1576 else:
1577
1578 self.debug_output = CommonRunCmd.debug_output
1579 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output:
1580 os.remove('ME5_debug')
1581 if not 'ME5_debug' in self.debug_output:
1582 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
1583
1584
1586 """Not in help: exit """
1587
1588 try:
1589 os.remove(pjoin(self.me_dir,'RunWeb'))
1590 except Exception:
1591 pass
1592 try:
1593 self.store_result()
1594 except Exception:
1595
1596 pass
1597
1598 try:
1599 self.update_status('', level=None)
1600 except Exception, error:
1601 pass
1602 devnull = open(os.devnull, 'w')
1603 try:
1604 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir,
1605 stdout=devnull, stderr=devnull)
1606 except Exception:
1607 pass
1608 devnull.close()
1609
1610 return super(CommonRunCmd, self).do_quit(line)
1611
1612
1613 do_EOF = do_quit
1614 do_exit = do_quit
1615
1616
1617 - def update_status(self, status, level, makehtml=True, force=True,
1618 error=False, starttime = None, update_results=True,
1619 print_log=True):
1620 """ update the index status """
1621
1622 if makehtml and not force:
1623 if hasattr(self, 'next_update') and time.time() < self.next_update:
1624 return
1625 else:
1626 self.next_update = time.time() + 3
1627
1628 if print_log:
1629 if isinstance(status, str):
1630 if '<br>' not in status:
1631 logger.info(status)
1632 elif starttime:
1633 running_time = misc.format_timer(time.time()-starttime)
1634 logger.info(' Idle: %s, Running: %s, Completed: %s [ %s ]' % \
1635 (status[0], status[1], status[2], running_time))
1636 else:
1637 logger.info(' Idle: %s, Running: %s, Completed: %s' % status[:3])
1638
1639 if update_results:
1640 self.results.update(status, level, makehtml=makehtml, error=error)
1641
1642
1643
1645 """Ask the question when launching generate_events/multi_run"""
1646
1647 check_card = ['pythia_card.dat', 'pgs_card.dat','delphes_card.dat',
1648 'delphes_trigger.dat', 'madspin_card.dat', 'shower_card.dat',
1649 'reweight_card.dat']
1650
1651 cards_path = pjoin(self.me_dir,'Cards')
1652 for card in check_card:
1653 if card in ignore:
1654 continue
1655 if card not in need_card:
1656 if os.path.exists(pjoin(cards_path, card)):
1657 os.remove(pjoin(cards_path, card))
1658 else:
1659 if not os.path.exists(pjoin(cards_path, card)):
1660 default = card.replace('.dat', '_default.dat')
1661 files.cp(pjoin(cards_path, default),pjoin(cards_path, card))
1662
1663
1664 - def set_configuration(self, config_path=None, final=True, initdir=None, amcatnlo=False):
1665 """ assign all configuration variable from file
1666 ./Cards/mg5_configuration.txt. assign to default if not define """
1667
1668 if not hasattr(self, 'options') or not self.options:
1669 self.options = dict(self.options_configuration)
1670 self.options.update(self.options_madgraph)
1671 self.options.update(self.options_madevent)
1672
1673 if not config_path:
1674 if os.environ.has_key('MADGRAPH_BASE'):
1675 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
1676 self.set_configuration(config_path=config_path, final=final)
1677 return
1678 if 'HOME' in os.environ:
1679 config_path = pjoin(os.environ['HOME'],'.mg5',
1680 'mg5_configuration.txt')
1681 if os.path.exists(config_path):
1682 self.set_configuration(config_path=config_path, final=False)
1683 if amcatnlo:
1684 me5_config = pjoin(self.me_dir, 'Cards', 'amcatnlo_configuration.txt')
1685 else:
1686 me5_config = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1687 self.set_configuration(config_path=me5_config, final=False, initdir=self.me_dir)
1688
1689 if self.options.has_key('mg5_path') and self.options['mg5_path']:
1690 MG5DIR = self.options['mg5_path']
1691 config_file = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
1692 self.set_configuration(config_path=config_file, final=False,initdir=MG5DIR)
1693 else:
1694 self.options['mg5_path'] = None
1695 return self.set_configuration(config_path=me5_config, final=final,initdir=self.me_dir)
1696
1697 config_file = open(config_path)
1698
1699
1700 logger.info('load configuration from %s ' % config_file.name)
1701 for line in config_file:
1702
1703 if '#' in line:
1704 line = line.split('#',1)[0]
1705 line = line.replace('\n','').replace('\r\n','')
1706 try:
1707 name, value = line.split('=')
1708 except ValueError:
1709 pass
1710 else:
1711 name = name.strip()
1712 value = value.strip()
1713 if name.endswith('_path') and not name.startswith('cluster'):
1714 path = value
1715 if os.path.isdir(path):
1716 self.options[name] = os.path.realpath(path)
1717 continue
1718 if not initdir:
1719 continue
1720 path = pjoin(initdir, value)
1721 if os.path.isdir(path):
1722 self.options[name] = os.path.realpath(path)
1723 continue
1724 else:
1725 self.options[name] = value
1726 if value.lower() == "none":
1727 self.options[name] = None
1728
1729 if not final:
1730 return self.options
1731
1732
1733
1734 for key in self.options:
1735
1736 if key.endswith('path') and not key.startswith("cluster"):
1737 path = self.options[key]
1738 if path is None:
1739 continue
1740 if os.path.isdir(path):
1741 self.options[key] = os.path.realpath(path)
1742 continue
1743 path = pjoin(self.me_dir, self.options[key])
1744 if os.path.isdir(path):
1745 self.options[key] = os.path.realpath(path)
1746 continue
1747 elif self.options.has_key('mg5_path') and self.options['mg5_path']:
1748 path = pjoin(self.options['mg5_path'], self.options[key])
1749 if os.path.isdir(path):
1750 self.options[key] = os.path.realpath(path)
1751 continue
1752 self.options[key] = None
1753 elif key.startswith('cluster') and key != 'cluster_status_update':
1754 if key in ('cluster_nb_retry','cluster_wait_retry'):
1755 self.options[key] = int(self.options[key])
1756 if hasattr(self,'cluster'):
1757 del self.cluster
1758 pass
1759 elif key == 'automatic_html_opening':
1760 if self.options[key] in ['False', 'True']:
1761 self.options[key] =eval(self.options[key])
1762 elif key not in ['text_editor','eps_viewer','web_browser','stdout_level',
1763 'complex_mass_scheme', 'gauge', 'group_subprocesses']:
1764
1765 try:
1766 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
1767 except self.InvalidCmd:
1768 logger.warning("Option %s from config file not understood" \
1769 % key)
1770
1771
1772 misc.open_file.configure(self.options)
1773 self.configure_run_mode(self.options['run_mode'])
1774 return self.options
1775
1776 @staticmethod
1778 """ find a valid run_name for the current job """
1779
1780 name = 'run_%02d'
1781 data = [int(s[4:j]) for s in os.listdir(pjoin(me_dir,'Events')) for
1782 j in range(4,len(s)+1) if \
1783 s.startswith('run_') and s[4:j].isdigit()]
1784 return name % (max(data+[0])+1)
1785
1786
1787
1789 """Require MG5 directory: decay events with spin correlations
1790 """
1791
1792 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'madspin_card.dat')):
1793 return
1794
1795
1796
1797
1798 if MADEVENT and not self.options['mg5_path']:
1799 raise self.InvalidCmd, '''The module decay_events requires that MG5 is installed on the system.
1800 You can install it and set its path in ./Cards/me5_configuration.txt'''
1801 elif MADEVENT:
1802 sys.path.append(self.options['mg5_path'])
1803 try:
1804 import MadSpin.decay as decay
1805 import MadSpin.interface_madspin as interface_madspin
1806 except ImportError:
1807 if __debug__:
1808 raise
1809 else:
1810 raise self.ConfigurationError, '''Can\'t load MadSpin
1811 The variable mg5_path might not be correctly configured.'''
1812
1813 self.update_status('Running MadSpin', level='madspin')
1814 if not '-from_cards' in line:
1815 self.keep_cards(['madspin_card.dat'])
1816 self.ask_edit_cards(['madspin_card.dat'], 'fixed', plot=False)
1817 self.help_decay_events(skip_syntax=True)
1818
1819
1820 args = self.split_arg(line)
1821 self.check_decay_events(args)
1822
1823 madspin_cmd = interface_madspin.MadSpinInterface(args[0])
1824 madspin_cmd.update_status = lambda *x,**opt: self.update_status(*x, level='madspin',**opt)
1825
1826 path = pjoin(self.me_dir, 'Cards', 'madspin_card.dat')
1827
1828 madspin_cmd.import_command_file(path)
1829
1830
1831 i = 1
1832 while os.path.exists(pjoin(self.me_dir,'Events', '%s_decayed_%i' % (self.run_name,i))):
1833 i+=1
1834 new_run = '%s_decayed_%i' % (self.run_name,i)
1835 evt_dir = pjoin(self.me_dir, 'Events')
1836
1837 os.mkdir(pjoin(evt_dir, new_run))
1838 current_file = args[0].replace('.lhe', '_decayed.lhe')
1839 new_file = pjoin(evt_dir, new_run, os.path.basename(args[0]))
1840 if not os.path.exists(current_file):
1841 if os.path.exists(current_file+'.gz'):
1842 current_file += '.gz'
1843 new_file += '.gz'
1844 else:
1845 logger.error('MadSpin fails to create any decayed file.')
1846 return
1847
1848 files.mv(current_file, new_file)
1849 logger.info("The decayed event file has been moved to the following location: ")
1850 logger.info(new_file)
1851
1852 if hasattr(self, 'results'):
1853 current = self.results.current
1854 nb_event = self.results.current['nb_event']
1855 if not nb_event:
1856 current = self.results[self.run_name][0]
1857 nb_event = current['nb_event']
1858
1859 cross = current['cross']
1860 error = current['error']
1861 self.results.add_run( new_run, self.run_card)
1862 self.results.add_detail('nb_event', nb_event)
1863 self.results.add_detail('cross', cross * madspin_cmd.branching_ratio)
1864 self.results.add_detail('error', error * madspin_cmd.branching_ratio + cross * madspin_cmd.err_branching_ratio)
1865 self.results.add_detail('run_mode', current['run_mode'])
1866
1867 self.run_name = new_run
1868 self.banner = madspin_cmd.banner
1869 self.banner.add(path)
1870 self.banner.write(pjoin(self.me_dir,'Events',self.run_name, '%s_%s_banner.txt' %
1871 (self.run_name, self.run_tag)))
1872 self.update_status('MadSpin Done', level='parton', makehtml=False)
1873 if 'unweighted' in os.path.basename(args[0]):
1874 self.create_plot('parton')
1875
1877 args = self.split_arg(line[0:begidx], error=False)
1878 if len(args) == 1:
1879 return self.complete_plot(text, line, begidx, endidx)
1880 else:
1881 return
1882
1884 "Complete the print results command"
1885 args = self.split_arg(line[0:begidx], error=False)
1886 if len(args) == 1:
1887
1888 data = glob.glob(pjoin(self.me_dir, 'Events', '*','unweighted_events.lhe.gz'))
1889 data = [n.rsplit('/',2)[1] for n in data]
1890 tmp1 = self.list_completion(text, data)
1891 return tmp1
1892 else:
1893 data = glob.glob(pjoin(self.me_dir, 'Events', args[0], '*_pythia_events.hep.gz'))
1894 data = [os.path.basename(p).rsplit('_',1)[0] for p in data]
1895 data += ["--mode=a", "--mode=w", "--path=", "--format=short"]
1896 tmp1 = self.list_completion(text, data)
1897 return tmp1
1898
1900 logger.info("syntax: print_result [RUN] [TAG] [options]")
1901 logger.info("-- show in text format the status of the run (cross-section/nb-event/...)")
1902 logger.info("--path= defines the path of the output file.")
1903 logger.info("--mode=a allow to add the information at the end of the file.")
1904 logger.info("--format=short (only if --path is define)")
1905 logger.info(" allows to have a multi-column output easy to parse")
1906
1907
1933
1934
1936 args = self.split_arg(line[0:begidx], error=False)
1937
1938 if len(args) == 1 and os.path.sep not in text:
1939
1940 data = glob.glob(pjoin(self.me_dir, 'Events', '*','*events.lhe*'))
1941 data = [n.rsplit('/',2)[1] for n in data]
1942 return self.list_completion(text, data, line)
1943 else:
1944 return self.path_completion(text,
1945 os.path.join('.',*[a for a in args \
1946 if a.endswith(os.path.sep)]))
1947
1949 "Complete the compute_widths command"
1950
1951 args = self.split_arg(line[0:begidx])
1952
1953 if args[-1] in ['--path=', '--output=']:
1954 completion = {'path': self.path_completion(text)}
1955 elif line[begidx-1] == os.path.sep:
1956 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)])
1957 if current_dir.startswith('--path='):
1958 current_dir = current_dir[7:]
1959 if current_dir.startswith('--output='):
1960 current_dir = current_dir[9:]
1961 completion = {'path': self.path_completion(text, current_dir)}
1962 else:
1963 completion = {}
1964 completion['options'] = self.list_completion(text,
1965 ['--path=', '--output=', '--min_br=0.\$', '--nlo',
1966 '--precision_channel=0.\$', '--body_decay='])
1967
1968 return self.deal_multiple_categories(completion)
1969
1970
1971
1973 """links lhapdf into libdir"""
1974
1975 lhapdf_version = self.get_lhapdf_version()
1976 logger.info('Using LHAPDF v%s interface for PDFs' % lhapdf_version)
1977 lhalibdir = subprocess.Popen([self.options['lhapdf'], '--libdir'],
1978 stdout = subprocess.PIPE).stdout.read().strip()
1979
1980 if lhapdf_version.startswith('5.'):
1981 pdfsetsdir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'],
1982 stdout = subprocess.PIPE).stdout.read().strip()
1983 else:
1984 pdfsetsdir = subprocess.Popen([self.options['lhapdf'], '--datadir'],
1985 stdout = subprocess.PIPE).stdout.read().strip()
1986
1987 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsetsdir)
1988
1989 lhalib = 'libLHAPDF.a'
1990
1991 if os.path.exists(pjoin(libdir, lhalib)):
1992 files.rm(pjoin(libdir, lhalib))
1993 files.ln(pjoin(lhalibdir, lhalib), libdir)
1994
1995 if not os.path.isdir(pjoin(libdir, 'PDFsets')):
1996 os.mkdir(pjoin(libdir, 'PDFsets'))
1997 os.environ['lhapdf'] = 'True'
1998 os.environ['lhapdf_config'] = self.options['lhapdf']
1999
2000
2002 """reads the proc_characteristics file and initialises the correspondant
2003 dictionary"""
2004
2005 if not path:
2006 path = os.path.join(self.me_dir, 'SubProcesses', 'proc_characteristics')
2007
2008 self.proc_characteristics = banner_mod.ProcCharacteristic(path)
2009 return self.proc_characteristics
2010
2011
2013 """copy (if needed) the lhapdf set corresponding to the lhaid in lhaid_list
2014 into lib/PDFsets"""
2015
2016 pdfsetname = ''
2017 for lhaid in lhaid_list:
2018 try:
2019 if not pdfsetname:
2020 if lhaid in self.lhapdf_pdfsets:
2021 pdfsetname = self.lhapdf_pdfsets[lhaid]['filename']
2022 else:
2023 raise MadGraph5Error('lhaid %s not valid input number for the current lhapdf' % lhaid )
2024
2025 elif not \
2026 self.lhapdf_pdfsets[lhaid]['filename'] == pdfsetname:
2027 raise MadGraph5Error(\
2028 'lhaid and PDF_set_min/max in the run_card do not correspond to the' + \
2029 'same PDF set. Please check the run_card.')
2030 except KeyError:
2031 if self.lhapdf_version.startswith('5'):
2032 raise MadGraph5Error(\
2033 ('invalid lhaid set in th run_card: %d .\nPlease note that some sets' % lhaid) + \
2034 '(eg MSTW 90%CL error sets) \nare not available in aMC@NLO + LHAPDF 5.x.x')
2035 else:
2036 logger.debug('%d not found in pdfsets.index' % lhaid)
2037
2038
2039
2040
2041
2042 if not os.path.isdir(pdfsets_dir):
2043 try:
2044 os.mkdir(pdfsets_dir)
2045 except OSError:
2046 pdfsets_dir = pjoin(self.me_dir, 'lib', 'PDFsets')
2047 else:
2048
2049 for name in os.listdir(pjoin(self.me_dir, 'lib', 'PDFsets')):
2050 if name != pdfsetname:
2051 try:
2052 if os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', name)):
2053 shutil.rmtree(pjoin(self.me_dir, 'lib', 'PDFsets', name))
2054 else:
2055 os.remove(pjoin(self.me_dir, 'lib', 'PDFsets', name))
2056 except Exception, error:
2057 logger.debug('%s', error)
2058
2059 if self.options["cluster_local_path"]:
2060 lhapdf_cluster_possibilities = [self.options["cluster_local_path"],
2061 pjoin(self.options["cluster_local_path"], "lhapdf"),
2062 pjoin(self.options["cluster_local_path"], "lhapdf", "pdfsets"),
2063 pjoin(self.options["cluster_local_path"], "..", "lhapdf"),
2064 pjoin(self.options["cluster_local_path"], "..", "lhapdf", "pdfsets"),
2065 pjoin(self.options["cluster_local_path"], "..", "lhapdf","pdfsets", "6.1")
2066 ]
2067 else:
2068 lhapdf_cluster_possibilities = []
2069
2070
2071 if self.options["cluster_local_path"] and self.options["run_mode"] == 1 and \
2072 any((os.path.exists(pjoin(d, pdfsetname)) for d in lhapdf_cluster_possibilities)):
2073
2074 os.environ["LHAPATH"] = [d for d in lhapdf_cluster_possibilities if os.path.exists(pjoin(d, pdfsetname))][0]
2075 os.environ["CLUSTER_LHAPATH"] = os.environ["LHAPATH"]
2076
2077 if os.path.exists(pjoin(pdfsets_dir, pdfsetname)):
2078 try:
2079 if os.path.isdir(pjoin(pdfsets_dir, name)):
2080 shutil.rmtree(pjoin(pdfsets_dir, name))
2081 else:
2082 os.remove(pjoin(pdfsets_dir, name))
2083 except Exception, error:
2084 logger.debug('%s', error)
2085
2086
2087 elif not os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets', pdfsetname)) and \
2088 not os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', pdfsetname)):
2089
2090 if pdfsetname and not os.path.exists(pjoin(pdfsets_dir, pdfsetname)):
2091 self.install_lhapdf_pdfset(pdfsets_dir, pdfsetname)
2092
2093 if os.path.exists(pjoin(pdfsets_dir, pdfsetname)):
2094 files.cp(pjoin(pdfsets_dir, pdfsetname), pjoin(self.me_dir, 'lib', 'PDFsets'))
2095 elif os.path.exists(pjoin(os.path.dirname(pdfsets_dir), pdfsetname)):
2096 files.cp(pjoin(os.path.dirname(pdfsets_dir), pdfsetname), pjoin(self.me_dir, 'lib', 'PDFsets'))
2097
2099 """idownloads and install the pdfset filename in the pdfsets_dir"""
2100 lhapdf_version = self.get_lhapdf_version()
2101 logger.info('Trying to download %s' % filename)
2102
2103 if lhapdf_version.startswith('5.'):
2104
2105
2106 getdata = self.options['lhapdf'].replace('lhapdf-config', ('lhapdf-getdata'))
2107 misc.call([getdata, filename], cwd = pdfsets_dir)
2108
2109 elif lhapdf_version.startswith('6.'):
2110
2111
2112 getdata = self.options['lhapdf'].replace('lhapdf-config', ('lhapdf'))
2113
2114 misc.call([getdata, 'install', filename], cwd = pdfsets_dir)
2115
2116 else:
2117 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version)
2118
2119
2120 if os.path.exists(pjoin(pdfsets_dir, filename)) or \
2121 os.path.isdir(pjoin(pdfsets_dir, filename)):
2122 logger.info('%s successfully downloaded and stored in %s' \
2123 % (filename, pdfsets_dir))
2124
2125 elif lhapdf_version.startswith('5.'):
2126 logger.warning('Could not download %s into %s. Trying to save it locally' \
2127 % (filename, pdfsets_dir))
2128 self.install_lhapdf_pdfset(pjoin(self.me_dir, 'lib', 'PDFsets'), filename)
2129 else:
2130 raise MadGraph5Error, \
2131 'Could not download %s into %s. Please try to install it manually.' \
2132 % (filename, pdfsets_dir)
2133
2134
2136 """read the PDFsets.index file, which should be located in the same
2137 place as pdfsets_dir, and return a list of dictionaries with the information
2138 about each pdf set"""
2139 lhapdf_version = self.get_lhapdf_version()
2140
2141 if lhapdf_version.startswith('5.'):
2142 if os.path.exists('%s.index' % pdfsets_dir):
2143 indexfile = '%s.index' % pdfsets_dir
2144 else:
2145 raise MadGraph5Error, 'index of lhapdf file not found'
2146 pdfsets_lines = \
2147 [l for l in open(indexfile).read().split('\n') if l.strip() and \
2148 not '90cl' in l]
2149 lhapdf_pdfsets = dict( (int(l.split()[0]), {'lhaid': int(l.split()[0]),
2150 'pdflib_ntype': int(l.split()[1]),
2151 'pdflib_ngroup': int(l.split()[2]),
2152 'pdflib_nset': int(l.split()[3]),
2153 'filename': l.split()[4],
2154 'lhapdf_nmem': int(l.split()[5]),
2155 'q2min': float(l.split()[6]),
2156 'q2max': float(l.split()[7]),
2157 'xmin': float(l.split()[8]),
2158 'xmax': float(l.split()[9]),
2159 'description': l.split()[10]}) \
2160 for l in pdfsets_lines)
2161
2162 elif lhapdf_version.startswith('6.'):
2163 pdfsets_lines = \
2164 [l for l in open(pjoin(pdfsets_dir, 'pdfsets.index')).read().split('\n') if l.strip()]
2165 lhapdf_pdfsets = dict( (int(l.split()[0]),
2166 {'lhaid': int(l.split()[0]),
2167 'filename': l.split()[1]}) \
2168 for l in pdfsets_lines)
2169
2170 else:
2171 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version)
2172
2173 return lhapdf_pdfsets
2174
2175
2177 """returns the lhapdf version number"""
2178 if not hasattr(self, 'lhapdfversion'):
2179 self.lhapdf_version = \
2180 subprocess.Popen([self.options['lhapdf'], '--version'],
2181 stdout = subprocess.PIPE).stdout.read().strip()
2182
2183
2184 if self.lhapdf_version.startswith('6.0'):
2185 raise MadGraph5Error('LHAPDF 6.0.x not supported. Please use v6.1 or later')
2186
2187 return self.lhapdf_version
2188
2189
2191 lhapdf_version = self.get_lhapdf_version()
2192
2193
2194 if 'LHAPDF_DATA_PATH' in os.environ.keys() and os.environ['LHAPDF_DATA_PATH']:
2195 datadir = os.environ['LHAPDF_DATA_PATH']
2196
2197 elif lhapdf_version.startswith('5.'):
2198 datadir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'],
2199 stdout = subprocess.PIPE).stdout.read().strip()
2200
2201 elif lhapdf_version.startswith('6.'):
2202 datadir = subprocess.Popen([self.options['lhapdf'], '--datadir'],
2203 stdout = subprocess.PIPE).stdout.read().strip()
2204
2205 return datadir
2206
2208 """A class for asking a question where in addition you can have the
2209 set command define and modifying the param_card/run_card correctly"""
2210
2211 special_shortcut = {'ebeam':['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s'],
2212 'lpp': ['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ],
2213 'lhc': ['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2'],
2214 'lep': ['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2'],
2215 'ilc': ['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2'],
2216 'lcc':['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2'],
2217 'fixed_scale': ['run_card fixed_fac_scale T', 'run_card fixed_ren_scale T', 'run_card scale %(0)s', 'run_card dsqrt_q2fact1 %(0)s' ,'run_card dsqrt_q2fact2 %(0)s'],
2218 }
2219
2220 - def __init__(self, question, cards=[], mode='auto', *args, **opt):
2221
2222
2223 if 'pwd' in opt:
2224 self.me_dir = opt['pwd']
2225 del opt['pwd']
2226
2227 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt)
2228
2229 if not hasattr(self, 'me_dir') or not self.me_dir:
2230 self.me_dir = self.mother_interface.me_dir
2231
2232
2233
2234
2235 try:
2236 self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat'))
2237 except (check_param_card.InvalidParamCard, ValueError) as e:
2238 logger.error('Current param_card is not valid. We are going to use the default one.')
2239 logger.error('problem detected: %s' % e)
2240 files.cp(pjoin(self.me_dir,'Cards','param_card_default.dat'),
2241 pjoin(self.me_dir,'Cards','param_card.dat'))
2242 self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat'))
2243 default_param = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card_default.dat'))
2244
2245
2246 try:
2247 self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat'))
2248 except IOError:
2249 self.run_card = {}
2250 try:
2251 run_card_def = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card_default.dat'))
2252 except IOError:
2253 run_card_def = {}
2254
2255 self.pname2block = {}
2256 self.conflict = []
2257 self.restricted_value = {}
2258 self.mode = mode
2259 self.cards = cards
2260
2261
2262
2263
2264 for bname, block in default_param.items():
2265 for lha_id, param in block.param_dict.items():
2266 all_var = []
2267 comment = param.comment
2268
2269 if comment.strip().startswith('set of param :'):
2270 all_var = list(re.findall(r'''[^-]1\*(\w*)\b''', comment))
2271
2272 elif len(comment.split()) == 1:
2273 all_var = [comment.strip().lower()]
2274
2275 else:
2276 split = comment.split()
2277 if len(split) >2 and split[1] == ':':
2278
2279 self.restricted_value[(bname, lha_id)] = ' '.join(split[1:])
2280 elif len(split) == 2:
2281 if re.search(r'''\[[A-Z]\]eV\^''', split[1]):
2282 all_var = [comment.strip().lower()]
2283 elif len(split) >=2 and split[1].startswith('('):
2284 all_var = [split[0].strip().lower()]
2285 else:
2286 if not bname.startswith('qnumbers'):
2287 logger.debug("not recognize information for %s %s : %s",
2288 bname, lha_id, comment)
2289
2290 continue
2291
2292 for var in all_var:
2293 var = var.lower()
2294 if var in self.pname2block:
2295 self.pname2block[var].append((bname, lha_id))
2296 else:
2297 self.pname2block[var] = [(bname, lha_id)]
2298
2299 if run_card_def:
2300 self.run_set = run_card_def.keys() + self.run_card.hidden_param
2301 elif self.run_card:
2302 self.run_set = self.run_card.keys()
2303 else:
2304 self.run_set = []
2305
2306 for var in self.pname2block:
2307 if var in self.run_set:
2308 self.conflict.append(var)
2309
2310
2311
2312 self.has_mw = False
2313 if 'madweight_card.dat' in cards:
2314
2315 self.do_change_tf = self.mother_interface.do_define_transfer_fct
2316 self.complete_change_tf = self.mother_interface.complete_define_transfer_fct
2317 self.help_change_tf = self.mother_interface.help_define_transfer_fct
2318 if not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')):
2319 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
2320
2321
2322 self.has_mw = True
2323 try:
2324 import madgraph.madweight.Cards as mwcards
2325 except:
2326 import internal.madweight.Cards as mwcards
2327 self.mw_card = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
2328 self.mw_card = self.mw_card.info
2329 self.mw_vars = []
2330 for key in self.mw_card:
2331 if key == 'comment':
2332 continue
2333 for key2 in self.mw_card.info[key]:
2334 if isinstance(key2, str) and not key2.isdigit():
2335 self.mw_vars.append(key2)
2336
2337
2338 for var in self.pname2block:
2339 if var in self.mw_vars:
2340 self.conflict.append(var)
2341 for var in self.mw_vars:
2342 if var in self.run_card:
2343 self.conflict.append(var)
2344
2345
2346 self.has_ml = False
2347 if os.path.isfile(pjoin(self.me_dir,'Cards','MadLoopParams.dat')):
2348 self.has_ml = True
2349 self.MLcard = banner_mod.MadLoopParam(pjoin(self.me_dir,'Cards','MadLoopParams.dat'))
2350 self.MLcardDefault = banner_mod.MadLoopParam()
2351
2352 self.ml_vars = [k.lower() for k in self.MLcard.keys()]
2353
2354 for var in self.MLcard:
2355 if var in self.run_card:
2356 self.conflict.append(var)
2357 if var in self.pname2block:
2358 self.conflict.append(var)
2359 if self.has_mw and var in self.mw_vars:
2360 self.conflict.append(var)
2361
2362
2363 self.has_shower = False
2364 if 'shower_card.dat' in cards:
2365 self.has_shower = True
2366 try:
2367 import madgraph.various.shower_card as showercards
2368 except:
2369 import internal.shower_card as showercards
2370 self.shower_card = showercards.ShowerCard(pjoin(self.me_dir,'Cards','shower_card.dat'))
2371 self.shower_vars = self.shower_card.keys()
2372
2373
2374 for var in self.pname2block:
2375 if var in self.shower_vars:
2376 self.conflict.append(var)
2377 for var in self.shower_vars:
2378 if var in self.run_card:
2379 self.conflict.append(var)
2380
2381
2383 """ Complete the set command"""
2384
2385 prev_timer = signal.alarm(0)
2386 if prev_timer:
2387 nb_back = len(line)
2388 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2389 self.stdout.write(line)
2390 self.stdout.flush()
2391
2392 possibilities = {}
2393 allowed = {}
2394 args = self.split_arg(line[0:begidx])
2395 if args[-1] in ['Auto', 'default']:
2396 return
2397 if len(args) == 1:
2398 allowed = {'category':'', 'run_card':'', 'block':'all', 'param_card':'','shortcut':''}
2399 if self.has_mw:
2400 allowed['madweight_card'] = ''
2401 allowed['mw_block'] = 'all'
2402 if self.has_shower:
2403 allowed['shower_card'] = ''
2404 if self.has_ml:
2405 allowed['madloop_card'] = ''
2406 elif len(args) == 2:
2407 if args[1] == 'run_card':
2408 allowed = {'run_card':'default'}
2409 elif args[1] == 'param_card':
2410 allowed = {'block':'all', 'param_card':'default'}
2411 elif args[1] in self.param_card.keys():
2412 allowed = {'block':args[1]}
2413 elif args[1] == 'width':
2414 allowed = {'block': 'decay'}
2415 elif args[1] == 'MadWeight_card':
2416 allowed = {'madweight_card':'default', 'mw_block': 'all'}
2417 elif args[1] == 'MadLoop_card':
2418 allowed = {'madloop_card':'default'}
2419 elif self.has_mw and args[1] in self.mw_card.keys():
2420 allowed = {'mw_block':args[1]}
2421 elif args[1] == 'shower_card':
2422 allowed = {'shower_card':'default'}
2423 else:
2424 allowed = {'value':''}
2425 else:
2426 start = 1
2427 if args[1] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card', 'MadLoop_card']:
2428 start = 2
2429 if args[-1] in self.pname2block.keys():
2430 allowed['value'] = 'default'
2431 elif args[start] in self.param_card.keys() or args[start] == 'width':
2432 if args[start] == 'width':
2433 args[start] = 'decay'
2434
2435 if args[start+1:]:
2436 allowed = {'block':(args[start], args[start+1:])}
2437 else:
2438 allowed = {'block':args[start]}
2439 elif self.has_mw and args[start] in self.mw_card.keys():
2440 if args[start+1:]:
2441 allowed = {'mw_block':(args[start], args[start+1:])}
2442 else:
2443 allowed = {'mw_block':args[start]}
2444
2445
2446 else:
2447 allowed['value'] = ''
2448
2449 if 'category' in allowed.keys():
2450 categories = ['run_card', 'param_card']
2451 if self.has_mw:
2452 categories.append('MadWeight_card')
2453 if self.has_shower:
2454 categories.append('shower_card')
2455 if self.has_ml:
2456 categories.append('MadLoop_card')
2457
2458 possibilities['category of parameter (optional)'] = \
2459 self.list_completion(text, categories)
2460
2461 if 'shortcut' in allowed.keys():
2462 possibilities['special values'] = self.list_completion(text, self.special_shortcut.keys()+['qcut', 'showerkt'])
2463
2464 if 'run_card' in allowed.keys():
2465 opts = self.run_set
2466 if allowed['run_card'] == 'default':
2467 opts.append('default')
2468
2469 possibilities['Run Card'] = self.list_completion(text, opts)
2470
2471 if 'param_card' in allowed.keys():
2472 opts = self.pname2block.keys()
2473 if allowed['param_card'] == 'default':
2474 opts.append('default')
2475 possibilities['Param Card'] = self.list_completion(text, opts)
2476
2477 if 'madweight_card' in allowed.keys():
2478 opts = self.mw_vars + [k for k in self.mw_card.keys() if k !='comment']
2479 if allowed['madweight_card'] == 'default':
2480 opts.append('default')
2481 possibilities['MadWeight Card'] = self.list_completion(text, opts)
2482
2483 if 'madloop_card' in allowed.keys():
2484 opts = self.ml_vars
2485 if allowed['madloop_card'] == 'default':
2486 opts.append('default')
2487
2488 possibilities['MadLoop Parameter'] = self.list_completion(text, opts)
2489
2490 if 'shower_card' in allowed.keys():
2491 opts = self.shower_vars + [k for k in self.shower_card.keys() if k !='comment']
2492 if allowed['shower_card'] == 'default':
2493 opts.append('default')
2494 possibilities['Shower Card'] = self.list_completion(text, opts)
2495
2496 if 'value' in allowed.keys():
2497 opts = ['default']
2498 if 'decay' in args:
2499 opts.append('Auto')
2500 opts.append('Auto@NLO')
2501 elif args[-1] in self.pname2block and self.pname2block[args[-1]][0][0] == 'decay':
2502 opts.append('Auto')
2503 opts.append('Auto@NLO')
2504 possibilities['Special Value'] = self.list_completion(text, opts)
2505
2506 if 'block' in allowed.keys():
2507 if allowed['block'] == 'all':
2508 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i]
2509 allowed_block.append('width')
2510 possibilities['Param Card Block' ] = \
2511 self.list_completion(text, allowed_block)
2512 elif isinstance(allowed['block'], basestring):
2513 block = self.param_card[allowed['block']].param_dict
2514 ids = [str(i[0]) for i in block
2515 if (allowed['block'], i) not in self.restricted_value]
2516 possibilities['Param Card id' ] = self.list_completion(text, ids)
2517 varname = [name for name, all_var in self.pname2block.items()
2518 if any((bname == allowed['block']
2519 for bname,lhaid in all_var))]
2520 possibilities['Param card variable'] = self.list_completion(text,
2521 varname)
2522 else:
2523 block = self.param_card[allowed['block'][0]].param_dict
2524 nb = len(allowed['block'][1])
2525 ids = [str(i[nb]) for i in block if len(i) > nb and \
2526 [str(a) for a in i[:nb]] == allowed['block'][1]]
2527
2528 if not ids:
2529 if tuple([int(i) for i in allowed['block'][1]]) in block:
2530 opts = ['default']
2531 if allowed['block'][0] == 'decay':
2532 opts.append('Auto')
2533 opts.append('Auto@NLO')
2534 possibilities['Special value'] = self.list_completion(text, opts)
2535 possibilities['Param Card id' ] = self.list_completion(text, ids)
2536
2537 if 'mw_block' in allowed.keys():
2538 if allowed['mw_block'] == 'all':
2539 allowed_block = [i for i in self.mw_card.keys() if 'comment' not in i]
2540 possibilities['MadWeight Block' ] = \
2541 self.list_completion(text, allowed_block)
2542 elif isinstance(allowed['mw_block'], basestring):
2543 block = self.mw_card[allowed['mw_block']]
2544 ids = [str(i[0]) if isinstance(i, tuple) else str(i) for i in block]
2545 possibilities['MadWeight Card id' ] = self.list_completion(text, ids)
2546 else:
2547 block = self.mw_card[allowed['mw_block'][0]]
2548 nb = len(allowed['mw_block'][1])
2549 ids = [str(i[nb]) for i in block if isinstance(i, tuple) and\
2550 len(i) > nb and \
2551 [str(a) for a in i[:nb]] == allowed['mw_block'][1]]
2552
2553 if not ids:
2554 if tuple([i for i in allowed['mw_block'][1]]) in block or \
2555 allowed['mw_block'][1][0] in block.keys():
2556 opts = ['default']
2557 possibilities['Special value'] = self.list_completion(text, opts)
2558 possibilities['MadWeight Card id' ] = self.list_completion(text, ids)
2559
2560 return self.deal_multiple_categories(possibilities)
2561
2563 """ edit the value of one parameter in the card"""
2564
2565 args = self.split_arg(line)
2566 if '=' in args[-1]:
2567 arg1, arg2 = args.pop(-1).split('=')
2568 args += [arg1, arg2]
2569 args[:-1] = [ a.lower() for a in args[:-1]]
2570
2571 if args[0] in self.special_shortcut:
2572 if len(args) == 1:
2573 values = {}
2574 elif len(args) == 2:
2575 targettype = float
2576 if args[1].strip().isdigit():
2577 targettype = int
2578
2579 try:
2580 values = {'0': targettype(args[1])}
2581 except ValueError as e:
2582 logger.warning("Wrong argument: The last entry should be a number.")
2583 return
2584 else:
2585 logger.warning("too many argument for this command")
2586 return
2587
2588 for arg in self.special_shortcut[args[0]]:
2589 try:
2590 text = arg % values
2591 except KeyError:
2592 logger.warning("This command requires one argument")
2593 return
2594 except Exception as e:
2595 logger.warning(str(e))
2596 return
2597 else:
2598 self.do_set(arg % values)
2599 return
2600
2601
2602 start = 0
2603 if len(args) < 2:
2604 logger.warning('Invalid set command %s (need two arguments)' % line)
2605 return
2606
2607
2608 if args[0].lower() == 'qcut':
2609 pythia_path = pjoin(self.me_dir, 'Cards','pythia_card.dat')
2610 if os.path.exists(pythia_path):
2611 logger.info('add line QCUT = %s in pythia_card.dat' % args[1])
2612 p_card = open(pythia_path,'r').read()
2613 p_card, n = re.subn('''^\s*QCUT\s*=\s*[\de\+\-\.]*\s*$''',
2614 ''' QCUT = %s ''' % args[1], \
2615 p_card, flags=(re.M+re.I))
2616 if n==0:
2617 p_card = '%s \n QCUT= %s' % (p_card, args[1])
2618 open(pythia_path, 'w').write(p_card)
2619 return
2620
2621 if args[0].lower() == 'showerkt':
2622 pythia_path = pjoin(self.me_dir, 'Cards','pythia_card.dat')
2623 if os.path.exists(pythia_path):
2624 logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper())
2625 p_card = open(pythia_path,'r').read()
2626 p_card, n = re.subn('''^\s*SHOWERKT\s*=\s*[default\de\+\-\.]*\s*$''',
2627 ''' SHOWERKT = %s ''' % args[1].upper(), \
2628 p_card, flags=(re.M+re.I))
2629 if n==0:
2630 p_card = '%s \n SHOWERKT= %s' % (p_card, args[1].upper())
2631 open(pythia_path, 'w').write(p_card)
2632 return
2633
2634
2635 card = ''
2636 if args[0] == 'madweight_card':
2637 if not self.mw_card:
2638 logger.warning('Invalid Command: No MadWeight card defined.')
2639 return
2640 args[0] = 'MadWeight_card'
2641
2642 if args[0] == 'shower_card':
2643 if not self.shower_card:
2644 logger.warning('Invalid Command: No Shower card defined.')
2645 return
2646 args[0] = 'shower_card'
2647
2648 if args[0] == "madloop_card":
2649 if not self.has_ml:
2650 logger.warning('Invalid Command: No MadLoopParam card defined.')
2651 return
2652 args[0] = 'MadLoop_card'
2653
2654 if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card']:
2655 if args[1] == 'default':
2656 logging.info('replace %s by the default card' % args[0])
2657 files.cp(pjoin(self.me_dir,'Cards','%s_default.dat' % args[0]),
2658 pjoin(self.me_dir,'Cards','%s.dat'% args[0]))
2659 if args[0] == 'param_card':
2660 self.param_card = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card.dat'))
2661 elif args[0] == 'run_card':
2662 self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat'))
2663 elif args[0] == 'shower_card':
2664 self.shower_card = shower_card_mod.ShowerCard(pjoin(self.me_dir,'Cards','shower_card.dat'))
2665 return
2666 else:
2667 card = args[0]
2668 start=1
2669 if len(args) < 3:
2670 logger.warning('Invalid set command: %s (not enough arguments)' % line)
2671 return
2672
2673 elif args[0] in ['MadLoop_card']:
2674 if args[1] == 'default':
2675 logging.info('replace MadLoopParams.dat by the default card')
2676 self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault)
2677 self.MLcard.write(pjoin(self.me_dir,'Cards','MadLoopParams.dat'),
2678 commentdefault=True)
2679 return
2680 else:
2681 card = args[0]
2682 start=1
2683 if len(args) < 3:
2684 logger.warning('Invalid set command: %s (not enough arguments)' % line)
2685 return
2686 elif args[0] in ['madspin_card']:
2687 if args[1] == 'default':
2688 logging.info('replace madspin_card.dat by the default card')
2689 files.cp(pjoin(self.me_dir,'Cards/madspin_card_default.dat'),
2690 pjoin(self.me_dir,'Cards/madspin_card.dat'))
2691 return
2692 else:
2693 logger.warning("""Command set not allowed for modifying the madspin_card.
2694 Check the command \"decay\" instead.""")
2695 return
2696
2697
2698 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']:
2699 if args[start] not in self.run_set:
2700 args[start] = [l for l in self.run_set if l.lower() == args[start]][0]
2701
2702 if args[start] in self.conflict and card == '':
2703 text = 'Ambiguous name (present in more than one card). Will assume it to be referred to run_card.\n'
2704 text += 'If this is not intended, please reset it in the run_card and specify the relevant card to \n'
2705 text += 'edit, in the format < set card parameter value >'
2706 logger.warning(text)
2707
2708 if args[start+1] == 'default':
2709 default = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card_default.dat'))
2710 if args[start] in default.keys():
2711 self.setR(args[start],default[args[start]])
2712 else:
2713 logger.info('remove information %s from the run_card' % args[start])
2714 del self.run_card[args[start]]
2715 elif args[start+1].lower() in ['t','.true.','true']:
2716 self.setR(args[start], '.true.')
2717 elif args[start+1].lower() in ['f','.false.','false']:
2718 self.setR(args[start], '.false.')
2719 else:
2720 if args[0].startswith('sys_'):
2721 val = ' '.join(args[start+1:])
2722 val = val.split('#')[0]
2723 else:
2724 try:
2725 val = eval(args[start+1])
2726 except NameError:
2727 val = args[start+1]
2728 self.setR(args[start], val)
2729 self.run_card.write(pjoin(self.me_dir,'Cards','run_card.dat'),
2730 pjoin(self.me_dir,'Cards','run_card_default.dat'))
2731
2732
2733 elif (args[start] in self.param_card or args[start] == 'width') \
2734 and card in ['','param_card']:
2735 if args[start] in self.conflict and card == '':
2736 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
2737 text += ' in the format < set card parameter value>'
2738 logger.warning(text)
2739 return
2740
2741 if args[start] == 'width':
2742 args[start] = 'decay'
2743
2744 if args[start+1] in self.pname2block:
2745 all_var = self.pname2block[args[start+1]]
2746 key = None
2747 for bname, lhaid in all_var:
2748 if bname == args[start]:
2749 key = lhaid
2750 break
2751 else:
2752 logger.warning('%s is not part of block "%s" but "%s". please correct.' %
2753 (args[start+1], args[start], bname))
2754 return
2755 else:
2756 try:
2757 key = tuple([int(i) for i in args[start+1:-1]])
2758 except ValueError:
2759 if args[start] == 'decay' and args[start+1:-1] == ['all']:
2760 for key in self.param_card[args[start]].param_dict:
2761 if (args[start], key) in self.restricted_value:
2762 continue
2763 else:
2764 self.setP(args[start], key, args[-1])
2765 self.param_card.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2766 return
2767 logger.warning('invalid set command %s (failed to identify LHA information)' % line)
2768 return
2769
2770 if key in self.param_card[args[start]].param_dict:
2771 if (args[start], key) in self.restricted_value:
2772 text = "Note that this parameter seems to be ignore by MG.\n"
2773 text += "MG will use instead the expression: %s\n" % \
2774 self.restricted_value[(args[start], key)]
2775 text += "You need to match this expression for external program (such pythia)."
2776 logger.warning(text)
2777
2778 if args[-1].lower() in ['default', 'auto', 'auto@nlo']:
2779 self.setP(args[start], key, args[-1])
2780 else:
2781 try:
2782 value = float(args[-1])
2783 except Exception:
2784 logger.warning('Invalid input: Expected number and not \'%s\'' \
2785 % args[-1])
2786 return
2787 self.setP(args[start], key, value)
2788 else:
2789 logger.warning('invalid set command %s' % line)
2790 return
2791 self.param_card.write(pjoin(self.me_dir,'Cards','param_card.dat'))
2792
2793
2794 elif args[start] in self.pname2block and card != 'run_card':
2795 if args[start] in self.conflict and card == '':
2796 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
2797 text += ' in the format < set card parameter value>'
2798 logger.warning(text)
2799 return
2800
2801 all_var = self.pname2block[args[start]]
2802 for bname, lhaid in all_var:
2803 new_line = 'param_card %s %s %s' % (bname,
2804 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:]))
2805 self.do_set(new_line)
2806 if len(all_var) > 1:
2807 logger.warning('This variable correspond to more than one parameter in the param_card.')
2808 for bname, lhaid in all_var:
2809 logger.warning(' %s %s' % (bname, ' '.join([str(i) for i in lhaid])))
2810 logger.warning('all listed variables have been modified')
2811
2812
2813 elif self.has_mw and (args[start] in self.mw_card and args[start] != 'comment') \
2814 and card in ['','MadWeight_card']:
2815
2816 if args[start] in self.conflict and card == '':
2817 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
2818 text += ' in the format < set card parameter value>'
2819 logger.warning(text)
2820 return
2821
2822 block = args[start]
2823 name = args[start+1]
2824 value = args[start+2:]
2825 self.setM(block, name, value)
2826 self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
2827
2828
2829 elif self.has_mw and args[start] in self.mw_vars \
2830 and card in ['', 'MadWeight_card']:
2831
2832 if args[start] in self.conflict and card == '':
2833 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
2834 text += ' in the format < set card parameter value>'
2835 logger.warning(text)
2836 return
2837
2838 block = [b for b, data in self.mw_card.items() if args[start] in data]
2839 if len(block) > 1:
2840 logger.warning('%s is define in more than one block: %s.Please specify.'
2841 % (args[start], ','.join(block)))
2842 return
2843
2844 block = block[0]
2845 name = args[start]
2846 value = args[start+1:]
2847 self.setM(block, name, value)
2848 self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
2849
2850
2851 elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\
2852 and card == 'MadWeight_card':
2853 block = args[start]
2854 name = args[start+1]
2855 value = args[start+2]
2856 self.setM(block, name, value)
2857 self.mw_card.write(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
2858
2859
2860 elif self.has_shower and args[start] in [l.lower() for l in \
2861 self.shower_card.keys()] and card in ['', 'shower_card']:
2862 if args[start] not in self.shower_card:
2863 args[start] = [l for l in self.shower_card if l.lower() == args[start]][0]
2864
2865 if args[start] in self.conflict and card == '':
2866 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
2867 text += ' in the format < set card parameter value>'
2868 logger.warning(text)
2869 return
2870
2871 if args[start+1].lower() == 'default':
2872 default = shower_card_mod.ShowerCard(pjoin(self.me_dir,'Cards','shower_card_default.dat'))
2873 if args[start] in default.keys():
2874 self.shower_card.set_param(args[start],default[args[start]],pjoin(self.me_dir,'Cards','shower_card.dat'))
2875 else:
2876 logger.info('remove information %s from the shower_card' % args[start])
2877 del self.shower_card[args[start]]
2878 elif args[start+1].lower() in ['t','.true.','true']:
2879 self.shower_card.set_param(args[start],'.true.',pjoin(self.me_dir,'Cards','shower_card.dat'))
2880 elif args[start+1].lower() in ['f','.false.','false']:
2881 self.shower_card.set_param(args[start],'.false.',pjoin(self.me_dir,'Cards','shower_card.dat'))
2882 else:
2883 args_str = ' '.join(str(a) for a in args[start+1:len(args)])
2884 self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat'))
2885
2886
2887 elif self.has_ml and args[start] in self.ml_vars \
2888 and card in ['', 'MadLoop_card']:
2889
2890 if args[start] in self.conflict and card == '':
2891 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
2892 logger.warning(text)
2893 return
2894
2895 if args[start+1] == 'default':
2896 value = self.MLcardDefault[args[start]]
2897 default = True
2898 else:
2899 value = args[start+1]
2900 default = False
2901 self.setML(args[start], value, default=default)
2902 self.MLcard.write(pjoin(self.me_dir,'Cards','MadLoopParams.dat'),
2903 commentdefault=True)
2904
2905
2906 else:
2907 logger.warning('invalid set command %s ' % line)
2908 return
2909
2910 - def setM(self, block, name, value):
2911
2912 if isinstance(value, list) and len(value) == 1:
2913 value = value[0]
2914
2915 if block not in self.mw_card:
2916 logger.warning('block %s was not present in the current MadWeight card. We are adding it' % block)
2917 self.mw_card[block] = {}
2918 elif name not in self.mw_card[block]:
2919 logger.info('name %s was not present in the block %s for the current MadWeight card. We are adding it' % (name,block),'$MG:color:BLACK')
2920 if value == 'default':
2921 import madgraph.madweight.Cards as mwcards
2922 mw_default = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card_default.dat'))
2923 try:
2924 value = mw_default[block][name]
2925 except KeyError:
2926 logger.info('removing id "%s" from Block "%s" '% (name, block))
2927 if name in self.mw_card[block]:
2928 del self.mw_card[block][name]
2929 return
2930 if value:
2931 logger.info('modify madweight_card information BLOCK "%s" with id "%s" set to %s' %\
2932 (block, name, value), '$MG:color:BLACK')
2933 else:
2934 logger.value("Invalid command: No value. To set default value. Use \"default\" as value")
2935 return
2936
2937 self.mw_card[block][name] = value
2938
2939 - def setR(self, name, value):
2940 logger.info('modify parameter %s of the run_card.dat to %s' % (name, value))
2941 self.run_card.set(name, value, user=True)
2942
2943 - def setML(self, name, value, default=False):
2944
2945 try:
2946 self.MLcard.set(name, value, user=True)
2947 except Exception, error:
2948 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error)
2949 return
2950 logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value))
2951 if default and name.lower() in self.MLcard.user_set:
2952 self.MLcard.user_set.remove(name.lower())
2953
2954 - def setP(self, block, lhaid, value):
2955 if isinstance(value, str):
2956 value = value.lower()
2957 if value == 'default':
2958 default = check_param_card.ParamCard(pjoin(self.me_dir,'Cards','param_card_default.dat'))
2959 value = default[block].param_dict[lhaid].value
2960
2961 elif value in ['auto', 'auto@nlo']:
2962 if 'nlo' in value:
2963 value = 'Auto@NLO'
2964 else:
2965 value = 'Auto'
2966 if block != 'decay':
2967 logger.warning('Invalid input: \'Auto\' value only valid for DECAY')
2968 return
2969 else:
2970 try:
2971 value = float(value)
2972 except ValueError:
2973 logger.warning('Invalid input: \'%s\' not valid intput.'% value)
2974
2975 logger.info('modify param_card information BLOCK %s with id %s set to %s' %\
2976 (block, lhaid, value), '$MG:color:BLACK')
2977 self.param_card[block].param_dict[lhaid].value = value
2978
2979 - def reask(self, *args, **opt):
2980
2981 cmd.OneLinePathCompletion.reask(self,*args, **opt)
2982 if self.has_mw and not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')):
2983 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
2984
2985
3013
3014
3016 """Default action if line is not recognized"""
3017
3018 line = line.strip()
3019 args = line.split()
3020 if line == '' and self.default_value is not None:
3021 self.value = self.default_value
3022
3023 elif hasattr(self, 'do_%s' % args[0]):
3024 self.do_set(' '.join(args[1:]))
3025 elif os.path.exists(line):
3026 self.copy_file(line)
3027 self.value = 'repeat'
3028 elif os.path.exists(pjoin(self.me_dir, line)):
3029 self.copy_file(pjoin(self.me_dir,line))
3030 self.value = 'repeat'
3031 elif line.strip() != '0' and line.strip() != 'done' and \
3032 str(line) != 'EOF' and line.strip() in self.allow_arg:
3033 self.open_file(line)
3034 self.value = 'repeat'
3035 else:
3036 self.value = line
3037
3038 return line
3039
3041 """edit the madspin_card to define the decay of the associate particle"""
3042 signal.alarm(0)
3043 path = pjoin(self.me_dir,'Cards','madspin_card.dat')
3044
3045 if 'madspin_card.dat' not in self.cards or not os.path.exists(path):
3046 logger.warning("Command decay not valid. Since MadSpin is not available.")
3047 return
3048
3049 if ">" not in line:
3050 logger.warning("invalid command for decay. Line ignored")
3051 return
3052
3053 misc.sprint( line, "-add" in line)
3054 if "-add" in line:
3055
3056 particle = line.split('>')[0].strip()
3057 text = open(path).read()
3058 line = line.replace('--add', '').replace('-add','')
3059 logger.info("change madspin_card to add one decay to %s: %s" %(particle, line.strip()), '$MG:color:BLACK')
3060
3061 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1)
3062 open(path,'w').write(text)
3063 else:
3064
3065
3066 particle = line.split('>')[0].strip()
3067 logger.info("change madspin_card to define the decay of %s: %s" %(particle, line.strip()), '$MG:color:BLACK')
3068 particle = particle.replace('+','\+').replace('-','\-')
3069 decay_pattern = re.compile(r"^\s*decay\s+%s\s*>[\s\w+-~]*?$" % particle, re.I+re.M)
3070 text= open(path).read()
3071 text = decay_pattern.sub('', text)
3072 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1)
3073 open(path,'w').write(text)
3074
3075
3076
3078 signal.alarm(0)
3079 path = pjoin(self.me_dir,'Cards','param_card.dat')
3080 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
3081 text = open(path).read()
3082 pdg_info = pattern.findall(text)
3083 has_nlo = any("@nlo"==nlo.lower() for _, nlo in pdg_info)
3084 pdg = [p for p,_ in pdg_info]
3085
3086
3087 line = '%s %s' % (line, ' '.join(pdg))
3088 if not '--path' in line:
3089 line += ' --path=%s' % path
3090 if has_nlo:
3091 line += ' --nlo'
3092
3093 try:
3094 return self.mother_interface.do_compute_widths(line)
3095 except InvalidCmd, error:
3096 logger.error("Invalid command: %s " % error)
3097
3101
3103 """help for command decay which modifies MadSpin_card"""
3104
3105 signal.alarm(0)
3106 print '--syntax: decay PROC [--add]'
3107 print ' '
3108 print ' modify the madspin_card to modify the decay of the associate particle.'
3109 print ' and define it to PROC.'
3110 print ' if --add is present, just add a new decay for the associate particle.'
3111
3115
3116
3118 """Help associated to the asperge command"""
3119 signal.alarm(0)
3120
3121 print '-- syntax: asperge [options]'
3122 print ' Call ASperGe to diagonalize all mass matrices in the model.'
3123 print ' This works only if the ASperGE module is part of the UFO model (a subdirectory).'
3124 print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only'
3125 print ' diagonalize the associate mass matrices (here m1 and m2).'
3126
3128 signal.alarm(0)
3129
3130 blockname = self.pname2block.keys()
3131
3132 wrong = ['decay', 'mass', 'sminput']
3133 valid = [k for k in blockname if 'mix' in k]
3134 potential = [k for k in blockname if k not in valid+wrong]
3135 output = {'Mixing matrices': self.list_completion(text, valid, line),
3136 'Other potential valid input': self.list_completion(text, potential, line)}
3137
3138 return self.deal_multiple_categories(output)
3139
3140
3142 """Running ASperGe"""
3143 signal.alarm(0)
3144
3145 path = pjoin(self.me_dir,'bin','internal','ufomodel','ASperGE')
3146 if not os.path.exists(path):
3147 logger.error('ASperge has not been detected in the current model, therefore it will not be run.')
3148 return
3149 elif not os.path.exists(pjoin(path,'ASperGe')):
3150 logger.info('ASperGe has been detected but is not compiled. Running the compilation now.')
3151 try:
3152 misc.compile(cwd=path,shell=True)
3153 except MadGraph5Error, error:
3154 logger.error('''ASperGe failed to compile. Note that gsl is needed
3155 for this compilation to go trough. More information on how to install this package on
3156 http://www.gnu.org/software/gsl/
3157 Full compilation log is available at %s''' % pjoin(self.me_dir, 'ASperge_compilation.log'))
3158 open(pjoin(self.me_dir, 'ASperge_compilation.log'),'w').write(str(error))
3159 return
3160
3161 opts = line.split()
3162 card = pjoin(self.me_dir,'Cards', 'param_card.dat')
3163 logger.info('running ASperGE')
3164 returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts)
3165 if returncode:
3166 logger.error('ASperGE fails with status %s' % returncode)
3167 else:
3168 logger.info('AsPerGe creates the file succesfully')
3169 files.mv(card, '%s.beforeasperge' % card)
3170 files.mv('%s.new' % card, card)
3171
3172
3173
3175 """detect the type of the file and overwritte the current file"""
3176
3177 if path.endswith('.lhco'):
3178
3179
3180 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
3181 return
3182 elif path.endswith('.lhco.gz'):
3183
3184
3185 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
3186 return
3187 else:
3188 card_name = CommonRunCmd.detect_card_type(path)
3189
3190 if card_name == 'unknown':
3191 logger.warning('Fail to determine the type of the file. Not copied')
3192 if card_name != 'banner':
3193 logger.info('copy %s as %s' % (path, card_name))
3194 files.cp(path, pjoin(self.mother_interface.me_dir, 'Cards', card_name))
3195 elif card_name == 'banner':
3196 banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False)
3197 logger.info('Splitting the banner in it\'s component')
3198 if not self.mode == 'auto':
3199 self.mother_interface.keep_cards(self.cards)
3200
3202 """open the file"""
3203 me_dir = self.mother_interface.me_dir
3204 if answer.isdigit():
3205 if answer == '9':
3206 answer = 'plot'
3207 else:
3208 answer = self.cards[int(answer)-1]
3209 if 'madweight' in answer:
3210 answer = answer.replace('madweight', 'MadWeight')
3211
3212 if 'MadLoopParams' in answer:
3213 answer = pjoin(me_dir,'Cards','MadLoopParams.dat')
3214 if not '.dat' in answer and not '.lhco' in answer:
3215 if answer != 'trigger':
3216 path = pjoin(me_dir,'Cards','%s_card.dat' % answer)
3217 else:
3218 path = pjoin(me_dir,'Cards','delphes_trigger.dat')
3219 elif not '.lhco' in answer:
3220 path = pjoin(me_dir, 'Cards', answer)
3221 else:
3222 path = pjoin(me_dir, self.mw_card['mw_run']['inputfile'])
3223 if not os.path.exists(path):
3224 logger.info('Path in MW_card not existing')
3225 path = pjoin(me_dir, 'Events', answer)
3226
3227 path = path.replace('_card_card','_card')
3228 try:
3229 self.mother_interface.exec_cmd('open %s' % path)
3230 except InvalidCmd, error:
3231 if str(error) != 'No default path for this file':
3232 raise
3233 if answer == 'transfer_card.dat':
3234 logger.warning('You have to specify a transfer function first!')
3235 elif answer == 'input.lhco':
3236 path = pjoin(me_dir,'Events', 'input.lhco')
3237 ff = open(path,'w')
3238 ff.write('''No LHCO information imported at current time.
3239 To import a lhco file: Close this file and type the path of your file.
3240 You can also copy/paste, your event file here.''')
3241 ff.close()
3242 self.open_file(path)
3243 else:
3244 raise
3245
3246
3247 if path == pjoin(self.me_dir,'Cards','param_card.dat'):
3248 try:
3249 self.param_card = check_param_card.ParamCard(path)
3250 except (check_param_card.InvalidParamCard, ValueError) as e:
3251 logger.error('Current param_card is not valid. We are going to use the default one.')
3252 logger.error('problem detected: %s' % e)
3253 logger.error('Please re-open the file and fix the problem.')
3254 logger.warning('using the \'set\' command without opening the file will discard all your manual change')
3255 elif path == pjoin(self.me_dir,'Cards','run_card.dat'):
3256 self.run_card = banner_mod.RunCard(pjoin(self.me_dir,'Cards','run_card.dat'))
3257 elif path == pjoin(self.me_dir,'Cards','MadLoopParams.dat'):
3258 self.MLcard = banner_mod.MadLoopParam(pjoin(self.me_dir,'Cards','MadLoopParams.dat'))
3259 elif path == pjoin(self.me_dir,'Cards','MadWeight_card.dat'):
3260 try:
3261 import madgraph.madweight.Cards as mwcards
3262 except:
3263 import internal.madweight.Cards as mwcards
3264 self.mw_card = mwcards.Card(pjoin(self.me_dir,'Cards','MadWeight_card.dat'))
3265