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