1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from __future__ import division
17 import collections
18 import copy
19 import logging
20 import numbers
21 import os
22 import sys
23 import re
24 import math
25 import StringIO
26
27 pjoin = os.path.join
28
29 try:
30 import madgraph
31 except ImportError:
32 MADEVENT = True
33 from internal import MadGraph5Error, InvalidCmd
34 import internal.file_writers as file_writers
35 import internal.files as files
36 import internal.check_param_card as param_card_reader
37 import internal.misc as misc
38 MEDIR = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
39 MEDIR = os.path.split(MEDIR)[0]
40 else:
41 MADEVENT = False
42 import madgraph.various.misc as misc
43 import madgraph.iolibs.file_writers as file_writers
44 import madgraph.iolibs.files as files
45 import models.check_param_card as param_card_reader
46 from madgraph import MG5DIR, MadGraph5Error, InvalidCmd
47
48
49 logger = logging.getLogger('madevent.cards')
54
57 """ """
58
59 ordered_items = ['mgversion', 'mg5proccard', 'mgproccard', 'mgruncard',
60 'slha','initrwgt','mggenerationinfo', 'mgpythiacard', 'mgpgscard',
61 'mgdelphescard', 'mgdelphestrigger','mgshowercard',
62 'ma5card_parton','ma5card_hadron','run_settings']
63
64 capitalized_items = {
65 'mgversion': 'MGVersion',
66 'mg5proccard': 'MG5ProcCard',
67 'mgproccard': 'MGProcCard',
68 'mgruncard': 'MGRunCard',
69 'ma5card_parton' : 'MA5Card_parton',
70 'ma5card_hadron' : 'MA5Card_hadron',
71 'mggenerationinfo': 'MGGenerationInfo',
72 'mgpythiacard': 'MGPythiaCard',
73 'mgpgscard': 'MGPGSCard',
74 'mgdelphescard': 'MGDelphesCard',
75 'mgdelphestrigger': 'MGDelphesTrigger',
76 'mgshowercard': 'MGShowerCard' }
77
78 forbid_cdata = ['initrwgt']
79
81 """ """
82
83 if isinstance(banner_path, Banner):
84 dict.__init__(self, banner_path)
85 self.lhe_version = banner_path.lhe_version
86 return
87 else:
88 dict.__init__(self)
89
90
91 if MADEVENT:
92 self['mgversion'] = '#%s\n' % open(pjoin(MEDIR, 'MGMEVersion.txt')).read()
93 else:
94 info = misc.get_pkg_info()
95 self['mgversion'] = info['version']+'\n'
96
97 self.lhe_version = None
98
99
100 if banner_path:
101 self.read_banner(banner_path)
102
103
104
105
106 pat_begin=re.compile('<(?P<name>\w*)>')
107 pat_end=re.compile('</(?P<name>\w*)>')
108
109 tag_to_file={'slha':'param_card.dat',
110 'mgruncard':'run_card.dat',
111 'mgpythiacard':'pythia_card.dat',
112 'mgpgscard' : 'pgs_card.dat',
113 'mgdelphescard':'delphes_card.dat',
114 'mgdelphestrigger':'delphes_trigger.dat',
115 'mg5proccard':'proc_card_mg5.dat',
116 'mgproccard': 'proc_card.dat',
117 'init': '',
118 'mggenerationinfo':'',
119 'scalesfunctionalform':'',
120 'montecarlomasses':'',
121 'initrwgt':'',
122 'madspin':'madspin_card.dat',
123 'mgshowercard':'shower_card.dat',
124 'pythia8':'pythia8_card.dat',
125 'ma5card_parton':'madanalysis5_parton_card.dat',
126 'ma5card_hadron':'madanalysis5_hadron_card.dat',
127 'run_settings':''
128 }
129
131 """read a banner"""
132
133 if isinstance(input_path, str):
134 if input_path.find('\n') ==-1:
135 input_path = open(input_path)
136 else:
137 def split_iter(string):
138 return (x.groups(0)[0] for x in re.finditer(r"([^\n]*\n)", string, re.DOTALL))
139 input_path = split_iter(input_path)
140
141 text = ''
142 store = False
143 for line in input_path:
144 if self.pat_begin.search(line):
145 if self.pat_begin.search(line).group('name').lower() in self.tag_to_file:
146 tag = self.pat_begin.search(line).group('name').lower()
147 store = True
148 continue
149 if store and self.pat_end.search(line):
150 if tag == self.pat_end.search(line).group('name').lower():
151 self[tag] = text
152 text = ''
153 store = False
154 if store and not line.startswith(('<![CDATA[',']]>')):
155 if line.endswith('\n'):
156 text += line
157 else:
158 text += '%s%s' % (line, '\n')
159
160
161 if "</init>" in line:
162 break
163 elif "<event>" in line:
164 break
165
167 """allow auto-build for the run_card/param_card/... """
168 try:
169 return super(Banner, self).__getattribute__(attr)
170 except:
171 if attr not in ['run_card', 'param_card', 'slha', 'mgruncard', 'mg5proccard', 'mgshowercard', 'foanalyse']:
172 raise
173 return self.charge_card(attr)
174
175
176
178 """change the lhe version associate to the banner"""
179
180 version = float(version)
181 if version < 3:
182 version = 1
183 elif version > 3:
184 raise Exception, "Not Supported version"
185 self.lhe_version = version
186
188 """return the cross-section of the file"""
189
190 if "init" not in self:
191 raise Exception
192
193 text = self["init"].split('\n')
194 cross = 0
195 error = 0
196 for line in text:
197 s = line.split()
198 if len(s)==4:
199 cross += float(s[0])
200 if witherror:
201 error += float(s[1])**2
202 if not witherror:
203 return cross
204 else:
205 return cross, math.sqrt(error)
206
207
209 """modify the init information with the associate scale"""
210
211 assert "init" in self
212
213 all_lines = self["init"].split('\n')
214 new_data = []
215 new_data.append(all_lines[0])
216 for i in range(1, len(all_lines)):
217 line = all_lines[i]
218 split = line.split()
219 if len(split) == 4:
220 xsec, xerr, xmax, pid = split
221 else:
222 new_data += all_lines[i:]
223 break
224 pid = int(pid)
225
226 line = " %+13.7e %+13.7e %+13.7e %i" % \
227 (ratio*float(xsec), ratio* float(xerr), ratio*float(xmax), pid)
228 new_data.append(line)
229 self['init'] = '\n'.join(new_data)
230
232 """return the pdg of each beam"""
233
234 assert "init" in self
235
236 all_lines = self["init"].split('\n')
237 pdg1,pdg2,_ = all_lines[0].split(None, 2)
238 return int(pdg1), int(pdg2)
239
241 """ Load the proc_card /param_card and run_card """
242
243 self.add(pjoin(medir,'Cards', 'param_card.dat'))
244 self.add(pjoin(medir,'Cards', 'run_card.dat'))
245 if os.path.exists(pjoin(medir, 'SubProcesses', 'procdef_mg5.dat')):
246 self.add(pjoin(medir,'SubProcesses', 'procdef_mg5.dat'))
247 self.add(pjoin(medir,'Cards', 'proc_card_mg5.dat'))
248 else:
249 self.add(pjoin(medir,'Cards', 'proc_card.dat'))
250
252 """Change the seed value in the banner"""
253
254 p = re.compile(r'''^\s*\d+\s*=\s*iseed''', re.M)
255 new_seed_str = " %s = iseed" % seed
256 self['mgruncard'] = p.sub(new_seed_str, self['mgruncard'])
257
259 """add info on MGGeneration"""
260
261 text = """
262 # Number of Events : %s
263 # Integrated weight (pb) : %s
264 """ % (nb_event, cross)
265 self['MGGenerationInfo'] = text
266
267
268
269
270 - def split(self, me_dir, proc_card=True):
271 """write the banner in the Cards directory.
272 proc_card argument is present to avoid the overwrite of proc_card
273 information"""
274
275 for tag, text in self.items():
276 if tag == 'mgversion':
277 continue
278 if not proc_card and tag in ['mg5proccard','mgproccard']:
279 continue
280 if not self.tag_to_file[tag]:
281 continue
282 ff = open(pjoin(me_dir, 'Cards', self.tag_to_file[tag]), 'w')
283 ff.write(text)
284 ff.close()
285
286
287
288
289
291 """special routine removing width/mass of particles not present in the model
292 This is usefull in case of loop model card, when we want to use the non
293 loop model."""
294
295 if not hasattr(self, 'param_card'):
296 self.charge_card('slha')
297
298 for tag in ['mass', 'decay']:
299 block = self.param_card.get(tag)
300 for data in block:
301 pid = data.lhacode[0]
302 if pid not in pid2label.keys():
303 block.remove((pid,))
304
306 """get the lha_strategy: how the weight have to be handle by the shower"""
307
308 if not self["init"]:
309 raise Exception, "No init block define"
310
311 data = self["init"].split('\n')[0].split()
312 if len(data) != 10:
313 misc.sprint(len(data), self['init'])
314 raise Exception, "init block has a wrong format"
315 return int(float(data[-2]))
316
318 """set the lha_strategy: how the weight have to be handle by the shower"""
319
320 if not (-4 <= int(value) <= 4):
321 raise Exception, "wrong value for lha_strategy", value
322 if not self["init"]:
323 raise Exception, "No init block define"
324
325 all_lines = self["init"].split('\n')
326 data = all_lines[0].split()
327 if len(data) != 10:
328 misc.sprint(len(data), self['init'])
329 raise Exception, "init block has a wrong format"
330 data[-2] = '%s' % value
331 all_lines[0] = ' '.join(data)
332 self['init'] = '\n'.join(all_lines)
333
334
336 """modify the init information with the associate cross-section"""
337 assert isinstance(cross, dict)
338
339 assert "init" in self
340
341 cross = dict(cross)
342 for key in cross.keys():
343 if isinstance(key, str) and key.isdigit() and int(key) not in cross:
344 cross[int(key)] = cross[key]
345
346
347 all_lines = self["init"].split('\n')
348 new_data = []
349 new_data.append(all_lines[0])
350 for i in range(1, len(all_lines)):
351 line = all_lines[i]
352 split = line.split()
353 if len(split) == 4:
354 xsec, xerr, xmax, pid = split
355 else:
356 new_data += all_lines[i:]
357 break
358 if int(pid) not in cross:
359 raise Exception
360 pid = int(pid)
361 if float(xsec):
362 ratio = cross[pid]/float(xsec)
363 else:
364 ratio = 0
365 line = " %+13.7e %+13.7e %+13.7e %i" % \
366 (float(cross[pid]), ratio* float(xerr), ratio*float(xmax), pid)
367 new_data.append(line)
368 self['init'] = '\n'.join(new_data)
369
370
371
372
373 - def write(self, output_path, close_tag=True, exclude=[]):
374 """write the banner"""
375
376 if isinstance(output_path, str):
377 ff = open(output_path, 'w')
378 else:
379 ff = output_path
380
381 if MADEVENT:
382 header = open(pjoin(MEDIR, 'Source', 'banner_header.txt')).read()
383 else:
384 header = open(pjoin(MG5DIR,'Template', 'LO', 'Source', 'banner_header.txt')).read()
385
386 if not self.lhe_version:
387 self.lhe_version = self.get('run_card', 'lhe_version', default=1.0)
388 if float(self.lhe_version) < 3:
389 self.lhe_version = 1.0
390
391 ff.write(header % { 'version':float(self.lhe_version)})
392
393
394 for tag in [t for t in self.ordered_items if t in self.keys()]+ \
395 [t for t in self.keys() if t not in self.ordered_items]:
396 if tag in ['init'] or tag in exclude:
397 continue
398 capitalized_tag = self.capitalized_items[tag] if tag in self.capitalized_items else tag
399 start_data, stop_data = '', ''
400 if capitalized_tag not in self.forbid_cdata and \
401 ('<' in self[tag] or '@' in self[tag]):
402 start_data = '\n<![CDATA['
403 stop_data = ']]>\n'
404 ff.write('<%(tag)s>%(start_data)s\n%(text)s\n%(stop_data)s</%(tag)s>\n' % \
405 {'tag':capitalized_tag, 'text':self[tag].strip(),
406 'start_data': start_data, 'stop_data':stop_data})
407
408
409 if not '/header' in exclude:
410 ff.write('</header>\n')
411
412 if 'init' in self and not 'init' in exclude:
413 text = self['init']
414 ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \
415 {'tag':'init', 'text':text.strip()})
416 if close_tag:
417 ff.write('</LesHouchesEvents>\n')
418 return ff
419
420
421
422
423
424 - def add(self, path, tag=None):
425 """Add the content of the file to the banner"""
426
427 if not tag:
428 card_name = os.path.basename(path)
429 if 'param_card' in card_name:
430 tag = 'slha'
431 elif 'run_card' in card_name:
432 tag = 'MGRunCard'
433 elif 'pythia_card' in card_name:
434 tag = 'MGPythiaCard'
435 elif 'pythia8_card' in card_name or 'pythia8.cmd' in card_name:
436 tag = 'MGPythiaCard'
437 elif 'pgs_card' in card_name:
438 tag = 'MGPGSCard'
439 elif 'delphes_card' in card_name:
440 tag = 'MGDelphesCard'
441 elif 'delphes_trigger' in card_name:
442 tag = 'MGDelphesTrigger'
443 elif 'proc_card_mg5' in card_name:
444 tag = 'MG5ProcCard'
445 elif 'proc_card' in card_name:
446 tag = 'MGProcCard'
447 elif 'procdef_mg5' in card_name:
448 tag = 'MGProcCard'
449 elif 'shower_card' in card_name:
450 tag = 'MGShowerCard'
451 elif 'madspin_card' in card_name:
452 tag = 'madspin'
453 elif 'FO_analyse_card' in card_name:
454 tag = 'foanalyse'
455 elif 'reweight_card' in card_name:
456 tag='reweight_card'
457 elif 'madanalysis5_parton_card' in card_name:
458 tag='MA5Card_parton'
459 elif 'madanalysis5_hadron_card' in card_name:
460 tag='MA5Card_hadron'
461 else:
462 raise Exception, 'Impossible to know the type of the card'
463
464 self.add_text(tag.lower(), open(path).read())
465
466 - def add_text(self, tag, text):
467 """Add the content of the file to the banner"""
468
469 if tag == 'param_card':
470 tag = 'slha'
471 elif tag == 'run_card':
472 tag = 'mgruncard'
473 elif tag == 'proc_card':
474 tag = 'mg5proccard'
475 elif tag == 'shower_card':
476 tag = 'mgshowercard'
477 elif tag == 'FO_analyse_card':
478 tag = 'foanalyse'
479
480 self[tag.lower()] = text
481
482
532
533
535 """return a specific """
536
537 if tag in ['param_card', 'param']:
538 tag = 'slha'
539 attr_tag = 'param_card'
540 elif tag in ['run_card', 'run']:
541 tag = 'mgruncard'
542 attr_tag = 'run_card'
543 elif tag == 'proc_card':
544 tag = 'mg5proccard'
545 attr_tag = 'proc_card'
546 elif tag == 'model':
547 tag = 'mg5proccard'
548 attr_tag = 'proc_card'
549 arg = ('model',)
550 elif tag == 'generate':
551 tag = 'mg5proccard'
552 attr_tag = 'proc_card'
553 arg = ('generate',)
554 elif tag == 'shower_card':
555 tag = 'mgshowercard'
556 attr_tag = 'shower_card'
557 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'shower_card'], '%s not recognized' % tag
558
559 if not hasattr(self, attr_tag):
560 self.charge_card(attr_tag)
561
562 card = getattr(self, attr_tag)
563 if len(arg) == 0:
564 return card
565 elif len(arg) == 1:
566 if tag == 'mg5proccard':
567 try:
568 return card.get(arg[0])
569 except KeyError, error:
570 if 'default' in opt:
571 return opt['default']
572 else:
573 raise
574 try:
575 return card[arg[0]]
576 except KeyError:
577 if 'default' in opt:
578 return opt['default']
579 else:
580 raise
581 elif len(arg) == 2 and tag == 'slha':
582 try:
583 return card[arg[0]].get(arg[1:])
584 except KeyError:
585 if 'default' in opt:
586 return opt['default']
587 else:
588 raise
589 elif len(arg) == 0:
590 return card
591 else:
592 raise Exception, "Unknow command"
593
594
595 get = get_detail
596
597 - def set(self, card, *args):
598 """modify one of the cards"""
599
600 if tag == 'param_card':
601 tag = 'slha'
602 attr_tag = 'param_card'
603 elif tag == 'run_card':
604 tag = 'mgruncard'
605 attr_tag = 'run_card'
606 elif tag == 'proc_card':
607 tag = 'mg5proccard'
608 attr_tag = 'proc_card'
609 elif tag == 'model':
610 tag = 'mg5proccard'
611 attr_tag = 'proc_card'
612 arg = ('model',)
613 elif tag == 'generate':
614 tag = 'mg5proccard'
615 attr_tag = 'proc_card'
616 arg = ('generate',)
617 elif tag == 'shower_card':
618 tag = 'mgshowercard'
619 attr_tag = 'shower_card'
620 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'shower_card'], 'not recognized'
621
622 if not hasattr(self, attr_tag):
623 self.charge_card(attr_tag)
624
625 card = getattr(self, attr_tag)
626 if len(args) ==2:
627 if tag == 'mg5proccard':
628 card.info[args[0]] = args[-1]
629 else:
630 card[args[0]] = args[1]
631 else:
632 card[args[:-1]] = args[-1]
633
634
635 @misc.multiple_try()
637 """Add the banner to a file and change the associate seed in the banner"""
638
639 if seed is not None:
640 self.set("run_card", "iseed", seed)
641
642 if not out:
643 path_out = "%s.tmp" % path
644 else:
645 path_out = out
646
647 ff = self.write(path_out, close_tag=False,
648 exclude=['MGGenerationInfo', '/header', 'init'])
649 ff.write("## END BANNER##\n")
650 if self.lhe_version >= 3:
651
652 [ff.write(line) if not line.startswith("<generator name='MadGraph5_aMC@NLO'")
653 else ff.write("<generator name='MadGraph5_aMC@NLO' version='%s'>" % self['mgversion'][:-1])
654 for line in open(path)]
655 else:
656 [ff.write(line) for line in open(path)]
657 ff.write("</LesHouchesEvents>\n")
658 ff.close()
659 if out:
660 os.remove(path)
661 else:
662 files.mv(path_out, path)
663
664
665
666 -def split_banner(banner_path, me_dir, proc_card=True):
671
673 """as input we receive a gen_crossxhtml.AllResults object.
674 This define the current banner and load it
675 """
676
677 if not run:
678 try:
679 _run = results_object.current['run_name']
680 _tag = results_object.current['tag']
681 except Exception:
682 return Banner()
683 else:
684 _run = run
685 if not tag:
686 try:
687 _tag = results_object[run].tags[-1]
688 except Exception,error:
689 return Banner()
690 else:
691 _tag = tag
692
693 path = results_object.path
694 banner_path = pjoin(path,'Events',run,'%s_%s_banner.txt' % (run, tag))
695
696 if not os.path.exists(banner_path):
697 if level != "parton" and tag != _tag:
698 return recover_banner(results_object, level, _run, results_object[_run].tags[0])
699 elif level == 'parton':
700 paths = [pjoin(path,'Events',run, 'unweighted_events.lhe.gz'),
701 pjoin(path,'Events',run, 'unweighted_events.lhe'),
702 pjoin(path,'Events',run, 'events.lhe.gz'),
703 pjoin(path,'Events',run, 'events.lhe')]
704 for p in paths:
705 if os.path.exists(p):
706 if MADEVENT:
707 import internal.lhe_parser as lhe_parser
708 else:
709 import madgraph.various.lhe_parser as lhe_parser
710 lhe = lhe_parser.EventFile(p)
711 return Banner(lhe.banner)
712
713
714 return Banner()
715 banner = Banner(banner_path)
716
717
718
719 if level == 'pythia':
720 if 'mgpythiacard' in banner:
721 del banner['mgpythiacard']
722 if level in ['pythia','pgs','delphes']:
723 for tag in ['mgpgscard', 'mgdelphescard', 'mgdelphestrigger']:
724 if tag in banner:
725 del banner[tag]
726 return banner
727
730
732 """Basic Proccard object"""
733
734 history_header = \
735 '#************************************************************\n' + \
736 '#* MadGraph5_aMC@NLO *\n' + \
737 '#* *\n' + \
738 "#* * * *\n" + \
739 "#* * * * * *\n" + \
740 "#* * * * * 5 * * * * *\n" + \
741 "#* * * * * *\n" + \
742 "#* * * *\n" + \
743 "#* *\n" + \
744 "#* *\n" + \
745 "%(info_line)s" +\
746 "#* *\n" + \
747 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
748 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
749 '#* *\n' + \
750 '#************************************************************\n' + \
751 '#* *\n' + \
752 '#* Command File for MadGraph5_aMC@NLO *\n' + \
753 '#* *\n' + \
754 '#* run as ./bin/mg5_aMC filename *\n' + \
755 '#* *\n' + \
756 '#************************************************************\n'
757
758
759
760
762 """ initialize a basic proc_card"""
763 self.info = {'model': 'sm', 'generate':None,
764 'full_model_line':'import model sm'}
765 list.__init__(self)
766 if init:
767 self.read(init)
768
769
770 - def read(self, init):
771 """read the proc_card and save the information"""
772
773 if isinstance(init, str):
774 init = file(init, 'r')
775
776 store_line = ''
777 for line in init:
778 line = line.rstrip()
779 if line.endswith('\\'):
780 store_line += line[:-1]
781 else:
782 tmp = store_line + line
783 self.append(tmp.strip())
784 store_line = ""
785 if store_line:
786 raise Exception, "WRONG CARD FORMAT"
787
788
790 """move an element to the last history."""
791 for line in self[:]:
792 if line.startswith(cmd):
793 self.remove(line)
794 list.append(self, line)
795
797 """"add a line in the proc_card perform automatically cleaning"""
798
799 line = line.strip()
800 cmds = line.split()
801 if len(cmds) == 0:
802 return
803
804 list.append(self, line)
805
806
807 cmd = cmds[0]
808
809 if cmd == 'output':
810
811 self.clean(allow_for_removal = ['output'], keep_switch=True,
812 remove_bef_last='output')
813 elif cmd == 'generate':
814
815 self.clean(remove_bef_last='generate', keep_switch=True,
816 allow_for_removal= ['generate', 'add process', 'output'])
817 self.info['generate'] = ' '.join(cmds[1:])
818 elif cmd == 'add' and cmds[1] == 'process' and not self.info['generate']:
819 self.info['generate'] = ' '.join(cmds[2:])
820 elif cmd == 'import':
821 if len(cmds) < 2:
822 return
823 if cmds[1].startswith('model'):
824 self.info['full_model_line'] = line
825 self.clean(remove_bef_last='import', keep_switch=True,
826 allow_for_removal=['generate', 'add process', 'add model', 'output'])
827 if cmds[1] == 'model':
828 self.info['model'] = cmds[2]
829 else:
830 self.info['model'] = None
831 elif cmds[1] == 'proc_v4':
832
833 self[:] = []
834
835
836 - def clean(self, to_keep=['set','add','load'],
837 remove_bef_last=None,
838 to_remove=['open','display','launch', 'check','history'],
839 allow_for_removal=None,
840 keep_switch=False):
841 """Remove command in arguments from history.
842 All command before the last occurrence of 'remove_bef_last'
843 (including it) will be removed (but if another options tells the opposite).
844 'to_keep' is a set of line to always keep.
845 'to_remove' is a set of line to always remove (don't care about remove_bef_
846 status but keep_switch acts.).
847 if 'allow_for_removal' is define only the command in that list can be
848 remove of the history for older command that remove_bef_lb1. all parameter
849 present in to_remove are always remove even if they are not part of this
850 list.
851 keep_switch force to keep the statement remove_bef_??? which changes starts
852 the removal mode.
853 """
854
855
856 if __debug__ and allow_for_removal:
857 for arg in to_keep:
858 assert arg not in allow_for_removal
859
860
861 nline = -1
862 removal = False
863
864 while nline > -len(self):
865 switch = False
866
867
868 if not removal and remove_bef_last:
869 if self[nline].startswith(remove_bef_last):
870 removal = True
871 switch = True
872
873
874 if switch and keep_switch:
875 nline -= 1
876 continue
877
878
879 if any([self[nline].startswith(arg) for arg in to_remove]):
880 self.pop(nline)
881 continue
882
883
884 if removal:
885 if allow_for_removal:
886
887 if any([self[nline].startswith(arg)
888 for arg in allow_for_removal]):
889 self.pop(nline)
890 continue
891 elif not any([self[nline].startswith(arg) for arg in to_keep]):
892
893 self.pop(nline)
894 continue
895
896
897 nline -= 1
898
899 - def get(self, tag, default=None):
900 if isinstance(tag, int):
901 list.__getattr__(self, tag)
902 elif tag == 'info' or tag == "__setstate__":
903 return default
904 elif tag == "multiparticles":
905 out = []
906 for line in self:
907 if line.startswith('define'):
908 try:
909 name, content = line[7:].split('=',1)
910 except ValueError:
911 name, content = line[7:].split(None,1)
912 out.append((name, content))
913 return out
914 else:
915 return self.info[tag]
916
918 """write the proc_card to a given path"""
919
920 fsock = open(path, 'w')
921 fsock.write(self.history_header)
922 for line in self:
923 while len(line) > 70:
924 sub, line = line[:70]+"\\" , line[70:]
925 fsock.write(sub+"\n")
926 else:
927 fsock.write(line+"\n")
928
930
932 """ a class for storing/dealing with input file.
933 """
934
935 - def __init__(self, finput=None, **opt):
936 """initialize a new instance. input can be an instance of MadLoopParam,
937 a file, a path to a file, or simply Nothing"""
938
939 if isinstance(finput, self.__class__):
940 dict.__init__(self, finput)
941 assert finput.__dict__.keys()
942 for key in finput.__dict__:
943 setattr(self, key, copy.copy(getattr(finput, key)) )
944 return
945 else:
946 dict.__init__(self)
947
948
949 self.user_set = set()
950 self.auto_set = set()
951 self.system_only = set()
952 self.lower_to_case = {}
953 self.list_parameter = {}
954 self.dict_parameter = {}
955 self.comments = {}
956
957 self.allowed_value = {}
958
959 self.default_setup()
960
961
962
963 if isinstance(finput, (file, str, StringIO.StringIO)):
964 self.read(finput, **opt)
965
968
970 return self.__class__(self)
971
973 """define the sum"""
974 assert isinstance(other, dict)
975 base = self.__class__(self)
976
977 base.update((key.lower(),value) for key, value in other.items())
978 return base
979
981 """define the sum"""
982 new = copy.copy(other)
983 new.update((key, value) for key, value in self.items())
984 return new
985
988
992
995
998
999 @staticmethod
1000 - def warn(text, level, raiseerror=False):
1001 """convenient proxy to raiseerror/print warning"""
1002
1003 if raiseerror is True:
1004 raise InvalidCardEdition(text)
1005 elif raiseerror:
1006 raise raiseerror(text)
1007
1008 if isinstance(level,str):
1009 log = getattr(logger, level.lower())
1010 elif isinstance(level, int):
1011 log = lambda t: logger.log(level, t)
1012 elif level:
1013 log = level
1014
1015 return log(text)
1016
1017 - def post_set(self, name, value, change_userdefine, raiseerror):
1018
1019 if value is None:
1020 value = self[name]
1021
1022 if hasattr(self, 'post_set_%s' % name):
1023 return getattr(self, 'post_set_%s' % name)(value, change_userdefine, raiseerror)
1024
1025 - def __setitem__(self, name, value, change_userdefine=False,raiseerror=False):
1026 """set the attribute and set correctly the type if the value is a string.
1027 change_userdefine on True if we have to add the parameter in user_set
1028 """
1029
1030 if not len(self):
1031
1032 self.__init__()
1033
1034 name = name.strip()
1035 lower_name = name.lower()
1036
1037
1038 if change_userdefine and lower_name in self.system_only:
1039 text='%s is a private entry which can not be modify by the user. Keep value at %s' % (name,self[name])
1040 self.warn(text, 'critical', raiseerror)
1041 return
1042
1043
1044 if lower_name in self:
1045 targettype = type(dict.__getitem__(self, lower_name))
1046 if targettype != str and isinstance(value, str) and value.lower() == 'auto':
1047 self.auto_set.add(lower_name)
1048 if lower_name in self.user_set:
1049 self.user_set.remove(lower_name)
1050
1051 self.post_set(lower_name, 'auto', change_userdefine, raiseerror)
1052 return
1053 elif lower_name in self.auto_set:
1054 self.auto_set.remove(lower_name)
1055
1056
1057 if lower_name in self.list_parameter:
1058 targettype = self.list_parameter[lower_name]
1059
1060
1061
1062 if isinstance(value, str):
1063
1064 value = value.strip()
1065 if value.startswith('[') and value.endswith(']'):
1066 value = value[1:-1]
1067
1068 data = re.split(r"((?<![\\])['\"])((?:.(?!(?<![\\])\1))*.?)\1", str(value))
1069 new_value = []
1070 i = 0
1071 while len(data) > i:
1072 current = filter(None, re.split(r'(?:(?<!\\)\s)|,', data[i]))
1073 i+=1
1074 if len(data) > i+1:
1075 if current:
1076 current[-1] += '{0}{1}{0}'.format(data[i], data[i+1])
1077 else:
1078 current = ['{0}{1}{0}'.format(data[i], data[i+1])]
1079 i+=2
1080 new_value += current
1081
1082 value = new_value
1083
1084 elif not hasattr(value, '__iter__'):
1085 value = [value]
1086 elif isinstance(value, dict):
1087 text = "not being able to handle dictionary in card entry"
1088 return self.warn(text, 'critical', raiseerror)
1089
1090
1091 values =[self.format_variable(v, targettype, name=name)
1092 for v in value]
1093
1094
1095 if lower_name in self.allowed_value and '*' not in self.allowed_value[lower_name]:
1096 new_values = []
1097 dropped = []
1098 for val in values:
1099 allowed = self.allowed_value[lower_name]
1100
1101 if val in allowed:
1102 new_values.append(val)
1103 continue
1104 elif isinstance(val, str):
1105 val = val.lower()
1106 allowed = allowed.lower()
1107 if value in allowed:
1108 i = allowed.index(value)
1109 new_values.append(self.allowed_value[i])
1110 continue
1111
1112 dropped.append(val)
1113
1114 if not new_values:
1115
1116 text= "value '%s' for entry '%s' is not valid. Preserving previous value: '%s'.\n" \
1117 % (value, name, self[lower_name])
1118 text += "allowed values are any list composed of the following entry: %s" % ', '.join([str(i) for i in self.allowed_value[lower_name]])
1119 return self.warn(text, 'warning', raiseerror)
1120 elif dropped:
1121 text = "some value for entry '%s' are not valid. Invalid item are: '%s'.\n" \
1122 % (value, name, dropped)
1123 text += "value will be set to %s" % new_values
1124 text += "allowed items in the list are: %s" % ', '.join([str(i) for i in self.allowed_value[lower_name]])
1125 self.warn(text, 'warning')
1126
1127 values = new_values
1128
1129
1130 dict.__setitem__(self, lower_name, values)
1131 if change_userdefine:
1132 self.user_set.add(lower_name)
1133
1134 return self.post_set(lower_name, None, change_userdefine, raiseerror)
1135 elif lower_name in self.dict_parameter:
1136 targettype = self.dict_parameter[lower_name]
1137 full_reset = True
1138
1139 if isinstance(value, str):
1140 value = value.strip()
1141
1142
1143
1144
1145
1146
1147
1148 if value.startswith('{') and value.endswith('}'):
1149 new_value = {}
1150 for pair in value[1:-1].split(','):
1151 if not pair.strip():
1152 break
1153 x, y = pair.split(':')
1154 x, y = x.strip(), y.strip()
1155 if x.startswith(('"',"'")) and x.endswith(x[0]):
1156 x = x[1:-1]
1157 new_value[x] = y
1158 value = new_value
1159 elif ',' in value:
1160 x,y = value.split(',')
1161 value = {x.strip():y.strip()}
1162 full_reset = False
1163
1164 elif ':' in value:
1165 x,y = value.split(':')
1166 value = {x.strip():y.strip()}
1167 full_reset = False
1168 else:
1169 x,y = value.split()
1170 value = {x:y}
1171 full_reset = False
1172
1173 if isinstance(value, dict):
1174 for key in value:
1175 value[key] = self.format_variable(value[key], targettype, name=name)
1176 if full_reset:
1177 dict.__setitem__(self, lower_name, value)
1178 else:
1179 dict.__getitem__(self, lower_name).update(value)
1180 else:
1181 raise Exception, '%s should be of dict type'% lower_name
1182 if change_userdefine:
1183 self.user_set.add(lower_name)
1184 return self.post_set(lower_name, None, change_userdefine, raiseerror)
1185 elif name in self:
1186 targettype = type(self[name])
1187 else:
1188 logger.debug('Trying to add argument %s in %s. ' % (name, self.__class__.__name__) +\
1189 'This argument is not defined by default. Please consider adding it.')
1190 suggestions = [k for k in self.keys() if k.startswith(name[0].lower())]
1191 if len(suggestions)>0:
1192 logger.debug("Did you mean one of the following: %s"%suggestions)
1193 self.add_param(lower_name, self.format_variable(UnknownType(value),
1194 UnknownType, name))
1195 self.lower_to_case[lower_name] = name
1196 if change_userdefine:
1197 self.user_set.add(lower_name)
1198 return self.post_set(lower_name, None, change_userdefine, raiseerror)
1199
1200 value = self.format_variable(value, targettype, name=name)
1201
1202 if lower_name in self.allowed_value and '*' not in self.allowed_value[lower_name]:
1203 valid = False
1204 allowed = self.allowed_value[lower_name]
1205
1206
1207 if value in allowed:
1208 valid=True
1209 elif isinstance(value, str):
1210 value = value.lower()
1211 allowed = [v.lower() for v in allowed]
1212 if value in allowed:
1213 i = allowed.index(value)
1214 value = self.allowed_value[lower_name][i]
1215 valid=True
1216
1217 if not valid:
1218
1219 text = "value '%s' for entry '%s' is not valid. Preserving previous value: '%s'.\n" \
1220 % (value, name, self[lower_name])
1221 text += "allowed values are %s\n" % ', '.join([str(i) for i in self.allowed_value[lower_name]])
1222 if lower_name in self.comments:
1223 text += 'type "help %s" for more information' % name
1224 return self.warn(text, 'warning', raiseerror)
1225
1226 dict.__setitem__(self, lower_name, value)
1227 if change_userdefine:
1228 self.user_set.add(lower_name)
1229 self.post_set(lower_name, None, change_userdefine, raiseerror)
1230
1231
1232 - def add_param(self, name, value, system=False, comment=False, typelist=None,
1233 allowed=[]):
1234 """add a default parameter to the class"""
1235
1236 lower_name = name.lower()
1237 if __debug__:
1238 if lower_name in self:
1239 raise Exception("Duplicate case for %s in %s" % (name,self.__class__))
1240
1241 dict.__setitem__(self, lower_name, value)
1242 self.lower_to_case[lower_name] = name
1243 if isinstance(value, list):
1244 if len(value):
1245 targettype = type(value[0])
1246 else:
1247 targettype=typelist
1248 assert typelist
1249 if any([targettype != type(v) for v in value]):
1250 raise Exception, "All entry should have the same type"
1251 self.list_parameter[lower_name] = targettype
1252 elif isinstance(value, dict):
1253 allvalues = value.values()
1254 if any([type(allvalues[0]) != type(v) for v in allvalues]):
1255 raise Exception, "All entry should have the same type"
1256 self.dict_parameter[lower_name] = type(allvalues[0])
1257 if '__type__' in value:
1258 del value['__type__']
1259 dict.__setitem__(self, lower_name, value)
1260
1261 if allowed and allowed != ['*']:
1262 self.allowed_value[lower_name] = allowed
1263 assert value in allowed or '*' in allowed
1264
1265
1266
1267 if system:
1268 self.system_only.add(lower_name)
1269 if comment:
1270 self.comments[lower_name] = comment
1271
1273 """return a minimal help for the parameter"""
1274
1275 out = "## Information on parameter %s from class %s\n" % (name, self.__class__.__name__)
1276 if name.lower() in self:
1277 out += "## current value: %s (parameter should be of type %s)\n" % (self[name], type(self[name]))
1278 if name.lower() in self.comments:
1279 out += '## %s\n' % self.comments[name.lower()].replace('\n', '\n## ')
1280 else:
1281 out += "## Unknown for this class\n"
1282 if name.lower() in self.user_set:
1283 out += "## This value is considered as been set by the user\n"
1284 else:
1285 out += "## This value is considered as been set by the system\n"
1286 if name.lower() in self.allowed_value:
1287 if '*' not in self.allowed_value[name.lower()]:
1288 out += "Allowed value are: %s\n" % ','.join([str(p) for p in self.allowed_value[name.lower()]])
1289 else:
1290 out += "Suggested value are : %s\n " % ','.join([str(p) for p in self.allowed_value[name.lower()] if p!='*'])
1291
1292 logger.info(out)
1293 return out
1294
1295 @staticmethod
1382
1383
1384
1386
1387 lower_name = name.lower()
1388 if __debug__:
1389 if lower_name not in self:
1390 if lower_name in [key.lower() for key in self] :
1391 raise Exception, "Some key are not lower case %s. Invalid use of the class!"\
1392 % [key for key in self if key.lower() != key]
1393
1394 if lower_name in self.auto_set:
1395 return 'auto'
1396
1397 return dict.__getitem__(self, name.lower())
1398
1399
1400 - def set(self, name, value, changeifuserset=True, user=False, raiseerror=False):
1401 """convenient way to change attribute.
1402 changeifuserset=False means that the value is NOT change is the value is not on default.
1403 user=True, means that the value will be marked as modified by the user
1404 (potentially preventing future change to the value)
1405 """
1406
1407
1408 if not changeifuserset:
1409 if name.lower() in self.user_set:
1410
1411 return
1412
1413 self.__setitem__(name, value, change_userdefine=user, raiseerror=raiseerror)
1414
1418 """A class to handle information which are passed from MadGraph to the madevent
1419 interface."""
1420
1422 """initialize the directory to the default value"""
1423
1424 self.add_param('loop_induced', False)
1425 self.add_param('has_isr', False)
1426 self.add_param('has_fsr', False)
1427 self.add_param('nb_channel', 0)
1428 self.add_param('nexternal', 0)
1429 self.add_param('ninitial', 0)
1430 self.add_param('grouped_matrix', True)
1431 self.add_param('has_loops', False)
1432 self.add_param('bias_module','None')
1433 self.add_param('max_n_matched_jets', 0)
1434 self.add_param('colored_pdgs', [1,2,3,4,5])
1435 self.add_param('complex_mass_scheme', False)
1436 self.add_param('pdg_initial1', [0])
1437 self.add_param('pdg_initial2', [0])
1438
1439 - def read(self, finput):
1440 """Read the input file, this can be a path to a file,
1441 a file object, a str with the content of the file."""
1442
1443 if isinstance(finput, str):
1444 if "\n" in finput:
1445 finput = finput.split('\n')
1446 elif os.path.isfile(finput):
1447 finput = open(finput)
1448 else:
1449 raise Exception, "No such file %s" % finput
1450
1451 for line in finput:
1452 if '#' in line:
1453 line = line.split('#',1)[0]
1454 if not line:
1455 continue
1456
1457 if '=' in line:
1458 key, value = line.split('=',1)
1459 self[key.strip()] = value
1460
1461 - def write(self, outputpath):
1462 """write the file"""
1463
1464 template ="# Information about the process #\n"
1465 template +="#########################################\n"
1466
1467 fsock = open(outputpath, 'w')
1468 fsock.write(template)
1469
1470 for key, value in self.items():
1471 fsock.write(" %s = %s \n" % (key, value))
1472
1473 fsock.close()
1474
1479 """an object for the GridpackCard"""
1480
1482 """default value for the GridpackCard"""
1483
1484 self.add_param("GridRun", True)
1485 self.add_param("gevents", 2500)
1486 self.add_param("gseed", 1)
1487 self.add_param("ngran", -1)
1488
1489 - def read(self, finput):
1490 """Read the input file, this can be a path to a file,
1491 a file object, a str with the content of the file."""
1492
1493 if isinstance(finput, str):
1494 if "\n" in finput:
1495 finput = finput.split('\n')
1496 elif os.path.isfile(finput):
1497 finput = open(finput)
1498 else:
1499 raise Exception, "No such file %s" % finput
1500
1501 for line in finput:
1502 line = line.split('#')[0]
1503 line = line.split('!')[0]
1504 line = line.split('=',1)
1505 if len(line) != 2:
1506 continue
1507 self[line[1].strip()] = line[0].replace('\'','').strip()
1508
1509 - def write(self, output_file, template=None):
1510 """Write the run_card in output_file according to template
1511 (a path to a valid run_card)"""
1512
1513 if not template:
1514 if not MADEVENT:
1515 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards',
1516 'grid_card_default.dat')
1517 else:
1518 template = pjoin(MEDIR, 'Cards', 'grid_card_default.dat')
1519
1520
1521 text = ""
1522 for line in file(template,'r'):
1523 nline = line.split('#')[0]
1524 nline = nline.split('!')[0]
1525 comment = line[len(nline):]
1526 nline = nline.split('=')
1527 if len(nline) != 2:
1528 text += line
1529 elif nline[1].strip() in self:
1530 text += ' %s\t= %s %s' % (self[nline[1].strip()],nline[1], comment)
1531 else:
1532 logger.info('Adding missing parameter %s to current run_card (with default value)' % nline[1].strip())
1533 text += line
1534
1535 if isinstance(output_file, str):
1536 fsock = open(output_file,'w')
1537 else:
1538 fsock = output_file
1539
1540 fsock.write(text)
1541 fsock.close()
1542
1544 """ Implements the Pythia8 card."""
1545
1547 """ Placeholder function to allow overwriting in the PY8SubRun daughter.
1548 The initialization of the self.subruns attribute should of course not
1549 be performed in PY8SubRun."""
1550 if type == 'parameters':
1551 if "LHEFInputs:nSubruns" not in self:
1552 self.add_param("LHEFInputs:nSubruns", 1,
1553 hidden='ALWAYS_WRITTEN',
1554 comment="""
1555 ====================
1556 Subrun definitions
1557 ====================
1558 """)
1559 if type == 'attributes':
1560 if not(hasattr(self,'subruns')):
1561 first_subrun = PY8SubRun(subrun_id=0)
1562 self.subruns = dict([(first_subrun['Main:subrun'],first_subrun)])
1563
1565 """ Sets up the list of available PY8 parameters."""
1566
1567
1568
1569 self.add_param("Main:numberOfEvents", -1)
1570
1571
1572 self.add_param("JetMatching:qCut", -1.0, always_write_to_card=False)
1573 self.add_param("JetMatching:doShowerKt",False,always_write_to_card=False)
1574
1575 self.add_param("JetMatching:nJetMax", -1, always_write_to_card=False)
1576
1577 self.add_param("Merging:TMS", -1.0, always_write_to_card=False)
1578 self.add_param("Merging:Process", '<set_by_user>', always_write_to_card=False)
1579
1580 self.add_param("Merging:nJetMax", -1, always_write_to_card=False)
1581
1582
1583 self.add_param("SysCalc:fullCutVariation", False)
1584
1585
1586
1587 self.add_param("HEPMCoutput:file", 'auto')
1588
1589
1590
1591 self.add_param("Beams:frameType", 4,
1592 hidden=True,
1593 comment='Tell Pythia8 that an LHEF input is used.')
1594 self.add_param("HEPMCoutput:scaling", 1.0e9,
1595 hidden=True,
1596 comment='1.0 corresponds to HEPMC weight given in [mb]. We choose here the [pb] normalization.')
1597 self.add_param("Check:epTolErr", 1e-2,
1598 hidden=True,
1599 comment='Be more forgiving with momentum mismatches.')
1600
1601
1602 self.add_param("JetMatching:etaJetMax", 1000.0, hidden=True, always_write_to_card=True)
1603
1604
1605
1606 self.add_param("PDF:pSet", 'LHAPDF5:CT10.LHgrid', hidden=True, always_write_to_card=False,
1607 comment='Reminder: Parameter below is shower tune dependent.')
1608 self.add_param("SpaceShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False,
1609 comment='Reminder: Parameter below is shower tune dependent.')
1610 self.add_param("TimeShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False,
1611 comment='Reminder: Parameter below is shower tune dependent.')
1612 self.add_param("hadronlevel:all", True, hidden=True, always_write_to_card=False,
1613 comment='This allows to turn on/off hadronization alltogether.')
1614 self.add_param("partonlevel:mpi", True, hidden=True, always_write_to_card=False,
1615 comment='This allows to turn on/off MPI alltogether.')
1616 self.add_param("Beams:setProductionScalesFromLHEF", False, hidden=True,
1617 always_write_to_card=False,
1618 comment='This parameter is automatically set to True by MG5aMC when doing MLM merging with PY8.')
1619
1620
1621 self.add_param("JetMatching:merge", False, hidden=True, always_write_to_card=False,
1622 comment='Specifiy if we are merging sample of different multiplicity.')
1623 self.add_param("SysCalc:qCutList", [10.0,20.0], hidden=True, always_write_to_card=False)
1624 self['SysCalc:qCutList'] = 'auto'
1625 self.add_param("SysCalc:qWeed",-1.0,hidden=True, always_write_to_card=False,
1626 comment='Value of the merging scale below which one does not even write the HepMC event.')
1627 self.add_param("JetMatching:doVeto", False, hidden=True, always_write_to_card=False,
1628 comment='Do veto externally (e.g. in SysCalc).')
1629 self.add_param("JetMatching:scheme", 1, hidden=True, always_write_to_card=False)
1630 self.add_param("JetMatching:setMad", False, hidden=True, always_write_to_card=False,
1631 comment='Specify one must read inputs from the MadGraph banner.')
1632 self.add_param("JetMatching:coneRadius", 1.0, hidden=True, always_write_to_card=False)
1633 self.add_param("JetMatching:nQmatch",4,hidden=True, always_write_to_card=False)
1634
1635 self.add_param("TimeShower:pTmaxMatch", 2, hidden=True, always_write_to_card=False)
1636 self.add_param("SpaceShower:pTmaxMatch", 1, hidden=True, always_write_to_card=False)
1637 self.add_param("SysCalc:tmsList", [10.0,20.0], hidden=True, always_write_to_card=False)
1638 self['SysCalc:tmsList'] = 'auto'
1639 self.add_param("Merging:muFac", 91.188, hidden=True, always_write_to_card=False,
1640 comment='Set factorisation scales of the 2->2 process.')
1641 self.add_param("Merging:applyVeto", False, hidden=True, always_write_to_card=False,
1642 comment='Do veto externally (e.g. in SysCalc).')
1643 self.add_param("Merging:includeWeightInXsection", True, hidden=True, always_write_to_card=False,
1644 comment='If turned off, then the option belows forces PY8 to keep the original weight.')
1645 self.add_param("Merging:muRen", 91.188, hidden=True, always_write_to_card=False,
1646 comment='Set renormalization scales of the 2->2 process.')
1647 self.add_param("Merging:muFacInME", 91.188, hidden=True, always_write_to_card=False,
1648 comment='Set factorisation scales of the 2->2 Matrix Element.')
1649 self.add_param("Merging:muRenInME", 91.188, hidden=True, always_write_to_card=False,
1650 comment='Set renormalization scales of the 2->2 Matrix Element.')
1651 self.add_param("SpaceShower:rapidityOrder", False, hidden=True, always_write_to_card=False)
1652 self.add_param("Merging:nQuarksMerge",4,hidden=True, always_write_to_card=False)
1653
1654 self.add_param("Merging:mayRemoveDecayProducts", False, hidden=True, always_write_to_card=False)
1655 self.add_param("Merging:doKTMerging", False, hidden=True, always_write_to_card=False)
1656 self.add_param("Merging:Dparameter", 0.4, hidden=True, always_write_to_card=False)
1657 self.add_param("Merging:doPTLundMerging", False, hidden=True, always_write_to_card=False)
1658
1659
1660 self.add_param("BeamRemnants:primordialKT", True, hidden=True, always_write_to_card=False, comment="see http://home.thep.lu.se/~torbjorn/pythia82html/BeamRemnants.html")
1661 self.add_param("PartonLevel:Remnants", True, hidden=True, always_write_to_card=False, comment="Master switch for addition of beam remnants. Cannot be used to generate complete events")
1662 self.add_param("Check:event", True, hidden=True, always_write_to_card=False, comment="check physical sanity of the events")
1663 self.add_param("TimeShower:QEDshowerByQ", True, hidden=True, always_write_to_card=False, comment="Allow quarks to radiate photons for FSR, i.e. branchings q -> q gamma")
1664 self.add_param("TimeShower:QEDshowerByL", True, hidden=True, always_write_to_card=False, comment="Allow leptons to radiate photons for FSR, i.e. branchings l -> l gamma")
1665 self.add_param("SpaceShower:QEDshowerByQ", True, hidden=True, always_write_to_card=False, comment="Allow quarks to radiate photons for ISR, i.e. branchings q -> q gamma")
1666 self.add_param("SpaceShower:QEDshowerByL", True, hidden=True, always_write_to_card=False, comment="Allow leptons to radiate photonsfor ISR, i.e. branchings l -> l gamma")
1667 self.add_param("PartonLevel:FSRinResonances", True, hidden=True, always_write_to_card=False, comment="Do not allow shower to run from decay product of unstable particle")
1668 self.add_param("ProcessLevel:resonanceDecays", True, hidden=True, always_write_to_card=False, comment="Do not allow unstable particle to decay.")
1669
1670
1671
1672 self.add_default_subruns('parameters')
1673
1675
1676
1677
1678 self.hidden_param = []
1679 self.hidden_params_to_always_write = set()
1680 self.visible_params_to_always_write = set()
1681
1682 self.params_to_never_write = set()
1683
1684
1685
1686 self.system_set = set()
1687
1688
1689
1690 self.add_default_subruns('attributes')
1691
1692
1693 super(PY8Card, self).__init__(*args, **opts)
1694
1695 - def add_param(self, name, value, hidden=False, always_write_to_card=True,
1696 comment=None):
1697 """ add a parameter to the card. value is the default value and
1698 defines the type (int/float/bool/str) of the input.
1699 The option 'hidden' decides whether the parameter should be visible to the user.
1700 The option 'always_write_to_card' decides whether it should
1701 always be printed or only when it is system_set or user_set.
1702 The option 'comment' can be used to specify a comment to write above
1703 hidden parameters.
1704 """
1705 super(PY8Card, self).add_param(name, value, comment=comment)
1706 name = name.lower()
1707 if hidden:
1708 self.hidden_param.append(name)
1709 if always_write_to_card:
1710 self.hidden_params_to_always_write.add(name)
1711 else:
1712 if always_write_to_card:
1713 self.visible_params_to_always_write.add(name)
1714 if not comment is None:
1715 if not isinstance(comment, str):
1716 raise MadGraph5Error("Option 'comment' must be a string, not"+\
1717 " '%s'."%str(comment))
1718
1720 """Add a subrun to this PY8 Card."""
1721 assert(isinstance(py8_subrun,PY8SubRun))
1722 if py8_subrun['Main:subrun']==-1:
1723 raise MadGraph5Error, "Make sure to correctly set the subrun ID"+\
1724 " 'Main:subrun' *before* adding it to the PY8 Card."
1725 if py8_subrun['Main:subrun'] in self.subruns:
1726 raise MadGraph5Error, "A subrun with ID '%s'"%py8_subrun['Main:subrun']+\
1727 " is already present in this PY8 card. Remove it first, or "+\
1728 " access it directly."
1729 self.subruns[py8_subrun['Main:subrun']] = py8_subrun
1730 if not 'LHEFInputs:nSubruns' in self.user_set:
1731 self['LHEFInputs:nSubruns'] = max(self.subruns.keys())
1732
1733 - def userSet(self, name, value, **opts):
1734 """Set an attribute of this card, following a user_request"""
1735 self.__setitem__(name, value, change_userdefine=True, **opts)
1736 if name.lower() in self.system_set:
1737 self.system_set.remove(name.lower())
1738
1740 """ Forbid the writeout of a specific parameter of this card when the
1741 "write" function will be invoked."""
1742 self.params_to_never_write.add(name.lower())
1743
1745 """Set an attribute of this card, independently of a specific user
1746 request and only if not already user_set."""
1747 try:
1748 force = opts.pop('force')
1749 except KeyError:
1750 force = False
1751 if force or name.lower() not in self.user_set:
1752 self.__setitem__(name, value, change_userdefine=False, **opts)
1753 self.system_set.add(name.lower())
1754
1756 """ Sets a card attribute, but only if it is absent or not already
1757 user_set."""
1758 try:
1759 force = opts.pop('force')
1760 except KeyError:
1761 force = False
1762 if name.lower() not in self or (force or name.lower() not in self.user_set):
1763 self.__setitem__(name, value, change_userdefine=False, **opts)
1764 self.system_set.add(name.lower())
1765
1768
1769 @staticmethod
1820
1821
1822 - def write(self, output_file, template, read_subrun=False,
1823 print_only_visible=False, direct_pythia_input=False, add_missing=True):
1824 """ Write the card to output_file using a specific template.
1825 > 'print_only_visible' specifies whether or not the hidden parameters
1826 should be written out if they are in the hidden_params_to_always_write
1827 list and system_set.
1828 > If 'direct_pythia_input' is true, then visible parameters which are not
1829 in the self.visible_params_to_always_write list and are not user_set
1830 or system_set are commented.
1831 > If 'add_missing' is False then parameters that should be written_out but are absent
1832 from the template will not be written out."""
1833
1834
1835 visible_param = [p for p in self if p.lower() not in self.hidden_param
1836 or p.lower() in self.user_set]
1837
1838 visible_param = [p for p in visible_param if p.lower() not in self.params_to_never_write]
1839
1840
1841 if print_only_visible:
1842 hidden_output_param = []
1843 else:
1844 hidden_output_param = [p for p in self if p.lower() in self.hidden_param and
1845 not p.lower() in self.user_set and
1846 (p.lower() in self.hidden_params_to_always_write or
1847 p.lower() in self.system_set)]
1848
1849 hidden_output_param = [p for p in hidden_output_param if p not in self.params_to_never_write]
1850
1851 if print_only_visible:
1852 subruns = []
1853 else:
1854 if not read_subrun:
1855 subruns = sorted(self.subruns.keys())
1856
1857
1858
1859 subruns_to_write = {}
1860
1861
1862
1863 def group_params(params):
1864 if len(params)==0:
1865 return []
1866 groups = {}
1867 for p in params:
1868 try:
1869 groups[':'.join(p.split(':')[:-1])].append(p)
1870 except KeyError:
1871 groups[':'.join(p.split(':')[:-1])] = [p,]
1872 res = sum(groups.values(),[])
1873
1874 if 'Main:subrun' in res:
1875 res.insert(0,res.pop(res.index('Main:subrun')))
1876
1877 if 'LHEFInputs:nSubruns' in res:
1878 res.append(res.pop(res.index('LHEFInputs:nSubruns')))
1879 return res
1880
1881 visible_param = group_params(visible_param)
1882 hidden_output_param = group_params(hidden_output_param)
1883
1884
1885
1886 output = StringIO.StringIO()
1887
1888
1889 if isinstance(template, str):
1890 if os.path.isfile(template):
1891 tmpl = open(template, 'r')
1892 elif '\n' in template:
1893 tmpl = StringIO.StringIO(template)
1894 else:
1895 raise Exception, "File input '%s' not found." % file_input
1896 elif template is None:
1897
1898 tmpl = StringIO.StringIO()
1899 elif isinstance(template, (StringIO.StringIO, file)):
1900 tmpl = template
1901 else:
1902 raise MadGraph5Error("Incorrect type for argument 'template': %s"%
1903 template.__class__.__name__)
1904
1905
1906 last_pos = tmpl.tell()
1907 line = tmpl.readline()
1908 started_subrun_reading = False
1909 while line!='':
1910
1911 if line.strip().startswith('!') or \
1912 line.strip().startswith('\n') or\
1913 line.strip() == '':
1914 output.write(line)
1915
1916 last_pos = tmpl.tell()
1917 line = tmpl.readline()
1918 continue
1919
1920 try:
1921 param_entry, value_entry = line.split('=')
1922 param = param_entry.strip()
1923 value = value_entry.strip()
1924 except ValueError:
1925 line = line.replace('\n','')
1926 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\
1927 line
1928
1929 if param=='Main:subrun':
1930 if read_subrun:
1931 if not started_subrun_reading:
1932
1933 started_subrun_reading = True
1934 else:
1935
1936 tmpl.seek(last_pos)
1937 break
1938 else:
1939
1940 tmpl.seek(last_pos)
1941 subruns_to_write[int(value)] = StringIO.StringIO()
1942 if int(value) in subruns:
1943 self.subruns[int(value)].write(subruns_to_write[int(value)],
1944 tmpl,read_subrun=True)
1945
1946 subruns.pop(subruns.index(int(value)))
1947 else:
1948
1949 DummySubrun=PY8SubRun()
1950
1951 DummySubrun.clear()
1952 DummySubrun.write(subruns_to_write[int(value)],
1953 tmpl, read_subrun=True,
1954 print_only_visible=print_only_visible,
1955 direct_pythia_input=direct_pythia_input)
1956
1957 logger.info('Adding new unknown subrun with ID %d.'%
1958 int(value))
1959
1960 last_pos = tmpl.tell()
1961 line = tmpl.readline()
1962 continue
1963
1964
1965 if param in visible_param:
1966 new_value = PY8Card.pythia8_formatting(self[param])
1967 visible_param.pop(visible_param.index(param))
1968 elif param in hidden_output_param:
1969 new_value = PY8Card.pythia8_formatting(self[param])
1970 hidden_output_param.pop(hidden_output_param.index(param))
1971 else:
1972
1973 if param.lower() not in self.params_to_never_write:
1974 output.write(line)
1975 else:
1976 output.write('! The following parameter was forced to be commented out by MG5aMC.\n')
1977 output.write('! %s'%line)
1978
1979 last_pos = tmpl.tell()
1980 line = tmpl.readline()
1981 continue
1982
1983
1984
1985
1986
1987 if ((not direct_pythia_input) or
1988 (param.lower() in self.visible_params_to_always_write) or
1989 (param.lower() in self.user_set) or
1990 (param.lower() in self.system_set)):
1991 template = '%s=%s'
1992 else:
1993
1994
1995
1996 template = '!%s=%s'
1997
1998 output.write(template%(param_entry,
1999 value_entry.replace(value,new_value)))
2000
2001
2002 last_pos = tmpl.tell()
2003 line = tmpl.readline()
2004
2005
2006 if not add_missing:
2007 visible_param = []
2008 hidden_output_param = []
2009
2010
2011 if len(visible_param)>0 and not template is None:
2012 output.write(
2013 """!
2014 ! Additional general parameters%s.
2015 !
2016 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else ''))
2017 for param in visible_param:
2018 value = PY8Card.pythia8_formatting(self[param])
2019 output.write('%s=%s\n'%(param,value))
2020 if template is None:
2021 if param=='Main:subrun':
2022 output.write(
2023 """!
2024 ! Definition of subrun %d
2025 !
2026 """%self['Main:subrun'])
2027 elif param.lower() not in self.hidden_param:
2028 logger.debug('Adding parameter %s (missing in the template) to current '+\
2029 'pythia8 card (with value %s)',param, value)
2030
2031 if len(hidden_output_param)>0 and not template is None:
2032 output.write(
2033 """!
2034 ! Additional technical parameters%s set by MG5_aMC.
2035 !
2036 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else ''))
2037 for param in hidden_output_param:
2038 if param.lower() in self.comments:
2039 comment = '\n'.join('! %s'%c for c in
2040 self.comments[param.lower()].split('\n'))
2041 output.write(comment+'\n')
2042 output.write('%s=%s\n'%(param,PY8Card.pythia8_formatting(self[param])))
2043
2044
2045
2046 if read_subrun:
2047 output_file.write(output.getvalue())
2048 return
2049
2050
2051 for subrunID in subruns:
2052 new_subrun = StringIO.StringIO()
2053 self.subruns[subrunID].write(new_subrun,None,read_subrun=True)
2054 subruns_to_write[subrunID] = new_subrun
2055
2056
2057 for subrunID in sorted(subruns_to_write):
2058 output.write(subruns_to_write[subrunID].getvalue())
2059
2060
2061
2062 if 'LHEFInputs:nSubruns'.lower() not in self.user_set and \
2063 len(subruns_to_write)>0 and 'LHEFInputs:nSubruns' in self\
2064 and self['LHEFInputs:nSubruns']<max(subruns_to_write.keys()):
2065 logger.info("Updating PY8 parameter 'LHEFInputs:nSubruns' to "+
2066 "%d so as to cover all defined subruns."%max(subruns_to_write.keys()))
2067 self['LHEFInputs:nSubruns'] = max(subruns_to_write.keys())
2068 output = StringIO.StringIO()
2069 self.write(output,template,print_only_visible=print_only_visible)
2070
2071
2072 if isinstance(output_file, str):
2073 out = open(output_file,'w')
2074 out.write(output.getvalue())
2075 out.close()
2076 else:
2077 output_file.write(output.getvalue())
2078
2079 - def read(self, file_input, read_subrun=False, setter='default'):
2080 """Read the input file, this can be a path to a file,
2081 a file object, a str with the content of the file.
2082 The setter option choses the authority that sets potential
2083 modified/new parameters. It can be either:
2084 'default' or 'user' or 'system'"""
2085 if isinstance(file_input, str):
2086 if "\n" in file_input:
2087 finput = StringIO.StringIO(file_input)
2088 elif os.path.isfile(file_input):
2089 finput = open(file_input)
2090 else:
2091 raise Exception, "File input '%s' not found." % file_input
2092 elif isinstance(file_input, (StringIO.StringIO, file)):
2093 finput = file_input
2094 else:
2095 raise MadGraph5Error("Incorrect type for argument 'file_input': %s"%
2096 file_input.__class__.__name__)
2097
2098
2099 last_pos = finput.tell()
2100 line = finput.readline()
2101 started_subrun_reading = False
2102 while line!='':
2103
2104 if line.strip().startswith('!') or line.strip()=='':
2105
2106 last_pos = finput.tell()
2107 line = finput.readline()
2108 continue
2109
2110 try:
2111 param, value = line.split('=',1)
2112 param = param.strip()
2113 value = value.strip()
2114 except ValueError:
2115 line = line.replace('\n','')
2116 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\
2117 line
2118 if '!' in value:
2119 value,_ = value.split('!',1)
2120
2121
2122 if param=='Main:subrun':
2123 if read_subrun:
2124 if not started_subrun_reading:
2125
2126 started_subrun_reading = True
2127 else:
2128
2129 finput.seek(last_pos)
2130 return
2131 else:
2132
2133 finput.seek(last_pos)
2134 if int(value) in self.subruns:
2135 self.subruns[int(value)].read(finput,read_subrun=True,
2136 setter=setter)
2137 else:
2138
2139 NewSubrun=PY8SubRun()
2140 NewSubrun.read(finput,read_subrun=True, setter=setter)
2141 self.add_subrun(NewSubrun)
2142
2143
2144 last_pos = finput.tell()
2145 line = finput.readline()
2146 continue
2147
2148
2149
2150
2151
2152 if setter == 'user':
2153 self.userSet(param,value)
2154 elif setter == 'system':
2155 self.systemSet(param,value)
2156 else:
2157 self.defaultSet(param,value)
2158
2159
2160 last_pos = finput.tell()
2161 line = finput.readline()
2162
2164 """ Class to characterize a specific PY8 card subrun section. """
2165
2167 """ Overloading of the homonym function called in the __init__ of PY8Card.
2168 The initialization of the self.subruns attribute should of course not
2169 be performed in PY8SubRun."""
2170 pass
2171
2173 """ Initialize a subrun """
2174
2175
2176 subrunID = -1
2177 if 'subrun_id' in opts:
2178 subrunID = opts.pop('subrun_id')
2179
2180 super(PY8SubRun, self).__init__(*args, **opts)
2181 self['Main:subrun']=subrunID
2182
2184 """Sets up the list of available PY8SubRun parameters."""
2185
2186
2187 super(PY8SubRun, self).default_setup()
2188
2189 self.hidden_param = [k.lower() for k in self.keys()]
2190 self.hidden_params_to_always_write = set()
2191 self.visible_params_to_always_write = set()
2192
2193
2194 self.add_param("Main:subrun", -1)
2195 self.add_param("Beams:LHEF", "events.lhe.gz")
2196
2197
2198
2199 runblock = collections.namedtuple('block', ('name', 'fields', 'template_on', 'template_off'))
2201
2202 filename = 'run_card'
2203 blocks = []
2204
2205 - def __new__(cls, finput=None, **opt):
2206 if cls is RunCard:
2207 if not finput:
2208 target_class = RunCardLO
2209 elif isinstance(finput, cls):
2210 target_class = finput.__class__
2211 elif isinstance(finput, str):
2212 if '\n' not in finput:
2213 finput = open(finput).read()
2214 if 'req_acc_FO' in finput:
2215 target_class = RunCardNLO
2216 else:
2217 target_class = RunCardLO
2218 else:
2219 return None
2220 return super(RunCard, cls).__new__(target_class, finput, **opt)
2221 else:
2222 return super(RunCard, cls).__new__(cls, finput, **opt)
2223
2225
2226
2227
2228
2229 self.hidden_param = []
2230
2231 self.includepath = collections.defaultdict(list)
2232
2233 self.fortran_name = {}
2234
2235 self.legacy_parameter = {}
2236
2237 self.cuts_parameter = []
2238
2239 self.system_default = {}
2240
2241 self.display_block = []
2242 self.warned=False
2243
2244
2245 super(RunCard, self).__init__(*args, **opts)
2246
2247 - def add_param(self, name, value, fortran_name=None, include=True,
2248 hidden=False, legacy=False, cut=False, system=False, sys_default=None,
2249 **opts):
2250 """ add a parameter to the card. value is the default value and
2251 defines the type (int/float/bool/str) of the input.
2252 fortran_name defines what is the associate name in the f77 code
2253 include defines if we have to put the value in the include file
2254 hidden defines if the parameter is expected to be define by the user.
2255 legacy:Parameter which is not used anymore (raise a warning if not default)
2256 cut: defines the list of cut parameter to allow to set them all to off.
2257 sys_default: default used if the parameter is not in the card
2258
2259 options of **opts:
2260 - allowed: list of valid options. '*' means anything else should be allowed.
2261 empty list means anything possible as well.
2262 - comment: add comment for writing/help
2263 - typelist: type of the list if default is empty
2264 """
2265
2266 super(RunCard, self).add_param(name, value, system=system,**opts)
2267 name = name.lower()
2268 if fortran_name:
2269 self.fortran_name[name] = fortran_name
2270 if legacy:
2271 self.legacy_parameter[name] = value
2272 include = False
2273 self.includepath[include].append(name)
2274 if hidden or system:
2275 self.hidden_param.append(name)
2276 if cut:
2277 self.cuts_parameter.append(name)
2278 if sys_default is not None:
2279 self.system_default[name] = sys_default
2280
2281
2282
2283 - def read(self, finput, consistency=True):
2284 """Read the input file, this can be a path to a file,
2285 a file object, a str with the content of the file."""
2286
2287 if isinstance(finput, str):
2288 if "\n" in finput:
2289 finput = finput.split('\n')
2290 elif os.path.isfile(finput):
2291 finput = open(finput)
2292 else:
2293 raise Exception, "No such file %s" % finput
2294
2295 for line in finput:
2296 line = line.split('#')[0]
2297 line = line.split('!')[0]
2298 line = line.rsplit('=',1)
2299 if len(line) != 2:
2300 continue
2301 value, name = line
2302 name = name.lower().strip()
2303 if name not in self and ('min' in name or 'max' in name):
2304
2305 self.add_param(name, float(value), hidden=True, cut=True)
2306 else:
2307 self.set( name, value, user=True)
2308
2309 if consistency:
2310 try:
2311 self.check_validity()
2312 except InvalidRunCard, error:
2313 if consistency == 'warning':
2314 logger.warning(str(error))
2315 else:
2316 raise
2317
2318
2319 - def write(self, output_file, template=None, python_template=False,
2320 write_hidden=False):
2321 """Write the run_card in output_file according to template
2322 (a path to a valid run_card)"""
2323
2324 to_write = set(self.user_set)
2325 written = set()
2326 if not template:
2327 raise Exception
2328
2329
2330 write_block= []
2331 for b in self.blocks:
2332 name = b.name
2333
2334 if name not in self.display_block and \
2335 not any(f in self.user_set for f in b.fields):
2336 continue
2337 write_block.append(b.name)
2338
2339 if python_template and not to_write:
2340 import string
2341 text = file(template,'r').read()
2342 if self.blocks:
2343 text = string.Template(text)
2344 mapping = {}
2345 for b in self.blocks:
2346 if b.name in write_block:
2347 mapping[b.name] = b.template_on
2348 else:
2349 mapping[b.name] = b.template_off
2350 text = text.substitute(mapping)
2351
2352 if not self.list_parameter:
2353 text = text % self
2354 else:
2355 data = dict(self)
2356 for name in self.list_parameter:
2357 if self.list_parameter[name] != str:
2358 data[name] = ', '.join(str(v) for v in data[name])
2359 else:
2360 data[name] = "['%s']" % "', '".join(str(v) for v in data[name])
2361 text = text % data
2362 else:
2363 text = ""
2364 for line in file(template,'r'):
2365 nline = line.split('#')[0]
2366 nline = nline.split('!')[0]
2367 comment = line[len(nline):]
2368 nline = nline.split('=')
2369 if python_template and nline[0].startswith('$'):
2370 block_name = nline[0][1:]
2371 this_group = [b for b in self.blocks if b.name == block_name]
2372 if not this_group:
2373 logger.debug("block %s not defined", block_name)
2374 continue
2375 else:
2376 this_group = this_group[0]
2377 if block_name in write_block:
2378 text += this_group.template_on % self
2379 for name in this_group.fields:
2380 written.add(name)
2381 if name in to_write:
2382 to_write.remove(name)
2383 else:
2384 text += this_group.template_off % self
2385
2386 elif len(nline) != 2:
2387 text += line
2388 elif nline[1].strip() in self:
2389 name = nline[1].strip().lower()
2390 value = self[name]
2391 if name in self.list_parameter:
2392 if self.list_parameter[name] != str:
2393 value = ', '.join([str(v) for v in value])
2394 else:
2395 value = "['%s']" % "', '".join(str(v) for v in value)
2396 if python_template:
2397 text += line % {nline[1].strip():value, name:value}
2398 written.add(name)
2399 else:
2400 if not comment or comment[-1]!='\n':
2401 endline = '\n'
2402 else:
2403 endline = ''
2404 text += ' %s\t= %s %s%s' % (value, name, comment, endline)
2405 written.add(name)
2406
2407 if name in to_write:
2408 to_write.remove(name)
2409 else:
2410 logger.info('Adding missing parameter %s to current %s (with default value)',
2411 (name, self.filename))
2412 written.add(name)
2413 text += line
2414
2415 for b in self.blocks:
2416 if b.name not in write_block:
2417 continue
2418
2419 if all(f in written for f in b.fields):
2420 continue
2421
2422 to_add = []
2423 for line in b.template_on.split('\n'):
2424 nline = line.split('#')[0]
2425 nline = nline.split('!')[0]
2426 nline = nline.split('=')
2427 if len(nline) != 2:
2428 to_add.append(line)
2429 elif nline[1].strip() in self:
2430 name = nline[1].strip().lower()
2431 value = self[name]
2432 if name in self.list_parameter:
2433 value = ', '.join([str(v) for v in value])
2434 if name in written:
2435 continue
2436 else:
2437 to_add.append(line % {nline[1].strip():value, name:value})
2438 written.add(name)
2439
2440 if name in to_write:
2441 to_write.remove(name)
2442 else:
2443 raise Exception
2444
2445 if b.template_off in text:
2446 text = text.replace(b.template_off, '\n'.join(to_add))
2447 else:
2448 text += '\n'.join(to_add)
2449
2450 if to_write or write_hidden:
2451 text+="""#*********************************************************************
2452 # Additional hidden parameters
2453 #*********************************************************************
2454 """
2455 if write_hidden:
2456
2457
2458
2459 if python_template:
2460 written = written.union(set(re.findall('\%\((\w*)\)s', file(template,'r').read(), re.M)))
2461 to_write = to_write.union(set(self.hidden_param))
2462 to_write = to_write.difference(written)
2463
2464 for key in to_write:
2465 if key in self.system_only:
2466 continue
2467
2468 comment = self.comments.get(key,'hidden_parameter').replace('\n','\n#')
2469 text += ' %s\t= %s # %s\n' % (self[key], key, comment)
2470
2471 if isinstance(output_file, str):
2472 fsock = open(output_file,'w')
2473 fsock.write(text)
2474 fsock.close()
2475 else:
2476 output_file.write(text)
2477
2478
2479 - def get_default(self, name, default=None, log_level=None):
2480 """return self[name] if exist otherwise default. log control if we
2481 put a warning or not if we use the default value"""
2482
2483 lower_name = name.lower()
2484 if lower_name not in self.user_set:
2485 if log_level is None:
2486 if lower_name in self.system_only:
2487 log_level = 5
2488 elif lower_name in self.auto_set:
2489 log_level = 5
2490 elif lower_name in self.hidden_param:
2491 log_level = 10
2492 else:
2493 log_level = 20
2494 if not default:
2495 default = dict.__getitem__(self, name.lower())
2496
2497 logger.log(log_level, '%s missed argument %s. Takes default: %s'
2498 % (self.filename, name, default))
2499 self[name] = default
2500 return default
2501 else:
2502 return self[name]
2503
2504
2505 @staticmethod
2554
2555
2556
2558 """check that parameter missing in the card are set to the expected value"""
2559
2560 for name, value in self.system_default.items():
2561 self.set(name, value, changeifuserset=False)
2562
2563
2564 for name in self.includepath[False]:
2565 to_bypass = self.hidden_param + self.legacy_parameter.keys()
2566 if name not in to_bypass:
2567 self.get_default(name, log_level=log_level)
2568
2569 for name in self.legacy_parameter:
2570 if self[name] != self.legacy_parameter[name]:
2571 logger.warning("The parameter %s is not supported anymore this parameter will be ignored." % name)
2572
2573 default_include_file = 'run_card.inc'
2574
2576 """update hidden system only parameter for the correct writtin in the
2577 include"""
2578 return
2579
2581 """Write the various include file in output_dir.
2582 The entry True of self.includepath will be written in run_card.inc
2583 The entry False will not be written anywhere"""
2584
2585
2586 self.check_validity()
2587
2588
2589 self.update_system_parameter_for_include()
2590
2591 for incname in self.includepath:
2592 if incname is True:
2593 pathinc = self.default_include_file
2594 elif incname is False:
2595 continue
2596 else:
2597 pathinc = incname
2598
2599 fsock = file_writers.FortranWriter(pjoin(output_dir,pathinc))
2600 for key in self.includepath[incname]:
2601
2602 if key in self.fortran_name:
2603 fortran_name = self.fortran_name[key]
2604 else:
2605 fortran_name = key
2606
2607
2608 value = self.get_default(key)
2609
2610
2611 if isinstance(value, list):
2612
2613
2614
2615 targettype = self.list_parameter[key]
2616 if targettype is bool:
2617 pass
2618 elif targettype is int:
2619 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(len(value)))
2620 fsock.writelines(line)
2621 elif targettype is float:
2622 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(float(len(value))))
2623 fsock.writelines(line)
2624
2625 for i,v in enumerate(value):
2626 line = '%s(%s) = %s \n' % (fortran_name, i+1, self.f77_formatting(v))
2627 fsock.writelines(line)
2628 elif isinstance(value, dict):
2629 for fortran_name, onevalue in value.items():
2630 line = '%s = %s \n' % (fortran_name, self.f77_formatting(onevalue))
2631 fsock.writelines(line)
2632 else:
2633 line = '%s = %s \n' % (fortran_name, self.f77_formatting(value))
2634 fsock.writelines(line)
2635 fsock.close()
2636
2637 @staticmethod
2639 """return the particle colliding pdg code"""
2640 if lpp in (1,2, -1,-2):
2641 return math.copysign(2212, lpp)
2642 elif lpp in (3,-3):
2643 return math.copysign(11, lpp)
2644 elif lpp == 0:
2645
2646 return 0
2647 else:
2648 return lpp
2649
2664
2666 if pdf == "lhapdf":
2667 lhaid = self["lhaid"]
2668 if isinstance(lhaid, list):
2669 return lhaid[0]
2670 else:
2671 return lhaid
2672 else:
2673 return {'none': 0,
2674 'cteq6_m':10000,'cteq6_l':10041,'cteq6l1':10042,
2675 'nn23lo':246800,'nn23lo1':247000,'nn23nlo':244800
2676 }[pdf]
2677
2680
2682 """remove all the cut"""
2683
2684 for name in self.cuts_parameter:
2685 targettype = type(self[name])
2686 if targettype == bool:
2687 self[name] = False
2688 elif 'min' in name:
2689 self[name] = 0
2690 elif 'max' in name:
2691 self[name] = -1
2692 elif 'eta' in name:
2693 self[name] = -1
2694 else:
2695 self[name] = 0
2696
2698 """an object to handle in a nice way the run_card information"""
2699
2700 blocks = [
2701
2702 runblock(name='ion_pdf', fields=('nb_neutron1', 'nb_neutron2','nb_proton1','nb_proton2','mass_ion1', 'mass_ion2'),
2703 template_on=\
2704 """#*********************************************************************
2705 # Heavy ion PDF / rescaling of PDF *
2706 #*********************************************************************
2707 %(nb_proton1)s = nb_proton1 # number of proton for the first beam
2708 %(nb_neutron1)s = nb_neutron1 # number of neutron for the first beam
2709 %(mass_ion1)s = mass_ion1 # mass of the heavy ion (first beam)
2710 # Note that seting differently the two beams only work if you use
2711 # group_subprocess=False when generating your matrix-element
2712 %(nb_proton2)s = nb_proton2 # number of proton for the second beam
2713 %(nb_neutron2)s = nb_neutron2 # number of neutron for the second beam
2714 %(mass_ion2)s = mass_ion2 # mass of the heavy ion (second beam)
2715 """,
2716 template_off='# To see heavy ion options: type "update ion_pdf"'),
2717
2718
2719
2720 runblock(name='beam_pol', fields=('polbeam1','polbeam2'),
2721 template_on=\
2722 """#*********************************************************************
2723 # Beam polarization from -100 (left-handed) to 100 (right-handed) *
2724 #*********************************************************************
2725 %(polbeam1)s = polbeam1 ! beam polarization for beam 1
2726 %(polbeam2)s = polbeam2 ! beam polarization for beam 2
2727 """,
2728 template_off='# To see polarised beam options: type "update beam_pol"'),
2729
2730
2731 runblock(name='syscalc', fields=('sys_scalefact', 'sys_alpsfact','sys_matchscale','sys_pdf'),
2732 template_on=\
2733 """#**************************************
2734 # Parameter below of the systematics study
2735 # will be used by SysCalc (if installed)
2736 #**************************************
2737 #
2738 %(sys_scalefact)s = sys_scalefact # factorization/renormalization scale factor
2739 %(sys_alpsfact)s = sys_alpsfact # \alpha_s emission scale factors
2740 %(sys_matchscale)s = sys_matchscale # variation of merging scale
2741 # PDF sets and number of members (0 or none for all members).
2742 %(sys_pdf)s = sys_pdf # list of pdf sets. (errorset not valid for syscalc)
2743 # MSTW2008nlo68cl.LHgrid 1 = sys_pdf
2744 #
2745 """,
2746 template_off= '# Syscalc is deprecated but to see the associate options type\'update syscalc\''),
2747 ]
2748
2749
2750
2752 """default value for the run_card.dat"""
2753
2754 self.add_param("run_tag", "tag_1", include=False)
2755 self.add_param("gridpack", False)
2756 self.add_param("time_of_flight", -1.0, include=False)
2757 self.add_param("nevents", 10000)
2758 self.add_param("iseed", 0)
2759 self.add_param("python_seed", -2, include=False, hidden=True, comment="controlling python seed [handling in particular the final unweighting].\n -1 means use default from random module.\n -2 means set to same value as iseed")
2760 self.add_param("lpp1", 1, fortran_name="lpp(1)", allowed=[-1,1,0,2,3,9, -2,-3],
2761 comment='first beam energy distribution:\n 0: fixed energy\n 1: PDF from proton\n -1: PDF from anti-proton\n 2:photon from proton, 3:photon from electron, 9: PLUGIN MODE')
2762 self.add_param("lpp2", 1, fortran_name="lpp(2)", allowed=[-1,1,0,2,3,9],
2763 comment='first beam energy distribution:\n 0: fixed energy\n 1: PDF from proton\n -1: PDF from anti-proton\n 2:photon from proton, 3:photon from electron, 9: PLUGIN MODE')
2764 self.add_param("ebeam1", 6500.0, fortran_name="ebeam(1)")
2765 self.add_param("ebeam2", 6500.0, fortran_name="ebeam(2)")
2766 self.add_param("polbeam1", 0.0, fortran_name="pb1", hidden=True,
2767 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--")
2768 self.add_param("polbeam2", 0.0, fortran_name="pb2", hidden=True,
2769 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--")
2770 self.add_param('nb_proton1', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(1)",
2771 comment='For heavy ion physics nb of proton in the ion (for both beam but if group_subprocess was False)')
2772 self.add_param('nb_proton2', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(2)",
2773 comment='For heavy ion physics nb of proton in the ion (used for beam 2 if group_subprocess was False)')
2774 self.add_param('nb_neutron1', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(1)",
2775 comment='For heavy ion physics nb of neutron in the ion (for both beam but if group_subprocess was False)')
2776 self.add_param('nb_neutron2', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(2)",
2777 comment='For heavy ion physics nb of neutron in the ion (of beam 2 if group_subprocess was False )')
2778 self.add_param('mass_ion1', -1.0, hidden=True, fortran_name="mass_ion(1)",
2779 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'],
2780 comment='For heavy ion physics mass in GeV of the ion (of beam 1)')
2781 self.add_param('mass_ion2', -1.0, hidden=True, fortran_name="mass_ion(2)",
2782 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'],
2783 comment='For heavy ion physics mass in GeV of the ion (of beam 2)')
2784
2785 self.add_param("pdlabel", "nn23lo1", allowed=['lhapdf', 'cteq6_m','cteq6_l', 'cteq6l1','nn23lo', 'nn23lo1', 'nn23nlo']),
2786 self.add_param("lhaid", 230000, hidden=True)
2787 self.add_param("fixed_ren_scale", False)
2788 self.add_param("fixed_fac_scale", False)
2789 self.add_param("scale", 91.1880)
2790 self.add_param("dsqrt_q2fact1", 91.1880, fortran_name="sf1")
2791 self.add_param("dsqrt_q2fact2", 91.1880, fortran_name="sf2")
2792 self.add_param("dynamical_scale_choice", -1, comment="\'-1\' is based on CKKW back clustering (following feynman diagram).\n \'1\' is the sum of transverse energy.\n '2' is HT (sum of the transverse mass)\n '3' is HT/2\n '4' is the center of mass energy",
2793 allowed=[-1,0,1,2,3,4])
2794
2795
2796 self.add_param("bias_module", 'None', include=False)
2797 self.add_param('bias_parameters', {'__type__':1.0}, include='BIAS/bias.inc')
2798
2799
2800 self.add_param("scalefact", 1.0)
2801 self.add_param("ickkw", 0, allowed=[0,1], comment="\'0\' for standard fixed order computation.\n\'1\' for MLM merging activates alphas and pdf re-weighting according to a kt clustering of the QCD radiation.")
2802 self.add_param("highestmult", 1, fortran_name="nhmult", hidden=True)
2803 self.add_param("ktscheme", 1, hidden=True)
2804 self.add_param("alpsfact", 1.0)
2805 self.add_param("chcluster", False, hidden=True)
2806 self.add_param("pdfwgt", True, hidden=True)
2807 self.add_param("asrwgtflavor", 5, comment = 'highest quark flavor for a_s reweighting in MLM')
2808 self.add_param("clusinfo", True)
2809 self.add_param("lhe_version", 3.0)
2810 self.add_param("event_norm", "average", allowed=['sum','average', 'unity'],
2811 include=False, sys_default='sum')
2812
2813 self.add_param("auto_ptj_mjj", False)
2814 self.add_param("bwcutoff", 15.0)
2815 self.add_param("cut_decays", False)
2816 self.add_param("nhel", 0, include=False)
2817
2818 self.add_param("ptj", 20.0, cut=True)
2819 self.add_param("ptb", 0.0, cut=True)
2820 self.add_param("pta", 10.0, cut=True)
2821 self.add_param("ptl", 10.0, cut=True)
2822 self.add_param("misset", 0.0, cut=True)
2823 self.add_param("ptheavy", 0.0, cut=True, comment='this cut apply on particle heavier than 10 GeV')
2824 self.add_param("ptonium", 1.0, legacy=True)
2825 self.add_param("ptjmax", -1.0, cut=True)
2826 self.add_param("ptbmax", -1.0, cut=True)
2827 self.add_param("ptamax", -1.0, cut=True)
2828 self.add_param("ptlmax", -1.0, cut=True)
2829 self.add_param("missetmax", -1.0, cut=True)
2830
2831 self.add_param("ej", 0.0, cut=True)
2832 self.add_param("eb", 0.0, cut=True)
2833 self.add_param("ea", 0.0, cut=True)
2834 self.add_param("el", 0.0, cut=True)
2835 self.add_param("ejmax", -1.0, cut=True)
2836 self.add_param("ebmax", -1.0, cut=True)
2837 self.add_param("eamax", -1.0, cut=True)
2838 self.add_param("elmax", -1.0, cut=True)
2839
2840 self.add_param("etaj", 5.0, cut=True)
2841 self.add_param("etab", -1.0, cut=True)
2842 self.add_param("etaa", 2.5, cut=True)
2843 self.add_param("etal", 2.5, cut=True)
2844 self.add_param("etaonium", 0.6, legacy=True)
2845 self.add_param("etajmin", 0.0, cut=True)
2846 self.add_param("etabmin", 0.0, cut=True)
2847 self.add_param("etaamin", 0.0, cut=True)
2848 self.add_param("etalmin", 0.0, cut=True)
2849
2850 self.add_param("drjj", 0.4, cut=True)
2851 self.add_param("drbb", 0.0, cut=True)
2852 self.add_param("drll", 0.4, cut=True)
2853 self.add_param("draa", 0.4, cut=True)
2854 self.add_param("drbj", 0.0, cut=True)
2855 self.add_param("draj", 0.4, cut=True)
2856 self.add_param("drjl", 0.4, cut=True)
2857 self.add_param("drab", 0.0, cut=True)
2858 self.add_param("drbl", 0.0, cut=True)
2859 self.add_param("dral", 0.4, cut=True)
2860 self.add_param("drjjmax", -1.0, cut=True)
2861 self.add_param("drbbmax", -1.0, cut=True)
2862 self.add_param("drllmax", -1.0, cut=True)
2863 self.add_param("draamax", -1.0, cut=True)
2864 self.add_param("drbjmax", -1.0, cut=True)
2865 self.add_param("drajmax", -1.0, cut=True)
2866 self.add_param("drjlmax", -1.0, cut=True)
2867 self.add_param("drabmax", -1.0, cut=True)
2868 self.add_param("drblmax", -1.0, cut=True)
2869 self.add_param("dralmax", -1.0, cut=True)
2870
2871 self.add_param("mmjj", 0.0, cut=True)
2872 self.add_param("mmbb", 0.0, cut=True)
2873 self.add_param("mmaa", 0.0, cut=True)
2874 self.add_param("mmll", 0.0, cut=True)
2875 self.add_param("mmjjmax", -1.0, cut=True)
2876 self.add_param("mmbbmax", -1.0, cut=True)
2877 self.add_param("mmaamax", -1.0, cut=True)
2878 self.add_param("mmllmax", -1.0, cut=True)
2879 self.add_param("mmnl", 0.0, cut=True)
2880 self.add_param("mmnlmax", -1.0, cut=True)
2881
2882 self.add_param("ptllmin", 0.0, cut=True)
2883 self.add_param("ptllmax", -1.0, cut=True)
2884 self.add_param("xptj", 0.0, cut=True)
2885 self.add_param("xptb", 0.0, cut=True)
2886 self.add_param("xpta", 0.0, cut=True)
2887 self.add_param("xptl", 0.0, cut=True)
2888
2889 self.add_param("ptj1min", 0.0, cut=True)
2890 self.add_param("ptj1max", -1.0, cut=True)
2891 self.add_param("ptj2min", 0.0, cut=True)
2892 self.add_param("ptj2max", -1.0, cut=True)
2893 self.add_param("ptj3min", 0.0, cut=True)
2894 self.add_param("ptj3max", -1.0, cut=True)
2895 self.add_param("ptj4min", 0.0, cut=True)
2896 self.add_param("ptj4max", -1.0, cut=True)
2897 self.add_param("cutuse", 0, cut=True)
2898
2899 self.add_param("ptl1min", 0.0, cut=True)
2900 self.add_param("ptl1max", -1.0, cut=True)
2901 self.add_param("ptl2min", 0.0, cut=True)
2902 self.add_param("ptl2max", -1.0, cut=True)
2903 self.add_param("ptl3min", 0.0, cut=True)
2904 self.add_param("ptl3max", -1.0, cut=True)
2905 self.add_param("ptl4min", 0.0, cut=True)
2906 self.add_param("ptl4max", -1.0, cut=True)
2907
2908 self.add_param("htjmin", 0.0, cut=True)
2909 self.add_param("htjmax", -1.0, cut=True)
2910 self.add_param("ihtmin", 0.0, cut=True)
2911 self.add_param("ihtmax", -1.0, cut=True)
2912 self.add_param("ht2min", 0.0, cut=True)
2913 self.add_param("ht3min", 0.0, cut=True)
2914 self.add_param("ht4min", 0.0, cut=True)
2915 self.add_param("ht2max", -1.0, cut=True)
2916 self.add_param("ht3max", -1.0, cut=True)
2917 self.add_param("ht4max", -1.0, cut=True)
2918
2919 self.add_param("ptgmin", 0.0, cut=True)
2920 self.add_param("r0gamma", 0.4)
2921 self.add_param("xn", 1.0)
2922 self.add_param("epsgamma", 1.0)
2923 self.add_param("isoem", True)
2924 self.add_param("xetamin", 0.0, cut=True)
2925 self.add_param("deltaeta", 0.0, cut=True)
2926 self.add_param("ktdurham", -1.0, fortran_name="kt_durham", cut=True)
2927 self.add_param("dparameter", 0.4, fortran_name="d_parameter", cut=True)
2928 self.add_param("ptlund", -1.0, fortran_name="pt_lund", cut=True)
2929 self.add_param("pdgs_for_merging_cut", [21, 1, 2, 3, 4, 5, 6])
2930 self.add_param("maxjetflavor", 4)
2931 self.add_param("xqcut", 0.0, cut=True)
2932 self.add_param("use_syst", True)
2933 self.add_param('systematics_program', 'systematics', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics, syscalc')
2934 self.add_param('systematics_arguments', ['--mur=0.5,1,2', '--muf=0.5,1,2', '--pdf=errorset'], include=False, hidden=True, comment='Choose the argment to pass to the systematics command. like --mur=0.25,1,4. Look at the help of the systematics function for more details.')
2935
2936 self.add_param("sys_scalefact", "0.5 1 2", include=False, hidden=True)
2937 self.add_param("sys_alpsfact", "None", include=False, hidden=True)
2938 self.add_param("sys_matchscale", "auto", include=False, hidden=True)
2939 self.add_param("sys_pdf", "errorset", include=False, hidden=True)
2940 self.add_param("sys_scalecorrelation", -1, include=False, hidden=True)
2941
2942
2943 self.add_param('gridrun', False, hidden=True)
2944 self.add_param('fixed_couplings', True, hidden=True)
2945 self.add_param('mc_grouped_subproc', True, hidden=True)
2946 self.add_param('xmtcentral', 0.0, hidden=True, fortran_name="xmtc")
2947 self.add_param('d', 1.0, hidden=True)
2948 self.add_param('gseed', 0, hidden=True, include=False)
2949 self.add_param('issgridfile', '', hidden=True)
2950
2951 self.add_param('job_strategy', 0, hidden=True, include=False, allowed=[0,1,2], comment='see appendix of 1507.00020 (page 26)')
2952 self.add_param('survey_splitting', -1, hidden=True, include=False, comment="for loop-induced control how many core are used at survey for the computation of a single iteration.")
2953 self.add_param('survey_nchannel_per_job', 2, hidden=True, include=False, comment="control how many Channel are integrated inside a single job on cluster/multicore")
2954 self.add_param('refine_evt_by_job', -1, hidden=True, include=False, comment="control the maximal number of events for the first iteration of the refine (larger means less jobs)")
2955 self.add_param('small_width_treatment', 1e-6, hidden=True, comment="generation where the width is below VALUE times mass will be replace by VALUE times mass for the computation. The cross-section will be corrected assuming NWA. Not used for loop-induced process")
2956
2957
2958
2959 self.add_param('pt_min_pdg',{'__type__':0.}, include=False)
2960 self.add_param('pt_max_pdg',{'__type__':0.}, include=False)
2961 self.add_param('E_min_pdg',{'__type__':0.}, include=False)
2962 self.add_param('E_max_pdg',{'__type__':0.}, include=False)
2963 self.add_param('eta_min_pdg',{'__type__':0.}, include=False)
2964 self.add_param('eta_max_pdg',{'__type__':0.}, include=False)
2965 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
2966 self.add_param('mxx_only_part_antipart', {'default':False}, include=False)
2967
2968 self.add_param('pdg_cut',[0], system=True)
2969 self.add_param('ptmin4pdg',[0.], system=True)
2970 self.add_param('ptmax4pdg',[-1.], system=True)
2971 self.add_param('Emin4pdg',[0.], system=True)
2972 self.add_param('Emax4pdg',[-1.], system=True)
2973 self.add_param('etamin4pdg',[0.], system=True)
2974 self.add_param('etamax4pdg',[-1.], system=True)
2975 self.add_param('mxxmin4pdg',[-1.], system=True)
2976 self.add_param('mxxpart_antipart', [False], system=True)
2977
2978
2980 """ """
2981
2982 super(RunCardLO, self).check_validity()
2983
2984
2985
2986
2987 if 'nhel' not in self.user_set:
2988 raise InvalidRunCard, "Parameter nhel is not defined in the run_card."
2989 if self['nhel'] not in [1,0]:
2990 raise InvalidRunCard, "Parameter nhel can only be '0' or '1', "+\
2991 "not %s." % self['nhel']
2992 if int(self['maxjetflavor']) > 6:
2993 raise InvalidRunCard, 'maxjetflavor should be lower than 5! (6 is partly supported)'
2994
2995 if len(self['pdgs_for_merging_cut']) > 1000:
2996 raise InvalidRunCard, "The number of elements in "+\
2997 "'pdgs_for_merging_cut' should not exceed 1000."
2998
2999
3000 if self['ptgmin'] > 0:
3001 if self['pta'] > 0:
3002 logger.warning('pta cut discarded since photon isolation is used')
3003 self['pta'] = 0.0
3004 if self['draj'] > 0:
3005 logger.warning('draj cut discarded since photon isolation is used')
3006 self['draj'] = 0.0
3007
3008
3009 if self['gridrun']:
3010 self['iseed'] = self['gseed']
3011
3012
3013 if self['use_syst']:
3014 if self['scalefact'] != 1.0:
3015 logger.warning('Since use_syst=T, We change the value of \'scalefact\' to 1')
3016 self['scalefact'] = 1.0
3017
3018
3019 if self['ickkw'] > 0:
3020 if self['ickkw'] != 1:
3021 logger.critical('ickkw >1 is pure alpha and only partly implemented.')
3022 import madgraph.interface.extended_cmd as basic_cmd
3023 answer = basic_cmd.smart_input('Do you really want to continue', allow_arg=['y','n'], default='n')
3024 if answer !='y':
3025 raise InvalidRunCard, 'ickkw>1 is still in alpha'
3026 if self['use_syst']:
3027
3028 if self['alpsfact'] != 1.0:
3029 logger.warning('Since use_syst=T, We change the value of \'alpsfact\' to 1')
3030 self['alpsfact'] =1.0
3031 if self['maxjetflavor'] == 6:
3032 raise InvalidRunCard, 'maxjetflavor at 6 is NOT supported for matching!'
3033 if self['ickkw'] == 2:
3034
3035 self.get_default('highestmult', log_level=20)
3036 self.get_default('issgridfile', 'issudgrid.dat', log_level=20)
3037 if self['xqcut'] > 0:
3038 if self['ickkw'] == 0:
3039 logger.error('xqcut>0 but ickkw=0. Potentially not fully consistent setup. Be carefull')
3040 import time
3041 time.sleep(5)
3042 if self['drjj'] != 0:
3043 logger.warning('Since icckw>0, We change the value of \'drjj\' to 0')
3044 self['drjj'] = 0
3045 if self['drjl'] != 0:
3046 logger.warning('Since icckw>0, We change the value of \'drjl\' to 0')
3047 self['drjl'] = 0
3048 if not self['auto_ptj_mjj']:
3049 if self['mmjj'] > self['xqcut']:
3050 logger.warning('mmjj > xqcut (and auto_ptj_mjj = F). MMJJ set to 0')
3051 self['mmjj'] = 0.0
3052
3053
3054
3055
3056 if self['pdlabel'] == 'lhapdf':
3057
3058 self.get_default('lhaid', log_level=20)
3059
3061
3062
3063 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys() +
3064 self['e_min_pdg'].keys() +self['e_max_pdg'].keys() +
3065 self['eta_min_pdg'].keys() +self['eta_max_pdg'].keys()+
3066 self['mxx_min_pdg'].keys() + self['mxx_only_part_antipart'].keys())
3067 pdg_to_cut.discard('__type__')
3068 pdg_to_cut.discard('default')
3069 if len(pdg_to_cut)>25:
3070 raise Exception, "Maximum 25 different pdgs are allowed for pdg specific cut"
3071
3072 if any(int(pdg)<0 for pdg in pdg_to_cut):
3073 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes')
3074 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative pdg code'
3075
3076
3077 if any(pdg in pdg_to_cut for pdg in [1,2,3,4,5,21,22,11,13,15]):
3078 raise Exception, "Can not use PDG related cut for light quark/b quark/lepton/gluon/photon"
3079
3080 if pdg_to_cut:
3081 self['pdg_cut'] = list(pdg_to_cut)
3082 self['ptmin4pdg'] = []
3083 self['Emin4pdg'] = []
3084 self['etamin4pdg'] =[]
3085 self['ptmax4pdg'] = []
3086 self['Emax4pdg'] = []
3087 self['etamax4pdg'] =[]
3088 self['mxxmin4pdg'] =[]
3089 self['mxxpart_antipart'] = []
3090 for pdg in self['pdg_cut']:
3091 for var in ['pt','e','eta', 'Mxx']:
3092 for minmax in ['min', 'max']:
3093 if var in ['Mxx'] and minmax =='max':
3094 continue
3095 new_var = '%s%s4pdg' % (var, minmax)
3096 old_var = '%s_%s_pdg' % (var, minmax)
3097 default = 0. if minmax=='min' else -1.
3098 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3099
3100 old_var = 'mxx_only_part_antipart'
3101 new_var = 'mxxpart_antipart'
3102 if 'default' in self[old_var]:
3103 default = self[old_var]['default']
3104 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3105 else:
3106 if str(pdg) not in self[old_var]:
3107 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg))
3108 self[new_var].append(self[old_var][str(pdg)])
3109 else:
3110 self['pdg_cut'] = [0]
3111 self['ptmin4pdg'] = [0.]
3112 self['Emin4pdg'] = [0.]
3113 self['etamin4pdg'] =[0.]
3114 self['ptmax4pdg'] = [-1.]
3115 self['Emax4pdg'] = [-1.]
3116 self['etamax4pdg'] =[-1.]
3117 self['mxxmin4pdg'] =[0.]
3118 self['mxxpart_antipart'] = [False]
3119
3120
3121
3123 """Rules
3124 process 1->N all cut set on off.
3125 loop_induced -> MC over helicity
3126 e+ e- beam -> lpp:0 ebeam:500
3127 p p beam -> set maxjetflavor automatically
3128 more than one multiplicity: ickkw=1 xqcut=30 use_syst=F
3129 """
3130
3131 if proc_characteristic['loop_induced']:
3132 self['nhel'] = 1
3133 self['pdgs_for_merging_cut'] = proc_characteristic['colored_pdgs']
3134
3135 if proc_characteristic['ninitial'] == 1:
3136
3137 self.remove_all_cut()
3138 self['use_syst'] = False
3139 else:
3140
3141 beam_id = set()
3142 for proc in proc_def:
3143 for oneproc in proc:
3144 for leg in oneproc['legs']:
3145 if not leg['state']:
3146 beam_id.add(leg['id'])
3147 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]):
3148 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7])
3149 self['maxjetflavor'] = maxjetflavor
3150 self['asrwgtflavor'] = maxjetflavor
3151 pass
3152 elif 11 in beam_id or -11 in beam_id:
3153 self['lpp1'] = 0
3154 self['lpp2'] = 0
3155 self['ebeam1'] = 500
3156 self['ebeam2'] = 500
3157 self['use_syst'] = False
3158 else:
3159 self['lpp1'] = 0
3160 self['lpp2'] = 0
3161 self['use_syst'] = False
3162
3163
3164 min_particle = 99
3165 max_particle = 0
3166 for proc in proc_def:
3167 min_particle = min(len(proc[0]['legs']), min_particle)
3168 max_particle = max(len(proc[0]['legs']), max_particle)
3169 if min_particle != max_particle:
3170
3171 for procmin in proc_def:
3172 if len(procmin[0]['legs']) != min_particle:
3173 continue
3174 else:
3175 idsmin = [l['id'] for l in procmin[0]['legs']]
3176 break
3177 matching = False
3178 for procmax in proc_def:
3179 if len(procmax[0]['legs']) != max_particle:
3180 continue
3181 idsmax = [l['id'] for l in procmax[0]['legs']]
3182 for i in idsmin:
3183 if i not in idsmax:
3184 continue
3185 else:
3186 idsmax.remove(i)
3187 for j in idsmax:
3188 if j not in [1,-1,2,-2,3,-3,4,-4,5,-5,21]:
3189 break
3190 else:
3191
3192 matching=True
3193 break
3194
3195 if matching:
3196 self['ickkw'] = 1
3197 self['xqcut'] = 30
3198
3199 self['drjj'] = 0
3200 self['drjl'] = 0
3201 self['sys_alpsfact'] = "0.5 1 2"
3202
3203
3204
3205 no_systematics = False
3206 for proc in proc_def:
3207 for oneproc in proc:
3208 if '^2' in oneproc.nice_string():
3209 no_systematics = True
3210 break
3211 else:
3212 continue
3213 break
3214 if no_systematics:
3215 self['use_syst'] = False
3216 self['systematics_program'] = 'none'
3217
3218 - def write(self, output_file, template=None, python_template=False,
3219 **opt):
3220 """Write the run_card in output_file according to template
3221 (a path to a valid run_card)"""
3222
3223 if not template:
3224 if not MADEVENT:
3225 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards',
3226 'run_card.dat')
3227 python_template = True
3228 else:
3229 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat')
3230 python_template = False
3231
3232 super(RunCardLO, self).write(output_file, template=template,
3233 python_template=python_template, **opt)
3234
3238
3240 """ A class to store a MadAnalysis5 card. Very basic since it is basically
3241 free format."""
3242
3243 _MG5aMC_escape_tag = '@MG5aMC'
3244
3245 _default_hadron_inputs = ['*.hepmc', '*.hep', '*.stdhep', '*.lhco','*.root']
3246 _default_parton_inputs = ['*.lhe']
3247 _skip_analysis = False
3248
3249 @classmethod
3251 """ Checks from the type of an event file whether it can be reconstructed or not."""
3252 return not (file_path.endswith('.lhco') or file_path.endswith('.lhco.gz') or \
3253 file_path.endswith('.root') or file_path.endswith('.root.gz'))
3254
3255 @classmethod
3257 """ A method returning the structure of an empty analysis """
3258 return {'commands':[],
3259 'reconstructions':[]}
3260
3261 @classmethod
3263 """ A method returning the structure of an empty reconstruction """
3264 return {'commands':[],
3265 'reco_output':'lhe'}
3266
3268 """define the default value"""
3269 self['mode'] = 'parton'
3270 self['inputs'] = []
3271
3272 self['stdout_lvl'] = None
3273
3274
3275
3276
3277
3278
3279
3280 self['analyses'] = {}
3281
3282
3283 self['recasting'] = {'commands':[],'card':[]}
3284
3285
3286 self['reconstruction'] = {'lhco_input':
3287 MadAnalysis5Card.empty_reconstruction(),
3288 'root_input':
3289 MadAnalysis5Card.empty_reconstruction()}
3290 self['reconstruction']['lhco_input']['reco_output']='lhco'
3291 self['reconstruction']['root_input']['reco_output']='root'
3292
3293
3294 self['order'] = []
3295
3296 - def __init__(self, finput=None,mode=None):
3297 if isinstance(finput, self.__class__):
3298 dict.__init__(self, finput)
3299 assert finput.__dict__.keys()
3300 for key in finput.__dict__:
3301 setattr(self, key, copy.copy(getattr(finput, key)) )
3302 return
3303 else:
3304 dict.__init__(self)
3305
3306
3307 self.default_setup()
3308 if not mode is None:
3309 self['mode']=mode
3310
3311
3312 if isinstance(finput, (file, str, StringIO.StringIO)):
3313 self.read(finput, mode=mode)
3314
3315 - def read(self, input, mode=None):
3316 """ Read an MA5 card"""
3317
3318 if mode not in [None,'parton','hadron']:
3319 raise MadGraph5Error('A MadAnalysis5Card can be read online the modes'+
3320 "'parton' or 'hadron'")
3321 card_mode = mode
3322
3323 if isinstance(input, (file, StringIO.StringIO)):
3324 input_stream = input
3325 elif isinstance(input, str):
3326 if not os.path.isfile(input):
3327 raise InvalidMadAnalysis5Card("Cannot read the MadAnalysis5 card."+\
3328 "File '%s' not found."%input)
3329 if mode is None and 'hadron' in input:
3330 card_mode = 'hadron'
3331 input_stream = open(input,'r')
3332 else:
3333 raise MadGraph5Error('Incorrect input for the read function of'+\
3334 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(input)))
3335
3336
3337 self.__init__()
3338 current_name = 'default'
3339 current_type = 'analyses'
3340 for line in input_stream:
3341
3342 if line.startswith('#'):
3343 continue
3344 if line.endswith('\n'):
3345 line = line[:-1]
3346 if line.strip()=='':
3347 continue
3348 if line.startswith(self._MG5aMC_escape_tag):
3349 try:
3350 option,value = line[len(self._MG5aMC_escape_tag):].split('=')
3351 value = value.strip()
3352 except ValueError:
3353 option = line[len(self._MG5aMC_escape_tag):]
3354 option = option.strip()
3355
3356 if option=='inputs':
3357 self['inputs'].extend([v.strip() for v in value.split(',')])
3358
3359 elif option == 'skip_analysis':
3360 self._skip_analysis = True
3361
3362 elif option=='stdout_lvl':
3363 try:
3364 self['stdout_lvl']=int(value)
3365 except ValueError:
3366 try:
3367 self['stdout_lvl']=eval(value)
3368 except:
3369 try:
3370 self['stdout_lvl']=eval('logging.%s'%value)
3371 except:
3372 raise InvalidMadAnalysis5Card(
3373 "MA5 output level specification '%s' is incorrect."%str(value))
3374
3375 elif option=='analysis_name':
3376 current_type = 'analyses'
3377 current_name = value
3378 if current_name in self[current_type]:
3379 raise InvalidMadAnalysis5Card(
3380 "Analysis '%s' already defined in MadAnalysis5 card"%current_name)
3381 else:
3382 self[current_type][current_name] = MadAnalysis5Card.empty_analysis()
3383
3384 elif option=='set_reconstructions':
3385 try:
3386 reconstructions = eval(value)
3387 if not isinstance(reconstructions, list):
3388 raise
3389 except:
3390 raise InvalidMadAnalysis5Card("List of reconstructions"+\
3391 " '%s' could not be parsed in MadAnalysis5 card."%value)
3392 if current_type!='analyses' and current_name not in self[current_type]:
3393 raise InvalidMadAnalysis5Card("A list of reconstructions"+\
3394 "can only be defined in the context of an "+\
3395 "analysis in a MadAnalysis5 card.")
3396 self[current_type][current_name]['reconstructions']=reconstructions
3397 continue
3398
3399 elif option=='reconstruction_name':
3400 current_type = 'reconstruction'
3401 current_name = value
3402 if current_name in self[current_type]:
3403 raise InvalidMadAnalysis5Card(
3404 "Reconstruction '%s' already defined in MadAnalysis5 hadron card"%current_name)
3405 else:
3406 self[current_type][current_name] = MadAnalysis5Card.empty_reconstruction()
3407
3408 elif option=='reco_output':
3409 if current_type!='reconstruction' or current_name not in \
3410 self['reconstruction']:
3411 raise InvalidMadAnalysis5Card(
3412 "Option '%s' is only available within the definition of a reconstruction"%option)
3413 if not value.lower() in ['lhe','root']:
3414 raise InvalidMadAnalysis5Card(
3415 "Option '%s' can only take the values 'lhe' or 'root'"%option)
3416 self['reconstruction'][current_name]['reco_output'] = value.lower()
3417
3418 elif option.startswith('recasting'):
3419 current_type = 'recasting'
3420 try:
3421 current_name = option.split('_')[1]
3422 except:
3423 raise InvalidMadAnalysis5Card('Malformed MA5 recasting option %s.'%option)
3424 if len(self['recasting'][current_name])>0:
3425 raise InvalidMadAnalysis5Card(
3426 "Only one recasting can be defined in MadAnalysis5 hadron card")
3427
3428 else:
3429 raise InvalidMadAnalysis5Card(
3430 "Unreckognized MG5aMC instruction in MadAnalysis5 card: '%s'"%option)
3431
3432 if option in ['analysis_name','reconstruction_name'] or \
3433 option.startswith('recasting'):
3434 self['order'].append((current_type,current_name))
3435 continue
3436
3437
3438
3439 if current_name == 'default' and current_type == 'analyses' and\
3440 'default' not in self['analyses']:
3441 self['analyses']['default'] = MadAnalysis5Card.empty_analysis()
3442 self['order'].append(('analyses','default'))
3443
3444 if current_type in ['recasting']:
3445 self[current_type][current_name].append(line)
3446 elif current_type in ['reconstruction']:
3447 self[current_type][current_name]['commands'].append(line)
3448 elif current_type in ['analyses']:
3449 self[current_type][current_name]['commands'].append(line)
3450
3451 if 'reconstruction' in self['analyses'] or len(self['recasting']['card'])>0:
3452 if mode=='parton':
3453 raise InvalidMadAnalysis5Card(
3454 "A parton MadAnalysis5 card cannot specify a recombination or recasting.")
3455 card_mode = 'hadron'
3456 elif mode is None:
3457 card_mode = 'parton'
3458
3459 self['mode'] = card_mode
3460 if self['inputs'] == []:
3461 if self['mode']=='hadron':
3462 self['inputs'] = self._default_hadron_inputs
3463 else:
3464 self['inputs'] = self._default_parton_inputs
3465
3466
3467
3468 if self['mode']=='hadron':
3469 for analysis_name, analysis in self['analyses'].items():
3470 if len(analysis['reconstructions'])==0:
3471 raise InvalidMadAnalysis5Card('Hadron-level analysis '+\
3472 "'%s' is not specified any reconstruction(s)."%analysis_name)
3473 if any(reco not in self['reconstruction'] for reco in \
3474 analysis['reconstructions']):
3475 raise InvalidMadAnalysis5Card('A reconstructions specified in'+\
3476 " analysis '%s' is not defined."%analysis_name)
3477
3478 - def write(self, output):
3479 """ Write an MA5 card."""
3480
3481 if isinstance(output, (file, StringIO.StringIO)):
3482 output_stream = output
3483 elif isinstance(output, str):
3484 output_stream = open(output,'w')
3485 else:
3486 raise MadGraph5Error('Incorrect input for the write function of'+\
3487 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(output)))
3488
3489 output_lines = []
3490 if self._skip_analysis:
3491 output_lines.append('%s skip_analysis'%self._MG5aMC_escape_tag)
3492 output_lines.append('%s inputs = %s'%(self._MG5aMC_escape_tag,','.join(self['inputs'])))
3493 if not self['stdout_lvl'] is None:
3494 output_lines.append('%s stdout_lvl=%s'%(self._MG5aMC_escape_tag,self['stdout_lvl']))
3495 for definition_type, name in self['order']:
3496
3497 if definition_type=='analyses':
3498 output_lines.append('%s analysis_name = %s'%(self._MG5aMC_escape_tag,name))
3499 output_lines.append('%s set_reconstructions = %s'%(self._MG5aMC_escape_tag,
3500 str(self['analyses'][name]['reconstructions'])))
3501 elif definition_type=='reconstruction':
3502 output_lines.append('%s reconstruction_name = %s'%(self._MG5aMC_escape_tag,name))
3503 elif definition_type=='recasting':
3504 output_lines.append('%s recasting_%s'%(self._MG5aMC_escape_tag,name))
3505
3506 if definition_type in ['recasting']:
3507 output_lines.extend(self[definition_type][name])
3508 elif definition_type in ['reconstruction']:
3509 output_lines.append('%s reco_output = %s'%(self._MG5aMC_escape_tag,
3510 self[definition_type][name]['reco_output']))
3511 output_lines.extend(self[definition_type][name]['commands'])
3512 elif definition_type in ['analyses']:
3513 output_lines.extend(self[definition_type][name]['commands'])
3514
3515 output_stream.write('\n'.join(output_lines))
3516
3517 return
3518
3519 - def get_MA5_cmds(self, inputs_arg, submit_folder, run_dir_path=None,
3520 UFO_model_path=None, run_tag=''):
3521 """ Returns a list of tuples ('AnalysisTag',['commands']) specifying
3522 the commands of the MadAnalysis runs required from this card.
3523 At parton-level, the number of such commands is the number of analysis
3524 asked for. In the future, the idea is that the entire card can be
3525 processed in one go from MA5 directly."""
3526
3527 if isinstance(inputs_arg, list):
3528 inputs = inputs_arg
3529 elif isinstance(inputs_arg, str):
3530 inputs = [inputs_arg]
3531 else:
3532 raise MadGraph5Error("The function 'get_MA5_cmds' can only take "+\
3533 " a string or a list for the argument 'inputs_arg'")
3534
3535 if len(inputs)==0:
3536 raise MadGraph5Error("The function 'get_MA5_cmds' must have "+\
3537 " at least one input specified'")
3538
3539 if run_dir_path is None:
3540 run_dir_path = os.path.dirname(inputs_arg)
3541
3542 cmds_list = []
3543
3544 UFO_load = []
3545
3546 if UFO_model_path:
3547 UFO_load.append('import %s'%UFO_model_path)
3548
3549 def get_import(input, type=None):
3550 """ Generates the MA5 import commands for that event file. """
3551 dataset_name = os.path.basename(input).split('.')[0]
3552 res = ['import %s as %s'%(input, dataset_name)]
3553 if not type is None:
3554 res.append('set %s.type = %s'%(dataset_name, type))
3555 return res
3556
3557 fifo_status = {'warned_fifo':False,'fifo_used_up':False}
3558 def warn_fifo(input):
3559 if not input.endswith('.fifo'):
3560 return False
3561 if not fifo_status['fifo_used_up']:
3562 fifo_status['fifo_used_up'] = True
3563 return False
3564 else:
3565 if not fifo_status['warned_fifo']:
3566 logger.warning('Only the first MA5 analysis/reconstructions can be run on a fifo. Subsequent runs will skip fifo inputs.')
3567 fifo_status['warned_fifo'] = True
3568 return True
3569
3570
3571 inputs_load = []
3572 for input in inputs:
3573 inputs_load.extend(get_import(input))
3574
3575 submit_command = 'submit %s'%submit_folder+'_%s'
3576
3577
3578
3579
3580 reconstruction_outputs = {
3581 'lhco_input':[f for f in inputs if
3582 f.endswith('.lhco') or f.endswith('.lhco.gz')],
3583 'root_input':[f for f in inputs if
3584 f.endswith('.root') or f.endswith('.root.gz')]}
3585
3586
3587 recasting_card_path = pjoin(run_dir_path,
3588 '_'.join([run_tag,os.path.basename(submit_folder),'recasting_card.dat']))
3589
3590
3591 for definition_type, name in self['order']:
3592 if definition_type == 'reconstruction':
3593 analysis_cmds = list(self['reconstruction'][name]['commands'])
3594 reco_outputs = []
3595 for i_input, input in enumerate(inputs):
3596
3597 if not MadAnalysis5Card.events_can_be_reconstructed(input):
3598 continue
3599
3600 if warn_fifo(input):
3601 continue
3602 analysis_cmds.append('import %s as reco_events'%input)
3603 if self['reconstruction'][name]['reco_output']=='lhe':
3604 reco_outputs.append('%s_%s.lhe.gz'%(os.path.basename(
3605 input).replace('_events','').split('.')[0],name))
3606 analysis_cmds.append('set main.outputfile=%s'%reco_outputs[-1])
3607 elif self['reconstruction'][name]['reco_output']=='root':
3608 reco_outputs.append('%s_%s.root'%(os.path.basename(
3609 input).replace('_events','').split('.')[0],name))
3610 analysis_cmds.append('set main.fastsim.rootfile=%s'%reco_outputs[-1])
3611 analysis_cmds.append(
3612 submit_command%('reco_%s_%d'%(name,i_input+1)))
3613 analysis_cmds.append('remove reco_events')
3614
3615 reconstruction_outputs[name]= [pjoin(run_dir_path,rec_out)
3616 for rec_out in reco_outputs]
3617 if len(reco_outputs)>0:
3618 cmds_list.append(('_reco_%s'%name,analysis_cmds))
3619
3620 elif definition_type == 'analyses':
3621 if self['mode']=='parton':
3622 cmds_list.append( (name, UFO_load+inputs_load+
3623 self['analyses'][name]['commands']+[submit_command%name]) )
3624 elif self['mode']=='hadron':
3625
3626 for reco in self['analyses'][name]['reconstructions']+\
3627 ['lhco_input','root_input']:
3628 if len(reconstruction_outputs[reco])==0:
3629 continue
3630 if self['reconstruction'][reco]['reco_output']=='lhe':
3631
3632 analysis_cmds = ['set main.mode = parton']
3633 else:
3634 analysis_cmds = []
3635 analysis_cmds.extend(sum([get_import(rec_out) for
3636 rec_out in reconstruction_outputs[reco]],[]))
3637 analysis_cmds.extend(self['analyses'][name]['commands'])
3638 analysis_cmds.append(submit_command%('%s_%s'%(name,reco)))
3639 cmds_list.append( ('%s_%s'%(name,reco),analysis_cmds) )
3640
3641 elif definition_type == 'recasting':
3642 if len(self['recasting']['card'])==0:
3643 continue
3644 if name == 'card':
3645
3646 open(recasting_card_path,'w').write('\n'.join(self['recasting']['card']))
3647 if name == 'commands':
3648 recasting_cmds = list(self['recasting']['commands'])
3649
3650 n_inputs = 0
3651 for input in inputs:
3652 if not MadAnalysis5Card.events_can_be_reconstructed(input):
3653 continue
3654
3655 if warn_fifo(input):
3656 continue
3657 recasting_cmds.extend(get_import(input,'signal'))
3658 n_inputs += 1
3659
3660 recasting_cmds.append('set main.recast.card_path=%s'%recasting_card_path)
3661 recasting_cmds.append(submit_command%'Recasting')
3662 if n_inputs>0:
3663 cmds_list.append( ('Recasting',recasting_cmds))
3664
3665 return cmds_list
3666
3668 """A class object for the run_card for a (aMC@)NLO pocess"""
3669
3671 """define the default value"""
3672
3673 self.add_param('run_tag', 'tag_1', include=False)
3674 self.add_param('nevents', 10000)
3675 self.add_param('req_acc', -1.0, include=False)
3676 self.add_param('nevt_job', -1, include=False)
3677 self.add_param('event_norm', 'average')
3678
3679 self.add_param('req_acc_fo', 0.01, include=False)
3680 self.add_param('npoints_fo_grid', 5000, include=False)
3681 self.add_param('niters_fo_grid', 4, include=False)
3682 self.add_param('npoints_fo', 10000, include=False)
3683 self.add_param('niters_fo', 6, include=False)
3684
3685 self.add_param('iseed', 0)
3686 self.add_param('lpp1', 1, fortran_name='lpp(1)')
3687 self.add_param('lpp2', 1, fortran_name='lpp(2)')
3688 self.add_param('ebeam1', 6500.0, fortran_name='ebeam(1)')
3689 self.add_param('ebeam2', 6500.0, fortran_name='ebeam(2)')
3690 self.add_param('pdlabel', 'nn23nlo', allowed=['lhapdf', 'cteq6_m','cteq6_d','cteq6_l','cteq6l1', 'nn23lo','nn23lo1','nn23nlo'])
3691 self.add_param('lhaid', [244600],fortran_name='lhaPDFid')
3692 self.add_param('lhapdfsetname', ['internal_use_only'], system=True)
3693
3694 self.add_param('parton_shower', 'HERWIG6', fortran_name='shower_mc')
3695 self.add_param('shower_scale_factor',1.0)
3696 self.add_param('fixed_ren_scale', False)
3697 self.add_param('fixed_fac_scale', False)
3698 self.add_param('mur_ref_fixed', 91.118)
3699 self.add_param('muf1_ref_fixed', -1.0, hidden=True)
3700 self.add_param('muf_ref_fixed', 91.118)
3701 self.add_param('muf2_ref_fixed', -1.0, hidden=True)
3702 self.add_param("dynamical_scale_choice", [-1],fortran_name='dyn_scale', comment="\'-1\' is based on CKKW back clustering (following feynman diagram).\n \'1\' is the sum of transverse energy.\n '2' is HT (sum of the transverse mass)\n '3' is HT/2")
3703 self.add_param('fixed_qes_scale', False, hidden=True)
3704 self.add_param('qes_ref_fixed', -1.0, hidden=True)
3705 self.add_param('mur_over_ref', 1.0)
3706 self.add_param('muf_over_ref', 1.0)
3707 self.add_param('muf1_over_ref', -1.0, hidden=True)
3708 self.add_param('muf2_over_ref', -1.0, hidden=True)
3709 self.add_param('qes_over_ref', -1.0, hidden=True)
3710 self.add_param('reweight_scale', [True], fortran_name='lscalevar')
3711 self.add_param('rw_rscale_down', -1.0, hidden=True)
3712 self.add_param('rw_rscale_up', -1.0, hidden=True)
3713 self.add_param('rw_fscale_down', -1.0, hidden=True)
3714 self.add_param('rw_fscale_up', -1.0, hidden=True)
3715 self.add_param('rw_rscale', [1.0,2.0,0.5], fortran_name='scalevarR')
3716 self.add_param('rw_fscale', [1.0,2.0,0.5], fortran_name='scalevarF')
3717 self.add_param('reweight_pdf', [False], fortran_name='lpdfvar')
3718 self.add_param('pdf_set_min', 244601, hidden=True)
3719 self.add_param('pdf_set_max', 244700, hidden=True)
3720 self.add_param('store_rwgt_info', False)
3721 self.add_param('systematics_program', 'none', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics')
3722 self.add_param('systematics_arguments', [''], include=False, hidden=True, comment='Choose the argment to pass to the systematics command. like --mur=0.25,1,4. Look at the help of the systematics function for more details.')
3723
3724
3725 self.add_param('ickkw', 0)
3726 self.add_param('bwcutoff', 15.0)
3727
3728 self.add_param('jetalgo', 1.0)
3729 self.add_param('jetradius', 0.7)
3730 self.add_param('ptj', 10.0 , cut=True)
3731 self.add_param('etaj', -1.0, cut=True)
3732 self.add_param('ptl', 0.0, cut=True)
3733 self.add_param('etal', -1.0, cut=True)
3734 self.add_param('drll', 0.0, cut=True)
3735 self.add_param('drll_sf', 0.0, cut=True)
3736 self.add_param('mll', 0.0, cut=True)
3737 self.add_param('mll_sf', 30.0, cut=True)
3738 self.add_param('ptgmin', 20.0, cut=True)
3739 self.add_param('etagamma', -1.0)
3740 self.add_param('r0gamma', 0.4)
3741 self.add_param('xn', 1.0)
3742 self.add_param('epsgamma', 1.0)
3743 self.add_param('isoem', True)
3744 self.add_param('maxjetflavor', 4, hidden=True)
3745 self.add_param('iappl', 0)
3746 self.add_param('lhe_version', 3, hidden=True, include=False)
3747
3748
3749 self.add_param('FO_LHE_weight_ratio',1e-3, hidden=True, system=True)
3750 self.add_param('FO_LHE_postprocessing',['grouping','random'],
3751 hidden=True, system=True, include=False)
3752
3753
3754 self.add_param('pt_min_pdg',{'__type__':0.}, include=False)
3755 self.add_param('pt_max_pdg',{'__type__':0.}, include=False)
3756 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
3757 self.add_param('mxx_only_part_antipart', {'default':False}, include=False, hidden=True)
3758
3759
3760 self.add_param('pdg_cut',[0], hidden=True, system=True)
3761 self.add_param('ptmin4pdg',[0.], hidden=True, system=True)
3762 self.add_param('ptmax4pdg',[-1.], hidden=True, system=True)
3763 self.add_param('mxxmin4pdg',[0.], hidden=True, system=True)
3764 self.add_param('mxxpart_antipart', [False], hidden=True, system=True)
3765
3767 """check the validity of the various input"""
3768
3769 super(RunCardNLO, self).check_validity()
3770
3771
3772 if self['lpp1']==0 and self['lpp2']==0:
3773 if self['pdlabel']!='nn23nlo' or self['reweight_pdf']:
3774 self['pdlabel']='nn23nlo'
3775 self['reweight_pdf']=[False]
3776 logger.info('''Lepton-lepton collisions: ignoring PDF related parameters in the run_card.dat (pdlabel, lhaid, reweight_pdf, ...)''')
3777
3778
3779 if self['ickkw'] == 3:
3780
3781 scales=['fixed_ren_scale','fixed_fac_scale','fixed_QES_scale']
3782 for scale in scales:
3783 if self[scale]:
3784 logger.warning('''For consistency in the FxFx merging, \'%s\' has been set to false'''
3785 % scale,'$MG:BOLD')
3786 self[scale]= False
3787
3788 if len(self["dynamical_scale_choice"]) > 1 or self["dynamical_scale_choice"][0] != -1:
3789 self["dynamical_scale_choice"] = [-1]
3790 self["reweight_scale"]=[self["reweight_scale"][0]]
3791 logger.warning('''For consistency in the FxFx merging, dynamical_scale_choice has been set to -1 (default)'''
3792 ,'$MG:BOLD')
3793
3794
3795 jetparams=['jetradius','jetalgo']
3796 for jetparam in jetparams:
3797 if float(self[jetparam]) != 1.0:
3798 logger.info('''For consistency in the FxFx merging, \'%s\' has been set to 1.0'''
3799 % jetparam ,'$MG:BOLD')
3800 self[jetparam] = 1.0
3801 elif self['ickkw'] == -1 and (self["dynamical_scale_choice"][0] != -1 or
3802 len(self["dynamical_scale_choice"]) > 1):
3803 self["dynamical_scale_choice"] = [-1]
3804 self["reweight_scale"]=[self["reweight_scale"][0]]
3805 logger.warning('''For consistency with the jet veto, the scale which will be used is ptj. dynamical_scale_choice will be set at -1.'''
3806 ,'$MG:BOLD')
3807
3808
3809 if self['iappl'] != 0 and self['pdlabel'].lower() != 'lhapdf':
3810 raise InvalidRunCard('APPLgrid generation only possible with the use of LHAPDF')
3811 if self['iappl'] != 0 and not self['reweight_scale']:
3812 raise InvalidRunCard('APPLgrid generation only possible with including' +\
3813 ' the reweighting to get scale dependence')
3814
3815
3816 if self['qes_ref_fixed'] == -1.0:
3817 self['qes_ref_fixed']=self['mur_ref_fixed']
3818 if self['qes_over_ref'] == -1.0:
3819 self['qes_over_ref']=self['mur_over_ref']
3820 if self['muf1_over_ref'] != -1.0 and self['muf1_over_ref'] == self['muf2_over_ref']:
3821 self['muf_over_ref']=self['muf1_over_ref']
3822 if self['muf1_over_ref'] == -1.0:
3823 self['muf1_over_ref']=self['muf_over_ref']
3824 if self['muf2_over_ref'] == -1.0:
3825 self['muf2_over_ref']=self['muf_over_ref']
3826 if self['muf1_ref_fixed'] != -1.0 and self['muf1_ref_fixed'] == self['muf2_ref_fixed']:
3827 self['muf_ref_fixed']=self['muf1_ref_fixed']
3828 if self['muf1_ref_fixed'] == -1.0:
3829 self['muf1_ref_fixed']=self['muf_ref_fixed']
3830 if self['muf2_ref_fixed'] == -1.0:
3831 self['muf2_ref_fixed']=self['muf_ref_fixed']
3832
3833 if (self['rw_rscale_down'] != -1.0 and ['rw_rscale_down'] not in self['rw_rscale']) or\
3834 (self['rw_rscale_up'] != -1.0 and ['rw_rscale_up'] not in self['rw_rscale']):
3835 self['rw_rscale']=[1.0,self['rw_rscale_up'],self['rw_rscale_down']]
3836 if (self['rw_fscale_down'] != -1.0 and ['rw_fscale_down'] not in self['rw_fscale']) or\
3837 (self['rw_fscale_up'] != -1.0 and ['rw_fscale_up'] not in self['rw_fscale']):
3838 self['rw_fscale']=[1.0,self['rw_fscale_up'],self['rw_fscale_down']]
3839
3840
3841 if any(self['reweight_pdf']):
3842
3843 if self['pdlabel'] != "lhapdf":
3844 raise InvalidRunCard, 'Reweight PDF option requires to use pdf sets associated to lhapdf. Please either change the pdlabel to use LHAPDF or set reweight_pdf to False.'
3845
3846
3847 if self['pdlabel'] != "lhapdf":
3848 self['reweight_pdf']=[self['reweight_pdf'][0]]
3849 self['lhaid']=[self['lhaid'][0]]
3850
3851
3852 if self['fixed_ren_scale'] and self['fixed_fac_scale']:
3853 self['reweight_scale']=[self['reweight_scale'][0]]
3854 self['dynamical_scale_choice']=[0]
3855
3856
3857
3858
3859 if len(self['reweight_pdf']) == 1 and len(self['lhaid']) != 1:
3860 self['reweight_pdf']=self['reweight_pdf']*len(self['lhaid'])
3861 logger.warning("Setting 'reweight_pdf' for all 'lhaid' to %s" % self['reweight_pdf'][0])
3862 if len(self['reweight_scale']) == 1 and len(self['dynamical_scale_choice']) != 1:
3863 self['reweight_scale']=self['reweight_scale']*len(self['dynamical_scale_choice'])
3864 logger.warning("Setting 'reweight_scale' for all 'dynamical_scale_choice' to %s" % self['reweight_pdf'][0])
3865
3866
3867 if len(self['lhaid']) != len(set(self['lhaid'])):
3868 raise InvalidRunCard, "'lhaid' has two or more identical entries. They have to be all different for the code to work correctly."
3869 if len(self['dynamical_scale_choice']) != len(set(self['dynamical_scale_choice'])):
3870 raise InvalidRunCard, "'dynamical_scale_choice' has two or more identical entries. They have to be all different for the code to work correctly."
3871
3872
3873 if len(self['reweight_pdf']) != len(self['lhaid']):
3874 raise InvalidRunCard, "'reweight_pdf' and 'lhaid' lists should have the same length"
3875 if len(self['reweight_scale']) != len(self['dynamical_scale_choice']):
3876 raise InvalidRunCard, "'reweight_scale' and 'dynamical_scale_choice' lists should have the same length"
3877 if len(self['dynamical_scale_choice']) > 10 :
3878 raise InvalidRunCard, "Length of list for 'dynamical_scale_choice' too long: max is 10."
3879 if len(self['lhaid']) > 25 :
3880 raise InvalidRunCard, "Length of list for 'lhaid' too long: max is 25."
3881 if len(self['rw_rscale']) > 9 :
3882 raise InvalidRunCard, "Length of list for 'rw_rscale' too long: max is 9."
3883 if len(self['rw_fscale']) > 9 :
3884 raise InvalidRunCard, "Length of list for 'rw_fscale' too long: max is 9."
3885
3886 if 1.0 not in self['rw_rscale']:
3887 logger.warning("'1.0' has to be part of 'rw_rscale', adding it")
3888 self['rw_rscale'].insert(0,1.0)
3889 if 1.0 not in self['rw_fscale']:
3890 logger.warning("'1.0' has to be part of 'rw_fscale', adding it")
3891 self['rw_fscale'].insert(0,1.0)
3892 if self['rw_rscale'][0] != 1.0 and 1.0 in self['rw_rscale']:
3893 a=self['rw_rscale'].index(1.0)
3894 self['rw_rscale'][0],self['rw_rscale'][a]=self['rw_rscale'][a],self['rw_rscale'][0]
3895 if self['rw_fscale'][0] != 1.0 and 1.0 in self['rw_fscale']:
3896 a=self['rw_fscale'].index(1.0)
3897 self['rw_fscale'][0],self['rw_fscale'][a]=self['rw_fscale'][a],self['rw_fscale'][0]
3898
3899 if len(self['rw_rscale']) != len(set(self['rw_rscale'])):
3900 raise InvalidRunCard, "'rw_rscale' has two or more identical entries. They have to be all different for the code to work correctly."
3901 if len(self['rw_fscale']) != len(set(self['rw_fscale'])):
3902 raise InvalidRunCard, "'rw_fscale' has two or more identical entries. They have to be all different for the code to work correctly."
3903
3904
3906
3907
3908 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys()+
3909 self['mxx_min_pdg'].keys()+ self['mxx_only_part_antipart'].keys())
3910 pdg_to_cut.discard('__type__')
3911 pdg_to_cut.discard('default')
3912 if len(pdg_to_cut)>25:
3913 raise Exception, "Maximum 25 different PDGs are allowed for PDG specific cut"
3914
3915 if any(int(pdg)<0 for pdg in pdg_to_cut):
3916 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes')
3917 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative PDG codes'
3918
3919
3920 if any(pdg in pdg_to_cut for pdg in [21,22,11,13,15]+ range(self['maxjetflavor']+1)):
3921
3922 raise Exception, "Can not use PDG related cuts for massless SM particles/leptons"
3923 if pdg_to_cut:
3924 self['pdg_cut'] = list(pdg_to_cut)
3925 self['ptmin4pdg'] = []
3926 self['ptmax4pdg'] = []
3927 self['mxxmin4pdg'] = []
3928 self['mxxpart_antipart'] = []
3929 for pdg in self['pdg_cut']:
3930 for var in ['pt','mxx']:
3931 for minmax in ['min', 'max']:
3932 if var == 'mxx' and minmax == 'max':
3933 continue
3934 new_var = '%s%s4pdg' % (var, minmax)
3935 old_var = '%s_%s_pdg' % (var, minmax)
3936 default = 0. if minmax=='min' else -1.
3937 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3938
3939 old_var = 'mxx_only_part_antipart'
3940 new_var = 'mxxpart_antipart'
3941 if 'default' in self[old_var]:
3942 default = self[old_var]['default']
3943 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3944 else:
3945 if str(pdg) not in self[old_var]:
3946 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg))
3947 self[new_var].append(self[old_var][str(pdg)])
3948 else:
3949 self['pdg_cut'] = [0]
3950 self['ptmin4pdg'] = [0.]
3951 self['ptmax4pdg'] = [-1.]
3952 self['mxxmin4pdg'] = [0.]
3953 self['mxxpart_antipart'] = [False]
3954
3955 - def write(self, output_file, template=None, python_template=False, **opt):
3956 """Write the run_card in output_file according to template
3957 (a path to a valid run_card)"""
3958
3959 if not template:
3960 if not MADEVENT:
3961 template = pjoin(MG5DIR, 'Template', 'NLO', 'Cards',
3962 'run_card.dat')
3963 python_template = True
3964 else:
3965 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat')
3966 python_template = False
3967
3968 super(RunCardNLO, self).write(output_file, template=template,
3969 python_template=python_template, **opt)
3970
3971
3973 """Rules
3974 e+ e- beam -> lpp:0 ebeam:500
3975 p p beam -> set maxjetflavor automatically
3976 """
3977
3978
3979 beam_id = set()
3980 for proc in proc_def:
3981 for leg in proc['legs']:
3982 if not leg['state']:
3983 beam_id.add(leg['id'])
3984 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]):
3985 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7])
3986 self['maxjetflavor'] = maxjetflavor
3987 pass
3988 elif 11 in beam_id or -11 in beam_id:
3989 self['lpp1'] = 0
3990 self['lpp2'] = 0
3991 self['ebeam1'] = 500
3992 self['ebeam2'] = 500
3993 else:
3994 self['lpp1'] = 0
3995 self['lpp2'] = 0
3996
3997 if proc_characteristic['ninitial'] == 1:
3998
3999 self.remove_all_cut()
4000
4004 """ a class for storing/dealing with the file MadLoopParam.dat
4005 contains a parser to read it, facilities to write a new file,...
4006 """
4007
4008 _ID_reduction_tool_map = {1:'CutTools',
4009 2:'PJFry++',
4010 3:'IREGI',
4011 4:'Golem95',
4012 5:'Samurai',
4013 6:'Ninja',
4014 7:'COLLIER'}
4015
4017 """initialize the directory to the default value"""
4018
4019 self.add_param("MLReductionLib", "6|7|1")
4020 self.add_param("IREGIMODE", 2)
4021 self.add_param("IREGIRECY", True)
4022 self.add_param("CTModeRun", -1)
4023 self.add_param("MLStabThres", 1e-3)
4024 self.add_param("NRotations_DP", 0)
4025 self.add_param("NRotations_QP", 0)
4026 self.add_param("ImprovePSPoint", 2)
4027 self.add_param("CTLoopLibrary", 2)
4028 self.add_param("CTStabThres", 1e-2)
4029 self.add_param("CTModeInit", 1)
4030 self.add_param("CheckCycle", 3)
4031 self.add_param("MaxAttempts", 10)
4032 self.add_param("ZeroThres", 1e-9)
4033 self.add_param("OSThres", 1.0e-8)
4034 self.add_param("DoubleCheckHelicityFilter", True)
4035 self.add_param("WriteOutFilters", True)
4036 self.add_param("UseLoopFilter", False)
4037 self.add_param("HelicityFilterLevel", 2)
4038 self.add_param("LoopInitStartOver", False)
4039 self.add_param("HelInitStartOver", False)
4040 self.add_param("UseQPIntegrandForNinja", True)
4041 self.add_param("UseQPIntegrandForCutTools", True)
4042 self.add_param("COLLIERMode", 1)
4043 self.add_param("COLLIERComputeUVpoles", True)
4044 self.add_param("COLLIERComputeIRpoles", True)
4045 self.add_param("COLLIERRequiredAccuracy", 1.0e-8)
4046 self.add_param("COLLIERCanOutput",False)
4047 self.add_param("COLLIERGlobalCache",-1)
4048 self.add_param("COLLIERUseCacheForPoles",False)
4049 self.add_param("COLLIERUseInternalStabilityTest",True)
4050
4051 - def read(self, finput):
4052 """Read the input file, this can be a path to a file,
4053 a file object, a str with the content of the file."""
4054
4055 if isinstance(finput, str):
4056 if "\n" in finput:
4057 finput = finput.split('\n')
4058 elif os.path.isfile(finput):
4059 finput = open(finput)
4060 else:
4061 raise Exception, "No such file %s" % input
4062
4063 previous_line= ''
4064 for line in finput:
4065 if previous_line.startswith('#'):
4066 name = previous_line[1:].split()[0]
4067 value = line.strip()
4068 if len(value) and value[0] not in ['#', '!']:
4069 self.__setitem__(name, value, change_userdefine=True)
4070 previous_line = line
4071
4072
4073 - def write(self, outputpath, template=None,commentdefault=False):
4074
4075 if not template:
4076 if not MADEVENT:
4077 template = pjoin(MG5DIR, 'Template', 'loop_material', 'StandAlone',
4078 'Cards', 'MadLoopParams.dat')
4079 else:
4080 template = pjoin(MEDIR, 'Cards', 'MadLoopParams_default.dat')
4081 fsock = open(template, 'r')
4082 template = fsock.readlines()
4083 fsock.close()
4084
4085 if isinstance(outputpath, str):
4086 output = open(outputpath, 'w')
4087 else:
4088 output = outputpath
4089
4090 def f77format(value):
4091 if isinstance(value, bool):
4092 if value:
4093 return '.true.'
4094 else:
4095 return '.false.'
4096 elif isinstance(value, int):
4097 return value
4098 elif isinstance(value, float):
4099 tmp ='%e' % value
4100 return tmp.replace('e','d')
4101 elif isinstance(value, str):
4102 return value
4103 else:
4104 raise Exception, "Can not format input %s" % type(value)
4105
4106 name = ''
4107 done = set()
4108 for line in template:
4109 if name:
4110 done.add(name)
4111 if commentdefault and name.lower() not in self.user_set :
4112 output.write('!%s\n' % f77format(self[name]))
4113 else:
4114 output.write('%s\n' % f77format(self[name]))
4115 name=''
4116 continue
4117 elif line.startswith('#'):
4118 name = line[1:].split()[0]
4119 output.write(line)
4120