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
21
22 import ast
23 import logging
24 import os
25 import re
26 import shutil
27 import signal
28 import stat
29 import subprocess
30 import sys
31 import time
32 import traceback
33 import glob
34 import StringIO
35
36 try:
37 import readline
38 GNU_SPLITTING = ('GNU' in readline.__doc__)
39 except:
40 GNU_SPLITTING = True
41
42 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
43 root_path = os.path.split(root_path)[0]
44 sys.path.insert(0, os.path.join(root_path,'bin'))
45
46
47 pjoin = os.path.join
48
49 logger = logging.getLogger('madgraph.stdout')
50 logger_stderr = logging.getLogger('madgraph.stderr')
51
52 try:
53 import madgraph
54 except ImportError:
55
56 import internal.extended_cmd as cmd
57 import internal.banner as banner_mod
58 import internal.shower_card as shower_card_mod
59 import internal.misc as misc
60 import internal.cluster as cluster
61 import internal.check_param_card as check_param_card
62 import internal.files as files
63
64 import internal.save_load_object as save_load_object
65 import internal.gen_crossxhtml as gen_crossxhtml
66 import internal.lhe_parser as lhe_parser
67 import internal.FO_analyse_card as FO_analyse_card
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 madgraph.various.lhe_parser as lhe_parser
79 import madgraph.various.FO_analyse_card as FO_analyse_card
80 import madgraph.iolibs.save_load_object as save_load_object
81 import madgraph.madevent.gen_crossxhtml as gen_crossxhtml
82 import models.check_param_card as check_param_card
83
84
85 from madgraph import InvalidCmd, MadGraph5Error, MG5DIR
86 MADEVENT=False
92 """ The Series of help routins in common between amcatnlo_run and
93 madevent interface"""
94
96 logger.info("syntax: treatcards [param|run] [--output_dir=] [--param_card=] [--run_card=]")
97 logger.info("-- create the .inc files containing the cards information." )
98
100 logger.info("syntax: set %s argument" % "|".join(self._set_options))
101 logger.info("-- set options")
102 logger.info(" stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL")
103 logger.info(" change the default level for printed information")
104 logger.info(" timeout VALUE")
105 logger.info(" (default 20) Seconds allowed to answer questions.")
106 logger.info(" Note that pressing tab always stops the timer.")
107 logger.info(" cluster_temp_path PATH")
108 logger.info(" (default None) Allow to perform the run in PATH directory")
109 logger.info(" This allow to not run on the central disk. This is not used")
110 logger.info(" by condor cluster (since condor has it's own way to prevent it).")
111
113 logger.info("syntax: help [RUN] [%s] [-f]" % '|'.join(self._plot_mode))
114 logger.info("-- create the plot for the RUN (current run by default)")
115 logger.info(" at the different stage of the event generation")
116 logger.info(" Note than more than one mode can be specified in the same command.")
117 logger.info(" This require to have MadAnalysis and td require. By default")
118 logger.info(" if those programs are installed correctly, the creation")
119 logger.info(" will be performed automaticaly during the event generation.")
120 logger.info(" -f options: answer all question by default.")
121
123 logger.info("syntax: compute_widths Particle [Particles] [OPTIONS]")
124 logger.info("-- Compute the widths for the particles specified.")
125 logger.info(" By default, this takes the current param_card and overwrites it.")
126 logger.info(" Precision allows to define when to include three/four/... body decays (LO).")
127 logger.info(" If this number is an integer then all N-body decay will be included.")
128 logger.info(" Various options:\n")
129 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
130 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
131 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
132 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
133 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
134 logger.info(" default: 4.0025")
135 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
136 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
137 logger.info(" --precision_channel=X: requested numerical precision for each channel")
138 logger.info(" default: 0.01")
139 logger.info(" --path=X: path for param_card")
140 logger.info(" default: take value from the model")
141 logger.info(" --output=X: path where to write the resulting card. ")
142 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
143 logger.info(" --nlo: Compute NLO width [if the model support it]")
144
146 logger.info("syntax: shower [shower_name] [shower_options]")
147 logger.info("-- This is equivalent to running '[shower_name] [shower_options]'")
148
150 logger.info("syntax: pgs [RUN] [--run_options]")
151 logger.info("-- run pgs on RUN (current one by default)")
152 self.run_options_help([('-f','answer all question by default'),
153 ('--tag=', 'define the tag for the pgs run'),
154 ('--no_default', 'not run if pgs_card not present')])
155
157 logger.info("syntax: delphes [RUN] [--run_options]")
158 logger.info("-- run delphes on RUN (current one by default)")
159 self.run_options_help([('-f','answer all question by default'),
160 ('--tag=', 'define the tag for the delphes run'),
161 ('--no_default', 'not run if delphes_card not present')])
162
164 if not skip_syntax:
165 logger.info("syntax: decay_events [RUN]")
166 logger.info("This functionality allows for the decay of resonances")
167 logger.info("in a .lhe file, keeping track of the spin correlation effets.")
168 logger.info("BE AWARE OF THE CURRENT LIMITATIONS:")
169 logger.info(" (1) Only a succession of 2 body decay are currently allowed")
170
174 """ The Series of check routines in common between amcatnlo_run and
175 madevent interface"""
176
178 """ check the validity of the line"""
179
180
181 if len(args) < 2:
182 if len(args)==1 and "=" in args[0]:
183 args[:] = args[0].split("=",1)
184 else:
185 self.help_set()
186 raise self.InvalidCmd('set needs an option and an argument')
187
188 if args[0] not in self._set_options + self.options.keys():
189 self.help_set()
190 raise self.InvalidCmd('Possible options for set are %s' % \
191 (self._set_options+self.options.keys()))
192
193 if args[0] in ['stdout_level']:
194 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \
195 and not args[1].isdigit():
196 raise self.InvalidCmd('output_level needs ' + \
197 'a valid level')
198
199 if args[0] in ['timeout']:
200 if not args[1].isdigit():
201 raise self.InvalidCmd('timeout values should be a integer')
202
204 """check that the model is loadable and check that the format is of the
205 type: PART PATH --output=PATH -f --precision=N
206 return the model.
207 """
208
209
210 if MADEVENT and not self.options['mg5_path']:
211 raise self.InvalidCmd, '''The automatic computations of widths requires that MG5 is installed on the system.
212 You can install it and set his path in ./Cards/me5_configuration.txt'''
213 elif MADEVENT:
214 sys.path.append(self.options['mg5_path'])
215 try:
216 import models.model_reader as model_reader
217 import models.import_ufo as import_ufo
218 except ImportError:
219 raise self.ConfigurationError, '''Can\'t load MG5.
220 The variable mg5_path should not be correctly configure.'''
221
222
223 ufo_path = pjoin(self.me_dir,'bin','internal', 'ufomodel')
224
225 if not MADEVENT:
226 modelname = self.find_model_name()
227
228
229
230
231 force_CMS = self.mother and self.mother.options['complex_mass_scheme']
232 model = import_ufo.import_model(modelname, decay=True,
233 restrict=True, complex_mass_scheme=force_CMS)
234 else:
235 force_CMS = self.proc_characteristics['complex_mass_scheme']
236 model = import_ufo.import_model(pjoin(self.me_dir,'bin','internal',
237 'ufomodel'), decay=True, complex_mass_scheme=force_CMS)
238
239
240
241
242
243 if '-modelname' not in open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')).read():
244 model.pass_particles_name_in_mg_default()
245 model = model_reader.ModelReader(model)
246 particles_name = dict([(p.get('name'), p.get('pdg_code'))
247 for p in model.get('particles')])
248 particles_name.update(dict([(p.get('antiname'), p.get('pdg_code'))
249 for p in model.get('particles')]))
250
251 output = {'model': model, 'force': False, 'output': None,
252 'path':None, 'particles': set(), 'body_decay':4.0025,
253 'min_br':None, 'precision_channel':0.01}
254 for arg in args:
255 if arg.startswith('--output='):
256 output_path = arg.split('=',1)[1]
257 if not os.path.exists(output_path):
258 raise self.InvalidCmd, 'Invalid Path for the output. Please retry.'
259 if not os.path.isfile(output_path):
260 output_path = pjoin(output_path, 'param_card.dat')
261 output['output'] = output_path
262 elif arg == '-f':
263 output['force'] = True
264 elif os.path.isfile(arg):
265 ftype = self.detect_card_type(arg)
266 if ftype != 'param_card.dat':
267 raise self.InvalidCmd , '%s is not a valid param_card.' % arg
268 output['path'] = arg
269 elif arg.startswith('--path='):
270 arg = arg.split('=',1)[1]
271 ftype = self.detect_card_type(arg)
272 if ftype != 'param_card.dat':
273 raise self.InvalidCmd , '%s is not a valid param_card.' % arg
274 output['path'] = arg
275 elif arg.startswith('--'):
276 if "=" in arg:
277 name, value = arg.split('=',1)
278 try:
279 value = float(value)
280 except Exception:
281 raise self.InvalidCmd, '--%s requires integer or a float' % name
282 output[name[2:]] = float(value)
283 elif arg == "--nlo":
284 output["nlo"] = True
285 elif arg in particles_name:
286
287 output['particles'].add(particles_name[arg])
288 elif arg.isdigit() and int(arg) in particles_name.values():
289 output['particles'].add(ast.literal_eval(arg))
290 elif arg == 'all':
291 output['particles'] = set(['all'])
292 else:
293 self.help_compute_widths()
294 raise self.InvalidCmd, '%s is not a valid argument for compute_widths' % arg
295 if self.force:
296 output['force'] = True
297
298 if not output['particles']:
299 raise self.InvalidCmd, '''This routines requires at least one particle in order to compute
300 the related width'''
301
302 if output['output'] is None:
303 output['output'] = output['path']
304
305 return output
306
308 """Check the argument for pythia command
309 syntax: delphes [NAME]
310 Note that other option are already remove at this point
311 """
312
313
314 if not self.options['delphes_path']:
315 logger.info('Retry to read configuration file to find delphes path')
316 self.set_configuration()
317
318 if not self.options['delphes_path']:
319 error_msg = 'No valid Delphes path set.\n'
320 error_msg += 'Please use the set command to define the path and retry.\n'
321 error_msg += 'You can also define it in the configuration file.\n'
322 raise self.InvalidCmd(error_msg)
323
324 tag = [a for a in arg if a.startswith('--tag=')]
325 if tag:
326 arg.remove(tag[0])
327 tag = tag[0][6:]
328
329
330 if len(arg) == 0 and not self.run_name:
331 if self.results.lastrun:
332 arg.insert(0, self.results.lastrun)
333 else:
334 raise self.InvalidCmd('No run name currently define. Please add this information.')
335
336 if len(arg) == 1 and self.run_name == arg[0]:
337 arg.pop(0)
338
339 filepath = None
340 if not len(arg):
341 prev_tag = self.set_run_name(self.run_name, tag, 'delphes')
342 paths = [pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia_events.hep.gz'),
343 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia8_events.hepmc.gz'),
344 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia_events.hep'),
345 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia8_events.hepmc'),
346 pjoin(self.me_dir,'Events','pythia_events.hep'),
347 pjoin(self.me_dir,'Events','pythia_events.hepmc'),
348 pjoin(self.me_dir,'Events','pythia8_events.hep.gz'),
349 pjoin(self.me_dir,'Events','pythia8_events.hepmc.gz')
350 ]
351 for p in paths:
352 if os.path.exists(p % {'tag': prev_tag}):
353 filepath = p % {'tag': prev_tag}
354 break
355 else:
356 a = raw_input("NO INPUT")
357 if nodefault:
358 return False
359 else:
360 self.help_pgs()
361 raise self.InvalidCmd('''No file file pythia_events.* currently available
362 Please specify a valid run_name''')
363
364 if len(arg) == 1:
365 prev_tag = self.set_run_name(arg[0], tag, 'delphes')
366 if os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)):
367 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
368 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)):
369 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)
370 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep' % prev_tag)):
371 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
372 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc' % prev_tag)):
373 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)
374 else:
375 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\
376 % (self.run_name, prev_tag,
377 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)))
378 else:
379 if tag:
380 self.run_card['run_tag'] = tag
381 self.set_run_name(self.run_name, tag, 'delphes')
382
383 return filepath
384
385
386
387
388
389
390
392 """ check the validity of the line """
393
394 if len(args) != 1:
395 self.help_open()
396 raise self.InvalidCmd('OPEN command requires exactly one argument')
397
398 if args[0].startswith('./'):
399 if not os.path.isfile(args[0]):
400 raise self.InvalidCmd('%s: not such file' % args[0])
401 return True
402
403
404 if not self.me_dir:
405 if not os.path.isfile(args[0]):
406 self.help_open()
407 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file')
408 else:
409 return True
410
411 path = self.me_dir
412 if os.path.isfile(os.path.join(path,args[0])):
413 args[0] = os.path.join(path,args[0])
414 elif os.path.isfile(os.path.join(path,'Cards',args[0])):
415 args[0] = os.path.join(path,'Cards',args[0])
416 elif os.path.isfile(os.path.join(path,'HTML',args[0])):
417 args[0] = os.path.join(path,'HTML',args[0])
418
419 elif '_card.dat' in args[0]:
420 name = args[0].replace('_card.dat','_card_default.dat')
421 if os.path.isfile(os.path.join(path,'Cards', name)):
422 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0]))
423 args[0] = os.path.join(path,'Cards', args[0])
424 else:
425 raise self.InvalidCmd('No default path for this file')
426 elif not os.path.isfile(args[0]):
427 raise self.InvalidCmd('No default path for this file')
428
430 """check that treatcards arguments are valid
431 [param|run|all] [--output_dir=] [--param_card=] [--run_card=]
432 """
433
434 opt = {'output_dir':pjoin(self.me_dir,'Source'),
435 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'),
436 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')}
437 mode = 'all'
438 for arg in args:
439 if arg.startswith('--') and '=' in arg:
440 key,value =arg[2:].split('=',1)
441 if not key in opt:
442 self.help_treatcards()
443 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \
444 % key)
445 if key in ['param_card', 'run_card']:
446 if os.path.isfile(value):
447 card_name = self.detect_card_type(value)
448 if card_name != key:
449 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
450 % (card_name, key))
451 opt[key] = value
452 elif os.path.isfile(pjoin(self.me_dir,value)):
453 card_name = self.detect_card_type(pjoin(self.me_dir,value))
454 if card_name != key:
455 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
456 % (card_name, key))
457 opt[key] = value
458 else:
459 raise self.InvalidCmd('No such file: %s ' % value)
460 elif key in ['output_dir']:
461 if os.path.isdir(value):
462 opt[key] = value
463 elif os.path.isdir(pjoin(self.me_dir,value)):
464 opt[key] = pjoin(self.me_dir, value)
465 else:
466 raise self.InvalidCmd('No such directory: %s' % value)
467 elif arg in ['MadLoop','param','run','all']:
468 mode = arg
469 else:
470 self.help_treatcards()
471 raise self.InvalidCmd('Unvalid argument %s' % arg)
472
473 return mode, opt
474
476 """Check the argument for decay_events command
477 syntax is "decay_events [NAME]"
478 Note that other option are already remove at this point
479 """
480
481 opts = []
482 if '-from_cards' in args:
483 args.remove('-from_cards')
484 opts.append('-from_cards')
485
486 if len(args) == 0:
487 if self.run_name:
488 args.insert(0, self.run_name)
489 elif self.results.lastrun:
490 args.insert(0, self.results.lastrun)
491 else:
492 raise self.InvalidCmd('No run name currently defined. Please add this information.')
493 return
494
495 if args[0] != self.run_name:
496 self.set_run_name(args[0])
497
498 args[0] = self.get_events_path(args[0])
499
500 args += opts
501
503 """Check the argument for decay_events command
504 syntax is "decay_events [NAME]"
505 Note that other option are already remove at this point
506 """
507
508 if len(args) == 0:
509 if self.run_name:
510 args.insert(0, self.run_name)
511 elif self.results.lastrun:
512 args.insert(0, self.results.lastrun)
513 else:
514 raise self.InvalidCmd('No run name currently defined. Please add this information.')
515 return
516
517 if args[0] and os.path.isfile(args[0]):
518 pass
519 else:
520 if args[0] != self.run_name:
521 self.set_run_name(args[0], allow_new_tag=False)
522
523 args[0] = self.get_events_path(args[0])
524
525
527 """return the path to the output events
528 """
529
530 if self.mode == 'madevent':
531 possible_path = [
532 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe.gz'),
533 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe')]
534 else:
535 possible_path = [
536 pjoin(self.me_dir,'Events', run_name, 'events.lhe.gz'),
537 pjoin(self.me_dir,'Events', run_name, 'events.lhe')]
538
539 for path in possible_path:
540 if os.path.exists(path):
541 correct_path = path
542 break
543 else:
544 if os.path.exists(run_name):
545 correct_path = run_name
546 else:
547 raise self.InvalidCmd('No events file corresponding to %s run. ' % run_name)
548 return correct_path
549
556
557
558
559
560 -class CommonRunCmd(HelpToCmd, CheckValidForCmd, cmd.Cmd):
561
562 debug_output = 'ME5_debug'
563 helporder = ['Main Commands', 'Documented commands', 'Require MG5 directory',
564 'Advanced commands']
565 sleep_for_error = True
566
567
568
569 options_configuration = {'pythia8_path': './pythia8',
570 'hwpp_path': './herwigPP',
571 'thepeg_path': './thepeg',
572 'hepmc_path': './hepmc',
573 'madanalysis_path': './MadAnalysis',
574 'madanalysis5_path': './HEPTools/madanalysis5',
575 'pythia-pgs_path':'./pythia-pgs',
576 'td_path':'./td',
577 'delphes_path':'./Delphes',
578 'exrootanalysis_path':'./ExRootAnalysis',
579 'syscalc_path': './SysCalc',
580 'lhapdf': 'lhapdf-config',
581 'timeout': 60,
582 'f2py_compiler':None,
583 'web_browser':None,
584 'eps_viewer':None,
585 'text_editor':None,
586 'fortran_compiler':None,
587 'cpp_compiler': None,
588 'auto_update':7,
589 'cluster_type': 'condor',
590 'cluster_status_update': (600, 30),
591 'cluster_nb_retry':1,
592 'cluster_local_path': None,
593 'cluster_retry_wait':300}
594
595 options_madgraph= {'stdout_level':None}
596
597 options_madevent = {'automatic_html_opening':True,
598 'notification_center':True,
599 'run_mode':2,
600 'cluster_queue':None,
601 'cluster_time':None,
602 'cluster_size':100,
603 'cluster_memory':None,
604 'nb_core': None,
605 'cluster_temp_path':None}
606
607
608 - def __init__(self, me_dir, options, *args, **opts):
609 """common"""
610
611 self.force_run = False
612 if 'force_run' in opts and opts['force_run']:
613 self.force_run = True
614 del opts['force_run']
615
616 cmd.Cmd.__init__(self, *args, **opts)
617
618 if me_dir is None and MADEVENT:
619 me_dir = root_path
620
621 if os.path.isabs(me_dir):
622 self.me_dir = me_dir
623 else:
624 self.me_dir = pjoin(os.getcwd(),me_dir)
625
626 self.options = options
627
628 self.param_card_iterator = []
629
630
631 self.status = pjoin(self.me_dir, 'status')
632 self.error = pjoin(self.me_dir, 'error')
633 self.dirbin = pjoin(self.me_dir, 'bin', 'internal')
634
635
636 if not self.force_run:
637 if os.path.exists(pjoin(me_dir,'RunWeb')):
638 message = '''Another instance of the program is currently running.
639 (for this exact same directory) Please wait that this is instance is
640 closed. If no instance is running, you can delete the file
641 %s and try again.''' % pjoin(me_dir,'RunWeb')
642 raise AlreadyRunning, message
643 else:
644 pid = os.getpid()
645 fsock = open(pjoin(me_dir,'RunWeb'),'w')
646 fsock.write(`pid`)
647 fsock.close()
648
649 misc.Popen([os.path.relpath(pjoin(self.dirbin, 'gen_cardhtml-pl'), me_dir)],
650 cwd=me_dir)
651
652 self.to_store = []
653 self.run_name = None
654 self.run_tag = None
655 self.banner = None
656
657 self.set_configuration()
658 self.configure_run_mode(self.options['run_mode'])
659
660
661 self.get_characteristics()
662
663 if not self.proc_characteristics['ninitial']:
664
665 nexternal = open(pjoin(self.me_dir,'Source','nexternal.inc')).read()
666 found = re.search("PARAMETER\s*\(NINCOMING=(\d)\)", nexternal)
667 self.ninitial = int(found.group(1))
668 else:
669 self.ninitial = self.proc_characteristics['ninitial']
670
671
672
706
707
708 @misc.multiple_try(nb_try=5, sleep=2)
710 """load the current results status"""
711
712
713 if os.path.exists(pjoin(self.me_dir,'HTML','results.pkl')):
714 try:
715 self.results = save_load_object.load_from_file(pjoin(self.me_dir,'HTML','results.pkl'))
716 except Exception:
717
718 model = self.find_model_name()
719 process = self.process
720 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
721 self.results.resetall(self.me_dir)
722 else:
723 try:
724 self.results.resetall(self.me_dir)
725 except Exception, error:
726 logger.debug(error)
727
728 model = self.find_model_name()
729 process = self.process
730 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
731 self.results.resetall(self.me_dir)
732 self.last_mode = ''
733 try:
734 self.last_mode = self.results[self.results.lastrun][-1]['run_mode']
735 except:
736 self.results.resetall(self.me_dir)
737 self.last_mode = ''
738
739 else:
740 model = self.find_model_name()
741 process = self.process
742 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
743 self.results.resetall(self.me_dir)
744 self.last_mode=''
745
746 return self.results
747
748
750 """Advanced commands: create .inc files from param_card.dat/run_card.dat"""
751
752 keepwidth = False
753 if '--keepwidth' in line:
754 keepwidth = True
755 line = line.replace('--keepwidth', '')
756 args = self.split_arg(line)
757 mode, opt = self.check_treatcards(args)
758
759 if mode in ['run', 'all']:
760 if not hasattr(self, 'run_card'):
761 if amcatnlo:
762 run_card = banner_mod.RunCardNLO(opt['run_card'])
763 else:
764 run_card = banner_mod.RunCard(opt['run_card'])
765 else:
766 run_card = self.run_card
767
768
769 if amcatnlo and run_card['pdlabel']=='lhapdf':
770 pdfsetsdir=self.get_lhapdf_pdfsetsdir()
771 pdfsets=self.get_lhapdf_pdfsets_list(pdfsetsdir)
772 lhapdfsetname=[]
773 for lhaid in run_card['lhaid']:
774 if lhaid in pdfsets:
775 lhapdfsetname.append(pdfsets[lhaid]['filename'])
776 else:
777 raise MadGraph5Error("lhaid %s is not a valid PDF identification number. This can be due to the use of an outdated version of LHAPDF, or %s is not a LHAGlue number corresponding to a central PDF set (but rather one of the error sets)." % (lhaid,lhaid))
778 run_card['lhapdfsetname']=lhapdfsetname
779 run_card.write_include_file(opt['output_dir'])
780
781 if mode in ['MadLoop', 'all']:
782 if os.path.exists(pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat')):
783 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir,
784 'Cards', 'MadLoopParams.dat'))
785
786 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses",
787 "MadLoopParams.dat"))
788
789 if mode in ['param', 'all']:
790 if os.path.exists(pjoin(self.me_dir, 'Source', 'MODEL', 'mp_coupl.inc')):
791 param_card = check_param_card.ParamCardMP(opt['param_card'])
792 else:
793 param_card = check_param_card.ParamCard(opt['param_card'])
794 outfile = pjoin(opt['output_dir'], 'param_card.inc')
795 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat')
796 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')):
797 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')
798 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')):
799 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
800 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')):
801 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w')
802 fsock.write(' ')
803 fsock.close()
804 return
805 else:
806 subprocess.call(['python', 'write_param_card.py'],
807 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'))
808 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
809
810
811 if amcatnlo and not keepwidth:
812
813 pids = self.get_pid_final_initial_states()
814
815 if not MADEVENT and pjoin(self.me_dir,'bin','internal') not in sys.path:
816 sys.path.insert(0,pjoin(self.me_dir,'bin','internal'))
817
818
819
820 to_del = [name for name in sys.modules.keys()
821 if name.startswith('internal.ufomodel')
822 or name.startswith('ufomodel')]
823 for name in to_del:
824 del(sys.modules[name])
825
826 import ufomodel as ufomodel
827 zero = ufomodel.parameters.ZERO
828 no_width = [p for p in ufomodel.all_particles
829 if (str(p.pdg_code) in pids or str(-p.pdg_code) in pids)
830 and p.color != 1 and p.width != zero]
831 done = []
832 for part in no_width:
833 if abs(part.pdg_code) in done:
834 continue
835 done.append(abs(part.pdg_code))
836 param = param_card['decay'].get((part.pdg_code,))
837
838 if param.value != 0:
839 logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.'''\
840 % part.name,'$MG:color:BLACK')
841 param.value = 0
842
843 param_card.write_inc_file(outfile, ident_card, default)
844
846 """return the model related to this process"""
847
848 if self.options['mg5_path']:
849 sys.path.append(self.options['mg5_path'])
850 import models.import_ufo as import_ufo
851 complexmass = self.proc_characteristics['complex_mass_scheme']
852 with misc.MuteLogger(['madgraph.model'],[50]):
853 out= import_ufo.import_model(pjoin(self.me_dir,'bin','internal','ufomodel'),
854 complex_mass_scheme=complexmass)
855 return out
856
857
858
859 else:
860 return None
861
862 - def ask_edit_cards(self, cards, mode='fixed', plot=True, first_cmd=None):
863 """ """
864 if not self.options['madanalysis_path']:
865 plot = False
866
867 self.ask_edit_card_static(cards, mode, plot, self.options['timeout'],
868 self.ask, first_cmd=first_cmd)
869
870 @staticmethod
873 if not ask:
874 ask = CommonRunCmd.ask
875
876 def path2name(path):
877 if '_card' in path:
878 return path.split('_card')[0]
879 elif path == 'delphes_trigger.dat':
880 return 'trigger'
881 elif path == 'input.lhco':
882 return 'lhco'
883 elif path == 'MadLoopParams.dat':
884 return 'MadLoopParams'
885 else:
886 raise Exception, 'Unknow cards name %s' % path
887
888
889
890 question = """Do you want to edit a card (press enter to bypass editing)?\n"""
891 possible_answer = ['0', 'done']
892 card = {0:'done'}
893
894 indent = max(len(path2name(card_name)) for card_name in cards)
895 question += '/'+'-'*60+'\\\n'
896 for i, card_name in enumerate(cards):
897 imode = path2name(card_name)
898 possible_answer.append(i+1)
899 possible_answer.append(imode)
900 question += '| %-77s|\n'%((' \x1b[31m%%s\x1b[0m. %%-%ds : \x1b[32m%%s\x1b[0m'%indent)%(i+1, imode, card_name))
901 card[i+1] = imode
902
903 if plot and not 'plot_card.dat' in cards:
904 question += '| %-77s|\n'%((' \x1b[31m9\x1b[0m. %%-%ds : \x1b[32mplot_card.dat\x1b[0m'%indent) % 'plot')
905 possible_answer.append(9)
906 possible_answer.append('plot')
907 card[9] = 'plot'
908
909 question += '\\'+'-'*60+'/\n'
910
911 if 'param_card.dat' in cards:
912
913 question += ' you can also\n'
914 question += ' - enter the path to a valid card or banner.\n'
915 question += ' - use the \'set\' command to modify a parameter directly.\n'
916 question += ' The set option works only for param_card and run_card.\n'
917 question += ' Type \'help set\' for more information on this command.\n'
918 question += ' - call an external program (ASperGE/MadWidth/...).\n'
919 question += ' Type \'help\' for the list of available command\n'
920 else:
921 question += ' you can also\n'
922 question += ' - enter the path to a valid card.\n'
923 if 'transfer_card.dat' in cards:
924 question += ' - use the \'change_tf\' command to set a transfer functions.\n'
925
926 out = 'to_run'
927 while out not in ['0', 'done']:
928 out = ask(question, '0', possible_answer, timeout=int(1.5*timeout),
929 path_msg='enter path', ask_class = AskforEditCard,
930 cards=cards, mode=mode, **opt)
931
932 @staticmethod
934 """detect the type of the card. Return value are
935 banner
936 param_card.dat
937 run_card.dat
938 pythia_card.dat
939 pythia8_card.dat
940 plot_card.dat
941 pgs_card.dat
942 delphes_card.dat
943 delphes_trigger.dat
944 shower_card.dat [aMCatNLO]
945 FO_analyse_card.dat [aMCatNLO]
946 madspin_card.dat [MS]
947 transfer_card.dat [MW]
948 madweight_card.dat [MW]
949 madanalysis5_hadron_card.dat
950 madanalysis5_parton_card.dat
951
952 Please update the unit-test: test_card_type_recognition when adding
953 cards.
954 """
955
956 fulltext = open(path).read(50000)
957 if fulltext == '':
958 logger.warning('File %s is empty' % path)
959 return 'unknown'
960
961 to_search = ['<MGVersion>',
962 '<mg5proccard>'
963 'ParticlePropagator',
964 'ExecutionPath',
965 'Treewriter',
966 'CEN_max_tracker',
967 '#TRIGGER CARD',
968 'parameter set name',
969 'muon eta coverage',
970 'req_acc_FO',
971 'MSTP',
972 'b_stable',
973 'FO_ANALYSIS_FORMAT',
974 'MSTU',
975 'Begin Minpts',
976 'gridpack',
977 'ebeam1',
978 'block\s+mw_run',
979 'BLOCK',
980 'DECAY',
981 'launch',
982 'madspin',
983 'transfer_card\.dat',
984 'set',
985 'main:numberofevents',
986 '@MG5aMC skip_analysis',
987 '@MG5aMC\s*inputs\s*=\s*\*\.(?:hepmc|lhe)',
988 '@MG5aMC\s*reconstruction_name',
989 '@MG5aMC'
990 ]
991
992
993 text = re.findall('(%s)' % '|'.join(to_search), fulltext, re.I)
994 text = [t.lower() for t in text]
995 if '<mgversion>' in text or '<mg5proccard>' in text:
996 return 'banner'
997 elif 'particlepropagator' in text or 'executionpath' in text or 'treewriter' in text:
998 return 'delphes_card.dat'
999 elif 'cen_max_tracker' in text:
1000 return 'delphes_card.dat'
1001 elif '@mg5amc' in text:
1002 ma5_flag = [f[7:].strip() for f in text if f.startswith('@mg5amc')]
1003 if any(f.startswith('reconstruction_name') for f in ma5_flag):
1004 return 'madanalysis5_hadron_card.dat'
1005 ma5_flag = [f.split('*.')[1] for f in ma5_flag if '*.' in f]
1006 if any(f.startswith('lhe') for f in ma5_flag):
1007 return 'madanalysis5_parton_card.dat'
1008 if any(f.startswith(('hepmc','hep','stdhep','lhco')) for f in ma5_flag):
1009 return 'madanalysis5_hadron_card.dat'
1010 else:
1011 return 'unknown'
1012 elif '#trigger card' in text:
1013 return 'delphes_trigger.dat'
1014 elif 'parameter set name' in text:
1015 return 'pgs_card.dat'
1016 elif 'muon eta coverage' in text:
1017 return 'pgs_card.dat'
1018 elif 'mstp' in text and not 'b_stable' in text:
1019 return 'pythia_card.dat'
1020 elif 'begin minpts' in text:
1021 return 'plot_card.dat'
1022 elif ('gridpack' in text and 'ebeam1' in text) or \
1023 ('req_acc_fo' in text and 'ebeam1' in text):
1024 return 'run_card.dat'
1025 elif any(t.endswith('mw_run') for t in text):
1026 return 'madweight_card.dat'
1027 elif 'transfer_card.dat' in text:
1028 return 'transfer_card.dat'
1029 elif 'block' in text and 'decay' in text:
1030 return 'param_card.dat'
1031 elif 'b_stable' in text:
1032 return 'shower_card.dat'
1033 elif 'fo_analysis_format' in text:
1034 return 'FO_analyse_card.dat'
1035 elif 'main:numberofevents' in text:
1036 return 'pythia8_card.dat'
1037 elif 'launch' in text:
1038
1039
1040 if 'madspin' in text:
1041 return 'madspin_card.dat'
1042 if 'decay' in text:
1043
1044 if re.search("(^|;)\s*decay", fulltext):
1045 return 'madspin_card.dat'
1046 else:
1047 return 'reweight_card.dat'
1048 else:
1049 return 'reweight_card.dat'
1050 else:
1051 return 'unknown'
1052
1053
1054
1056 """create automatically a tag"""
1057
1058 used_tags = [r['tag'] for r in self.results[self.run_name]]
1059 i=0
1060 while 1:
1061 i+=1
1062 if 'tag_%s' %i not in used_tags:
1063 return 'tag_%s' % i
1064
1065
1066
1067 @misc.mute_logger(names=['madgraph.various.histograms',
1068 'internal.histograms'],levels=[20,20])
1072 """Generated the HwU plots from Pythia8 driver output for a specific
1073 observable."""
1074
1075 try:
1076 import madgraph
1077 except ImportError:
1078 import internal.histograms as histograms
1079 else:
1080 import madgraph.various.histograms as histograms
1081
1082
1083 if not os.path.isfile(data_path):
1084 return False
1085
1086
1087 histos = histograms.HwUList(data_path, consider_reweights='ALL',run_id=0)
1088 if len(histos)==0:
1089 return False
1090
1091
1092 merging_scales_available = [label[1] for label in \
1093 histos[0].bins.weight_labels if
1094 histograms.HwU.get_HwU_wgt_label_type(label)=='merging_scale']
1095 if len(merging_scales_available)>=2:
1096 min_merging_scale = min(merging_scales_available)
1097 max_merging_scale = max(merging_scales_available)
1098 else:
1099 min_merging_scale = None
1100 max_merging_scale = None
1101
1102
1103 histo_output_options = {
1104 'format':'gnuplot',
1105 'uncertainties':['scale','pdf','statistical',
1106 'merging_scale','alpsfact'],
1107 'ratio_correlations':True,
1108 'arg_string':'Automatic plotting from MG5aMC',
1109 'jet_samples_to_keep':None,
1110 'use_band':['merging_scale','alpsfact'],
1111 'auto_open':False
1112 }
1113
1114 if not (int(self.run_card['ickkw'])==1):
1115 histo_output_options['uncertainties'].pop(
1116 histo_output_options['uncertainties'].index('alpsfact'))
1117 histo_output_options['use_band'].pop(
1118 histo_output_options['use_band'].index('alpsfact'))
1119
1120 histos.output(pjoin(plot_root_path,
1121 'central_%s_%s_plots'%(merging_scale_name,observable_name)),
1122 **histo_output_options)
1123
1124 for scale in merging_scales_available:
1125 that_scale_histos = histograms.HwUList(
1126 data_path, run_id=0, merging_scale=scale)
1127 that_scale_histos.output(pjoin(plot_root_path,
1128 '%s_%.3g_%s_plots'%(merging_scale_name,scale,observable_name)),
1129 **histo_output_options)
1130
1131
1132
1133
1134 if not min_merging_scale is None:
1135 min_scale_histos = histograms.HwUList(data_path,
1136 consider_reweights=[], run_id=0,
1137 merging_scale=min_merging_scale)
1138 max_scale_histos = histograms.HwUList(data_path,
1139 consider_reweights=[], run_id=0,
1140 merging_scale=max_merging_scale)
1141
1142
1143 for histo in min_scale_histos:
1144 if histo.type is None:
1145 histo.type = '%s=%.4g'%(merging_scale_name, min_merging_scale)
1146 else:
1147 histo.type += '|%s=%.4g'%(merging_scale_name, min_merging_scale)
1148 for histo in max_scale_histos:
1149 if histo.type is None:
1150 histo.type = '%s=%.4g'%(merging_scale_name, max_merging_scale)
1151 else:
1152 histo.type += '|%s=%.4g'%(merging_scale_name, max_merging_scale)
1153
1154
1155 histograms.HwUList(min_scale_histos+max_scale_histos).output(
1156 pjoin(plot_root_path,'min_max_%s_%s_comparison'
1157 %(merging_scale_name,observable_name)),
1158 format='gnuplot',
1159 uncertainties=[],
1160 ratio_correlations=True,
1161 arg_string='Automatic plotting from MG5aMC',
1162 jet_samples_to_keep=[],
1163 use_band=[],
1164 auto_open=False)
1165 return True
1166
1167 - def create_plot(self, mode='parton', event_path=None, output=None, tag=None):
1168 """create the plot"""
1169
1170 if not tag:
1171 tag = self.run_card['run_tag']
1172
1173 if mode != 'Pythia8':
1174 madir = self.options['madanalysis_path']
1175 td = self.options['td_path']
1176
1177 if not madir or not td or \
1178 not os.path.exists(pjoin(self.me_dir, 'Cards', 'plot_card.dat')):
1179 return False
1180 else:
1181 PY8_plots_root_path = pjoin(self.me_dir,'HTML',
1182 self.run_name,'%s_PY8_plots'%tag)
1183
1184 if 'ickkw' in self.run_card:
1185 if int(self.run_card['ickkw']) and mode == 'Pythia':
1186 self.update_status('Create matching plots for Pythia', level='pythia')
1187
1188 if not os.path.exists(pjoin(self.me_dir,'Events','events.tree')):
1189 misc.gunzip(pjoin(self.me_dir,'Events',
1190 self.run_name, '%s_pythia_events.tree.gz' % tag), keep=True,
1191 stdout=pjoin(self.me_dir,'Events','events.tree'))
1192 files.mv(pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'),
1193 pjoin(self.me_dir,'Events','xsecs.tree'))
1194
1195
1196 misc.call([self.dirbin+'/create_matching_plots.sh',
1197 self.run_name, tag, madir],
1198 stdout = os.open(os.devnull, os.O_RDWR),
1199 cwd=pjoin(self.me_dir,'Events'))
1200
1201
1202 misc.gzip(pjoin(self.me_dir,"Events","events.tree"),
1203 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_events.tree.gz'))
1204 files.mv(pjoin(self.me_dir,'Events','xsecs.tree'),
1205 pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'))
1206
1207 elif mode == 'Pythia8' and (int(self.run_card['ickkw'])==1 or \
1208 self.run_card['ktdurham']>0.0 or self.run_card['ptlund']>0.0):
1209
1210 self.update_status('Create matching plots for Pythia8',
1211 level='pythia8')
1212
1213
1214 if not os.path.isdir(PY8_plots_root_path):
1215 os.makedirs(PY8_plots_root_path)
1216
1217 merging_scale_name = 'qCut' if int(self.run_card['ickkw'])==1 \
1218 else 'TMS'
1219
1220 djr_path = pjoin(self.me_dir,'Events',
1221 self.run_name, '%s_djrs.dat' % tag)
1222 pt_path = pjoin(self.me_dir,'Events',
1223 self.run_name, '%s_pts.dat' % tag)
1224 for observable_name, data_path in [('djr',djr_path),
1225 ('pt',pt_path)]:
1226 if not self.generate_Pythia8_HwU_plots(
1227 PY8_plots_root_path, merging_scale_name,
1228 observable_name,data_path):
1229 return False
1230
1231 if mode == 'Pythia8':
1232 plot_files = glob.glob(pjoin(PY8_plots_root_path,'*.gnuplot'))
1233 if not misc.which('gnuplot'):
1234 logger.warning("Install gnuplot to be able to view the plots"+\
1235 " generated at :\n "+\
1236 '\n '.join('%s.gnuplot'%p for p in plot_files))
1237 return True
1238 for plot in plot_files:
1239 command = ['gnuplot',plot]
1240 try:
1241 subprocess.call(command,cwd=PY8_plots_root_path,stderr=subprocess.PIPE)
1242 except Exception as e:
1243 logger.warning("Automatic processing of the Pythia8 "+\
1244 "merging plots with gnuplot failed. Try the"+\
1245 " following command by hand:\n %s"%(' '.join(command))+\
1246 "\nException was: %s"%str(e))
1247 return False
1248
1249 plot_files = glob.glob(pjoin(PY8_plots_root_path,'*.pdf'))
1250 if len(plot_files)>0:
1251
1252 html = "<html>\n<head>\n<TITLE>PLOT FOR PYTHIA8</TITLE>"
1253 html+= '<link rel=stylesheet href="../../mgstyle.css" type="text/css">\n</head>\n<body>\n'
1254 html += "<h2> Plot for Pythia8 </h2>\n"
1255 html += '<a href=../../../crossx.html>return to summary</a><br>'
1256 html += "<table>\n<tr> <td> <b>Obs.</b> </td> <td> <b>Type of plot</b> </td> <td><b> PDF</b> </td> <td><b> input file</b> </td> </tr>\n"
1257 def sorted_plots(elem):
1258 name = os.path.basename(elem[1])
1259 if 'central' in name:
1260 return -100
1261 if 'min_max' in name:
1262 return -10
1263 merging_re = re.match(r'^.*_(\d+)_.*$',name)
1264 if not merging_re is None:
1265 return int(merging_re.group(1))
1266 else:
1267 return 1e10
1268 djr_plot_files = sorted(
1269 (('DJR',p) for p in plot_files if '_djr_' in p),
1270 key = sorted_plots)
1271 pt_plot_files = sorted(
1272 (('Pt',p) for p in plot_files if '_pt_' in p),
1273 key = sorted_plots)
1274 last_obs = None
1275 for obs, one_plot in djr_plot_files+pt_plot_files:
1276 if obs!=last_obs:
1277
1278 html += "<tr><td></td></tr>"
1279 last_obs = obs
1280 name = os.path.basename(one_plot).replace('.pdf','')
1281 short_name = name
1282 for dummy in ['_plots','_djr','_pt']:
1283 short_name = short_name.replace(dummy,'')
1284 short_name = short_name.replace('_',' ')
1285 if 'min max' in short_name:
1286 short_name = "%s comparison with min/max merging scale"%obs
1287 if 'central' in short_name:
1288 short_name = "Merging uncertainty band around central scale"
1289 html += "<tr><td>%(obs)s</td><td>%(sn)s</td><td> <a href=./%(n)s.pdf>PDF</a> </td><td> <a href=./%(n)s.HwU>HwU</a> <a href=./%(n)s.gnuplot>GNUPLOT</a> </td></tr>\n" %\
1290 {'obs':obs, 'sn': short_name, 'n': name}
1291 html += '</table>\n'
1292 html += '<a href=../../../bin/internal/plot_djrs.py> Example of code to plot the above with matplotlib </a><br><br>'
1293 html+='</body>\n</html>'
1294 ff=open(pjoin(PY8_plots_root_path, 'index.html'),'w')
1295 ff.write(html)
1296 return True
1297
1298 if not event_path:
1299 if mode == 'parton':
1300 possibilities=[
1301 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
1302 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe.gz'),
1303 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe'),
1304 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')]
1305 for event_path in possibilities:
1306 if os.path.exists(event_path):
1307 break
1308 output = pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
1309
1310 elif mode == 'Pythia':
1311 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe')
1312 output = pjoin(self.me_dir, 'HTML',self.run_name,
1313 'plots_pythia_%s.html' % tag)
1314 elif mode == 'PGS':
1315 event_path = pjoin(self.me_dir, 'Events', self.run_name,
1316 '%s_pgs_events.lhco' % tag)
1317 output = pjoin(self.me_dir, 'HTML',self.run_name,
1318 'plots_pgs_%s.html' % tag)
1319 elif mode == 'Delphes':
1320 event_path = pjoin(self.me_dir, 'Events', self.run_name,'%s_delphes_events.lhco' % tag)
1321 output = pjoin(self.me_dir, 'HTML',self.run_name,
1322 'plots_delphes_%s.html' % tag)
1323 elif mode == "shower":
1324 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe')
1325 output = pjoin(self.me_dir, 'HTML',self.run_name,
1326 'plots_shower_%s.html' % tag)
1327 if not self.options['pythia-pgs_path']:
1328 return
1329 else:
1330 raise self.InvalidCmd, 'Invalid mode %s' % mode
1331 elif mode == 'reweight' and not output:
1332 output = pjoin(self.me_dir, 'HTML',self.run_name,
1333 'plots_%s.html' % tag)
1334
1335 if not os.path.exists(event_path):
1336 if os.path.exists(event_path+'.gz'):
1337 misc.gunzip('%s.gz' % event_path)
1338 else:
1339 raise self.InvalidCmd, 'Events file %s does not exist' % event_path
1340 elif event_path.endswith(".gz"):
1341 misc.gunzip(event_path)
1342 event_path = event_path[:-3]
1343
1344
1345 self.update_status('Creating Plots for %s level' % mode, level = mode.lower())
1346
1347 mode = mode.lower()
1348 if mode not in ['parton', 'reweight']:
1349 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s_%s' % (mode.lower(),tag))
1350 elif mode == 'parton':
1351 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_parton')
1352 else:
1353 plot_dir =pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s' % (tag))
1354
1355 if not os.path.isdir(plot_dir):
1356 os.makedirs(plot_dir)
1357
1358 files.ln(pjoin(self.me_dir, 'Cards','plot_card.dat'), plot_dir, 'ma_card.dat')
1359
1360 try:
1361 proc = misc.Popen([os.path.join(madir, 'plot_events')],
1362 stdout = open(pjoin(plot_dir, 'plot.log'),'w'),
1363 stderr = subprocess.STDOUT,
1364 stdin=subprocess.PIPE,
1365 cwd=plot_dir)
1366 proc.communicate('%s\n' % event_path)
1367 del proc
1368
1369 misc.call(['%s/plot' % self.dirbin, madir, td],
1370 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
1371 stderr = subprocess.STDOUT,
1372 cwd=plot_dir)
1373
1374 misc.call(['%s/plot_page-pl' % self.dirbin,
1375 os.path.basename(plot_dir),
1376 mode],
1377 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
1378 stderr = subprocess.STDOUT,
1379 cwd=pjoin(self.me_dir, 'HTML', self.run_name))
1380
1381 shutil.move(pjoin(self.me_dir, 'HTML',self.run_name ,'plots.html'),
1382 output)
1383
1384 logger.info("Plots for %s level generated, see %s" % \
1385 (mode, output))
1386 except OSError, error:
1387 logger.error('fail to create plot: %s. Please check that MadAnalysis is correctly installed.' % error)
1388
1389 self.update_status('End Plots for %s level' % mode, level = mode.lower(),
1390 makehtml=False)
1391
1392 return True
1393
1395 """Run hep2lhe on the file Events/pythia_events.hep"""
1396
1397 if not self.options['pythia-pgs_path']:
1398 raise self.InvalidCmd, 'No pythia-pgs path defined'
1399
1400 pydir = pjoin(self.options['pythia-pgs_path'], 'src')
1401 eradir = self.options['exrootanalysis_path']
1402
1403
1404 if misc.is_executable(pjoin(pydir, 'hep2lhe')):
1405 self.update_status('Creating shower LHE File (for plot)', level='pythia')
1406
1407 out = open(pjoin(self.me_dir,'Events','pythia_events.lhe'), 'w')
1408
1409 out.writelines('<!--\n')
1410 out.writelines('# Warning! Never use this file for detector studies!\n')
1411 out.writelines('-->\n<!--\n')
1412 if banner_path:
1413 out.writelines(open(banner_path).read().replace('<LesHouchesEvents version="1.0">',''))
1414 out.writelines('\n-->\n')
1415 out.close()
1416
1417 self.cluster.launch_and_wait(self.dirbin+'/run_hep2lhe',
1418 argument= [pydir],
1419 cwd=pjoin(self.me_dir,'Events'),
1420 stdout=os.devnull)
1421
1422 logger.info('Warning! Never use this lhe file for detector studies!')
1423
1424 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHEFConverter')):
1425 self.update_status('Creating Pythia LHE Root File', level='pythia')
1426 try:
1427 misc.call([eradir+'/ExRootLHEFConverter',
1428 'pythia_events.lhe',
1429 pjoin(self.run_name, '%s_pythia_lhe_events.root' % self.run_tag)],
1430 cwd=pjoin(self.me_dir,'Events'))
1431 except Exception, error:
1432 misc.sprint('ExRootLHEFConverter fails', str(error),
1433 log=logger)
1434 pass
1435
1437 """Dummy routine, to be overwritten by daughter classes"""
1438
1439 pass
1440
1441
1443 """help for systematics command"""
1444 logger.info("syntax: systematics RUN_NAME [OUTPUT] [options]",'$MG:color:BLACK')
1445 logger.info("-- Run the systematics run on the RUN_NAME run.")
1446 logger.info(" RUN_NAME can be a path to a lhef file.")
1447 logger.info(" OUTPUT can be the path to the output lhe file, otherwise the input file will be overwritten")
1448 logger.info("")
1449 logger.info("options: (values written are the default)", '$MG:color:BLACK')
1450 logger.info("")
1451 logger.info(" --mur=0.5,1,2 # specify the values for renormalisation scale variation")
1452 logger.info(" --muf=0.5,1,2 # specify the values for factorisation scale variation")
1453 logger.info(" --alps=1 # specify the values for MLM emission scale variation (LO only)")
1454 logger.info(" --dyn=-1,1,2,3,4 # specify the dynamical schemes to use.")
1455 logger.info(" # -1 is the one used by the sample.")
1456 logger.info(" # > 0 correspond to options of dynamical_scale_choice of the run_card.")
1457 logger.info(" --pdf=errorset # specify the pdfs to use for pdf variation. (see below)")
1458 logger.info(" --together=mur,muf,dyn # lists the parameter that must be varied simultaneously so as to ")
1459 logger.info(" # compute the weights for all combinations of their variations.")
1460 logger.info(" --from_card # use the information from the run_card (LO only).")
1461 logger.info("")
1462 logger.info(" Allowed value for the pdf options:", '$MG:color:BLACK')
1463 logger.info(" central : Do not perform any pdf variation" )
1464 logger.info(" errorset : runs over the all the members of the PDF set used to generate the events")
1465 logger.info(" 244800 : runs over the associated set and all its members")
1466 logger.info(" 244800@0 : runs over the central member of the associated set")
1467
1468 logger.info(" CT10 : runs over the associated set and all its members")
1469 logger.info(" CT10@0 : runs over the central member of the associated set")
1470 logger.info(" CT10@X : runs over the Xth member of the associated PDF set")
1471 logger.info(" XX,YY,ZZ : runs over the sets for XX,YY,ZZ (those three follows above syntax)")
1472
1474 """auto completion for the systematics command"""
1475
1476 args = self.split_arg(line[0:begidx], error=False)
1477 options = ['--mur=', '--muf=', '--pdf=', '--dyn=','--alps=','--together=','--from_card ']
1478
1479 if len(args) == 1 and os.path.sep not in text:
1480
1481 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events'))
1482 data = [n.rsplit('/',2)[1] for n in data]
1483 return self.list_completion(text, data, line)
1484 elif len(args)==1:
1485
1486 return self.path_completion(text,
1487 os.path.join('.',*[a for a in args \
1488 if a.endswith(os.path.sep)]))
1489 elif len(args)==2 and os.path.sep in args[1]:
1490
1491 return self.path_completion(text, '.')
1492
1493 elif not line.endswith(tuple(options)):
1494 return self.list_completion(text, options)
1495
1496
1497
1499 """ syntax is 'systematics [INPUT [OUTPUT]] OPTIONS'
1500 --mur=0.5,1,2
1501 --muf=0.5,1,2
1502 --alps=1
1503 --dyn=-1
1504 --together=mur,muf #can be repeated
1505
1506 #special options
1507 --from_card=
1508 """
1509
1510 try:
1511 lhapdf_version = self.get_lhapdf_version()
1512 except Exception:
1513 logger.info('No version of lhapdf. Can not run systematics computation')
1514 return
1515 else:
1516 if lhapdf_version.startswith('5'):
1517 logger.info('can not run systematics with lhapdf 5')
1518 return
1519
1520 lhapdf = misc.import_python_lhapdf(self.options['lhapdf'])
1521 if not lhapdf:
1522 logger.info('can not run systematics since can not link python to lhapdf')
1523 return
1524
1525
1526
1527
1528 self.update_status('Running Systematics computation', level='parton')
1529 args = self.split_arg(line)
1530
1531 opts= []
1532 args = [a for a in args if not a.startswith('-') or opts.append(a)]
1533
1534
1535 if any(not o.startswith(('--mur=', '--muf=', '--alps=','--dyn=','--together=','--from_card','--pdf='))
1536 for o in opts):
1537 raise self.InvalidCmd, "command systematics called with invalid option syntax. Please retry."
1538
1539
1540 if len(args) == 0:
1541 if self.run_name:
1542 args[0] = self.run_name
1543 else:
1544 raise self.InvalidCmd, 'no default run. Please specify the run_name'
1545
1546 if args[0] != self.run_name:
1547 self.set_run_name(args[0])
1548
1549
1550 result_file= sys.stdout
1551 if not os.path.isfile(args[0]) and not os.path.sep in args[0]:
1552 path = [pjoin(self.me_dir, 'Events', args[0], 'unweighted_events.lhe.gz'),
1553 pjoin(self.me_dir, 'Events', args[0], 'unweighted_events.lhe'),
1554 pjoin(self.me_dir, 'Events', args[0], 'events.lhe.gz'),
1555 pjoin(self.me_dir, 'Events', args[0], 'events.lhe')]
1556
1557 for p in path:
1558 if os.path.exists(p):
1559 nb_event = self.results[args[0]].get_current_info()['nb_event']
1560
1561
1562 if self.run_name != args[0]:
1563 tag = self.results[args[0]].tags[0]
1564 self.set_run_name(args[0], tag,'parton', False)
1565 result_file = open(pjoin(self.me_dir,'Events', self.run_name, 'parton_systematics.log'),'w')
1566 args[0] = p
1567 break
1568 else:
1569 raise self.InvalidCmd, 'Invalid run name. Please retry'
1570 elif self.options['nb_core'] != 1:
1571 lhe = lhe_parser.EventFile(args[0])
1572 nb_event = len(lhe)
1573 lhe.close()
1574
1575 input = args[0]
1576 if len(args)>1:
1577 output = pjoin(os.getcwd(),args[1])
1578 else:
1579 output = input
1580
1581 lhaid = [self.run_card.get_lhapdf_id()]
1582 if 'store_rwgt_info' in self.run_card and not self.run_card['store_rwgt_info']:
1583 raise self.InvalidCmd, "The events was not generated with store_rwgt_info=True. Can not evaluate systematics error on this event file."
1584 elif 'use_syst' in self.run_card:
1585 if not self.run_card['use_syst']:
1586 raise self.InvalidCmd, "The events was not generated with use_syst=True. Can not evaluate systematics error on this event file."
1587 elif self.proc_characteristics['ninitial'] ==1:
1588 if '--from_card' in opts:
1589 logger.warning('systematics not available for decay processes. Bypass it')
1590 return
1591 else:
1592 raise self.InvalidCmd, 'systematics not available for decay processes.'
1593
1594 try:
1595 pdfsets_dir = self.get_lhapdf_pdfsetsdir()
1596 except Exception, error:
1597 logger.debug(str(error))
1598 logger.warning('Systematic computation requires lhapdf to run. Bypass Systematics')
1599 return
1600
1601 if '--from_card' in opts:
1602 opts.remove('--from_card')
1603 opts.append('--from_card=internal')
1604
1605
1606 if 'sys_pdf' in self.run_card:
1607 if '&&' in self.run_card['sys_pdf']:
1608 line = ' '.join(self.run_card['sys_pdf'])
1609 sys_pdf = line.split('&&')
1610 lhaid += [l.split()[0] for l in sys_pdf]
1611 else:
1612 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500]
1613
1614 else:
1615
1616 pdf = [a[6:] for a in opts if a.startswith('--pdf=')]
1617 lhaid += [t.split('@')[0] for p in pdf for t in p.split(',')
1618 if t not in ['errorset', 'central']]
1619
1620
1621 try:
1622 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid]
1623 except Exception, error:
1624 logger.debug(str(error))
1625 logger.warning('impossible to download all the pdfsets. Bypass systematics')
1626 return
1627
1628 if self.options['run_mode'] ==2:
1629 nb_submit = min(self.options['nb_core'], nb_event//2500)
1630 elif self.options['run_mode'] ==1:
1631 nb_submit = min(self.options['cluster_size'], nb_event//25000)
1632 else:
1633 nb_submit =1
1634
1635 if MADEVENT:
1636 import internal.systematics as systematics
1637 else:
1638 import madgraph.various.systematics as systematics
1639
1640
1641 if nb_submit in [0,1]:
1642 systematics.call_systematics([input, output] + opts,
1643 log=lambda x: logger.info(str(x)),
1644 result=result_file
1645 )
1646
1647 elif self.options['run_mode'] in [1,2]:
1648 event_per_job = nb_event // nb_submit
1649 nb_job_with_plus_one = nb_event % nb_submit
1650 start_event, stop_event = 0,0
1651 for i in range(nb_submit):
1652
1653 event_requested = event_per_job
1654 if i < nb_job_with_plus_one:
1655 event_requested += 1
1656 start_event = stop_event
1657 stop_event = start_event + event_requested
1658
1659 prog = sys.executable
1660 input_files = [os.path.basename(input)]
1661 output_files = ['./tmp_%s_%s' % (i, os.path.basename(output)),
1662 './log_sys_%s.txt' % (i)]
1663 argument = []
1664 if not __debug__:
1665 argument.append('-O')
1666 argument += [pjoin(self.me_dir, 'bin', 'internal', 'systematics.py'),
1667 input_files[0], output_files[0]] + opts +\
1668 ['--start_event=%i' % start_event,
1669 '--stop_event=%i' %stop_event,
1670 '--result=./log_sys_%s.txt' %i,
1671 '--lhapdf_config=%s' % self.options['lhapdf']]
1672 required_output = output_files
1673 self.cluster.cluster_submit(prog, argument,
1674 input_files=input_files,
1675 output_files=output_files,
1676 cwd=os.path.dirname(output),
1677 required_output=required_output,
1678 stdout='/dev/null'
1679 )
1680 starttime = time.time()
1681 update_status = lambda idle, run, finish: \
1682 self.update_status((idle, run, finish, 'running systematics'), level=None,
1683 force=False, starttime=starttime)
1684
1685 try:
1686 self.cluster.wait(os.path.dirname(output), update_status, update_first=update_status)
1687 except Exception:
1688 self.cluster.remove()
1689 old_run_mode = self.options['run_mode']
1690 self.options['run_mode'] =0
1691 try:
1692 out = self.do_systematics(line)
1693 finally:
1694 self.options['run_mode'] = old_run_mode
1695
1696 all_cross = []
1697 for i in range(nb_submit):
1698 pos=0
1699 for line in open(pjoin(os.path.dirname(output), 'log_sys_%s.txt'%i)):
1700 if line.startswith('#'):
1701 continue
1702 split = line.split()
1703 if len(split) in [0,1]:
1704 continue
1705 key = tuple(float(x) for x in split[:-1])
1706 cross= float(split[-1])
1707 if 'event_norm' in self.run_card and \
1708 self.run_card['event_norm'] in ['average', 'unity']:
1709 cross *= (event_per_job+1 if i <nb_job_with_plus_one else event_per_job)
1710 if len(all_cross) > pos:
1711 all_cross[pos] += cross
1712 else:
1713 all_cross.append(cross)
1714 pos+=1
1715
1716 if 'event_norm' in self.run_card and \
1717 self.run_card['event_norm'] in ['unity']:
1718 all_cross= [cross/nb_event for cross in all_cross]
1719
1720 sys_obj = systematics.call_systematics([input, None] + opts,
1721 log=lambda x: logger.info(str(x)),
1722 result=result_file,
1723 running=False
1724 )
1725 sys_obj.print_cross_sections(all_cross, nb_event, result_file)
1726
1727
1728 subprocess.call(['cat']+\
1729 ['./tmp_%s_%s' % (i, os.path.basename(output)) for i in range(nb_submit)],
1730 stdout=open(output,'w'),
1731 cwd=os.path.dirname(output))
1732 for i in range(nb_submit):
1733 os.remove('%s/tmp_%s_%s' %(os.path.dirname(output),i,os.path.basename(output)))
1734
1735
1736
1737
1738
1739
1740 self.update_status('End of systematics computation', level='parton', makehtml=False)
1741
1742
1743
1745 """ syntax is "reweight RUN_NAME"
1746 Allow to reweight the events generated with a new choices of model
1747 parameter. Description of the methods are available here
1748 cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Reweight
1749 """
1750
1751
1752 def check_multicore(self):
1753 """ determine if the cards are save for multicore use"""
1754 card = pjoin(self.me_dir, 'Cards', 'reweight_card.dat')
1755
1756 multicore = True
1757 if self.options['run_mode'] in [0,1]:
1758 multicore = False
1759
1760 lines = [l.strip() for l in open(card) if not l.strip().startswith('#')]
1761 while lines and not lines[0].startswith('launch'):
1762 line = lines.pop(0)
1763
1764 if line.startswith('change') and line[6:].strip().startswith('output'):
1765 return False
1766 if line.startswith('change') and line[6:].strip().startswith('multicore'):
1767 split_line = line.split()
1768 if len(split_line) > 2:
1769 multicore = bool(split_line[2])
1770
1771
1772 lines = [line[6:].strip() for line in lines if line.startswith('change')]
1773 for line in lines:
1774 if line.startswith(('process','model','output', 'rwgt_dir')):
1775 return False
1776 elif line.startswith('multicore'):
1777 split_line = line.split()
1778 if len(split_line) > 1:
1779 multicore = bool(split_line[1])
1780
1781 return multicore
1782
1783
1784
1785 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')):
1786 return
1787
1788 if '--multicore=create' in line:
1789 multicore='create'
1790 elif '--multicore=wait' in line:
1791 multicore='wait'
1792 else:
1793 multicore=False
1794
1795
1796 if MADEVENT and not self.options['mg5_path']:
1797 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system.
1798 You can install it and set its path in ./Cards/me5_configuration.txt'''
1799 elif MADEVENT:
1800 sys.path.append(self.options['mg5_path'])
1801 try:
1802 import madgraph.interface.reweight_interface as reweight_interface
1803 except ImportError:
1804 raise self.ConfigurationError, '''Can\'t load Reweight module.
1805 The variable mg5_path might not be correctly configured.'''
1806
1807
1808
1809 if not '-from_cards' in line:
1810 self.keep_cards(['reweight_card.dat'], ignore=['*'])
1811 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False)
1812
1813
1814 args = self.split_arg(line)
1815
1816 if not self.force_run:
1817
1818 if self.run_name and self.results.current and self.results.current['cross'] == 0:
1819 self.results.delete_run(self.run_name, self.run_tag)
1820 self.results.save()
1821
1822 if not hasattr(self, 'run_card'):
1823 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat'))
1824
1825
1826 command = [sys.executable]
1827 if os.path.exists(pjoin(self.me_dir, 'bin', 'madevent')):
1828 command.append(pjoin(self.me_dir, 'bin', 'internal','madevent_interface.py'))
1829 else:
1830 command.append(pjoin(self.me_dir, 'bin', 'internal', 'amcatnlo_run_interface.py'))
1831 if not isinstance(self, cmd.CmdShell):
1832 command.append('--web')
1833 command.append('reweight')
1834
1835
1836 if self.options['nb_core']==1 or self.run_card['nevents'] < 101 or not check_multicore(self):
1837 if self.run_name:
1838 command.append(self.run_name)
1839 else:
1840 command += args
1841 if '-from_cards' not in command:
1842 command.append('-from_cards')
1843 p = misc.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, cwd=os.getcwd())
1844 while p.poll() is None:
1845 line = p.stdout.readline()
1846 if any(t in line for t in ['INFO:', 'WARNING:', 'CRITICAL:', 'ERROR:', 'root:','KEEP:']) and \
1847 not '***********' in line:
1848 print line[:-1].replace('INFO', 'REWEIGHT').replace('KEEP:','')
1849 elif __debug__ and line:
1850 logger.debug(line[:-1])
1851 if p.returncode !=0:
1852 logger.error("Reweighting failed")
1853 return
1854 self.results = self.load_results_db()
1855
1856 try:
1857 if self.results[self.run_name][-2]['cross']==0:
1858 self.results.delete_run(self.run_name,self.results[self.run_name][-2]['tag'])
1859 except:
1860 pass
1861 try:
1862 if self.results.current['cross'] == 0 and self.run_name:
1863 self.results.delete_run(self.run_name, self.run_tag)
1864 except:
1865 pass
1866
1867 try:
1868 self.results.def_current(self.run_name, self.run_tag)
1869 except Exception:
1870 pass
1871 return
1872
1873 else:
1874
1875 if not isinstance(self.cluster, cluster.MultiCore):
1876 mycluster = cluster.MultiCore(nb_core=self.options['nb_core'])
1877 else:
1878 mycluster = self.cluster
1879
1880 new_args=list(args)
1881 self.check_decay_events(new_args)
1882 try:
1883 os.remove(pjoin(self.me_dir,'rw_me','rwgt.pkl'))
1884 except Exception, error:
1885 pass
1886
1887 import madgraph.various.lhe_parser as lhe_parser
1888
1889 if 'nevt_job' in self.run_card and self.run_card['nevt_job'] !=-1:
1890 nevt_job = self.run_card['nevt_job']
1891 else:
1892 nevt_job = max(5000, self.run_card['nevents']/50)
1893 logger.info("split the event file in bunch of %s events" % nevt_job)
1894 nb_file = lhe_parser.EventFile(new_args[0]).split(nevt_job)
1895 starttime = time.time()
1896 update_status = lambda idle, run, finish: \
1897 self.update_status((idle, run, finish, 'reweight'), level=None,
1898 force=False, starttime=starttime)
1899
1900 all_lhe = []
1901 devnull= open(os.devnull)
1902 for i in range(nb_file):
1903 new_command = list(command)
1904 new_command.append('%s_%s.lhe' % (new_args[0],i))
1905 all_lhe.append('%s_%s.lhe' % (new_args[0],i))
1906 if '-from_cards' not in command:
1907 new_command.append('-from_cards')
1908 if i==0:
1909 if __debug__:
1910 stdout = None
1911 else:
1912 stdout = open(pjoin(self.me_dir,'Events', self.run_name, 'reweight.log'),'w')
1913 new_command.append('--multicore=create')
1914 else:
1915 stdout = devnull
1916
1917 new_command.append('--multicore=wait')
1918 mycluster.submit(prog=command[0], argument=new_command[1:], stdout=stdout, cwd=os.getcwd())
1919 mycluster.wait(self.me_dir,update_status)
1920 devnull.close()
1921 logger.info("Collect and combine the various output file.")
1922 lhe = lhe_parser.MultiEventFile(all_lhe, parse=False)
1923 nb_event, cross_sections = lhe.write(new_args[0], get_info=True)
1924 if any(os.path.exists('%s_%s_debug.log' % (f, self.run_tag)) for f in all_lhe):
1925 for f in all_lhe:
1926 if os.path.exists('%s_%s_debug.log' % (f, self.run_tag)):
1927 raise Exception, "Some of the run failed: Please read %s_%s_debug.log" % (f, self.run_tag)
1928
1929
1930 if 'event_norm' in self.run_card and self.run_card['event_norm'] == 'average':
1931 for key, value in cross_sections.items():
1932 cross_sections[key] = value / (nb_event+1)
1933 lhe.remove()
1934 for key in cross_sections:
1935 if key == 'orig' or key.isdigit():
1936 continue
1937 logger.info('%s : %s pb' % (key, cross_sections[key]))
1938 return
1939
1940
1941
1942 self.to_store.append('event')
1943
1944 if self.results.current['cross'] == 0 and self.run_name:
1945 self.results.delete_run(self.run_name, self.run_tag)
1946
1947 self.check_decay_events(args)
1948
1949 reweight_cmd = reweight_interface.ReweightInterface(args[0], mother=self)
1950
1951
1952 wgt_names = reweight_cmd.get_weight_names()
1953 if wgt_names == [''] and reweight_cmd.has_nlo:
1954 self.update_status('Running Reweighting (LO approximate)', level='madspin')
1955 else:
1956 self.update_status('Running Reweighting', level='madspin')
1957
1958 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat')
1959 reweight_cmd.raw_input=False
1960 reweight_cmd.me_dir = self.me_dir
1961 reweight_cmd.multicore = multicore
1962 print "We are in mode", multicore
1963 reweight_cmd.import_command_file(path)
1964 reweight_cmd.do_quit('')
1965
1966 logger.info("quit rwgt")
1967
1968
1969
1970
1971 try:
1972 self.results.def_current(self.run_name, self.run_tag)
1973 except Exception:
1974 pass
1975
1976
1978 """launch pgs"""
1979
1980 args = self.split_arg(line)
1981
1982 if '--no_default' in args:
1983 no_default = True
1984 args.remove('--no_default')
1985 else:
1986 no_default = False
1987
1988 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
1989 logger.info('No pgs_card detected, so not run pgs')
1990 return
1991
1992
1993
1994
1995
1996
1997 lock = self.check_pgs(args, no_default=no_default)
1998
1999
2000 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
2001 files.cp(pjoin(self.me_dir, 'Cards', 'pgs_card_default.dat'),
2002 pjoin(self.me_dir, 'Cards', 'pgs_card.dat'))
2003 logger.info('No pgs card found. Take the default one.')
2004
2005 if not (no_default or self.force):
2006 self.ask_edit_cards(['pgs_card.dat'])
2007
2008 self.update_status('prepare PGS run', level=None)
2009
2010 pgsdir = pjoin(self.options['pythia-pgs_path'], 'src')
2011 eradir = self.options['exrootanalysis_path']
2012 madir = self.options['madanalysis_path']
2013 td = self.options['td_path']
2014
2015
2016 if not misc.is_executable(pjoin(pgsdir, 'pgs')):
2017 logger.info('No PGS executable -- running make')
2018 misc.compile(cwd=pgsdir)
2019
2020 self.update_status('Running PGS', level='pgs')
2021
2022 tag = self.run_tag
2023
2024 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, self.run_tag))
2025 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
2026 self.banner.add(pjoin(self.me_dir, 'Cards','pgs_card.dat'))
2027 self.banner.write(banner_path)
2028 else:
2029 open(banner_path, 'w').close()
2030
2031
2032
2033
2034 if lock:
2035 lock.wait()
2036
2037 ff = open(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 'w')
2038 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
2039 text = open(banner_path).read()
2040 text = '#%s' % text.replace('\n','\n#')
2041 dico = self.results[self.run_name].get_current_info()
2042 text +='\n## Integrated weight (pb) : %.4g' % dico['cross']
2043 text +='\n## Number of Event : %s\n' % dico['nb_event']
2044 ff.writelines(text)
2045 ff.close()
2046
2047 try:
2048 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done'))
2049 except Exception:
2050 pass
2051
2052 pgs_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_pgs.log" % tag)
2053 self.cluster.launch_and_wait('../bin/internal/run_pgs',
2054 argument=[pgsdir], cwd=pjoin(self.me_dir,'Events'),
2055 stdout=pgs_log, stderr=subprocess.STDOUT)
2056
2057 if not os.path.exists(pjoin(self.me_dir, 'Events', 'pgs.done')):
2058 logger.error('Fail to create LHCO events')
2059 return
2060 else:
2061 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done'))
2062
2063 if os.path.getsize(banner_path) == os.path.getsize(pjoin(self.me_dir, 'Events','pgs_events.lhco')):
2064 misc.call(['cat pgs_uncleaned_events.lhco >> pgs_events.lhco'],
2065 cwd=pjoin(self.me_dir, 'Events'))
2066 os.remove(pjoin(self.me_dir, 'Events', 'pgs_uncleaned_events.lhco '))
2067
2068
2069 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHCOlympicsConverter')):
2070 self.update_status('Creating PGS Root File', level='pgs')
2071 try:
2072 misc.call([eradir+'/ExRootLHCOlympicsConverter',
2073 'pgs_events.lhco',pjoin('%s/%s_pgs_events.root' % (self.run_name, tag))],
2074 cwd=pjoin(self.me_dir, 'Events'))
2075 except Exception:
2076 logger.warning('fail to produce Root output [problem with ExRootAnalysis')
2077 if os.path.exists(pjoin(self.me_dir, 'Events', 'pgs_events.lhco')):
2078
2079 files.mv(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'),
2080 pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag))
2081 self.create_plot('PGS')
2082 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag))
2083
2084 self.update_status('finish', level='pgs', makehtml=False)
2085
2086
2088 """Require MG5 directory: Compute automatically the widths of a set
2089 of particles"""
2090
2091
2092
2093 args = self.split_arg(line)
2094 opts = self.check_compute_widths(args)
2095
2096 from madgraph.interface.master_interface import MasterCmd
2097 cmd = MasterCmd()
2098 self.define_child_cmd_interface(cmd, interface=False)
2099 cmd.exec_cmd('set automatic_html_opening False --no_save')
2100 if not opts['path']:
2101 opts['path'] = pjoin(self.me_dir, 'Cards', 'param_card.dat')
2102 if not opts['force'] :
2103 self.ask_edit_cards(['param_card'],[], plot=False)
2104
2105
2106 line = 'compute_widths %s %s' % \
2107 (' '.join([str(i) for i in opts['particles']]),
2108 ' '.join('--%s=%s' % (key,value) for (key,value) in opts.items()
2109 if key not in ['model', 'force', 'particles'] and value))
2110 cmd.exec_cmd(line, model=opts['model'])
2111 self.child = None
2112 del cmd
2113
2114
2116 """Not in help:Print the cross-section/ number of events for a given run"""
2117
2118 args = self.split_arg(line)
2119 options={'path':None, 'mode':'w', 'format':'full'}
2120 for arg in list(args):
2121 if arg.startswith('--') and '=' in arg:
2122 name,value=arg.split('=',1)
2123 name = name [2:]
2124 options[name] = value
2125 args.remove(arg)
2126
2127
2128 if len(args) > 0:
2129 run_name = args[0]
2130 else:
2131 for i, run_name in enumerate(self.results.order):
2132 for j, one_result in enumerate(self.results[run_name]):
2133 if i or j:
2134 options['mode'] = "a"
2135 if options['path']:
2136 self.print_results_in_file(one_result, options['path'], options['mode'], options['format'])
2137 else:
2138 self.print_results_in_shell(one_result)
2139 return
2140
2141 if run_name not in self.results:
2142 raise self.InvalidCmd('%s is not a valid run_name or it doesn\'t have any information' \
2143 % run_name)
2144
2145
2146 if len(args) == 2:
2147 tag = args[1]
2148 if tag.isdigit():
2149 tag = int(tag) - 1
2150 if len(self.results[run_name]) < tag:
2151 raise self.InvalidCmd('Only %s different tag available' % \
2152 len(self.results[run_name]))
2153 data = self.results[run_name][tag]
2154 else:
2155 data = self.results[run_name].return_tag(tag)
2156 else:
2157 data = self.results[run_name].return_tag(None)
2158
2159 if options['path']:
2160 self.print_results_in_file(data, options['path'], options['mode'], options['format'])
2161 else:
2162 self.print_results_in_shell(data)
2163
2168
2169
2170
2171
2172
2173 @staticmethod
2174 - def runMA5(MA5_interpreter, MA5_cmds, MA5_runtag, logfile_path, advertise_log=True):
2175 """ Run MA5 in a controlled environnment."""
2176 successfull_MA5_run = True
2177
2178 try:
2179
2180 MA5_logger = None
2181 MA5_logger = logging.getLogger('MA5')
2182 BackUp_MA5_handlers = MA5_logger.handlers
2183 for handler in BackUp_MA5_handlers:
2184 MA5_logger.removeHandler(handler)
2185 file_handler = logging.FileHandler(logfile_path)
2186 MA5_logger.addHandler(file_handler)
2187 if advertise_log:
2188 logger.info("Follow Madanalysis5 run with the following command in a separate terminal:")
2189 logger.info(' tail -f %s'%logfile_path)
2190
2191 with misc.stdchannel_redirected(sys.stdout, os.devnull):
2192 with misc.stdchannel_redirected(sys.stderr, os.devnull):
2193 MA5_interpreter.print_banner()
2194 MA5_interpreter.load(MA5_cmds)
2195 except Exception as e:
2196 logger.warning("MadAnalysis5 failed to run the commands for task "+
2197 "'%s'. Madanalys5 analysis will be skipped."%MA5_runtag)
2198 error=StringIO.StringIO()
2199 traceback.print_exc(file=error)
2200 logger.debug('MadAnalysis5 error was:')
2201 logger.debug('-'*60)
2202 logger.debug(error.getvalue()[:-1])
2203 logger.debug('-'*60)
2204 successfull_MA5_run = False
2205 finally:
2206 if not MA5_logger is None:
2207 for handler in MA5_logger.handlers:
2208 MA5_logger.removeHandler(handler)
2209 for handler in BackUp_MA5_handlers:
2210 MA5_logger.addHandler(handler)
2211
2212 return successfull_MA5_run
2213
2214
2215
2216
2217 @staticmethod
2221 """ Makes sure to correctly setup paths and constructs and return an MA5 path"""
2222
2223 MA5path = os.path.normpath(pjoin(mg5_path,ma5_path))
2224
2225 if MA5path is None or not os.path.isfile(pjoin(MA5path,'bin','ma5')):
2226 return None
2227 if MA5path not in sys.path:
2228 sys.path.insert(0, MA5path)
2229
2230 try:
2231
2232
2233 import readline
2234 old_completer = readline.get_completer()
2235 old_delims = readline.get_completer_delims()
2236 old_history = [readline.get_history_item(i) for i in range(1,readline.get_current_history_length()+1)]
2237 except ImportError:
2238 old_completer, old_delims, old_history = None, None, None
2239 try:
2240 from madanalysis.interpreter.ma5_interpreter import MA5Interpreter
2241 with misc.stdchannel_redirected(sys.stdout, os.devnull):
2242 with misc.stdchannel_redirected(sys.stderr, os.devnull):
2243 MA5_interpreter = MA5Interpreter(MA5path, LoggerLevel=loglevel,
2244 LoggerStream=logstream,forced=forced,
2245 no_compilation=not compilation)
2246 except Exception as e:
2247 logger.warning('MadAnalysis5 failed to start so that MA5 analysis will be skipped.')
2248 error=StringIO.StringIO()
2249 traceback.print_exc(file=error)
2250 logger.debug('MadAnalysis5 error was:')
2251 logger.debug('-'*60)
2252 logger.debug(error.getvalue()[:-1])
2253 logger.debug('-'*60)
2254 MA5_interpreter = None
2255 finally:
2256
2257 if not old_history is None:
2258 readline.clear_history()
2259 for line in old_history:
2260 readline.add_history(line)
2261 if not old_completer is None:
2262 readline.set_completer(old_completer)
2263 if not old_delims is None:
2264 readline.set_completer_delims(old_delims)
2265
2266
2267 if not mg5_interface is None and any(not elem is None for elem in [old_completer, old_delims, old_history]):
2268 mg5_interface.set_readline_completion_display_matches_hook()
2269
2270 return MA5_interpreter
2271
2273 """Check the argument for the madanalysis5 command
2274 syntax: madanalysis5_parton [NAME]
2275 """
2276
2277 MA5_options = {'MA5_stdout_lvl':'default'}
2278
2279 stdout_level_tags = [a for a in args if a.startswith('--MA5_stdout_lvl=')]
2280 for slt in stdout_level_tags:
2281 lvl = slt.split('=')[1].strip()
2282 try:
2283
2284 MA5_options['MA5_stdout_lvl']=int(lvl)
2285 except ValueError:
2286 if lvl.startswith('logging.'):
2287 lvl = lvl[8:]
2288 try:
2289 MA5_options['MA5_stdout_lvl'] = getattr(logging, lvl)
2290 except:
2291 raise InvalidCmd("MA5 output level specification"+\
2292 " '%s' is incorrect." % str(lvl))
2293 args.remove(slt)
2294
2295 if mode=='parton':
2296
2297
2298 MA5_options['inputs'] = '*.lhe'
2299 elif mode=='hadron':
2300
2301
2302
2303 MA5_options['inputs'] = ['fromCard']
2304 else:
2305 raise MadGraph5Error('Mode %s not reckognized'%mode+
2306 ' in function check_madanalysis5.')
2307
2308 if not self.options['madanalysis5_path']:
2309 logger.info('Now trying to read the configuration file again'+
2310 ' to find MadAnalysis5 path')
2311 self.set_configuration()
2312
2313 if not self.options['madanalysis5_path'] or not \
2314 os.path.exists(pjoin(self.options['madanalysis5_path'],'bin','ma5')):
2315 error_msg = 'No valid MadAnalysis5 path set.\n'
2316 error_msg += 'Please use the set command to define the path and retry.\n'
2317 error_msg += 'You can also define it in the configuration file.\n'
2318 error_msg += 'Finally, it can be installed automatically using the'
2319 error_msg += ' install command.\n'
2320 raise self.InvalidCmd(error_msg)
2321
2322
2323 if not os.path.isfile(pjoin(self.me_dir,
2324 'Cards','madanalysis5_%s_card.dat'%mode)):
2325 raise self.InvalidCmd('Your installed version of MadAnalysis5 and/or'+\
2326 ' MadGraph5_aMCatNLO does not seem to support analysis at'+
2327 '%s level.'%mode)
2328
2329 tag = [a for a in args if a.startswith('--tag=')]
2330 if tag:
2331 args.remove(tag[0])
2332 tag = tag[0][6:]
2333
2334 if len(args) == 0 and not self.run_name:
2335 if self.results.lastrun:
2336 args.insert(0, self.results.lastrun)
2337 else:
2338 raise self.InvalidCmd('No run name currently defined. '+
2339 'Please add this information.')
2340
2341 if len(args) >= 1:
2342 if mode=='parton' and args[0] != self.run_name and \
2343 not os.path.exists(pjoin(self.me_dir,'Events',args[0],
2344 'unweighted_events.lhe.gz')) and not os.path.exists(
2345 pjoin(self.me_dir,'Events',args[0])):
2346 raise self.InvalidCmd('No events file in the %s run.'%args[0])
2347 self.set_run_name(args[0], tag, level='madanalysis5_%s'%mode)
2348 else:
2349 if tag:
2350 self.run_card['run_tag'] = args[0]
2351 self.set_run_name(self.run_name, tag, level='madanalysis5_%s'%mode)
2352
2353 if mode=='parton':
2354 if any(t for t in args if t.startswith('--input=')):
2355 raise InvalidCmd('The option --input=<input_file> is not'+
2356 ' available when running partonic MadAnalysis5 analysis. The'+
2357 ' .lhe output of the selected run is used automatically.')
2358 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe')
2359 MA5_options['inputs'] = '%s.gz'%input_file
2360 if not os.path.exists('%s.gz'%input_file):
2361 if os.path.exists(input_file):
2362 misc.gzip(input_file, stdout='%s.gz' % input_file)
2363 else:
2364 logger.warning("LHE event file not found in \n%s\ns"%input_file+
2365 "Parton-level MA5 analysis will be skipped.")
2366
2367 if mode=='hadron':
2368
2369
2370 self.store_result()
2371
2372 hadron_tag = [t for t in args if t.startswith('--input=')]
2373 if hadron_tag and hadron_tag[0][8:]:
2374 hadron_inputs = hadron_tag[0][8:].split(',')
2375
2376
2377 elif MA5_options['inputs'] == ['fromCard']:
2378 hadron_inputs = banner_mod.MadAnalysis5Card(pjoin(self.me_dir,
2379 'Cards','madanalysis5_hadron_card.dat'),mode='hadron')['inputs']
2380
2381
2382
2383 MA5_options['inputs'] = []
2384 special_source_tags = []
2385 for htag in hadron_inputs:
2386
2387 if htag in special_source_tags:
2388
2389 continue
2390
2391 if os.path.isfile(htag) or (os.path.exists(htag) and
2392 stat.S_ISFIFO(os.stat(htag).st_mode)):
2393 MA5_options['inputs'].append(htag)
2394 continue
2395
2396
2397
2398 file_candidates = misc.glob(htag, pjoin(self.me_dir,'Events',self.run_name))+\
2399 misc.glob('%s.gz'%htag, pjoin(self.me_dir,'Events',self.run_name))
2400 priority_files = [f for f in file_candidates if
2401 self.run_card['run_tag'] in os.path.basename(f)]
2402 priority_files = [f for f in priority_files if
2403 'EVENTS' in os.path.basename(f).upper()]
2404
2405 for f in file_candidates:
2406 if os.path.basename(f).startswith('unweighted_events.lhe'):
2407 priority_files.append(f)
2408 if priority_files:
2409 MA5_options['inputs'].append(priority_files[-1])
2410 continue
2411 if file_candidates:
2412 MA5_options['inputs'].append(file_candidates[-1])
2413 continue
2414
2415 return MA5_options
2416
2418 """Ask the question when launching madanalysis5.
2419 In the future we can ask here further question about the MA5 run, but
2420 for now we just edit the cards"""
2421
2422 cards = ['madanalysis5_%s_card.dat'%runtype]
2423 self.keep_cards(cards)
2424
2425 if self.force:
2426 return runtype
2427
2428
2429
2430 auto=False
2431 if mode=='auto':
2432 auto=True
2433 if auto:
2434 self.ask_edit_cards(cards, mode='auto', plot=False)
2435 else:
2436 self.ask_edit_cards(cards, plot=False)
2437
2438
2439
2440 mode = runtype
2441 return mode
2442
2444 "Complete the madanalysis5 command"
2445 args = self.split_arg(line[0:begidx], error=False)
2446 if len(args) == 1:
2447
2448 data = []
2449 for name in banner_mod.MadAnalysis5Card._default_hadron_inputs:
2450 data += misc.glob(pjoin('*','%s'%name), pjoin(self.me_dir, 'Events'))
2451 data += misc.glob(pjoin('*','%s.gz'%name), pjoin(self.me_dir, 'Events'))
2452 data = [n.rsplit('/',2)[1] for n in data]
2453 tmp1 = self.list_completion(text, data)
2454 if not self.run_name:
2455 return tmp1
2456 else:
2457 tmp2 = self.list_completion(text, ['-f',
2458 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line)
2459 return tmp1 + tmp2
2460
2461 elif '--MA5_stdout_lvl=' in line and not any(arg.startswith(
2462 '--MA5_stdout_lvl=') for arg in args):
2463 return self.list_completion(text,
2464 ['--MA5_stdout_lvl=%s'%opt for opt in
2465 ['logging.INFO','logging.DEBUG','logging.WARNING',
2466 'logging.CRITICAL','90']], line)
2467 elif '--input=' in line and not any(arg.startswith(
2468 '--input=') for arg in args):
2469 return self.list_completion(text, ['--input=%s'%opt for opt in
2470 (banner_mod.MadAnalysis5Card._default_hadron_inputs +['path'])], line)
2471 else:
2472 return self.list_completion(text, ['-f',
2473 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line)
2474
2476 """launch MadAnalysis5 at the hadron level."""
2477 return self.run_madanalysis5(line,mode='hadron')
2478
2480 """launch MadAnalysis5 at the parton level or at the hadron level with
2481 a specific command line."""
2482
2483
2484 args = self.split_arg(line)
2485
2486 if '--no_default' in args:
2487 no_default = True
2488 args.remove('--no_default')
2489 else:
2490 no_default = False
2491
2492 if no_default:
2493
2494 if mode=='parton' and not os.path.exists(pjoin(self.me_dir, 'Cards',
2495 'madanalysis5_parton_card.dat')):
2496 return
2497 if mode=='hadron' and not os.path.exists(pjoin(self.me_dir, 'Cards',
2498 'madanalysis5_hadron_card.dat')):
2499 return
2500 else:
2501
2502
2503 self.ask_madanalysis5_run_configuration(runtype=mode)
2504
2505 if not self.options['madanalysis5_path'] or \
2506 all(not os.path.exists(pjoin(self.me_dir, 'Cards',card)) for card in
2507 ['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat']):
2508 if no_default:
2509 return
2510 else:
2511 raise InvalidCmd('You must have MadAnalysis5 available to run'+
2512 " this command. Consider installing it with the 'install' function.")
2513
2514 if not self.run_name:
2515 MA5_opts = self.check_madanalysis5(args, mode=mode)
2516 self.configure_directory(html_opening =False)
2517 else:
2518
2519 self.configure_directory(html_opening =False)
2520 MA5_opts = self.check_madanalysis5(args, mode=mode)
2521
2522
2523 if MA5_opts['inputs']==[]:
2524 if no_default:
2525 logger.warning('No hadron level input found to run MadAnalysis5 on.'+
2526 ' Skipping its hadron-level analysis.')
2527 return
2528 else:
2529 raise self.InvalidCmd('\nNo input files specified or availabled for'+
2530 ' this MadAnalysis5 hadron-level run.\nPlease double-check the options of this'+
2531 ' MA5 command (or card) and which output files\nare currently in the chosen'+
2532 " run directory '%s'."%self.run_name)
2533
2534 MA5_card = banner_mod.MadAnalysis5Card(pjoin(self.me_dir, 'Cards',
2535 'madanalysis5_%s_card.dat'%mode), mode=mode)
2536
2537 if MA5_card._skip_analysis:
2538 logger.info('Madanalysis5 %s-level analysis was skipped following user request.'%mode)
2539 logger.info("To run the analysis, remove or comment the tag '%s skip_analysis' "
2540 %banner_mod.MadAnalysis5Card._MG5aMC_escape_tag+
2541 "in\n '%s'."%pjoin(self.me_dir, 'Cards','madanalysis5_%s_card.dat'%mode))
2542 return
2543
2544 MA5_cmds_list = MA5_card.get_MA5_cmds(MA5_opts['inputs'],
2545 pjoin(self.me_dir,'MA5_%s_ANALYSIS'%mode.upper()),
2546 run_dir_path = pjoin(self.me_dir,'Events', self.run_name),
2547 UFO_model_path=pjoin(self.me_dir,'bin','internal','ufomodel'),
2548 run_tag = self.run_tag)
2549
2550
2551
2552
2553
2554
2555
2556
2557 self.update_status('\033[92mRunning MadAnalysis5 [arXiv:1206.1599]\033[0m',
2558 level='madanalysis5_%s'%mode)
2559 if mode=='hadron':
2560 logger.info('Hadron input files considered:')
2561 for input in MA5_opts['inputs']:
2562 logger.info(' --> %s'%input)
2563 elif mode=='parton':
2564 logger.info('Parton input file considered:')
2565 logger.info(' --> %s'%MA5_opts['inputs'])
2566
2567
2568
2569
2570 if MA5_opts['MA5_stdout_lvl']=='default':
2571 if MA5_card['stdout_lvl'] is None:
2572 MA5_lvl = self.options['stdout_level']
2573 else:
2574 MA5_lvl = MA5_card['stdout_lvl']
2575 else:
2576 MA5_lvl = MA5_opts['MA5_stdout_lvl']
2577
2578
2579 MA5_interpreter = CommonRunCmd.get_MadAnalysis5_interpreter(
2580 self.options['mg5_path'],
2581 self.options['madanalysis5_path'],
2582 logstream=sys.stdout,
2583 loglevel=100,
2584 forced=True,
2585 compilation=True)
2586
2587
2588
2589 if MA5_interpreter is None:
2590 return
2591
2592
2593 used_up_fifos = []
2594
2595 for MA5_runtag, MA5_cmds in MA5_cmds_list:
2596
2597
2598 MA5_interpreter.setLogLevel(100)
2599
2600 if mode=='hadron':
2601 MA5_interpreter.init_reco()
2602 else:
2603 MA5_interpreter.init_parton()
2604 MA5_interpreter.setLogLevel(MA5_lvl)
2605
2606 if MA5_runtag!='default':
2607 if MA5_runtag.startswith('_reco_'):
2608 logger.info("MadAnalysis5 now running the reconstruction '%s'..."%
2609 MA5_runtag[6:],'$MG:color:GREEN')
2610 elif MA5_runtag=='Recasting':
2611 logger.info("MadAnalysis5 now running the recasting...",
2612 '$MG:color:GREEN')
2613 else:
2614 logger.info("MadAnalysis5 now running the '%s' analysis..."%
2615 MA5_runtag,'$MG:color:GREEN')
2616
2617
2618
2619 if not CommonRunCmd.runMA5(MA5_interpreter, MA5_cmds, MA5_runtag,
2620 pjoin(self.me_dir,'Events',self.run_name,'%s_MA5_%s.log'%(self.run_tag,MA5_runtag))):
2621
2622 return
2623
2624 if MA5_runtag.startswith('_reco_'):
2625
2626
2627
2628
2629 links_created=[]
2630 for i, input in enumerate(MA5_opts['inputs']):
2631
2632
2633 if not banner_mod.MadAnalysis5Card.events_can_be_reconstructed(input):
2634 continue
2635
2636 if input.endswith('.fifo'):
2637 if input in used_up_fifos:
2638
2639 continue
2640 else:
2641 used_up_fifos.append(input)
2642
2643 reco_output = pjoin(self.me_dir,
2644 'MA5_%s_ANALYSIS%s_%d'%(mode.upper(),MA5_runtag,i+1))
2645
2646 reco_event_file = misc.glob('*.lhe.gz',pjoin(reco_output,'Output','_reco_events'))+\
2647 misc.glob('*.root',pjoin(reco_output,'Output','_reco_events'))
2648 if len(reco_event_file)==0:
2649 raise MadGraph5Error, "MadAnalysis5 failed to produce the "+\
2650 "reconstructed event file for reconstruction '%s'."%MA5_runtag[6:]
2651 reco_event_file = reco_event_file[0]
2652
2653 shutil.move(reco_output,pjoin(self.me_dir,'HTML',
2654 self.run_name,'%s_MA5_%s_ANALYSIS%s_%d'%
2655 (self.run_tag,mode.upper(),MA5_runtag,i+1)))
2656
2657 links_created.append(os.path.basename(reco_event_file))
2658 files.ln(pjoin(self.me_dir,'HTML',self.run_name,
2659 '%s_MA5_%s_ANALYSIS%s_%d'%(self.run_tag,mode.upper(),
2660 MA5_runtag,i+1),'Output','_reco_events',links_created[-1]),
2661 pjoin(self.me_dir,'Events',self.run_name))
2662
2663 logger.info("MadAnalysis5 successfully completed the reconstruction "+
2664 "'%s'. Links to the reconstructed event files are:"%MA5_runtag[6:])
2665 for link in links_created:
2666 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,link))
2667 continue
2668
2669 if MA5_runtag.upper()=='RECASTING':
2670 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\
2671 %(mode.upper(),MA5_runtag),'Output','CLs_output_summary.dat')
2672 else:
2673 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\
2674 %(mode.upper(),MA5_runtag),'PDF','main.pdf')
2675 has_pdf = True
2676 if not os.path.isfile(target):
2677 has_pdf = False
2678
2679
2680 if MA5_runtag.upper()=='RECASTING':
2681 carboncopy_name = '%s_MA5_CLs.dat'%(self.run_tag)
2682 else:
2683 carboncopy_name = '%s_MA5_%s_analysis_%s.pdf'%(
2684 self.run_tag,mode,MA5_runtag)
2685 if has_pdf:
2686 shutil.copy(target, pjoin(self.me_dir,'Events',self.run_name,carboncopy_name))
2687 else:
2688 logger.error('MadAnalysis5 failed to create PDF output')
2689 if MA5_runtag!='default':
2690 logger.info("MadAnalysis5 successfully completed the "+
2691 "%s. Reported results are placed in:"%("analysis '%s'"%MA5_runtag
2692 if MA5_runtag.upper()!='RECASTING' else "recasting"))
2693 else:
2694 logger.info("MadAnalysis5 successfully completed the analysis."+
2695 " Reported results are placed in:")
2696 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,carboncopy_name))
2697
2698 anal_dir = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s' %(mode.upper(),MA5_runtag))
2699 if not os.path.exists(anal_dir):
2700 logger.error('MadAnalysis5 failed to completed succesfully')
2701 return
2702
2703 shutil.move(anal_dir, pjoin(self.me_dir,'HTML',self.run_name,
2704 '%s_MA5_%s_ANALYSIS_%s'%(self.run_tag,mode.upper(),MA5_runtag)))
2705
2706
2707
2708 new_details={}
2709 for detail in ['nb_event','cross','error']:
2710 new_details[detail] = \
2711 self.results[self.run_name].get_current_info()[detail]
2712 for detail in new_details:
2713 self.results.add_detail(detail,new_details[detail])
2714
2715 self.update_status('Finished MA5 analyses.', level='madanalysis5_%s'%mode,
2716 makehtml=False)
2717
2718
2719 self.banner.add(pjoin(self.me_dir, 'Cards',
2720 'madanalysis5_%s_card.dat'%mode))
2721 banner_path = pjoin(self.me_dir,'Events', self.run_name,
2722 '%s_%s_banner.txt'%(self.run_name, self.run_tag))
2723 self.banner.write(banner_path)
2724
2725 if not no_default:
2726 logger.info('Find more information about this run on the HTML local page')
2727 logger.info(' --> %s'%pjoin(self.me_dir,'index.html'))
2728
2729
2730
2731
2732
2734 """ run delphes and make associate root file/plot """
2735
2736 args = self.split_arg(line)
2737
2738 if '--no_default' in args:
2739 no_default = True
2740 args.remove('--no_default')
2741 else:
2742 no_default = False
2743
2744 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
2745 logger.info('No delphes_card detected, so not run Delphes')
2746 return
2747
2748
2749 filepath = self.check_delphes(args, nodefault=no_default)
2750 if no_default and not filepath:
2751 return
2752
2753 self.update_status('prepare delphes run', level=None)
2754
2755 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
2756 delphes3 = False
2757 prog = '../bin/internal/run_delphes'
2758 if filepath and '.hepmc' in filepath[:-10]:
2759 raise self.InvalidCmd, 'delphes2 do not support hepmc'
2760 else:
2761 delphes3 = True
2762 prog = '../bin/internal/run_delphes3'
2763
2764
2765
2766 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
2767 if no_default:
2768 logger.info('No delphes_card detected, so not running Delphes')
2769 return
2770 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_card_default.dat'),
2771 pjoin(self.me_dir, 'Cards', 'delphes_card.dat'))
2772 logger.info('No delphes card found. Take the default one.')
2773 if not delphes3 and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')):
2774 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_trigger_default.dat'),
2775 pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat'))
2776 if not (no_default or self.force):
2777 if delphes3:
2778 self.ask_edit_cards(['delphes_card.dat'], args)
2779 else:
2780 self.ask_edit_cards(['delphes_card.dat', 'delphes_trigger.dat'], args)
2781
2782 self.update_status('Running Delphes', level=None)
2783
2784 delphes_dir = self.options['delphes_path']
2785 tag = self.run_tag
2786 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
2787 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_card.dat'))
2788 if not delphes3:
2789 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_trigger.dat'))
2790 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)))
2791
2792 cross = self.results[self.run_name].get_current_info()['cross']
2793
2794 delphes_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_delphes.log" % tag)
2795 if not self.cluster:
2796 clus = cluster.onecore
2797 else:
2798 clus = self.cluster
2799 clus.launch_and_wait(prog,
2800 argument= [delphes_dir, self.run_name, tag, str(cross), filepath],
2801 stdout=delphes_log, stderr=subprocess.STDOUT,
2802 cwd=pjoin(self.me_dir,'Events'))
2803
2804 if not os.path.exists(pjoin(self.me_dir, 'Events',
2805 self.run_name, '%s_delphes_events.lhco.gz' % tag))\
2806 and not os.path.exists(pjoin(self.me_dir, 'Events',
2807 self.run_name, '%s_delphes_events.lhco' % tag)):
2808 logger.info('If you are interested in lhco output. please run root2lhco converter.')
2809 logger.info(' or edit bin/internal/run_delphes3 to run the converter automatically.')
2810
2811
2812
2813 madir = self.options['madanalysis_path']
2814 td = self.options['td_path']
2815
2816 if os.path.exists(pjoin(self.me_dir, 'Events',
2817 self.run_name, '%s_delphes_events.lhco' % tag)):
2818
2819 self.create_plot('Delphes')
2820
2821 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)):
2822 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag))
2823
2824 self.update_status('delphes done', level='delphes', makehtml=False)
2825
2826
2827
2829 """Find the pid of all particles in the final and initial states"""
2830 pids = set()
2831 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
2832 'subproc.mg'))]
2833 nb_init = self.ninitial
2834 pat = re.compile(r'''DATA \(IDUP\(I,\d+\),I=1,\d+\)/([\+\-\d,\s]*)/''', re.I)
2835 for Pdir in subproc:
2836 text = open(pjoin(self.me_dir, 'SubProcesses', Pdir, 'born_leshouche.inc')).read()
2837 group = pat.findall(text)
2838 for particles in group:
2839 particles = particles.split(',')
2840 pids.update(set(particles))
2841
2842 return pids
2843
2844
2869
2870
2871 if hasattr(self, 'pdffile') and self.pdffile:
2872 return self.pdffile
2873 else:
2874 for line in open(pjoin(self.me_dir,'Source','PDF','pdf_list.txt')):
2875 data = line.split()
2876 if len(data) < 4:
2877 continue
2878 if data[1].lower() == self.run_card['pdlabel'].lower():
2879 self.pdffile = check_cluster(pjoin(self.me_dir, 'lib', 'Pdfdata', data[2]))
2880 return self.pdffile
2881 else:
2882
2883 path = pjoin(self.me_dir, 'lib', 'PDFsets')
2884 if os.path.exists(path):
2885 self.pdffile = path
2886 else:
2887 self.pdffile = " "
2888 return self.pdffile
2889
2890
2900
2901
2902 - def do_set(self, line, log=True):
2903 """Set an option, which will be default for coming generations/outputs
2904 """
2905
2906
2907
2908 args = self.split_arg(line)
2909
2910 self.check_set(args)
2911
2912 if args[0] in self.options_configuration and '--no_save' not in args:
2913 self.do_save('options --auto')
2914
2915 if args[0] == "stdout_level":
2916 if args[1].isdigit():
2917 logging.root.setLevel(int(args[1]))
2918 logging.getLogger('madgraph').setLevel(int(args[1]))
2919 else:
2920 logging.root.setLevel(eval('logging.' + args[1]))
2921 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1]))
2922 if log: logger.info('set output information to level: %s' % args[1])
2923 elif args[0] == "fortran_compiler":
2924 if args[1] == 'None':
2925 args[1] = None
2926 self.options['fortran_compiler'] = args[1]
2927 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'fortran')
2928 if current != args[1] and args[1] != None:
2929 misc.mod_compilator(self.me_dir, args[1], current, 'gfortran')
2930 elif args[0] == "cpp_compiler":
2931 if args[1] == 'None':
2932 args[1] = None
2933 self.options['cpp_compiler'] = args[1]
2934 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'cpp')
2935 if current != args[1] and args[1] != None:
2936 misc.mod_compilator(self.me_dir, args[1], current, 'cpp')
2937 elif args[0] == "run_mode":
2938 if not args[1] in [0,1,2,'0','1','2']:
2939 raise self.InvalidCmd, 'run_mode should be 0, 1 or 2.'
2940 self.cluster_mode = int(args[1])
2941 self.options['run_mode'] = self.cluster_mode
2942 elif args[0] in ['cluster_type', 'cluster_queue', 'cluster_temp_path']:
2943 if args[1] == 'None':
2944 args[1] = None
2945 self.options[args[0]] = args[1]
2946
2947
2948 elif args[0] in ['cluster_nb_retry', 'cluster_retry_wait', 'cluster_size']:
2949 self.options[args[0]] = int(args[1])
2950
2951 elif args[0] == 'nb_core':
2952 if args[1] == 'None':
2953 import multiprocessing
2954 self.nb_core = multiprocessing.cpu_count()
2955 self.options['nb_core'] = self.nb_core
2956 return
2957 if not args[1].isdigit():
2958 raise self.InvalidCmd('nb_core should be a positive number')
2959 self.nb_core = int(args[1])
2960 self.options['nb_core'] = self.nb_core
2961 elif args[0] == 'timeout':
2962 self.options[args[0]] = int(args[1])
2963 elif args[0] == 'cluster_status_update':
2964 if '(' in args[1]:
2965 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
2966 data = data.replace('(','').replace(')','').replace(',',' ').split()
2967 first, second = data[:2]
2968 else:
2969 first, second = args[1:3]
2970
2971 self.options[args[0]] = (int(first), int(second))
2972 elif args[0] == 'notification_center':
2973 if args[1] in ['None','True','False']:
2974 self.allow_notification_center = eval(args[1])
2975 self.options[args[0]] = eval(args[1])
2976 else:
2977 raise self.InvalidCmd('Not a valid value for notification_center')
2978
2979 elif args[0] in ['crash_on_error']:
2980 tmp = banner_mod.ConfigFile.format_variable(args[1], bool, 'crash_on_error')
2981 self.options[args[0]] = tmp
2982 elif args[0] in self.options:
2983 if args[1] in ['None','True','False']:
2984 self.options[args[0]] = ast.literal_eval(args[1])
2985 elif args[0].endswith('path'):
2986 if os.path.exists(args[1]):
2987 self.options[args[0]] = args[1]
2988 elif os.path.exists(pjoin(self.me_dir, args[1])):
2989 self.options[args[0]] = pjoin(self.me_dir, args[1])
2990 else:
2991 raise self.InvalidCmd('Not a valid path: keep previous value: \'%s\'' % self.options[args[0]])
2992 else:
2993 self.options[args[0]] = args[1]
2994
2995 - def post_set(self, stop, line):
2996 """Check if we need to save this in the option file"""
2997 try:
2998 args = self.split_arg(line)
2999 if 'cluster' in args[0] or args[0] == 'run_mode':
3000 self.configure_run_mode(self.options['run_mode'])
3001
3002
3003
3004 self.check_set(args)
3005
3006 if args[0] in self.options_configuration and '--no_save' not in args:
3007 self.exec_cmd('save options %s --auto' % args[0])
3008 elif args[0] in self.options_madevent:
3009 logger.info('This option will be the default in any output that you are going to create in this session.')
3010 logger.info('In order to keep this changes permanent please run \'save options\'')
3011 return stop
3012 except self.InvalidCmd:
3013 return stop
3014
3080
3081
3083 """
3084 1) Check that no scan parameter are present
3085 2) Check that all the width are define in the param_card.
3086 - If a scan parameter is define. create the iterator and recall this fonction
3087 on the first element.
3088 - If some width are set on 'Auto', call the computation tools.
3089 - Check that no width are too small (raise a warning if this is the case)
3090 3) if dependent is on True check for dependent parameter (automatic for scan)"""
3091
3092 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M)
3093 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
3094 text = open(path).read()
3095
3096 if pattern_scan.search(text):
3097 if not isinstance(self, cmd.CmdShell):
3098
3099 raise Exception, "Scan are not allowed in web mode"
3100
3101 main_card = check_param_card.ParamCardIterator(text)
3102 self.param_card_iterator = main_card
3103 first_card = main_card.next(autostart=True)
3104 first_card.write(path)
3105 return self.check_param_card(path, run, dependent=True)
3106
3107 pdg_info = pattern_width.findall(text)
3108 if pdg_info:
3109 if run:
3110 logger.info('Computing the width set on auto in the param_card.dat')
3111 has_nlo = any(nlo.lower()=="@nlo" for _,nlo in pdg_info)
3112 pdg = [pdg for pdg,nlo in pdg_info]
3113 if not has_nlo:
3114 self.do_compute_widths('%s %s' % (' '.join(pdg), path))
3115 else:
3116 self.do_compute_widths('%s %s --nlo' % (' '.join(pdg), path))
3117 else:
3118 logger.info('''Some width are on Auto in the card.
3119 Those will be computed as soon as you have finish the edition of the cards.
3120 If you want to force the computation right now and being able to re-edit
3121 the cards afterwards, you can type \"compute_wdiths\".''')
3122
3123 card = check_param_card.ParamCard(path)
3124 if dependent:
3125
3126 AskforEditCard.update_dependent(self, self.me_dir, card, path, timer=20)
3127
3128 for param in card['decay']:
3129 width = param.value
3130 if width == 0:
3131 continue
3132 try:
3133 mass = card['mass'].get(param.lhacode).value
3134 except Exception:
3135 logger.warning('Missing mass in the lhef file (%s) . Please fix this (use the "update missing" command if needed)', param.lhacode[0])
3136 continue
3137 if mass and width/mass < 1e-12:
3138 logger.error('The width of particle %s is too small for an s-channel resonance (%s). If you have this particle in an s-channel, this is likely to create numerical instabilities .', param.lhacode[0], width)
3139 if CommonRunCmd.sleep_for_error:
3140 time.sleep(5)
3141 CommonRunCmd.sleep_for_error = False
3142 elif not mass and width:
3143 logger.error('The width of particle %s is different of zero for a massless particle.', param.lhacode[0])
3144 if CommonRunCmd.sleep_for_error:
3145 time.sleep(5)
3146 CommonRunCmd.sleep_for_error = False
3147 return
3148
3150 """If a ME run is currently running add a link in the html output"""
3151
3152
3153
3154 if hasattr(self, 'results') and hasattr(self.results, 'current') and\
3155 self.results.current and 'run_name' in self.results.current and \
3156 hasattr(self, 'me_dir'):
3157 name = self.results.current['run_name']
3158 tag = self.results.current['tag']
3159 self.debug_output = pjoin(self.me_dir, '%s_%s_debug.log' % (name,tag))
3160 if errortype:
3161 self.results.current.debug = errortype
3162 else:
3163 self.results.current.debug = self.debug_output
3164
3165 else:
3166
3167 self.debug_output = CommonRunCmd.debug_output
3168 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output:
3169 os.remove('ME5_debug')
3170 if not 'ME5_debug' in self.debug_output:
3171 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
3172
3173
3175 """Not in help: exit """
3176
3177 if not self.force_run:
3178 try:
3179 os.remove(pjoin(self.me_dir,'RunWeb'))
3180 except Exception:
3181 pass
3182 try:
3183 self.store_result()
3184 except Exception:
3185
3186 pass
3187
3188 try:
3189 self.update_status('', level=None)
3190 except Exception, error:
3191 pass
3192 devnull = open(os.devnull, 'w')
3193 try:
3194 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir,
3195 stdout=devnull, stderr=devnull)
3196 except Exception:
3197 pass
3198 devnull.close()
3199
3200 return super(CommonRunCmd, self).do_quit(line)
3201
3202
3203 do_EOF = do_quit
3204 do_exit = do_quit
3205
3206
3207 - def update_status(self, status, level, makehtml=True, force=True,
3208 error=False, starttime = None, update_results=True,
3209 print_log=True):
3210 """ update the index status """
3211
3212 if makehtml and not force:
3213 if hasattr(self, 'next_update') and time.time() < self.next_update:
3214 return
3215 else:
3216 self.next_update = time.time() + 3
3217
3218 if print_log:
3219 if isinstance(status, str):
3220 if '<br>' not in status:
3221 logger.info(status)
3222 elif starttime:
3223 running_time = misc.format_timer(time.time()-starttime)
3224 logger.info(' Idle: %s, Running: %s, Completed: %s [ %s ]' % \
3225 (status[0], status[1], status[2], running_time))
3226 else:
3227 logger.info(' Idle: %s, Running: %s, Completed: %s' % status[:3])
3228
3229 if isinstance(status, str) and status.startswith('\x1b['):
3230 status = status[status.index('m')+1:-7]
3231 if 'arXiv' in status:
3232 if '[' in status:
3233 status = status.split('[',1)[0]
3234 else:
3235 status = status.split('arXiv',1)[0]
3236
3237 if update_results:
3238 self.results.update(status, level, makehtml=makehtml, error=error)
3239
3240
3242 """Ask the question when launching generate_events/multi_run"""
3243
3244 check_card = ['pythia_card.dat', 'pgs_card.dat','delphes_card.dat',
3245 'delphes_trigger.dat', 'madspin_card.dat', 'shower_card.dat',
3246 'reweight_card.dat','pythia8_card.dat',
3247 'madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat',
3248 'plot_card.dat']
3249
3250 cards_path = pjoin(self.me_dir,'Cards')
3251 for card in check_card:
3252 if card in ignore or (ignore == ['*'] and card not in need_card):
3253 continue
3254 if card not in need_card:
3255 if os.path.exists(pjoin(cards_path, card)):
3256 files.mv(pjoin(cards_path, card), pjoin(cards_path, '.%s' % card))
3257 else:
3258 if not os.path.exists(pjoin(cards_path, card)):
3259 if os.path.exists(pjoin(cards_path, '.%s' % card)):
3260 files.mv(pjoin(cards_path, '.%s' % card), pjoin(cards_path, card))
3261 else:
3262 default = card.replace('.dat', '_default.dat')
3263 files.cp(pjoin(cards_path, default),pjoin(cards_path, card))
3264
3265
3266 - def set_configuration(self, config_path=None, final=True, initdir=None, amcatnlo=False):
3267 """ assign all configuration variable from file
3268 ./Cards/mg5_configuration.txt. assign to default if not define """
3269
3270 if not hasattr(self, 'options') or not self.options:
3271 self.options = dict(self.options_configuration)
3272 self.options.update(self.options_madgraph)
3273 self.options.update(self.options_madevent)
3274
3275 if not config_path:
3276 if os.environ.has_key('MADGRAPH_BASE'):
3277 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
3278 self.set_configuration(config_path=config_path, final=False)
3279 if 'HOME' in os.environ:
3280 config_path = pjoin(os.environ['HOME'],'.mg5',
3281 'mg5_configuration.txt')
3282 if os.path.exists(config_path):
3283 self.set_configuration(config_path=config_path, final=False)
3284 if amcatnlo:
3285 me5_config = pjoin(self.me_dir, 'Cards', 'amcatnlo_configuration.txt')
3286 else:
3287 me5_config = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
3288 self.set_configuration(config_path=me5_config, final=False, initdir=self.me_dir)
3289
3290 if self.options.has_key('mg5_path') and self.options['mg5_path']:
3291 MG5DIR = self.options['mg5_path']
3292 config_file = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
3293 self.set_configuration(config_path=config_file, final=False,initdir=MG5DIR)
3294 else:
3295 self.options['mg5_path'] = None
3296 return self.set_configuration(config_path=me5_config, final=final,initdir=self.me_dir)
3297
3298 config_file = open(config_path)
3299
3300
3301 logger.info('load configuration from %s ' % config_file.name)
3302 for line in config_file:
3303
3304 if '#' in line:
3305 line = line.split('#',1)[0]
3306 line = line.replace('\n','').replace('\r\n','')
3307 try:
3308 name, value = line.split('=')
3309 except ValueError:
3310 pass
3311 else:
3312 name = name.strip()
3313 value = value.strip()
3314 if name.endswith('_path') and not name.startswith('cluster'):
3315 path = value
3316 if os.path.isdir(path):
3317 self.options[name] = os.path.realpath(path)
3318 continue
3319 if not initdir:
3320 continue
3321 path = pjoin(initdir, value)
3322 if os.path.isdir(path):
3323 self.options[name] = os.path.realpath(path)
3324 continue
3325 else:
3326 self.options[name] = value
3327 if value.lower() == "none":
3328 self.options[name] = None
3329
3330 if not final:
3331 return self.options
3332
3333
3334
3335 for key in self.options:
3336
3337 if key.endswith('path') and not key.startswith("cluster"):
3338 path = self.options[key]
3339 if path is None:
3340 continue
3341 if os.path.isdir(path):
3342 self.options[key] = os.path.realpath(path)
3343 continue
3344 path = pjoin(self.me_dir, self.options[key])
3345 if os.path.isdir(path):
3346 self.options[key] = os.path.realpath(path)
3347 continue
3348 elif self.options.has_key('mg5_path') and self.options['mg5_path']:
3349 path = pjoin(self.options['mg5_path'], self.options[key])
3350 if os.path.isdir(path):
3351 self.options[key] = os.path.realpath(path)
3352 continue
3353 self.options[key] = None
3354 elif key.startswith('cluster') and key != 'cluster_status_update':
3355 if key in ('cluster_nb_retry','cluster_wait_retry'):
3356 self.options[key] = int(self.options[key])
3357 if hasattr(self,'cluster'):
3358 del self.cluster
3359 pass
3360 elif key == 'automatic_html_opening':
3361 if self.options[key] in ['False', 'True']:
3362 self.options[key] =ast.literal_eval(self.options[key])
3363 elif key == "notification_center":
3364 if self.options[key] in ['False', 'True']:
3365 self.allow_notification_center =ast.literal_eval(self.options[key])
3366 self.options[key] =ast.literal_eval(self.options[key])
3367 elif key not in ['text_editor','eps_viewer','web_browser','stdout_level',
3368 'complex_mass_scheme', 'gauge', 'group_subprocesses']:
3369
3370 try:
3371 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
3372 except self.InvalidCmd:
3373 logger.warning("Option %s from config file not understood" \
3374 % key)
3375
3376
3377 misc.open_file.configure(self.options)
3378 self.configure_run_mode(self.options['run_mode'])
3379 return self.options
3380
3381 @staticmethod
3383 """ find a valid run_name for the current job """
3384
3385 name = 'run_%02d'
3386 data = [int(s[4:j]) for s in os.listdir(pjoin(me_dir,'Events')) for
3387 j in range(4,len(s)+1) if \
3388 s.startswith('run_') and s[4:j].isdigit()]
3389 return name % (max(data+[0])+1)
3390
3391
3392
3394 """Require MG5 directory: decay events with spin correlations
3395 """
3396
3397 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'madspin_card.dat')):
3398 return
3399
3400
3401
3402 if MADEVENT and not self.options['mg5_path']:
3403 raise self.InvalidCmd, '''The module decay_events requires that MG5 is installed on the system.
3404 You can install it and set its path in ./Cards/me5_configuration.txt'''
3405 elif MADEVENT:
3406 sys.path.append(self.options['mg5_path'])
3407 try:
3408 import MadSpin.decay as decay
3409 import MadSpin.interface_madspin as interface_madspin
3410 except ImportError:
3411 if __debug__:
3412 raise
3413 else:
3414 raise self.ConfigurationError, '''Can\'t load MadSpin
3415 The variable mg5_path might not be correctly configured.'''
3416
3417 self.update_status('Running MadSpin', level='madspin')
3418 if not '-from_cards' in line and '-f' not in line:
3419 self.keep_cards(['madspin_card.dat'], ignore=['*'])
3420 self.ask_edit_cards(['madspin_card.dat'], 'fixed', plot=False)
3421 self.help_decay_events(skip_syntax=True)
3422
3423
3424 args = self.split_arg(line)
3425 self.check_decay_events(args)
3426
3427 madspin_cmd = interface_madspin.MadSpinInterface(args[0])
3428
3429 madspin_cmd.mg5cmd.options.update(self.options)
3430 madspin_cmd.cluster = self.cluster
3431
3432 madspin_cmd.update_status = lambda *x,**opt: self.update_status(*x, level='madspin',**opt)
3433
3434 path = pjoin(self.me_dir, 'Cards', 'madspin_card.dat')
3435
3436 madspin_cmd.import_command_file(path)
3437
3438
3439 i = 1
3440 while os.path.exists(pjoin(self.me_dir,'Events', '%s_decayed_%i' % (self.run_name,i))):
3441 i+=1
3442 new_run = '%s_decayed_%i' % (self.run_name,i)
3443 evt_dir = pjoin(self.me_dir, 'Events')
3444
3445 os.mkdir(pjoin(evt_dir, new_run))
3446 current_file = args[0].replace('.lhe', '_decayed.lhe')
3447 new_file = pjoin(evt_dir, new_run, os.path.basename(args[0]))
3448 if not os.path.exists(current_file):
3449 if os.path.exists(current_file+'.gz'):
3450 current_file += '.gz'
3451 new_file += '.gz'
3452 elif current_file.endswith('.gz') and os.path.exists(current_file[:-3]):
3453 current_file = current_file[:-3]
3454 new_file = new_file[:-3]
3455 else:
3456 logger.error('MadSpin fails to create any decayed file.')
3457 return
3458
3459 files.mv(current_file, new_file)
3460 logger.info("The decayed event file has been moved to the following location: ")
3461 logger.info(new_file)
3462
3463 if hasattr(self, 'results'):
3464 current = self.results.current
3465 nb_event = self.results.current['nb_event']
3466 if not nb_event:
3467 current = self.results[self.run_name][0]
3468 nb_event = current['nb_event']
3469
3470 cross = current['cross']
3471 error = current['error']
3472 self.results.add_run( new_run, self.run_card)
3473 self.results.add_detail('nb_event', int(nb_event*madspin_cmd.efficiency))
3474 self.results.add_detail('cross', madspin_cmd.cross)
3475 self.results.add_detail('error', madspin_cmd.error+ cross * madspin_cmd.err_branching_ratio)
3476 self.results.add_detail('run_mode', current['run_mode'])
3477
3478 self.run_name = new_run
3479 self.banner = madspin_cmd.banner
3480 self.banner.add(path)
3481 self.banner.write(pjoin(self.me_dir,'Events',self.run_name, '%s_%s_banner.txt' %
3482 (self.run_name, self.run_tag)))
3483 self.update_status('MadSpin Done', level='parton', makehtml=False)
3484 if 'unweighted' in os.path.basename(args[0]):
3485 self.create_plot('parton')
3486
3493
3495 "Complete the print results command"
3496 args = self.split_arg(line[0:begidx], error=False)
3497 if len(args) == 1:
3498
3499 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'),
3500 pjoin(self.me_dir, 'Events'))
3501
3502 data = [n.rsplit('/',2)[1] for n in data]
3503 tmp1 = self.list_completion(text, data)
3504 return tmp1
3505 else:
3506 data = misc.glob('*_pythia_events.hep.gz', pjoin(self.me_dir, 'Events', args[0]))
3507 data = [os.path.basename(p).rsplit('_',1)[0] for p in data]
3508 data += ["--mode=a", "--mode=w", "--path=", "--format=short"]
3509 tmp1 = self.list_completion(text, data)
3510 return tmp1
3511
3513 logger.info("syntax: print_result [RUN] [TAG] [options]")
3514 logger.info("-- show in text format the status of the run (cross-section/nb-event/...)")
3515 logger.info("--path= defines the path of the output file.")
3516 logger.info("--mode=a allow to add the information at the end of the file.")
3517 logger.info("--format=short (only if --path is define)")
3518 logger.info(" allows to have a multi-column output easy to parse")
3519
3520
3546
3547
3549 args = self.split_arg(line[0:begidx], error=False)
3550
3551 if len(args) == 1 and os.path.sep not in text:
3552
3553 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events'))
3554 data = [n.rsplit('/',2)[1] for n in data]
3555 return self.list_completion(text, data, line)
3556 else:
3557 return self.path_completion(text,
3558 os.path.join('.',*[a for a in args \
3559 if a.endswith(os.path.sep)]))
3560
3572
3573
3574
3576 "Complete the compute_widths command"
3577
3578 args = self.split_arg(line[0:begidx])
3579
3580 if args[-1] in ['--path=', '--output=']:
3581 completion = {'path': self.path_completion(text)}
3582 elif line[begidx-1] == os.path.sep:
3583 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)])
3584 if current_dir.startswith('--path='):
3585 current_dir = current_dir[7:]
3586 if current_dir.startswith('--output='):
3587 current_dir = current_dir[9:]
3588 completion = {'path': self.path_completion(text, current_dir)}
3589 else:
3590 completion = {}
3591 completion['options'] = self.list_completion(text,
3592 ['--path=', '--output=', '--min_br=0.\$', '--nlo',
3593 '--precision_channel=0.\$', '--body_decay='])
3594
3595 return self.deal_multiple_categories(completion, formatting)
3596
3597
3599 """update the make_opts file writing the environmental variables
3600 stored in make_opts_var"""
3601 make_opts = os.path.join(self.me_dir, 'Source', 'make_opts')
3602
3603
3604 if not hasattr(self,'options') or not 'pythia8_path' in self.options or \
3605 not self.options['pythia8_path'] or \
3606 not os.path.isfile(pjoin(self.options['pythia8_path'],'bin','pythia8-config')):
3607 self.make_opts_var['PYTHIA8_PATH']='NotInstalled'
3608 else:
3609 self.make_opts_var['PYTHIA8_PATH']=self.options['pythia8_path']
3610
3611 self.make_opts_var['MG5AMC_VERSION'] = misc.get_pkg_info()['version']
3612
3613 return self.update_make_opts_full(make_opts, self.make_opts_var)
3614
3615 @staticmethod
3617 """update the make_opts file writing the environmental variables
3618 of def_variables.
3619 if a value of the dictionary is None then it is not written.
3620 """
3621 make_opts = path
3622 pattern = re.compile(r'^(\w+)\s*=\s*(.*)$',re.DOTALL)
3623 diff = False
3624
3625
3626 tag = '#end_of_make_opts_variables\n'
3627 make_opts_variable = True
3628 content = []
3629 variables = dict(def_variables)
3630 need_keys = variables.keys()
3631 for line in open(make_opts):
3632 line = line.strip()
3633 if make_opts_variable:
3634 if line.startswith('#') or not line:
3635 if line.startswith('#end_of_make_opts_variables'):
3636 make_opts_variable = False
3637 continue
3638 elif pattern.search(line):
3639 key, value = pattern.search(line).groups()
3640 if key not in variables:
3641 variables[key] = value
3642 elif value != variables[key]:
3643 diff=True
3644 else:
3645 need_keys.remove(key)
3646 else:
3647 make_opts_variable = False
3648 content.append(line)
3649 else:
3650 content.append(line)
3651
3652 if need_keys:
3653 diff=True
3654
3655 content_variables = '\n'.join('%s=%s' % (k,v) for k, v in variables.items() if v is not None)
3656 content_variables += '\n%s' % tag
3657
3658 if diff:
3659 with open(make_opts, 'w') as fsock:
3660 fsock.write(content_variables + '\n'.join(content))
3661 return
3662
3663
3664
3666 """links lhapdf into libdir"""
3667
3668 lhapdf_version = self.get_lhapdf_version()
3669 logger.info('Using LHAPDF v%s interface for PDFs' % lhapdf_version)
3670 lhalibdir = subprocess.Popen([self.options['lhapdf'], '--libdir'],
3671 stdout = subprocess.PIPE).stdout.read().strip()
3672
3673 if lhapdf_version.startswith('5.'):
3674 pdfsetsdir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'],
3675 stdout = subprocess.PIPE).stdout.read().strip()
3676 else:
3677 pdfsetsdir = subprocess.Popen([self.options['lhapdf'], '--datadir'],
3678 stdout = subprocess.PIPE).stdout.read().strip()
3679
3680 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsetsdir)
3681
3682 lhalib = 'libLHAPDF.a'
3683
3684 if os.path.exists(pjoin(libdir, lhalib)):
3685 files.rm(pjoin(libdir, lhalib))
3686 files.ln(pjoin(lhalibdir, lhalib), libdir)
3687
3688 if not os.path.isdir(pjoin(libdir, 'PDFsets')):
3689 os.mkdir(pjoin(libdir, 'PDFsets'))
3690 self.make_opts_var['lhapdf'] = self.options['lhapdf']
3691 self.make_opts_var['lhapdfversion'] = lhapdf_version[0]
3692 self.make_opts_var['lhapdf_config'] = self.options['lhapdf']
3693
3694
3696 """reads the proc_characteristics file and initialises the correspondant
3697 dictionary"""
3698
3699 if not path:
3700 path = os.path.join(self.me_dir, 'SubProcesses', 'proc_characteristics')
3701
3702 self.proc_characteristics = banner_mod.ProcCharacteristic(path)
3703 return self.proc_characteristics
3704
3705
3707 """copy (if needed) the lhapdf set corresponding to the lhaid in lhaid_list
3708 into lib/PDFsets"""
3709
3710 if not hasattr(self, 'lhapdf_pdfsets'):
3711 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsets_dir)
3712
3713 pdfsetname=set()
3714 for lhaid in lhaid_list:
3715 if isinstance(lhaid, str) and lhaid.isdigit():
3716 lhaid = int(lhaid)
3717 if isinstance(lhaid, (int,float)):
3718 try:
3719 if lhaid in self.lhapdf_pdfsets:
3720 pdfsetname.add(self.lhapdf_pdfsets[lhaid]['filename'])
3721 else:
3722 raise MadGraph5Error('lhaid %s not valid input number for the current lhapdf' % lhaid )
3723 except KeyError:
3724 if self.lhapdf_version.startswith('5'):
3725 raise MadGraph5Error(\
3726 ('invalid lhaid set in th run_card: %d .\nPlease note that some sets' % lhaid) + \
3727 '(eg MSTW 90%CL error sets) \nare not available in aMC@NLO + LHAPDF 5.x.x')
3728 else:
3729 logger.debug('%d not found in pdfsets.index' % lhaid)
3730 else:
3731 pdfsetname.add(lhaid)
3732
3733
3734
3735
3736 if not os.path.isdir(pdfsets_dir):
3737 try:
3738 os.mkdir(pdfsets_dir)
3739 except OSError:
3740 pdfsets_dir = pjoin(self.me_dir, 'lib', 'PDFsets')
3741 elif os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets')):
3742
3743 for name in os.listdir(pjoin(self.me_dir, 'lib', 'PDFsets')):
3744 if name not in pdfsetname:
3745 try:
3746 if os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', name)):
3747 shutil.rmtree(pjoin(self.me_dir, 'lib', 'PDFsets', name))
3748 else:
3749 os.remove(pjoin(self.me_dir, 'lib', 'PDFsets', name))
3750 except Exception, error:
3751 logger.debug('%s', error)
3752
3753 if self.options["cluster_local_path"]:
3754 lhapdf_cluster_possibilities = [self.options["cluster_local_path"],
3755 pjoin(self.options["cluster_local_path"], "lhapdf"),
3756 pjoin(self.options["cluster_local_path"], "lhapdf", "pdfsets"),
3757 pjoin(self.options["cluster_local_path"], "..", "lhapdf"),
3758 pjoin(self.options["cluster_local_path"], "..", "lhapdf", "pdfsets"),
3759 pjoin(self.options["cluster_local_path"], "..", "lhapdf","pdfsets", "6.1")
3760 ]
3761 else:
3762 lhapdf_cluster_possibilities = []
3763
3764 for pdfset in pdfsetname:
3765
3766 if self.options["cluster_local_path"] and self.options["run_mode"] == 1 and \
3767 any((os.path.exists(pjoin(d, pdfset)) for d in lhapdf_cluster_possibilities)):
3768
3769 os.environ["LHAPATH"] = [d for d in lhapdf_cluster_possibilities if os.path.exists(pjoin(d, pdfset))][0]
3770 os.environ["CLUSTER_LHAPATH"] = os.environ["LHAPATH"]
3771
3772 if os.path.exists(pjoin(pdfsets_dir, pdfset)):
3773 try:
3774 if os.path.isdir(pjoin(pdfsets_dir, name)):
3775 shutil.rmtree(pjoin(pdfsets_dir, name))
3776 else:
3777 os.remove(pjoin(pdfsets_dir, name))
3778 except Exception, error:
3779 logger.debug('%s', error)
3780
3781
3782 elif not os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)) and \
3783 not os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)):
3784
3785 if pdfset and not os.path.exists(pjoin(pdfsets_dir, pdfset)):
3786 self.install_lhapdf_pdfset(pdfsets_dir, pdfset)
3787
3788 if os.path.exists(pjoin(pdfsets_dir, pdfset)):
3789 files.cp(pjoin(pdfsets_dir, pdfset), pjoin(self.me_dir, 'lib', 'PDFsets'))
3790 elif os.path.exists(pjoin(os.path.dirname(pdfsets_dir), pdfset)):
3791 files.cp(pjoin(os.path.dirname(pdfsets_dir), pdfset), pjoin(self.me_dir, 'lib', 'PDFsets'))
3792
3794 """idownloads and install the pdfset filename in the pdfsets_dir"""
3795 lhapdf_version = self.get_lhapdf_version()
3796 local_path = pjoin(self.me_dir, 'lib', 'PDFsets')
3797 return self.install_lhapdf_pdfset_static(self.options['lhapdf'],
3798 pdfsets_dir, filename,
3799 lhapdf_version=lhapdf_version,
3800 alternate_path=local_path)
3801
3802
3803 @staticmethod
3806 """idownloads and install the pdfset filename in the pdfsets_dir.
3807 Version which can be used independently of the class.
3808 local path is used if the global installation fails.
3809 """
3810
3811 if not lhapdf_version:
3812 lhapdf_version = subprocess.Popen([lhapdf_config, '--version'],
3813 stdout = subprocess.PIPE).stdout.read().strip()
3814 if not pdfsets_dir:
3815 pdfsets_dir = subprocess.Popen([lhapdf_config, '--datadir'],
3816 stdout = subprocess.PIPE).stdout.read().strip()
3817
3818 if isinstance(filename, int):
3819 pdf_info = CommonRunCmd.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version)
3820 filename = pdf_info[filename]['filename']
3821
3822 if os.path.exists(pjoin(pdfsets_dir, filename)):
3823 logger.debug('%s is already present in %s', filename, pdfsets_dir)
3824 return
3825
3826 logger.info('Trying to download %s' % filename)
3827
3828 if lhapdf_version.startswith('5.'):
3829
3830
3831
3832 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf-getdata'))
3833 misc.call([getdata, filename], cwd = pdfsets_dir)
3834
3835 elif lhapdf_version.startswith('6.'):
3836
3837
3838 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf'))
3839
3840 misc.call([getdata, 'install', filename], cwd = pdfsets_dir)
3841
3842 else:
3843 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version)
3844
3845
3846 if os.path.exists(pjoin(pdfsets_dir, filename)) or \
3847 os.path.isdir(pjoin(pdfsets_dir, filename)):
3848 logger.info('%s successfully downloaded and stored in %s' \
3849 % (filename, pdfsets_dir))
3850
3851 elif lhapdf_version.startswith('5.'):
3852 logger.warning('Could not download %s into %s. Trying to save it locally' \
3853 % (filename, pdfsets_dir))
3854 CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, alternate_path, filename,
3855 lhapdf_version=lhapdf_version)
3856 elif lhapdf_version.startswith('6.') and '.LHgrid' in filename:
3857 logger.info('Could not download %s: Try %s', filename, filename.replace('.LHgrid',''))
3858 return CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, pdfsets_dir,
3859 filename.replace('.LHgrid',''),
3860 lhapdf_version, alternate_path)
3861
3862 else:
3863 raise MadGraph5Error, \
3864 'Could not download %s into %s. Please try to install it manually.' \
3865 % (filename, pdfsets_dir)
3866
3867
3868
3870 """read the PDFsets.index file, which should be located in the same
3871 place as pdfsets_dir, and return a list of dictionaries with the information
3872 about each pdf set"""
3873 lhapdf_version = self.get_lhapdf_version()
3874 return self.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version)
3875
3876 @staticmethod
3878
3879 if lhapdf_version.startswith('5.'):
3880 if os.path.exists('%s.index' % pdfsets_dir):
3881 indexfile = '%s.index' % pdfsets_dir
3882 else:
3883 raise MadGraph5Error, 'index of lhapdf file not found'
3884 pdfsets_lines = \
3885 [l for l in open(indexfile).read().split('\n') if l.strip() and \
3886 not '90cl' in l]
3887 lhapdf_pdfsets = dict( (int(l.split()[0]), {'lhaid': int(l.split()[0]),
3888 'pdflib_ntype': int(l.split()[1]),
3889 'pdflib_ngroup': int(l.split()[2]),
3890 'pdflib_nset': int(l.split()[3]),
3891 'filename': l.split()[4],
3892 'lhapdf_nmem': int(l.split()[5]),
3893 'q2min': float(l.split()[6]),
3894 'q2max': float(l.split()[7]),
3895 'xmin': float(l.split()[8]),
3896 'xmax': float(l.split()[9]),
3897 'description': l.split()[10]}) \
3898 for l in pdfsets_lines)
3899
3900 elif lhapdf_version.startswith('6.'):
3901 pdfsets_lines = \
3902 [l for l in open(pjoin(pdfsets_dir, 'pdfsets.index')).read().split('\n') if l.strip()]
3903 lhapdf_pdfsets = dict( (int(l.split()[0]),
3904 {'lhaid': int(l.split()[0]),
3905 'filename': l.split()[1]}) \
3906 for l in pdfsets_lines)
3907
3908 else:
3909 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version)
3910
3911 return lhapdf_pdfsets
3912
3913
3915 """returns the lhapdf version number"""
3916 if not hasattr(self, 'lhapdfversion'):
3917 try:
3918 self.lhapdf_version = \
3919 subprocess.Popen([self.options['lhapdf'], '--version'],
3920 stdout = subprocess.PIPE).stdout.read().strip()
3921 except OSError, error:
3922 if error.errno == 2:
3923 raise Exception, 'lhapdf executable (%s) is not found on your system. Please install it and/or indicate the path to the correct executable in input/mg5_configuration.txt' % self.options['lhapdf']
3924 else:
3925 raise
3926
3927
3928 if self.lhapdf_version.startswith('6.0'):
3929 raise MadGraph5Error('LHAPDF 6.0.x not supported. Please use v6.1 or later')
3930
3931 return self.lhapdf_version
3932
3933
3935 lhapdf_version = self.get_lhapdf_version()
3936
3937
3938 if 'LHAPDF_DATA_PATH' in os.environ.keys() and os.environ['LHAPDF_DATA_PATH']:
3939 datadir = os.environ['LHAPDF_DATA_PATH']
3940
3941 elif lhapdf_version.startswith('5.'):
3942 datadir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'],
3943 stdout = subprocess.PIPE).stdout.read().strip()
3944
3945 elif lhapdf_version.startswith('6.'):
3946 datadir = subprocess.Popen([self.options['lhapdf'], '--datadir'],
3947 stdout = subprocess.PIPE).stdout.read().strip()
3948
3949 return datadir
3950
3952 lhapdf_version = self.get_lhapdf_version()
3953
3954 if lhapdf_version.startswith('5.'):
3955 libdir = subprocess.Popen([self.options['lhapdf-config'], '--libdir'],
3956 stdout = subprocess.PIPE).stdout.read().strip()
3957
3958 elif lhapdf_version.startswith('6.'):
3959 libdir = subprocess.Popen([self.options['lhapdf'], '--libs'],
3960 stdout = subprocess.PIPE).stdout.read().strip()
3961
3962 return libdir
3963
3965 """A class for asking a question where in addition you can have the
3966 set command define and modifying the param_card/run_card correctly"""
3967
3968 all_card_name = ['param_card', 'run_card', 'pythia_card', 'pythia8_card',
3969 'madweight_card', 'MadLoopParams', 'shower_card']
3970
3971 special_shortcut = {'ebeam':([float],['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s']),
3972 'lpp': ([int],['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ]),
3973 'lhc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
3974 'lep': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
3975 'ilc': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
3976 'lcc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
3977 'fixed_scale': ([float],['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']),
3978 'simplepy8':([],['pythia8_card hadronlevel:all False',
3979 'pythia8_card partonlevel:mpi False',
3980 'pythia8_card BeamRemnants:primordialKT False',
3981 'pythia8_card PartonLevel:Remnants False',
3982 'pythia8_card Check:event False',
3983 'pythia8_card TimeShower:QEDshowerByQ False',
3984 'pythia8_card TimeShower:QEDshowerByL False',
3985 'pythia8_card SpaceShower:QEDshowerByQ False',
3986 'pythia8_card SpaceShower:QEDshowerByL False',
3987 'pythia8_card PartonLevel:FSRinResonances False',
3988 'pythia8_card ProcessLevel:resonanceDecays False',
3989 ]),
3990 'mpi':([bool],['pythia8_card partonlevel:mpi %(0)s']),
3991 'no_parton_cut':([],['run_card nocut T'])
3992 }
3993
3994 special_shortcut_help = {
3995 'ebeam' : 'syntax: set ebeam VALUE:\n This parameter sets the energy to both beam to the value in GeV',
3996 'lpp' : 'syntax: set ebeam VALUE:\n'+\
3997 ' Set the type of beam to a given value for both beam\n'+\
3998 ' 0 : means no PDF\n'+\
3999 ' 1 : means proton PDF\n'+\
4000 ' -1 : means antiproton PDF\n'+\
4001 ' 2 : means PDF for elastic photon emited from a proton\n'+\
4002 ' 3 : means PDF for elastic photon emited from an electron',
4003 'lhc' : 'syntax: set lhc VALUE:\n Set for a proton-proton collision with that given center of mass energy (in TeV)',
4004 'lep' : 'syntax: set lep VALUE:\n Set for a electron-positron collision with that given center of mass energy (in GeV)',
4005 'fixed_scale' : 'syntax: set fixed_scale VALUE:\n Set all scales to the give value (in GeV)',
4006 'simplepy8' : 'Turn off non-perturbative slow features of Pythia8.',
4007 'mpi' : 'syntax: set mpi value: allow to turn mpi in Pythia8 on/off'
4008 }
4009
4011 """ define all default variable. No load of card here.
4012 This allow to subclass this class and just change init and still have
4013 all variables defined."""
4014
4015 self.me_dir = None
4016 self.param_card = None
4017 self.run_card = {}
4018 self.pname2block = {}
4019 self.conflict = []
4020 self.restricted_value = {}
4021 self.mode = ''
4022 self.cards = []
4023 self.run_set = []
4024 self.has_mw = False
4025 self.has_ml = False
4026 self.has_shower = False
4027 self.has_PY8 = False
4028 self.paths = {}
4029
4030
4032
4033 if 'pwd' in opt:
4034 self.me_dir = opt['pwd']
4035 elif 'mother_interface' in opt:
4036 self.mother_interface = opt['mother_interface']
4037 if not hasattr(self, 'me_dir') or not self.me_dir:
4038 self.me_dir = self.mother_interface.me_dir
4039
4040
4041 self.paths['param'] = pjoin(self.me_dir,'Cards','param_card.dat')
4042 self.paths['param_default'] = pjoin(self.me_dir,'Cards','param_card_default.dat')
4043 self.paths['run'] = pjoin(self.me_dir,'Cards','run_card.dat')
4044 self.paths['run_default'] = pjoin(self.me_dir,'Cards','run_card_default.dat')
4045 self.paths['transfer'] =pjoin(self.me_dir,'Cards','transfer_card.dat')
4046 self.paths['MadWeight'] =pjoin(self.me_dir,'Cards','MadWeight_card.dat')
4047 self.paths['MadWeight_default'] =pjoin(self.me_dir,'Cards','MadWeight_card_default.dat')
4048 self.paths['ML'] =pjoin(self.me_dir,'Cards','MadLoopParams.dat')
4049 self.paths['shower'] = pjoin(self.me_dir,'Cards','shower_card.dat')
4050 self.paths['shower_default'] = pjoin(self.me_dir,'Cards','shower_card_default.dat')
4051 self.paths['FO_analyse'] = pjoin(self.me_dir,'Cards','FO_analyse_card.dat')
4052 self.paths['FO_analyse_default'] = pjoin(self.me_dir,'Cards','FO_analyse_card_default.dat')
4053 self.paths['pythia'] =pjoin(self.me_dir, 'Cards','pythia_card.dat')
4054 self.paths['PY8'] = pjoin(self.me_dir, 'Cards','pythia8_card.dat')
4055 self.paths['PY8_default'] = pjoin(self.me_dir, 'Cards','pythia8_card_default.dat')
4056 self.paths['madspin_default'] = pjoin(self.me_dir,'Cards/madspin_card_default.dat')
4057 self.paths['madspin'] = pjoin(self.me_dir,'Cards/madspin_card.dat')
4058 self.paths['reweight'] = pjoin(self.me_dir,'Cards','reweight_card.dat')
4059 self.paths['delphes'] = pjoin(self.me_dir,'Cards','delphes_card.dat')
4060 self.paths['plot'] = pjoin(self.me_dir,'Cards','plot_card.dat')
4061 self.paths['plot_default'] = pjoin(self.me_dir,'Cards','plot_card_default.dat')
4062 self.paths['madanalysis5_parton'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card.dat')
4063 self.paths['madanalysis5_hadron'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card.dat')
4064 self.paths['madanalysis5_parton_default'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat')
4065 self.paths['madanalysis5_hadron_default'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')
4066 self.paths['FO_analyse'] = pjoin(self.me_dir,'Cards', 'FO_analyse_card.dat')
4067
4068 - def __init__(self, question, cards=[], mode='auto', *args, **opt):
4069
4070 self.load_default()
4071 self.define_paths(**opt)
4072 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt)
4073
4074
4075 try:
4076 self.param_card = check_param_card.ParamCard(self.paths['param'])
4077 except (check_param_card.InvalidParamCard, ValueError) as e:
4078 logger.error('Current param_card is not valid. We are going to use the default one.')
4079 logger.error('problem detected: %s' % e)
4080 files.cp(self.paths['param_default'], self.paths['param'])
4081 self.param_card = check_param_card.ParamCard(self.paths['param'])
4082 default_param = check_param_card.ParamCard(self.paths['param_default'])
4083 self.param_card_default = default_param
4084
4085 try:
4086 self.run_card = banner_mod.RunCard(self.paths['run'], consistency='warning')
4087 except IOError:
4088 self.run_card = {}
4089 try:
4090 run_card_def = banner_mod.RunCard(self.paths['run_default'])
4091 except IOError:
4092 run_card_def = {}
4093
4094 self.pname2block = {}
4095 self.conflict = []
4096 self.restricted_value = {}
4097 self.mode = mode
4098 self.cards = cards
4099
4100
4101
4102
4103 self.pname2block, self.restricted_value = \
4104 default_param.analyze_param_card()
4105
4106 if run_card_def:
4107 self.run_set = run_card_def.keys() + self.run_card.hidden_param
4108 elif self.run_card:
4109 self.run_set = self.run_card.keys()
4110 else:
4111 self.run_set = []
4112
4113 for var in self.pname2block:
4114 if var in self.run_set:
4115 self.conflict.append(var)
4116
4117
4118 self.has_delphes = False
4119 if 'delphes_card.dat' in cards:
4120 self.has_delphes = True
4121
4122
4123 self.has_mw = False
4124 if 'madweight_card.dat' in cards:
4125
4126 self.do_change_tf = self.mother_interface.do_define_transfer_fct
4127 self.complete_change_tf = self.mother_interface.complete_define_transfer_fct
4128 self.help_change_tf = self.mother_interface.help_define_transfer_fct
4129 if not os.path.exists(self.paths['transfer']):
4130 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
4131
4132
4133 self.has_mw = True
4134 try:
4135 import madgraph.madweight.Cards as mwcards
4136 except:
4137 import internal.madweight.Cards as mwcards
4138 self.mw_card = mwcards.Card(self.paths['MadWeight'])
4139 self.mw_card = self.mw_card.info
4140 self.mw_vars = []
4141 for key in self.mw_card:
4142 if key == 'comment':
4143 continue
4144 for key2 in self.mw_card.info[key]:
4145 if isinstance(key2, str) and not key2.isdigit():
4146 self.mw_vars.append(key2)
4147
4148
4149 for var in self.pname2block:
4150 if var in self.mw_vars:
4151 self.conflict.append(var)
4152 for var in self.mw_vars:
4153 if var in self.run_card:
4154 self.conflict.append(var)
4155
4156
4157 self.has_ml = False
4158 if os.path.isfile(self.paths['ML']):
4159 self.has_ml = True
4160 self.MLcard = banner_mod.MadLoopParam(self.paths['ML'])
4161 self.MLcardDefault = banner_mod.MadLoopParam()
4162
4163 self.ml_vars = [k.lower() for k in self.MLcard.keys()]
4164
4165 for var in self.ml_vars:
4166 if var in self.run_card:
4167 self.conflict.append(var)
4168 if var in self.pname2block:
4169 self.conflict.append(var)
4170 if self.has_mw and var in self.mw_vars:
4171 self.conflict.append(var)
4172
4173
4174 self.has_shower = False
4175 if 'shower_card.dat' in cards:
4176 self.has_shower = True
4177 try:
4178 import madgraph.various.shower_card as showercards
4179 except:
4180 import internal.shower_card as showercards
4181 self.shower_card = showercards.ShowerCard(self.paths['shower'])
4182 self.shower_vars = self.shower_card.keys()
4183
4184
4185 for var in self.pname2block:
4186 if var in self.shower_vars:
4187 self.conflict.append(var)
4188 for var in self.shower_vars:
4189 if var in self.run_card:
4190 self.conflict.append(var)
4191
4192
4193 self.has_PY8 = False
4194 if 'pythia8_card.dat' in cards:
4195 self.has_PY8 = True
4196 self.PY8Card = banner_mod.PY8Card(self.paths['PY8'])
4197 self.PY8CardDefault = banner_mod.PY8Card()
4198
4199 self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
4200
4201 for var in self.py8_vars:
4202 if var in self.run_card:
4203 self.conflict.append(var)
4204 if var in self.pname2block:
4205 self.conflict.append(var)
4206 if self.has_mw and var in self.mw_vars:
4207 self.conflict.append(var)
4208 if self.has_ml and var in self.ml_vars:
4209 self.conflict.append(var)
4210
4211 - def do_help(self, line, conflict_raise=False, banner=True):
4212
4213 if banner:
4214 logger.info('*** HELP MESSAGE ***', '$MG:color:BLACK')
4215
4216 args = self.split_arg(line)
4217
4218 if len(args)==0 or (len(args) == 1 and hasattr(self, 'do_%s' % args[0])):
4219 out = cmd.BasicCmd.do_help(self, line)
4220 if len(args)==0:
4221 print 'Allowed Argument'
4222 print '================'
4223 print '\t'.join(self.allow_arg)
4224 print
4225 print 'Special shortcut: (type help <name>)'
4226 print '===================================='
4227 print ' syntax: set <name> <value>'
4228 print '\t'.join(self.special_shortcut)
4229 print
4230 if banner:
4231 logger.info('*** END HELP ***', '$MG:color:BLACK')
4232 return out
4233
4234
4235 if args[0] in self.special_shortcut:
4236 if args[0] in self.special_shortcut_help:
4237 print self.special_shortcut_help[args[0]]
4238 if banner:
4239 logger.info('*** END HELP ***', '$MG:color:BLACK')
4240 return
4241
4242 start = 0
4243 card = ''
4244 if args[0]+'_card' in self.all_card_name+ self.cards:
4245 args[0] += '_card'
4246 elif args[0]+'.dat' in self.all_card_name+ self.cards:
4247 args[0] += '.dat'
4248 elif args[0]+'_card.dat' in self.all_card_name+ self.cards:
4249 args[0] += '_card.dat'
4250 if args[0] in self.all_card_name + self.cards:
4251 start += 1
4252 card = args[0]
4253 if len(args) == 1:
4254 if args[0] == 'pythia8_card':
4255 args[0] = 'PY8Card'
4256 if args[0] == 'param_card':
4257 logger.info("Param_card information: ", '$MG:color:BLUE')
4258 print "File to define the various model parameter"
4259 logger.info("List of the Block defined:",'$MG:color:BLUE')
4260 print "\t".join(self.param_card.keys())
4261 elif args[0].startswith('madanalysis5'):
4262 print 'This card allow to make plot with the madanalysis5 package'
4263 print 'An example card is provided. For more information about the '
4264 print 'syntax please refer to: https://madanalysis.irmp.ucl.ac.be/'
4265 print 'or to the user manual [arXiv:1206.1599]'
4266 if args[0].startswith('madanalysis5_hadron'):
4267 print
4268 print 'This card also allow to make recasting analysis'
4269 print 'For more detail, see: arXiv:1407.3278'
4270 elif hasattr(self, args[0]):
4271 logger.info("%s information: " % args[0], '$MG:color:BLUE')
4272 print(eval('self.%s' % args[0]).__doc__)
4273 logger.info("List of parameter associated", '$MG:color:BLUE')
4274 print "\t".join(eval('self.%s' % args[0]).keys())
4275 if banner:
4276 logger.info('*** END HELP ***', '$MG:color:BLACK')
4277 return
4278
4279
4280 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']:
4281 if args[start] not in self.run_set:
4282 args[start] = [l for l in self.run_set if l.lower() == args[start]][0]
4283
4284 if args[start] in self.conflict and not conflict_raise:
4285 conflict_raise = True
4286 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK')
4287 if card == '':
4288 logger.info('** If not explicitely speficy this parameter will modif the run_card file', '$MG:color:BLACK')
4289
4290 self.run_card.do_help(args[start])
4291
4292 elif (args[start] in self.param_card or args[start] == 'width') \
4293 and card in ['','param_card']:
4294 if args[start] in self.conflict and not conflict_raise:
4295 conflict_raise = True
4296 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK')
4297 if card == '':
4298 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:color:BLACK')
4299
4300 if args[start] == 'width':
4301 args[start] = 'decay'
4302
4303 if len(args) == start+1:
4304 self.param_card.do_help(args[start], tuple())
4305 key = None
4306 elif args[start+1] in self.pname2block:
4307 all_var = self.pname2block[args[start+1]]
4308 key = None
4309 for bname, lhaid in all_var:
4310 if bname == args[start]:
4311 key = lhaid
4312 break
4313 else:
4314 logger.warning('%s is not part of block "%s" but "%s". please correct.' %
4315 (args[start+1], args[start], bname))
4316 else:
4317 try:
4318 key = tuple([int(i) for i in args[start+1:]])
4319 except ValueError:
4320 logger.warning('Failed to identify LHA information')
4321 return
4322
4323 if key in self.param_card[args[start]].param_dict:
4324 self.param_card.do_help(args[start], key, default=self.param_card_default)
4325 elif key:
4326 logger.warning('invalid information: %s not defined in the param_card' % (key,))
4327
4328 elif args[start] in self.pname2block and card in ['','param_card']:
4329 if args[start] in self.conflict and not conflict_raise:
4330 conflict_raise = True
4331 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK')
4332 if card == '':
4333 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:color:BLACK')
4334
4335 all_var = self.pname2block[args[start]]
4336 for bname, lhaid in all_var:
4337 new_line = 'param_card %s %s %s' % (bname,
4338 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:]))
4339 self.do_help(new_line, conflict_raise=True, banner=False)
4340
4341
4342 elif self.has_ml and args[start] in self.ml_vars \
4343 and card in ['', 'MadLoop_card']:
4344
4345 if args[start] in self.conflict and not conflict_raise:
4346 conflict_raise = True
4347 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK')
4348 if card == '':
4349 logger.info('** If not explicitely speficy this parameter will modif the madloop_card file', '$MG:color:BLACK')
4350
4351 self.MLcard.do_help(args[start])
4352
4353
4354 elif self.has_PY8 and args[start] in self.PY8Card:
4355 if args[start] in self.conflict and not conflict_raise:
4356 conflict_raise = True
4357 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:color:BLACK')
4358 if card == '':
4359 logger.info('** If not explicitely speficy this parameter will modif the pythia8_card file', '$MG:color:BLACK')
4360
4361 self.PY8Card.do_help(args[start])
4362 elif card.startswith('madanalysis5'):
4363 print 'MA5'
4364
4365
4366 else:
4367 print "no help available"
4368
4369 if banner:
4370 logger.info('*** END HELP ***', '$MG:color:BLACK')
4371
4372 return
4373
4374
4375
4376
4377
4378
4380 prev_timer = signal.alarm(0)
4381 if prev_timer:
4382 nb_back = len(line)
4383 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
4384 self.stdout.write(line)
4385 self.stdout.flush()
4386
4387 possibilities = self.complete_set(text, line, begidx, endidx,formatting=False)
4388 if line[:begidx].strip() == 'help':
4389 possibilities['Defined command'] = cmd.BasicCmd.completenames(self, text, line)
4390 possibilities.update(self.complete_add(text, line, begidx, endidx,formatting=False))
4391 return self.deal_multiple_categories(possibilities)
4392
4393
4394
4395
4396
4398 prev_timer = signal.alarm(0)
4399 if prev_timer:
4400 nb_back = len(line)
4401 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
4402 self.stdout.write(line)
4403 self.stdout.flush()
4404
4405 arg = line[:begidx].split()
4406 if len(arg) <=1:
4407 return self.list_completion(text, ['dependent', 'missing', 'to_slha1', 'to_slha2'], line)
4408
4409
4410 - def complete_set(self, text, line, begidx, endidx, formatting=True):
4411 """ Complete the set command"""
4412
4413 prev_timer = signal.alarm(0)
4414 if prev_timer:
4415 nb_back = len(line)
4416 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
4417 self.stdout.write(line)
4418 self.stdout.flush()
4419
4420 possibilities = {}
4421 allowed = {}
4422 args = self.split_arg(line[0:begidx])
4423 if args[-1] in ['Auto', 'default']:
4424 return
4425 if len(args) == 1:
4426 allowed = {'category':'', 'run_card':'', 'block':'all', 'param_card':'','shortcut':''}
4427 if self.has_mw:
4428 allowed['madweight_card'] = ''
4429 allowed['mw_block'] = 'all'
4430 if self.has_shower:
4431 allowed['shower_card'] = ''
4432 if self.has_ml:
4433 allowed['madloop_card'] = ''
4434 if self.has_PY8:
4435 allowed['pythia8_card'] = ''
4436 if self.has_delphes:
4437 allowed['delphes_card'] = ''
4438
4439 elif len(args) == 2:
4440 if args[1] == 'run_card':
4441 allowed = {'run_card':'default'}
4442 elif args[1] == 'param_card':
4443 allowed = {'block':'all', 'param_card':'default'}
4444 elif args[1] in self.param_card.keys():
4445 allowed = {'block':args[1]}
4446 elif args[1] == 'width':
4447 allowed = {'block': 'decay'}
4448 elif args[1] == 'MadWeight_card':
4449 allowed = {'madweight_card':'default', 'mw_block': 'all'}
4450 elif args[1] == 'MadLoop_card':
4451 allowed = {'madloop_card':'default'}
4452 elif args[1] == 'pythia8_card':
4453 allowed = {'pythia8_card':'default'}
4454 elif self.has_mw and args[1] in self.mw_card.keys():
4455 allowed = {'mw_block':args[1]}
4456 elif args[1] == 'shower_card':
4457 allowed = {'shower_card':'default'}
4458 elif args[1] == 'delphes_card':
4459 allowed = {'delphes_card':'default'}
4460 else:
4461 allowed = {'value':''}
4462 else:
4463 start = 1
4464 if args[1] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card',
4465 'MadLoop_card','pythia8_card','delphes_card','plot_card',
4466 'madanalysis5_parton_card','madanalysis5_hadron_card']:
4467 start = 2
4468 if args[-1] in self.pname2block.keys():
4469 allowed['value'] = 'default'
4470 elif args[start] in self.param_card.keys() or args[start] == 'width':
4471 if args[start] == 'width':
4472 args[start] = 'decay'
4473
4474 if args[start+1:]:
4475 allowed = {'block':(args[start], args[start+1:])}
4476 else:
4477 allowed = {'block':args[start]}
4478 elif self.has_mw and args[start] in self.mw_card.keys():
4479 if args[start+1:]:
4480 allowed = {'mw_block':(args[start], args[start+1:])}
4481 else:
4482 allowed = {'mw_block':args[start]}
4483
4484
4485 else:
4486 allowed['value'] = ''
4487
4488 if 'category' in allowed.keys():
4489 categories = ['run_card', 'param_card']
4490 if self.has_mw:
4491 categories.append('MadWeight_card')
4492 if self.has_shower:
4493 categories.append('shower_card')
4494 if self.has_ml:
4495 categories.append('MadLoop_card')
4496 if self.has_PY8:
4497 categories.append('pythia8_card')
4498 if self.has_delphes:
4499 categories.append('delphes_card')
4500
4501 possibilities['category of parameter (optional)'] = \
4502 self.list_completion(text, categories)
4503
4504 if 'shortcut' in allowed.keys():
4505 possibilities['special values'] = self.list_completion(text, self.special_shortcut.keys()+['qcut', 'showerkt'])
4506
4507 if 'run_card' in allowed.keys():
4508 opts = self.run_set
4509 if allowed['run_card'] == 'default':
4510 opts.append('default')
4511
4512 possibilities['Run Card'] = self.list_completion(text, opts)
4513
4514 if 'param_card' in allowed.keys():
4515 opts = self.pname2block.keys()
4516 if allowed['param_card'] == 'default':
4517 opts.append('default')
4518 possibilities['Param Card'] = self.list_completion(text, opts)
4519
4520 if 'madweight_card' in allowed.keys():
4521 opts = self.mw_vars + [k for k in self.mw_card.keys() if k !='comment']
4522 if allowed['madweight_card'] == 'default':
4523 opts.append('default')
4524 possibilities['MadWeight Card'] = self.list_completion(text, opts)
4525
4526 if 'madloop_card' in allowed.keys():
4527 opts = self.ml_vars
4528 if allowed['madloop_card'] == 'default':
4529 opts.append('default')
4530 possibilities['MadLoop Parameter'] = self.list_completion(text, opts)
4531
4532 if 'pythia8_card' in allowed.keys():
4533 opts = self.py8_vars
4534 if allowed['pythia8_card'] == 'default':
4535 opts.append('default')
4536 possibilities['Pythia8 Parameter'] = self.list_completion(text, opts)
4537
4538 if 'shower_card' in allowed.keys():
4539 opts = self.shower_vars + [k for k in self.shower_card.keys() if k !='comment']
4540 if allowed['shower_card'] == 'default':
4541 opts.append('default')
4542 possibilities['Shower Card'] = self.list_completion(text, opts)
4543
4544 if 'delphes_card' in allowed:
4545 if allowed['delphes_card'] == 'default':
4546 opts = ['default', 'atlas', 'cms']
4547 possibilities['Delphes Card'] = self.list_completion(text, opts)
4548
4549 if 'value' in allowed.keys():
4550 opts = ['default']
4551 if 'decay' in args:
4552 opts.append('Auto')
4553 opts.append('Auto@NLO')
4554 elif args[-1] in self.pname2block and self.pname2block[args[-1]][0][0] == 'decay':
4555 opts.append('Auto')
4556 opts.append('Auto@NLO')
4557 possibilities['Special Value'] = self.list_completion(text, opts)
4558
4559 if 'block' in allowed.keys():
4560 if allowed['block'] == 'all':
4561 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i]
4562 allowed_block.append('width')
4563 possibilities['Param Card Block' ] = \
4564 self.list_completion(text, allowed_block)
4565 elif isinstance(allowed['block'], basestring):
4566 block = self.param_card[allowed['block']].param_dict
4567 ids = [str(i[0]) for i in block
4568 if (allowed['block'], i) not in self.restricted_value]
4569 possibilities['Param Card id' ] = self.list_completion(text, ids)
4570 varname = [name for name, all_var in self.pname2block.items()
4571 if any((bname == allowed['block']
4572 for bname,lhaid in all_var))]
4573 possibilities['Param card variable'] = self.list_completion(text,
4574 varname)
4575 else:
4576 block = self.param_card[allowed['block'][0]].param_dict
4577 nb = len(allowed['block'][1])
4578 ids = [str(i[nb]) for i in block if len(i) > nb and \
4579 [str(a) for a in i[:nb]] == allowed['block'][1]]
4580
4581 if not ids:
4582 if tuple([int(i) for i in allowed['block'][1]]) in block:
4583 opts = ['default']
4584 if allowed['block'][0] == 'decay':
4585 opts.append('Auto')
4586 opts.append('Auto@NLO')
4587 possibilities['Special value'] = self.list_completion(text, opts)
4588 possibilities['Param Card id' ] = self.list_completion(text, ids)
4589
4590 if 'mw_block' in allowed.keys():
4591 if allowed['mw_block'] == 'all':
4592 allowed_block = [i for i in self.mw_card.keys() if 'comment' not in i]
4593 possibilities['MadWeight Block' ] = \
4594 self.list_completion(text, allowed_block)
4595 elif isinstance(allowed['mw_block'], basestring):
4596 block = self.mw_card[allowed['mw_block']]
4597 ids = [str(i[0]) if isinstance(i, tuple) else str(i) for i in block]
4598 possibilities['MadWeight Card id' ] = self.list_completion(text, ids)
4599 else:
4600 block = self.mw_card[allowed['mw_block'][0]]
4601 nb = len(allowed['mw_block'][1])
4602 ids = [str(i[nb]) for i in block if isinstance(i, tuple) and\
4603 len(i) > nb and \
4604 [str(a) for a in i[:nb]] == allowed['mw_block'][1]]
4605
4606 if not ids:
4607 if tuple([i for i in allowed['mw_block'][1]]) in block or \
4608 allowed['mw_block'][1][0] in block.keys():
4609 opts = ['default']
4610 possibilities['Special value'] = self.list_completion(text, opts)
4611 possibilities['MadWeight Card id' ] = self.list_completion(text, ids)
4612
4613 return self.deal_multiple_categories(possibilities, formatting)
4614
4616 """ edit the value of one parameter in the card"""
4617
4618
4619 args = self.split_arg(line)
4620 if len(args) == 0:
4621 logger.warning("No argument. For help type 'help set'.")
4622
4623 if len(args)==1 and '=' in args[-1]:
4624 arg1, arg2 = args.pop(-1).split('=',1)
4625 args += [arg1, arg2]
4626 if '=' in args:
4627 args.remove('=')
4628
4629 args[:-1] = [ a.lower() for a in args[:-1]]
4630
4631 if args[0] in self.special_shortcut:
4632 targettypes , cmd = self.special_shortcut[args[0]]
4633 if len(args) != len(targettypes) +1:
4634 logger.warning('shortcut %s requires %s argument' % (args[0], len(targettypes)))
4635 if len(args) < len(targettypes) +1:
4636 return
4637 else:
4638 logger.warning('additional argument will be ignored')
4639 values ={}
4640 for i, argtype in enumerate(targettypes):
4641 try:
4642 values = {str(i): banner_mod.ConfigFile.format_variable(args[i+1], argtype, args[0])}
4643 except ValueError as e:
4644 logger.warning("Wrong argument: The entry #%s should be of type %s.", i+1, argtype)
4645 return
4646
4647
4648
4649 for arg in cmd:
4650 try:
4651 text = arg % values
4652 except KeyError:
4653 logger.warning("This command requires one argument")
4654 return
4655 except Exception as e:
4656 logger.warning(str(e))
4657 return
4658 else:
4659 self.do_set(arg % values)
4660 return
4661
4662
4663 start = 0
4664 if len(args) < 2:
4665 logger.warning('Invalid set command %s (need two arguments)' % line)
4666 return
4667
4668
4669 if args[0].lower() == 'qcut':
4670 pythia_path = self.paths['pythia']
4671 if os.path.exists(pythia_path):
4672 logger.info('add line QCUT = %s in pythia_card.dat' % args[1])
4673 p_card = open(pythia_path,'r').read()
4674 p_card, n = re.subn('''^\s*QCUT\s*=\s*[\de\+\-\.]*\s*$''',
4675 ''' QCUT = %s ''' % args[1], \
4676 p_card, flags=(re.M+re.I))
4677 if n==0:
4678 p_card = '%s \n QCUT= %s' % (p_card, args[1])
4679 with open(pythia_path, 'w') as fsock:
4680 fsock.write(p_card)
4681 return
4682
4683 if args[0].lower() == 'showerkt':
4684 pythia_path = self.paths['pythia']
4685 if os.path.exists(pythia_path):
4686 logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper())
4687 p_card = open(pythia_path,'r').read()
4688 p_card, n = re.subn('''^\s*SHOWERKT\s*=\s*[default\de\+\-\.]*\s*$''',
4689 ''' SHOWERKT = %s ''' % args[1].upper(), \
4690 p_card, flags=(re.M+re.I))
4691 if n==0:
4692 p_card = '%s \n SHOWERKT= %s' % (p_card, args[1].upper())
4693 with open(pythia_path, 'w') as fsock:
4694 fsock.write(p_card)
4695 return
4696
4697 card = ''
4698 if args[0] == 'madweight_card':
4699 if not self.mw_card:
4700 logger.warning('Invalid Command: No MadWeight card defined.')
4701 return
4702 args[0] = 'MadWeight_card'
4703
4704 if args[0] == 'shower_card':
4705 if not self.shower_card:
4706 logger.warning('Invalid Command: No Shower card defined.')
4707 return
4708 args[0] = 'shower_card'
4709
4710 if args[0] == "madloop_card":
4711 if not self.has_ml:
4712 logger.warning('Invalid Command: No MadLoopParam card defined.')
4713 return
4714 args[0] = 'MadLoop_card'
4715
4716 if args[0] == "pythia8_card":
4717 if not self.has_PY8:
4718 logger.warning('Invalid Command: No Pythia8 card defined.')
4719 return
4720 args[0] = 'pythia8_card'
4721
4722 if args[0] == 'delphes_card':
4723 if not self.has_delphes:
4724 logger.warning('Invalid Command: No Delphes card defined.')
4725 return
4726 if args[1] == 'atlas':
4727 logger.info("set default ATLAS configuration for Delphes", '$MG:color:BLACK')
4728 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_ATLAS.dat'),
4729 pjoin(self.me_dir,'Cards', 'delphes_card.dat'))
4730 return
4731 elif args[1] == 'cms':
4732 logger.info("set default CMS configuration for Delphes",'$MG:color:BLACK')
4733 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_CMS.dat'),
4734 pjoin(self.me_dir,'Cards', 'delphes_card.dat'))
4735 return
4736
4737 if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card',
4738 'delphes_card','madanalysis5_hadron_card','madanalysis5_parton_card']:
4739 if args[1] == 'default':
4740 logger.info('replace %s by the default card' % args[0],'$MG:color:BLACK')
4741 files.cp(self.paths['%s_default' %args[0][:-5]], self.paths[args[0][:-5]])
4742 if args[0] == 'param_card':
4743 self.param_card = check_param_card.ParamCard(self.paths['param'])
4744 elif args[0] == 'run_card':
4745 self.run_card = banner_mod.RunCard(self.paths['run'])
4746 elif args[0] == 'shower_card':
4747 self.shower_card = shower_card_mod.ShowerCard(self.paths['shower'])
4748 return
4749 else:
4750 card = args[0]
4751 start=1
4752 if len(args) < 3:
4753 logger.warning('Invalid set command: %s (not enough arguments)' % line)
4754 return
4755
4756 elif args[0] in ['MadLoop_card']:
4757 if args[1] == 'default':
4758 logger.info('replace MadLoopParams.dat by the default card','$MG:color:BLACK')
4759 self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault)
4760 self.MLcard.write(self.paths['ML'],
4761 commentdefault=True)
4762 return
4763 else:
4764 card = args[0]
4765 start=1
4766 if len(args) < 3:
4767 logger.warning('Invalid set command: %s (not enough arguments)' % line)
4768 return
4769 elif args[0] in ['pythia8_card']:
4770 if args[1] == 'default':
4771 logger.info('replace pythia8_card.dat by the default card','$MG:color:BLACK')
4772 self.PY8Card = banner_mod.PY8Card(self.PY8CardDefault)
4773 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
4774 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
4775 print_only_visible=True)
4776 return
4777 else:
4778 card = args[0]
4779 start=1
4780 if len(args) < 3:
4781 logger.warning('Invalid set command: %s (not enough arguments)' % line)
4782 return
4783 elif args[0] in ['madspin_card']:
4784 if args[1] == 'default':
4785 logger.info('replace madspin_card.dat by the default card','$MG:color:BLACK')
4786 files.cp(self.paths['MS_default'], self.paths['madspin'])
4787 return
4788 else:
4789 logger.warning("""Command set not allowed for modifying the madspin_card.
4790 Check the command \"decay\" instead.""")
4791 return
4792
4793
4794 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']:
4795 if args[start] not in self.run_set:
4796 args[start] = [l for l in self.run_set if l.lower() == args[start]][0]
4797
4798 if args[start] in self.conflict and card == '':
4799 text = 'Ambiguous name (present in more than one card). Will assume it to be referred to run_card.\n'
4800 text += 'If this is not intended, please reset it in the run_card and specify the relevant card to \n'
4801 text += 'edit, in the format < set card parameter value >'
4802 logger.warning(text)
4803
4804 if args[start+1] == 'default':
4805 default = banner_mod.RunCard(self.paths['run_default'])
4806 if args[start] in default.keys():
4807 self.setR(args[start],default[args[start]])
4808 else:
4809 logger.info('remove information %s from the run_card' % args[start],'$MG:color:BLACK')
4810 del self.run_card[args[start]]
4811 else:
4812 if args[0].startswith('sys_') or \
4813 args[0] in self.run_card.list_parameter or \
4814 args[0] in self.run_card.dict_parameter:
4815 val = ' '.join(args[start+1:])
4816 val = val.split('#')[0]
4817 else:
4818 val = args[start+1]
4819 self.setR(args[start], val)
4820 self.run_card.write(self.paths['run'], self.paths['run_default'])
4821
4822 elif card == 'run_card' and args[start] in ['nocut', 'no_cut']:
4823 logger.info("Going to remove all cuts from the run_card", '$MG:color:BLACK')
4824 self.run_card.remove_all_cut()
4825 self.run_card.write(self.paths['run'], self.paths['run_default'])
4826
4827 elif (args[start] in self.param_card or args[start] == 'width') \
4828 and card in ['','param_card']:
4829
4830 if any(t.startswith('scan') for t in args):
4831 index = [i for i,t in enumerate(args) if t.startswith('scan')][0]
4832 args = args[:index] + [' '.join(args[index:])]
4833
4834 if args[start] in self.conflict and card == '':
4835 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
4836 text += ' in the format < set card parameter value>'
4837 logger.warning(text)
4838 return
4839
4840 if args[start] == 'width':
4841 args[start] = 'decay'
4842
4843 if args[start+1] in self.pname2block:
4844 all_var = self.pname2block[args[start+1]]
4845 key = None
4846 for bname, lhaid in all_var:
4847 if bname == args[start]:
4848 key = lhaid
4849 break
4850 else:
4851 logger.warning('%s is not part of block "%s" but "%s". please correct.' %
4852 (args[start+1], args[start], bname))
4853 return
4854 else:
4855 try:
4856 key = tuple([int(i) for i in args[start+1:-1]])
4857 except ValueError:
4858 if args[start] == 'decay' and args[start+1:-1] == ['all']:
4859 for key in self.param_card[args[start]].param_dict:
4860 if (args[start], key) in self.restricted_value:
4861 continue
4862 else:
4863 self.setP(args[start], key, args[-1])
4864 self.param_card.write(self.paths['param'])
4865 return
4866 logger.warning('invalid set command %s (failed to identify LHA information)' % line)
4867 return
4868
4869 if key in self.param_card[args[start]].param_dict:
4870 if (args[start], key) in self.restricted_value:
4871 text = "Note that this parameter seems to be ignore by MG.\n"
4872 text += "MG will use instead the expression: %s\n" % \
4873 self.restricted_value[(args[start], key)]
4874 text += "You need to match this expression for external program (such pythia)."
4875 logger.warning(text)
4876
4877 if args[-1].lower() in ['default', 'auto', 'auto@nlo'] or args[-1].startswith('scan'):
4878 self.setP(args[start], key, args[-1])
4879 else:
4880 try:
4881 value = float(args[-1])
4882 except Exception:
4883 logger.warning('Invalid input: Expected number and not \'%s\'' \
4884 % args[-1])
4885 return
4886 self.setP(args[start], key, value)
4887 else:
4888 logger.warning('invalid set command %s' % line)
4889 return
4890 self.param_card.write(self.paths['param'])
4891
4892
4893 elif args[start] in self.pname2block and card in ['','param_card']:
4894 if args[start] in self.conflict and card == '':
4895 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
4896 text += ' in the format < set card parameter value>'
4897 logger.warning(text)
4898 return
4899
4900 all_var = self.pname2block[args[start]]
4901 for bname, lhaid in all_var:
4902 new_line = 'param_card %s %s %s' % (bname,
4903 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:]))
4904 self.do_set(new_line)
4905 if len(all_var) > 1:
4906 logger.warning('This variable correspond to more than one parameter in the param_card.')
4907 for bname, lhaid in all_var:
4908 logger.warning(' %s %s' % (bname, ' '.join([str(i) for i in lhaid])))
4909 logger.warning('all listed variables have been modified')
4910
4911
4912 elif self.has_mw and (args[start] in self.mw_card and args[start] != 'comment') \
4913 and card in ['','MadWeight_card']:
4914
4915 if args[start] in self.conflict and card == '':
4916 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
4917 text += ' in the format < set card parameter value>'
4918 logger.warning(text)
4919 return
4920
4921 block = args[start]
4922 name = args[start+1]
4923 value = args[start+2:]
4924 self.setM(block, name, value)
4925 self.mw_card.write(self.paths['MadWeight'])
4926
4927
4928 elif self.has_mw and args[start] in self.mw_vars \
4929 and card in ['', 'MadWeight_card']:
4930
4931 if args[start] in self.conflict and card == '':
4932 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
4933 text += ' in the format < set card parameter value>'
4934 logger.warning(text)
4935 return
4936
4937 block = [b for b, data in self.mw_card.items() if args[start] in data]
4938 if len(block) > 1:
4939 logger.warning('%s is define in more than one block: %s.Please specify.'
4940 % (args[start], ','.join(block)))
4941 return
4942
4943 block = block[0]
4944 name = args[start]
4945 value = args[start+1:]
4946 self.setM(block, name, value)
4947 self.mw_card.write(self.paths['MadWeight'])
4948
4949
4950 elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\
4951 and card == 'MadWeight_card':
4952 block = args[start]
4953 name = args[start+1]
4954 value = args[start+2]
4955 self.setM(block, name, value)
4956 self.mw_card.write(self.paths['MadWeight'])
4957
4958
4959 elif self.has_shower and args[start].lower() in [l.lower() for l in \
4960 self.shower_card.keys()] and card in ['', 'shower_card']:
4961 if args[start] not in self.shower_card:
4962 args[start] = [l for l in self.shower_card if l.lower() == args[start].lower()][0]
4963
4964 if args[start] in self.conflict and card == '':
4965 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
4966 text += ' in the format < set card parameter value>'
4967 logger.warning(text)
4968 return
4969
4970 if args[start+1].lower() == 'default':
4971 default = shower_card_mod.ShowerCard(self.paths['shower_default'])
4972 if args[start] in default.keys():
4973 self.shower_card.set_param(args[start],default[args[start]], self.paths['shower'])
4974 else:
4975 logger.info('remove information %s from the shower_card' % args[start],'$MG:color:BLACK')
4976 del self.shower_card[args[start]]
4977 elif args[start+1].lower() in ['t','.true.','true']:
4978 self.shower_card.set_param(args[start],'.true.',self.paths['shower'])
4979 elif args[start+1].lower() in ['f','.false.','false']:
4980 self.shower_card.set_param(args[start],'.false.',self.paths['shower'])
4981 elif args[start] in ['analyse', 'extralibs', 'extrapaths', 'includepaths'] or\
4982 args[start].startswith('dm_'):
4983
4984 args = line.split()
4985 args_str = ' '.join(str(a) for a in args[start+1:len(args)])
4986 self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat'))
4987 else:
4988 args_str = ' '.join(str(a) for a in args[start+1:len(args)])
4989 self.shower_card.set_param(args[start],args_str,self.paths['shower'])
4990
4991
4992 elif self.has_ml and args[start] in self.ml_vars \
4993 and card in ['', 'MadLoop_card']:
4994
4995 if args[start] in self.conflict and card == '':
4996 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
4997 logger.warning(text)
4998 return
4999
5000 if args[start+1] == 'default':
5001 value = self.MLcardDefault[args[start]]
5002 default = True
5003 else:
5004 value = args[start+1]
5005 default = False
5006 self.setML(args[start], value, default=default)
5007 self.MLcard.write(self.paths['ML'],
5008 commentdefault=True)
5009
5010
5011 elif self.has_PY8 and (card == 'pythia8_card' or (card == '' and \
5012 args[start] in self.PY8Card)):
5013
5014 if args[start] in self.conflict and card == '':
5015 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5016 logger.warning(text)
5017 return
5018
5019 if args[start+1] == 'default':
5020 value = self.PY8CardDefault[args[start]]
5021 default = True
5022 else:
5023 value = ' '.join(args[start+1:])
5024 default = False
5025 self.setPY8(args[start], value, default=default)
5026 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
5027 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
5028 print_only_visible=True)
5029
5030
5031 else:
5032 logger.warning('invalid set command %s ' % line)
5033 arg = args[start].lower()
5034 if self.has_PY8:
5035 close_opts = [name for name in self.PY8Card if name.lower().startswith(arg[:3]) or arg in name.lower()]
5036 if close_opts:
5037 logger.info('Did you mean one of the following PY8 options:\n%s' % '\t'.join(close_opts))
5038 if self.run_card:
5039 close_opts = [name for name in self.run_card if name.lower().startswith(arg[:3]) or arg in name.lower()]
5040 if close_opts:
5041 logger.info('Did you mean one of the following run_card options:\n%s' % '\t'.join(close_opts))
5042
5043 return
5044
5045 - def setM(self, block, name, value):
5046
5047 if isinstance(value, list) and len(value) == 1:
5048 value = value[0]
5049
5050 if block not in self.mw_card:
5051 logger.warning('block %s was not present in the current MadWeight card. We are adding it' % block)
5052 self.mw_card[block] = {}
5053 elif name not in self.mw_card[block]:
5054 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')
5055 if value == 'default':
5056 import madgraph.madweight.Cards as mwcards
5057 mw_default = mwcards.Card(self.paths['MadWeight_default'])
5058 try:
5059 value = mw_default[block][name]
5060 except KeyError:
5061 logger.info('removing id "%s" from Block "%s" '% (name, block),'$MG:color:BLACK')
5062 if name in self.mw_card[block]:
5063 del self.mw_card[block][name]
5064 return
5065 if value:
5066 logger.info('modify madweight_card information BLOCK "%s" with id "%s" set to %s',
5067 block, name, value, '$MG:color:BLACK')
5068 else:
5069 logger.warning("Invalid command: No value. To set default value. Use \"default\" as value")
5070 return
5071
5072 self.mw_card[block][name] = value
5073
5074 - def setR(self, name, value):
5075 logger.info('modify parameter %s of the run_card.dat to %s' % (name, value),'$MG:color:BLACK')
5076 self.run_card.set(name, value, user=True)
5077
5078 - def setML(self, name, value, default=False):
5079
5080 try:
5081 self.MLcard.set(name, value, user=True)
5082 except Exception, error:
5083 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error)
5084 return
5085 logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value),'$MG:color:BLACK')
5086 if default and name.lower() in self.MLcard.user_set:
5087 self.MLcard.user_set.remove(name.lower())
5088
5089 - def setPY8(self, name, value, default=False):
5098
5099 - def setP(self, block, lhaid, value):
5100 if isinstance(value, str):
5101 value = value.lower()
5102 if value == 'default':
5103 default = check_param_card.ParamCard(self.paths['param_default'])
5104 value = default[block].param_dict[lhaid].value
5105
5106 elif value in ['auto', 'auto@nlo']:
5107 if 'nlo' in value:
5108 value = 'Auto@NLO'
5109 else:
5110 value = 'Auto'
5111 if block != 'decay':
5112 logger.warning('Invalid input: \'Auto\' value only valid for DECAY')
5113 return
5114 elif value.startswith('scan'):
5115 if ':' not in value:
5116 logger.warning('Invalid input: \'scan\' mode requires a \':\' before the definition.')
5117 return
5118 tag = value.split(':')[0]
5119 tag = tag[4:].strip()
5120 if tag and not tag.isdigit():
5121 logger.warning('Invalid input: scan tag need to be integer and not "%s"' % tag)
5122 return
5123
5124
5125 pass
5126 else:
5127 try:
5128 value = float(value)
5129 except ValueError:
5130 logger.warning('Invalid input: \'%s\' not valid intput.'% value)
5131
5132 logger.info('modify param_card information BLOCK %s with id %s set to %s' %\
5133 (block, lhaid, value), '$MG:color:BLACK')
5134 self.param_card[block].param_dict[lhaid].value = value
5135
5137 """This is run on quitting the class. Apply here all the self-consistency
5138 rule that you want. Do the modification via the set command."""
5139
5140
5141 if 'reweight' in self.allow_arg and 'run' in self.allow_arg and \
5142 isinstance(self.run_card,banner_mod.RunCardNLO) and \
5143 not self.run_card['store_rwgt_info']:
5144
5145 re_pattern = re.compile(r'''^\s*change\s*mode\s* (LO\+NLO|LO|NLO)\s*(?:#|$)''', re.M+re.I)
5146 text = open(self.paths['reweight']).read()
5147 options = re_pattern.findall(text)
5148 if any(o in ['NLO', 'LO+NLO'] for o in options):
5149 logger.info('NLO reweighting is on ON. Automatically set store_rwgt_info to True', '$MG:color:BLACK' )
5150 self.do_set('run_card store_rwgt_info True')
5151
5152
5153
5154 if 'run' in self.allow_arg and \
5155 self.run_card['systematics_program'] == 'systematics' and \
5156 isinstance(self.run_card,banner_mod.RunCardNLO) and \
5157 not self.run_card['store_rwgt_info']:
5158 logger.warning('To be able to run systematics program, we set store_rwgt_info to True')
5159 self.do_set('run_card store_rwgt_info True')
5160
5161
5162 if 'pythia_card.dat' in self.cards:
5163 if self.run_card['event_norm'] != 'sum':
5164 logger.info('Pythia6 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' )
5165 self.do_set('run_card event_norm sum')
5166
5167 elif 'pythia8_card.dat' in self.cards:
5168 if self.run_card['event_norm'] == 'sum':
5169 logger.info('Pythia8 needs a specific normalisation of the events. We will change it accordingly.', '$MG:color:BLACK' )
5170 self.do_set('run_card event_norm average')
5171
5172
5173 if self.has_shower and isinstance(self.run_card, banner_mod.RunCardNLO):
5174 modify_extralibs, modify_extrapaths = False,False
5175 extralibs = self.shower_card['extralibs'].split()
5176 extrapaths = self.shower_card['extrapaths'].split()
5177
5178 if self.run_card['parton_shower'] in ['PYTHIA8', 'HERWIGPP', 'HW7']:
5179 if 'stdhep' in self.shower_card['extralibs']:
5180 extralibs.remove('stdhep')
5181 modify_extralibs = True
5182 if 'Fmcfio' in self.shower_card['extralibs']:
5183 extralibs.remove('Fmcfio')
5184 modify_extralibs = True
5185 if self.run_card['parton_shower'] == 'PYTHIA8':
5186
5187 if not self.mother_interface.options['pythia8_path']:
5188 raise self.mother_interface.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO'
5189 executable = pjoin(self.mother_interface.options['pythia8_path'], 'bin', 'pythia8-config')
5190 if not os.path.exists(executable):
5191 raise self.mother.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO'
5192
5193
5194 libs , paths = [], []
5195 p = misc.subprocess.Popen([executable, '--libs'], stdout=subprocess.PIPE)
5196 stdout, _ = p. communicate()
5197 libs = [x[2:] for x in stdout.split() if x.startswith('-l') or paths.append(x[2:])]
5198
5199
5200 p = misc.subprocess.Popen([executable, '--config'], stdout=subprocess.PIPE)
5201 stdout, _ = p. communicate()
5202 for lib in ['-ldl','-lstdc++','-lc++']:
5203 if lib in stdout:
5204 libs.append(lib[2:])
5205
5206
5207
5208 supports_HEPMCHACK = '-DHEPMC2HACK' in stdout
5209
5210
5211 for l in libs:
5212 if l not in extralibs:
5213 modify_extralibs = True
5214 extralibs.append(l)
5215 for L in paths:
5216 if L not in extrapaths:
5217 modify_extrapaths = True
5218 extrapaths.append(L)
5219
5220
5221 if modify_extralibs:
5222 if extralibs:
5223 self.do_set('shower_card extralibs %s ' % ' '.join(extralibs))
5224 else:
5225 self.do_set('shower_card extralibs None ')
5226 if modify_extrapaths:
5227 if extrapaths:
5228 self.do_set('shower_card extrapaths %s ' % ' '.join(extrapaths))
5229 else:
5230 self.do_set('shower_card extrapaths None ')
5231
5232
5233 - def reask(self, *args, **opt):
5234
5235 cmd.OneLinePathCompletion.reask(self,*args, **opt)
5236 if self.has_mw and not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')):
5237 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
5238
5239 fail_due_to_format = 0
5240 - def postcmd(self, stop, line):
5241 ending_question = cmd.OneLinePathCompletion.postcmd(self,stop,line)
5242
5243 if ending_question:
5244 self.check_card_consistency()
5245 try:
5246 self.do_update('dependent', timer=20)
5247 except MadGraph5Error, error:
5248 if 'Missing block:' in str(error):
5249 self.fail_due_to_format +=1
5250 if self.fail_due_to_format == 10:
5251 missing, unknow = str(error).split('\n')[-2:]
5252 logger.warning("Invalid param_card:\n%s\n%s\n" % (missing, unknow))
5253 logger.info("Type \"update missing\" to use default value.\n ", '$MG:color:BLACK')
5254 self.value = False
5255 return self.reask(True)
5256 else:
5257 raise
5258
5259 return ending_question
5260
5261
5262
5263
5264
5266 """ syntax: update dependent: Change the mass/width of particles which are not free parameter for the model.
5267 update missing: add to the current param_card missing blocks/parameters.
5268 update to_slha1: pass SLHA2 card to SLHA1 convention. (beta)
5269 update to_slha2: pass SLHA1 card to SLHA2 convention. (beta)"""
5270
5271 args = self.split_arg(line)
5272 if len(args)==0:
5273 logger.warning('miss an argument (dependent or missing). Please retry')
5274 return
5275
5276 if args[0] == 'dependent':
5277 if not self.mother_interface:
5278 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)')
5279
5280 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
5281 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M)
5282 param_text= open(self.paths['param']).read()
5283
5284 if pattern_scan.search(param_text):
5285
5286
5287
5288 return
5289 elif pattern_width.search(param_text):
5290 self.do_compute_widths('')
5291 self.param_card = check_param_card.ParamCard(self.paths['param'])
5292
5293
5294 self.update_dependent(self.mother_interface, self.me_dir, self.param_card,
5295 self.paths['param'], timer)
5296
5297 elif args[0] == 'missing':
5298 self.update_missing()
5299 return
5300
5301 elif args[0] == 'to_slha2':
5302 try:
5303 check_param_card.convert_to_mg5card(self.paths['param'])
5304 logger.info('card updated')
5305 except Exception, error:
5306 logger.warning('failed to update to slha2 due to %s' % error)
5307 self.param_card = check_param_card.ParamCard(self.paths['param'])
5308 elif args[0] == 'to_slha1':
5309 try:
5310 check_param_card.convert_to_slha1(self.paths['param'])
5311 logger.info('card updated')
5312 except Exception, error:
5313 logger.warning('failed to update to slha1 due to %s' % error)
5314 self.param_card = check_param_card.ParamCard(self.paths['param'])
5315
5316 @staticmethod
5318 """static method which can also be called from outside the class
5319 usefull in presence of scan.
5320 return if the param_card was updated or not
5321 """
5322 logger.info('Update the dependent parameter of the param_card.dat')
5323 modify = True
5324 class TimeOutError(Exception):
5325 pass
5326 def handle_alarm(signum, frame):
5327 raise TimeOutError
5328 signal.signal(signal.SIGALRM, handle_alarm)
5329 if timer:
5330 signal.alarm(timer)
5331 log_level=30
5332 else:
5333 log_level=20
5334
5335 try:
5336 model = mecmd.get_model()
5337 signal.alarm(0)
5338 except TimeOutError:
5339 logger.warning('The model takes too long to load so we bypass the updating of dependent parameter.\n'+\
5340 'This might create trouble for external program (like MadSpin/shower/...)\n'+\
5341 'The update can be forced without timer by typing \'update dependent\' at the time of the card edition')
5342 modify =False
5343 except Exception,error:
5344 logger.debug(str(error))
5345 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)')
5346 signal.alarm(0)
5347 else:
5348 restrict_card = pjoin(me_dir,'Source','MODEL','param_card_rule.dat')
5349 if not os.path.exists(restrict_card):
5350 restrict_card = None
5351
5352 if model:
5353 modify = param_card.update_dependent(model, restrict_card, log_level)
5354 if modify and path:
5355 param_card.write(path)
5356 else:
5357 logger.warning('missing MG5aMC code. Fail to update dependent parameter. This might create trouble for program like MadSpin/shower/...')
5358
5359 if log_level==20:
5360 logger.info('param_card up to date.')
5361
5362 return modify
5363
5364
5365
5367
5368 def check_block(self, blockname):
5369 add_entry = 0
5370 if blockname.lower() not in self.param_card_default:
5371 logger.info('unknow block %s: block will be ignored', blockname)
5372 return add_entry
5373 block = self.param_card_default[blockname]
5374 for key in block.keys():
5375 if key not in input_in_block:
5376 param = block.get(key)
5377 if blockname != 'decay':
5378 text.append('\t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment))
5379 else:
5380 text.append('DECAY \t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment))
5381 add_entry += 1
5382 if add_entry:
5383 text.append('\n')
5384 if add_entry:
5385 logger.info("Adding %s parameter(s) to block %s", add_entry, blockname)
5386 return add_entry
5387
5388
5389 current_block = ''
5390 input_in_block = set()
5391 defined_blocks = set()
5392 decay = set()
5393 text = []
5394 add_entry = 0
5395 for line in open(self.paths['param']):
5396
5397 new_block = re.findall(r'^\s*(block|decay)\s*(\w*)', line, re.I)
5398 if new_block:
5399 new_block = new_block[0]
5400 defined_blocks.add(new_block[1].lower())
5401 if current_block:
5402 add_entry += check_block(self, current_block)
5403
5404 current_block= new_block[1]
5405 input_in_block = set()
5406 if new_block[0].lower() == 'decay':
5407 decay.add((int(new_block[1]),))
5408 current_block = ''
5409 if new_block[1].lower() == 'qnumbers':
5410 current_block = ''
5411
5412 text.append(line)
5413 if not current_block:
5414 continue
5415
5416
5417
5418 line = line.split('#',1)[0]
5419 split = line.split()
5420 if not split:
5421 continue
5422 else:
5423 try:
5424 lhacode = [int(i) for i in split[:-1]]
5425 except:
5426 continue
5427 input_in_block.add(tuple(lhacode))
5428
5429 if current_block:
5430 add_entry += check_block(self, current_block)
5431
5432
5433 for block in self.param_card_default:
5434
5435 if block.startswith(('qnumbers', 'decay')):
5436 continue
5437
5438 if block not in defined_blocks:
5439 nb_entry = len(self.param_card_default[block])
5440 logger.info("Block %s was missing. Adding the %s associated parameter(s)", block,nb_entry)
5441 add_entry += nb_entry
5442 text.append(str(self.param_card_default[block]))
5443
5444
5445 input_in_block = decay
5446 add_entry += check_block(self, 'decay')
5447
5448 if add_entry:
5449 logger.info('write new param_card with %s new parameter(s).', add_entry, '$MG:color:BLACK')
5450 open(self.paths['param'],'w').write(''.join(text))
5451 self.reload_card(self.paths['param'])
5452 else:
5453 logger.info('No missing parameter detected.', '$MG:color:BLACK')
5454
5455
5460
5488
5489
5491 """Default action if line is not recognized"""
5492
5493 line = line.strip()
5494 args = line.split()
5495 if line == '' and self.default_value is not None:
5496 self.value = self.default_value
5497
5498 elif hasattr(self, 'do_%s' % args[0]):
5499 self.do_set(' '.join(args[1:]))
5500 elif os.path.isfile(line):
5501 self.copy_file(line)
5502 self.value = 'repeat'
5503 elif self.me_dir and os.path.exists(pjoin(self.me_dir, line)):
5504 self.copy_file(pjoin(self.me_dir,line))
5505 self.value = 'repeat'
5506 elif line.strip() != '0' and line.strip() != 'done' and \
5507 str(line) != 'EOF' and line.strip() in self.allow_arg:
5508 self.open_file(line)
5509 self.value = 'repeat'
5510 else:
5511 self.value = line
5512
5513 return line
5514
5516 """edit the madspin_card to define the decay of the associate particle"""
5517 signal.alarm(0)
5518 path = self.paths['madspin']
5519
5520 if 'madspin_card.dat' not in self.cards or not os.path.exists(path):
5521 logger.warning("Command decay not valid. Since MadSpin is not available.")
5522 return
5523
5524 if ">" not in line:
5525 logger.warning("invalid command for decay. Line ignored")
5526 return
5527
5528 if "-add" in line:
5529
5530 particle = line.split('>')[0].strip()
5531 text = open(path).read()
5532 line = line.replace('--add', '').replace('-add','')
5533 logger.info("change madspin_card to add one decay to %s: %s" %(particle, line.strip()), '$MG:color:BLACK')
5534 if 'launch' in text:
5535 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1)
5536 else:
5537 text += '\ndecay %s\n launch \n' % line
5538 else:
5539
5540
5541 particle = line.split('>')[0].strip()
5542 logger.info("change madspin_card to define the decay of %s: %s" %(particle, line.strip()), '$MG:color:BLACK')
5543 particle = particle.replace('+','\+').replace('-','\-')
5544 decay_pattern = re.compile(r"^\s*decay\s+%s\s*>[\s\w+-~]*?$" % particle, re.I+re.M)
5545 text= open(path).read()
5546 text = decay_pattern.sub('', text)
5547 if 'launch' in text:
5548 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1)
5549 else:
5550 text += '\ndecay %s\n launch \n' % line
5551
5552 with open(path,'w') as fsock:
5553 fsock.write(text)
5554 self.reload_card(path)
5555
5556
5557
5559 signal.alarm(0)
5560 path = self.paths['param']
5561 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
5562 text = open(path).read()
5563 pdg_info = pattern.findall(text)
5564 has_nlo = any("@nlo"==nlo.lower() for _, nlo in pdg_info)
5565 pdg = [p for p,_ in pdg_info]
5566
5567
5568 line = '%s %s' % (line, ' '.join(pdg))
5569 if not '--path' in line:
5570 line += ' --path=%s' % path
5571 if has_nlo:
5572 line += ' --nlo'
5573
5574 try:
5575 return self.mother_interface.do_compute_widths(line)
5576 except InvalidCmd, error:
5577 logger.error("Invalid command: %s " % error)
5578
5582
5584 """help for command decay which modifies MadSpin_card"""
5585
5586 signal.alarm(0)
5587 print '--syntax: decay PROC [--add]'
5588 print ' '
5589 print ' modify the madspin_card to modify the decay of the associate particle.'
5590 print ' and define it to PROC.'
5591 print ' if --add is present, just add a new decay for the associate particle.'
5592
5594 prev_timer = signal.alarm(0)
5595 if prev_timer:
5596 nb_back = len(line)
5597 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
5598 self.stdout.write(line)
5599 self.stdout.flush()
5600 return self.mother_interface.complete_compute_widths(*args,**opts)
5601
5602
5604 """help for add command"""
5605
5606 logger.info('********************* HELP ADD ***************************')
5607 logger.info( '-- syntax: add pythia8_card NAME VALUE')
5608 logger.info( " add a definition of name in the pythia8_card with the given value")
5609 logger.info( " Do not work for the param_card" )
5610 logger.info( '-- syntax: add filename [OPTION] line')
5611 logger.info( ' add the given LINE to the end of the associate file (all file supportedd).')
5612 logger.info( ' OPTION parameter allows to change the position where to write in the file')
5613 logger.info( ' --after_line=banner : write the line at the end of the banner')
5614 logger.info( ' --line_position=X : insert the line before line X (starts at 0)')
5615 logger.info( ' --after_line="<regular-expression>" write the line after the first line matching the regular expression')
5616 logger.info( ' --before_line="<regular-expression>" write the line before the first line matching the regular expression')
5617 logger.info(' --clean remove all previously existing line in the file')
5618 logger.info( ' example: change reweight --after_line="^\s*change mode" change model heft')
5619 logger.info('********************* HELP ADD ***************************')
5620
5621
5622 - def complete_add(self, text, line, begidx, endidx, formatting=True):
5623 """ auto-completion for add command"""
5624
5625 prev_timer = signal.alarm(0)
5626 if prev_timer:
5627 nb_back = len(line)
5628 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
5629 self.stdout.write(line)
5630 self.stdout.flush()
5631
5632 split = line[:begidx].split()
5633 if len(split)==1:
5634 possibilities = {}
5635 cards = [c.rsplit('.',1)[0] for c in self.cards]
5636 possibilities['category of parameter (optional)'] = \
5637 self.list_completion(text, cards)
5638 elif len(split) == 2:
5639 possibilities = {}
5640 options = ['--line_position=','--after_line=banner', '--after_line="','--before_line="']
5641 possibilities['category of parameter (optional)'] = \
5642 self.list_completion(text, options, line)
5643 else:
5644 return
5645 return self.deal_multiple_categories(possibilities, formatting)
5646
5648 """ syntax: add filename NAME VALUE
5649 syntax: add filename LINE"""
5650
5651 args = self.split_arg(line)
5652 if len(args) == 3 and args[0] in ['pythia8_card', 'pythia8_card.dat'] and self.has_PY8:
5653 name= args[1]
5654 value = args[2]
5655 self.PY8Card.userSet(name, value)
5656 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
5657 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
5658 print_only_visible=True)
5659 logger.info("add in the pythia8_card the parameter \"%s\" with value \"%s\"" % (name, value), '$MG:color:BLACK')
5660 elif len(args) > 0:
5661 if args[0] in self.cards:
5662 card = args[0]
5663 elif "%s.dat" % args[0] in self.cards:
5664 card = "%s.dat" % args[0]
5665 elif "%s_card.dat" % args[0] in self.cards:
5666 card = "%s_card.dat" % args[0]
5667 elif self.has_ml and args[0].lower() == "madloop":
5668 card = "MadLoopParams.dat"
5669 else:
5670 logger.error("unknow card %s. Please retry." % args[0])
5671 return
5672
5673 if args[1] == '--clean':
5674 ff = open(pjoin(self.me_dir,'Cards',card),'w')
5675 ff.write("# %s \n" % card)
5676 ff.write("%s \n" % line.split(None,2)[2])
5677 ff.close()
5678 logger.info("writing the line in %s (empty file) the line: \"%s\"" %(card, line.split(None,2)[2] ),'$MG:color:BLACK')
5679
5680 elif args[1].startswith('--line_position='):
5681
5682 text = open(pjoin(self.me_dir,'Cards',card)).read()
5683 split = text.split('\n')
5684 pos = int(args[1].split('=',1)[1])
5685 newline = line.split(None,2)[2]
5686 split.insert(pos, newline)
5687 ff = open(pjoin(self.me_dir,'Cards',card),'w')
5688 ff.write('\n'.join(split))
5689 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,1)[1] ),'$MG:color:BLACK')
5690
5691 elif args[1].startswith('--after_line=banner'):
5692
5693 text = open(pjoin(self.me_dir,'Cards',card)).read()
5694 split = text.split('\n')
5695 for posline,l in enumerate(split):
5696 if not l.startswith('#'):
5697 break
5698 split.insert(posline, line.split(None,2)[2])
5699 ff = open(pjoin(self.me_dir,'Cards',card),'w')
5700 ff.write('\n'.join(split))
5701 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] ),'$MG:color:BLACK')
5702
5703 elif args[1].startswith('--before_line='):
5704
5705 text = open(pjoin(self.me_dir,'Cards',card)).read()
5706 split = text.split('\n')
5707 search_pattern=r'''before_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
5708 pattern = re.search(search_pattern, line).group()[13:-1]
5709 for posline,l in enumerate(split):
5710 if re.search(pattern, l):
5711 break
5712 else:
5713 raise Exception, 'invalid regular expression: not found in file'
5714 split.insert(posline, re.split(search_pattern,line)[-1])
5715 ff = open(pjoin(self.me_dir,'Cards',card),'w')
5716 ff.write('\n'.join(split))
5717 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] ),'$MG:color:BLACK')
5718
5719 elif args[1].startswith('--after_line='):
5720
5721 text = open(pjoin(self.me_dir,'Cards',card)).read()
5722 split = text.split('\n')
5723 search_pattern = r'''after_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
5724 pattern = re.search(search_pattern, line).group()[12:-1]
5725 for posline,l in enumerate(split):
5726 if re.search(pattern, l):
5727 break
5728 else:
5729 posline=len(split)
5730 split.insert(posline+1, re.split(search_pattern,line)[-1])
5731 ff = open(pjoin(self.me_dir,'Cards',card),'w')
5732 ff.write('\n'.join(split))
5733 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,1)[1] ),'$MG:color:BLACK')
5734 else:
5735 ff = open(pjoin(self.me_dir,'Cards',card),'a')
5736 ff.write("%s \n" % line.split(None,1)[1])
5737 ff.close()
5738 logger.info("adding at the end of the file %s the line: \"%s\"" %(card, line.split(None,1)[1] ),'$MG:color:BLACK')
5739
5740 self.reload_card(pjoin(self.me_dir,'Cards',card))
5741
5742
5743
5745 """Help associated to the asperge command"""
5746 signal.alarm(0)
5747
5748 print '-- syntax: asperge [options]'
5749 print ' Call ASperGe to diagonalize all mass matrices in the model.'
5750 print ' This works only if the ASperGE module is part of the UFO model (a subdirectory).'
5751 print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only'
5752 print ' diagonalize the associate mass matrices (here m1 and m2).'
5753
5755 prev_timer = signal.alarm(0)
5756 if prev_timer:
5757 nb_back = len(line)
5758 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
5759 self.stdout.write(line)
5760 self.stdout.flush()
5761 blockname = self.pname2block.keys()
5762
5763 wrong = ['decay', 'mass', 'sminput']
5764 valid = [k for k in blockname if 'mix' in k]
5765 potential = [k for k in blockname if k not in valid+wrong]
5766 output = {'Mixing matrices': self.list_completion(text, valid, line),
5767 'Other potential valid input': self.list_completion(text, potential, line)}
5768
5769 return self.deal_multiple_categories(output, formatting)
5770
5771
5773 """Running ASperGe"""
5774 signal.alarm(0)
5775
5776 path = pjoin(self.me_dir,'bin','internal','ufomodel','ASperGE')
5777 if not os.path.exists(path):
5778 logger.error('ASperge has not been detected in the current model, therefore it will not be run.')
5779 return
5780 elif not os.path.exists(pjoin(path,'ASperGe')):
5781 logger.info('ASperGe has been detected but is not compiled. Running the compilation now.')
5782 try:
5783 misc.compile(cwd=path,shell=True)
5784 except MadGraph5Error, error:
5785 logger.error('''ASperGe failed to compile. Note that gsl is needed
5786 for this compilation to go trough. More information on how to install this package on
5787 http://www.gnu.org/software/gsl/
5788 Full compilation log is available at %s''' % pjoin(self.me_dir, 'ASperge_compilation.log'))
5789 open(pjoin(self.me_dir, 'ASperge_compilation.log'),'w').write(str(error))
5790 return
5791
5792 opts = line.split()
5793 card = self.paths['param']
5794 logger.info('running ASperGE')
5795 returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts)
5796 if returncode:
5797 logger.error('ASperGE fails with status %s' % returncode)
5798 else:
5799 logger.info('AsPerGe creates the file succesfully')
5800 files.mv(card, '%s.beforeasperge' % card)
5801 files.mv('%s.new' % card, card)
5802
5803
5804
5806 """detect the type of the file and overwritte the current file"""
5807
5808 if path.endswith('.lhco'):
5809
5810
5811 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
5812 return
5813 elif path.endswith('.lhco.gz'):
5814
5815
5816 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
5817 return
5818 else:
5819 card_name = CommonRunCmd.detect_card_type(path)
5820
5821 if card_name == 'unknown':
5822 logger.warning('Fail to determine the type of the file. Not copied')
5823 if card_name != 'banner':
5824 logger.info('copy %s as %s' % (path, card_name))
5825 files.cp(path, self.paths[card_name.split('_',1)[0]])
5826 self.reload_card(self.paths[card_name.split('_',1)[0]])
5827 elif card_name == 'banner':
5828 banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False)
5829 logger.info('Splitting the banner in it\'s component')
5830 if not self.mode == 'auto':
5831 self.mother_interface.keep_cards(self.cards)
5832 for card_name in self.cards:
5833 self.reload_card(pjoin(self.me_dir, 'Cards', card_name))
5834
5836 """open the file"""
5837 try:
5838 me_dir = self.mother_interface.me_dir
5839 except:
5840 me_dir = None
5841
5842 if answer.isdigit():
5843 if answer == '9':
5844 answer = 'plot'
5845 else:
5846 answer = self.cards[int(answer)-1]
5847
5848 if 'madweight' in answer:
5849 answer = answer.replace('madweight', 'MadWeight')
5850 elif 'MadLoopParams' in answer:
5851 answer = self.paths['ML']
5852 elif 'pythia8_card' in answer:
5853 answer = self.paths['PY8']
5854 if os.path.exists(answer):
5855 path = answer
5856 else:
5857 if not '.dat' in answer and not '.lhco' in answer:
5858 if answer != 'trigger':
5859 path = self.paths[answer]
5860 else:
5861 path = self.paths['delphes']
5862 elif not '.lhco' in answer:
5863 if '_' in answer:
5864 path = self.paths['_'.join(answer.split('_')[:-1])]
5865 else:
5866 path = pjoin(me_dir, 'Cards', answer)
5867 else:
5868 path = pjoin(me_dir, self.mw_card['mw_run']['inputfile'])
5869 if not os.path.exists(path):
5870 logger.info('Path in MW_card not existing')
5871 path = pjoin(me_dir, 'Events', answer)
5872
5873 path = path.replace('_card_card','_card')
5874 try:
5875 self.mother_interface.exec_cmd('open %s' % path)
5876 except InvalidCmd, error:
5877 if str(error) != 'No default path for this file':
5878 raise
5879 if answer == 'transfer_card.dat':
5880 logger.warning('You have to specify a transfer function first!')
5881 elif answer == 'input.lhco':
5882 path = pjoin(me_dir,'Events', 'input.lhco')
5883 ff = open(path,'w')
5884 ff.write('''No LHCO information imported at current time.
5885 To import a lhco file: Close this file and type the path of your file.
5886 You can also copy/paste, your event file here.''')
5887 ff.close()
5888 self.open_file(path)
5889 else:
5890 raise
5891 self.reload_card(path)
5892
5894 """reload object to have it in sync"""
5895
5896 if path == self.paths['param']:
5897 try:
5898 self.param_card = check_param_card.ParamCard(path)
5899 except (check_param_card.InvalidParamCard, ValueError) as e:
5900 logger.error('Current param_card is not valid. We are going to use the default one.')
5901 logger.error('problem detected: %s' % e)
5902 logger.error('Please re-open the file and fix the problem.')
5903 logger.warning('using the \'set\' command without opening the file will discard all your manual change')
5904 elif path == self.paths['run']:
5905 self.run_card = banner_mod.RunCard(path)
5906 elif path == self.paths['ML']:
5907 self.MLcard = banner_mod.MadLoopParam(path)
5908 elif path == self.paths['PY8']:
5909
5910
5911 if not self.PY8Card:
5912 self.PY8Card = banner_mod.PY8Card(self.paths['PY8_default'])
5913
5914 self.PY8Card.read(self.paths['PY8'], setter='user')
5915 self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
5916 elif path == self.paths['MadWeight']:
5917 try:
5918 import madgraph.madweight.Cards as mwcards
5919 except:
5920 import internal.madweight.Cards as mwcards
5921 self.mw_card = mwcards.Card(path)
5922 return path
5923
5925 """a dedicated module for the param"""
5926
5927 special_shortcut ={}
5928
5929 - def __init__(self, question, card=[], mode='auto', *args, **opt):
5930
5931 self.load_default()
5932 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt)
5933 if os.path.isfile(card[0]):
5934 self.param_card = check_param_card.ParamCard(card[0])
5935 self.paths['param'] = card[0]
5936 if os.path.isfile(card[0].replace('.dat', '_default.dat')):
5937 self.paths['param_default'] = card[0].replace('.dat', '_default.dat')
5938 else:
5939 self.paths['param_default'] = card[0]
5940 else:
5941 raise Exception, 'path %s do not exists' % card[0]
5942
5943 self.pname2block, self.restricted_value = self.param_card.analyze_param_card()
5944 self.cards=['param']
5945
5947 "Not available"
5948 logger.warning("asperge not available in this mode")
5949