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 self.add_param('splitting_types',[], typelist=str)
1439 self.add_param('perturbation_order', [], typelist=str)
1440
1441 - def read(self, finput):
1442 """Read the input file, this can be a path to a file,
1443 a file object, a str with the content of the file."""
1444
1445 if isinstance(finput, str):
1446 if "\n" in finput:
1447 finput = finput.split('\n')
1448 elif os.path.isfile(finput):
1449 finput = open(finput)
1450 else:
1451 raise Exception, "No such file %s" % finput
1452
1453 for line in finput:
1454 if '#' in line:
1455 line = line.split('#',1)[0]
1456 if not line:
1457 continue
1458
1459 if '=' in line:
1460 key, value = line.split('=',1)
1461 self[key.strip()] = value
1462
1463 - def write(self, outputpath):
1464 """write the file"""
1465
1466 template ="# Information about the process #\n"
1467 template +="#########################################\n"
1468
1469 fsock = open(outputpath, 'w')
1470 fsock.write(template)
1471
1472 for key, value in self.items():
1473 fsock.write(" %s = %s \n" % (key, value))
1474
1475 fsock.close()
1476
1481 """an object for the GridpackCard"""
1482
1484 """default value for the GridpackCard"""
1485
1486 self.add_param("GridRun", True)
1487 self.add_param("gevents", 2500)
1488 self.add_param("gseed", 1)
1489 self.add_param("ngran", -1)
1490
1491 - def read(self, finput):
1492 """Read the input file, this can be a path to a file,
1493 a file object, a str with the content of the file."""
1494
1495 if isinstance(finput, str):
1496 if "\n" in finput:
1497 finput = finput.split('\n')
1498 elif os.path.isfile(finput):
1499 finput = open(finput)
1500 else:
1501 raise Exception, "No such file %s" % finput
1502
1503 for line in finput:
1504 line = line.split('#')[0]
1505 line = line.split('!')[0]
1506 line = line.split('=',1)
1507 if len(line) != 2:
1508 continue
1509 self[line[1].strip()] = line[0].replace('\'','').strip()
1510
1511 - def write(self, output_file, template=None):
1512 """Write the run_card in output_file according to template
1513 (a path to a valid run_card)"""
1514
1515 if not template:
1516 if not MADEVENT:
1517 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards',
1518 'grid_card_default.dat')
1519 else:
1520 template = pjoin(MEDIR, 'Cards', 'grid_card_default.dat')
1521
1522
1523 text = ""
1524 for line in file(template,'r'):
1525 nline = line.split('#')[0]
1526 nline = nline.split('!')[0]
1527 comment = line[len(nline):]
1528 nline = nline.split('=')
1529 if len(nline) != 2:
1530 text += line
1531 elif nline[1].strip() in self:
1532 text += ' %s\t= %s %s' % (self[nline[1].strip()],nline[1], comment)
1533 else:
1534 logger.info('Adding missing parameter %s to current run_card (with default value)' % nline[1].strip())
1535 text += line
1536
1537 if isinstance(output_file, str):
1538 fsock = open(output_file,'w')
1539 else:
1540 fsock = output_file
1541
1542 fsock.write(text)
1543 fsock.close()
1544
1546 """ Implements the Pythia8 card."""
1547
1549 """ Placeholder function to allow overwriting in the PY8SubRun daughter.
1550 The initialization of the self.subruns attribute should of course not
1551 be performed in PY8SubRun."""
1552 if type == 'parameters':
1553 if "LHEFInputs:nSubruns" not in self:
1554 self.add_param("LHEFInputs:nSubruns", 1,
1555 hidden='ALWAYS_WRITTEN',
1556 comment="""
1557 ====================
1558 Subrun definitions
1559 ====================
1560 """)
1561 if type == 'attributes':
1562 if not(hasattr(self,'subruns')):
1563 first_subrun = PY8SubRun(subrun_id=0)
1564 self.subruns = dict([(first_subrun['Main:subrun'],first_subrun)])
1565
1567 """ Sets up the list of available PY8 parameters."""
1568
1569
1570
1571 self.add_param("Main:numberOfEvents", -1)
1572
1573
1574 self.add_param("JetMatching:qCut", -1.0, always_write_to_card=False)
1575 self.add_param("JetMatching:doShowerKt",False,always_write_to_card=False)
1576
1577 self.add_param("JetMatching:nJetMax", -1, always_write_to_card=False)
1578
1579 self.add_param("Merging:TMS", -1.0, always_write_to_card=False)
1580 self.add_param("Merging:Process", '<set_by_user>', always_write_to_card=False)
1581
1582 self.add_param("Merging:nJetMax", -1, always_write_to_card=False)
1583
1584
1585 self.add_param("SysCalc:fullCutVariation", False)
1586
1587
1588
1589 self.add_param("HEPMCoutput:file", 'auto')
1590
1591
1592
1593 self.add_param("Beams:frameType", 4,
1594 hidden=True,
1595 comment='Tell Pythia8 that an LHEF input is used.')
1596 self.add_param("HEPMCoutput:scaling", 1.0e9,
1597 hidden=True,
1598 comment='1.0 corresponds to HEPMC weight given in [mb]. We choose here the [pb] normalization.')
1599 self.add_param("Check:epTolErr", 1e-2,
1600 hidden=True,
1601 comment='Be more forgiving with momentum mismatches.')
1602
1603
1604 self.add_param("JetMatching:etaJetMax", 1000.0, hidden=True, always_write_to_card=True)
1605
1606
1607
1608 self.add_param("PDF:pSet", 'LHAPDF5:CT10.LHgrid', hidden=True, always_write_to_card=False,
1609 comment='Reminder: Parameter below is shower tune dependent.')
1610 self.add_param("SpaceShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False,
1611 comment='Reminder: Parameter below is shower tune dependent.')
1612 self.add_param("TimeShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False,
1613 comment='Reminder: Parameter below is shower tune dependent.')
1614 self.add_param("hadronlevel:all", True, hidden=True, always_write_to_card=False,
1615 comment='This allows to turn on/off hadronization alltogether.')
1616 self.add_param("partonlevel:mpi", True, hidden=True, always_write_to_card=False,
1617 comment='This allows to turn on/off MPI alltogether.')
1618 self.add_param("Beams:setProductionScalesFromLHEF", False, hidden=True,
1619 always_write_to_card=False,
1620 comment='This parameter is automatically set to True by MG5aMC when doing MLM merging with PY8.')
1621
1622
1623 self.add_param("JetMatching:merge", False, hidden=True, always_write_to_card=False,
1624 comment='Specifiy if we are merging sample of different multiplicity.')
1625 self.add_param("SysCalc:qCutList", [10.0,20.0], hidden=True, always_write_to_card=False)
1626 self['SysCalc:qCutList'] = 'auto'
1627 self.add_param("SysCalc:qWeed",-1.0,hidden=True, always_write_to_card=False,
1628 comment='Value of the merging scale below which one does not even write the HepMC event.')
1629 self.add_param("JetMatching:doVeto", False, hidden=True, always_write_to_card=False,
1630 comment='Do veto externally (e.g. in SysCalc).')
1631 self.add_param("JetMatching:scheme", 1, hidden=True, always_write_to_card=False)
1632 self.add_param("JetMatching:setMad", False, hidden=True, always_write_to_card=False,
1633 comment='Specify one must read inputs from the MadGraph banner.')
1634 self.add_param("JetMatching:coneRadius", 1.0, hidden=True, always_write_to_card=False)
1635 self.add_param("JetMatching:nQmatch",4,hidden=True, always_write_to_card=False)
1636
1637 self.add_param("TimeShower:pTmaxMatch", 2, hidden=True, always_write_to_card=False)
1638 self.add_param("SpaceShower:pTmaxMatch", 1, hidden=True, always_write_to_card=False)
1639 self.add_param("SysCalc:tmsList", [10.0,20.0], hidden=True, always_write_to_card=False)
1640 self['SysCalc:tmsList'] = 'auto'
1641 self.add_param("Merging:muFac", 91.188, hidden=True, always_write_to_card=False,
1642 comment='Set factorisation scales of the 2->2 process.')
1643 self.add_param("Merging:applyVeto", False, hidden=True, always_write_to_card=False,
1644 comment='Do veto externally (e.g. in SysCalc).')
1645 self.add_param("Merging:includeWeightInXsection", True, hidden=True, always_write_to_card=False,
1646 comment='If turned off, then the option belows forces PY8 to keep the original weight.')
1647 self.add_param("Merging:muRen", 91.188, hidden=True, always_write_to_card=False,
1648 comment='Set renormalization scales of the 2->2 process.')
1649 self.add_param("Merging:muFacInME", 91.188, hidden=True, always_write_to_card=False,
1650 comment='Set factorisation scales of the 2->2 Matrix Element.')
1651 self.add_param("Merging:muRenInME", 91.188, hidden=True, always_write_to_card=False,
1652 comment='Set renormalization scales of the 2->2 Matrix Element.')
1653 self.add_param("SpaceShower:rapidityOrder", False, hidden=True, always_write_to_card=False)
1654 self.add_param("Merging:nQuarksMerge",4,hidden=True, always_write_to_card=False)
1655
1656 self.add_param("Merging:mayRemoveDecayProducts", False, hidden=True, always_write_to_card=False)
1657 self.add_param("Merging:doKTMerging", False, hidden=True, always_write_to_card=False)
1658 self.add_param("Merging:Dparameter", 0.4, hidden=True, always_write_to_card=False)
1659 self.add_param("Merging:doPTLundMerging", False, hidden=True, always_write_to_card=False)
1660
1661
1662 self.add_param("BeamRemnants:primordialKT", True, hidden=True, always_write_to_card=False, comment="see http://home.thep.lu.se/~torbjorn/pythia82html/BeamRemnants.html")
1663 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")
1664 self.add_param("Check:event", True, hidden=True, always_write_to_card=False, comment="check physical sanity of the events")
1665 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")
1666 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")
1667 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")
1668 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")
1669 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")
1670 self.add_param("ProcessLevel:resonanceDecays", True, hidden=True, always_write_to_card=False, comment="Do not allow unstable particle to decay.")
1671
1672
1673
1674 self.add_default_subruns('parameters')
1675
1677
1678
1679
1680 self.hidden_param = []
1681 self.hidden_params_to_always_write = set()
1682 self.visible_params_to_always_write = set()
1683
1684 self.params_to_never_write = set()
1685
1686
1687
1688 self.system_set = set()
1689
1690
1691
1692 self.add_default_subruns('attributes')
1693
1694
1695 super(PY8Card, self).__init__(*args, **opts)
1696
1697 - def add_param(self, name, value, hidden=False, always_write_to_card=True,
1698 comment=None):
1699 """ add a parameter to the card. value is the default value and
1700 defines the type (int/float/bool/str) of the input.
1701 The option 'hidden' decides whether the parameter should be visible to the user.
1702 The option 'always_write_to_card' decides whether it should
1703 always be printed or only when it is system_set or user_set.
1704 The option 'comment' can be used to specify a comment to write above
1705 hidden parameters.
1706 """
1707 super(PY8Card, self).add_param(name, value, comment=comment)
1708 name = name.lower()
1709 if hidden:
1710 self.hidden_param.append(name)
1711 if always_write_to_card:
1712 self.hidden_params_to_always_write.add(name)
1713 else:
1714 if always_write_to_card:
1715 self.visible_params_to_always_write.add(name)
1716 if not comment is None:
1717 if not isinstance(comment, str):
1718 raise MadGraph5Error("Option 'comment' must be a string, not"+\
1719 " '%s'."%str(comment))
1720
1722 """Add a subrun to this PY8 Card."""
1723 assert(isinstance(py8_subrun,PY8SubRun))
1724 if py8_subrun['Main:subrun']==-1:
1725 raise MadGraph5Error, "Make sure to correctly set the subrun ID"+\
1726 " 'Main:subrun' *before* adding it to the PY8 Card."
1727 if py8_subrun['Main:subrun'] in self.subruns:
1728 raise MadGraph5Error, "A subrun with ID '%s'"%py8_subrun['Main:subrun']+\
1729 " is already present in this PY8 card. Remove it first, or "+\
1730 " access it directly."
1731 self.subruns[py8_subrun['Main:subrun']] = py8_subrun
1732 if not 'LHEFInputs:nSubruns' in self.user_set:
1733 self['LHEFInputs:nSubruns'] = max(self.subruns.keys())
1734
1735 - def userSet(self, name, value, **opts):
1736 """Set an attribute of this card, following a user_request"""
1737 self.__setitem__(name, value, change_userdefine=True, **opts)
1738 if name.lower() in self.system_set:
1739 self.system_set.remove(name.lower())
1740
1742 """ Forbid the writeout of a specific parameter of this card when the
1743 "write" function will be invoked."""
1744 self.params_to_never_write.add(name.lower())
1745
1747 """Set an attribute of this card, independently of a specific user
1748 request and only if not already user_set."""
1749 try:
1750 force = opts.pop('force')
1751 except KeyError:
1752 force = False
1753 if force or name.lower() not in self.user_set:
1754 self.__setitem__(name, value, change_userdefine=False, **opts)
1755 self.system_set.add(name.lower())
1756
1758 """ Sets a card attribute, but only if it is absent or not already
1759 user_set."""
1760 try:
1761 force = opts.pop('force')
1762 except KeyError:
1763 force = False
1764 if name.lower() not in self or (force or name.lower() not in self.user_set):
1765 self.__setitem__(name, value, change_userdefine=False, **opts)
1766 self.system_set.add(name.lower())
1767
1770
1771 @staticmethod
1822
1823
1824 - def write(self, output_file, template, read_subrun=False,
1825 print_only_visible=False, direct_pythia_input=False, add_missing=True):
1826 """ Write the card to output_file using a specific template.
1827 > 'print_only_visible' specifies whether or not the hidden parameters
1828 should be written out if they are in the hidden_params_to_always_write
1829 list and system_set.
1830 > If 'direct_pythia_input' is true, then visible parameters which are not
1831 in the self.visible_params_to_always_write list and are not user_set
1832 or system_set are commented.
1833 > If 'add_missing' is False then parameters that should be written_out but are absent
1834 from the template will not be written out."""
1835
1836
1837 visible_param = [p for p in self if p.lower() not in self.hidden_param
1838 or p.lower() in self.user_set]
1839
1840 visible_param = [p for p in visible_param if p.lower() not in self.params_to_never_write]
1841
1842
1843 if print_only_visible:
1844 hidden_output_param = []
1845 else:
1846 hidden_output_param = [p for p in self if p.lower() in self.hidden_param and
1847 not p.lower() in self.user_set and
1848 (p.lower() in self.hidden_params_to_always_write or
1849 p.lower() in self.system_set)]
1850
1851 hidden_output_param = [p for p in hidden_output_param if p not in self.params_to_never_write]
1852
1853 if print_only_visible:
1854 subruns = []
1855 else:
1856 if not read_subrun:
1857 subruns = sorted(self.subruns.keys())
1858
1859
1860
1861 subruns_to_write = {}
1862
1863
1864
1865 def group_params(params):
1866 if len(params)==0:
1867 return []
1868 groups = {}
1869 for p in params:
1870 try:
1871 groups[':'.join(p.split(':')[:-1])].append(p)
1872 except KeyError:
1873 groups[':'.join(p.split(':')[:-1])] = [p,]
1874 res = sum(groups.values(),[])
1875
1876 if 'Main:subrun' in res:
1877 res.insert(0,res.pop(res.index('Main:subrun')))
1878
1879 if 'LHEFInputs:nSubruns' in res:
1880 res.append(res.pop(res.index('LHEFInputs:nSubruns')))
1881 return res
1882
1883 visible_param = group_params(visible_param)
1884 hidden_output_param = group_params(hidden_output_param)
1885
1886
1887
1888 output = StringIO.StringIO()
1889
1890
1891 if isinstance(template, str):
1892 if os.path.isfile(template):
1893 tmpl = open(template, 'r')
1894 elif '\n' in template:
1895 tmpl = StringIO.StringIO(template)
1896 else:
1897 raise Exception, "File input '%s' not found." % file_input
1898 elif template is None:
1899
1900 tmpl = StringIO.StringIO()
1901 elif isinstance(template, (StringIO.StringIO, file)):
1902 tmpl = template
1903 else:
1904 raise MadGraph5Error("Incorrect type for argument 'template': %s"%
1905 template.__class__.__name__)
1906
1907
1908 last_pos = tmpl.tell()
1909 line = tmpl.readline()
1910 started_subrun_reading = False
1911 while line!='':
1912
1913 if line.strip().startswith('!') or \
1914 line.strip().startswith('\n') or\
1915 line.strip() == '':
1916 output.write(line)
1917
1918 last_pos = tmpl.tell()
1919 line = tmpl.readline()
1920 continue
1921
1922 try:
1923 param_entry, value_entry = line.split('=')
1924 param = param_entry.strip()
1925 value = value_entry.strip()
1926 except ValueError:
1927 line = line.replace('\n','')
1928 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\
1929 line
1930
1931 if param=='Main:subrun':
1932 if read_subrun:
1933 if not started_subrun_reading:
1934
1935 started_subrun_reading = True
1936 else:
1937
1938 tmpl.seek(last_pos)
1939 break
1940 else:
1941
1942 tmpl.seek(last_pos)
1943 subruns_to_write[int(value)] = StringIO.StringIO()
1944 if int(value) in subruns:
1945 self.subruns[int(value)].write(subruns_to_write[int(value)],
1946 tmpl,read_subrun=True)
1947
1948 subruns.pop(subruns.index(int(value)))
1949 else:
1950
1951 DummySubrun=PY8SubRun()
1952
1953 DummySubrun.clear()
1954 DummySubrun.write(subruns_to_write[int(value)],
1955 tmpl, read_subrun=True,
1956 print_only_visible=print_only_visible,
1957 direct_pythia_input=direct_pythia_input)
1958
1959 logger.info('Adding new unknown subrun with ID %d.'%
1960 int(value))
1961
1962 last_pos = tmpl.tell()
1963 line = tmpl.readline()
1964 continue
1965
1966
1967 if param in visible_param:
1968 new_value = PY8Card.pythia8_formatting(self[param])
1969 visible_param.pop(visible_param.index(param))
1970 elif param in hidden_output_param:
1971 new_value = PY8Card.pythia8_formatting(self[param])
1972 hidden_output_param.pop(hidden_output_param.index(param))
1973 else:
1974
1975 if param.lower() not in self.params_to_never_write:
1976 output.write(line)
1977 else:
1978 output.write('! The following parameter was forced to be commented out by MG5aMC.\n')
1979 output.write('! %s'%line)
1980
1981 last_pos = tmpl.tell()
1982 line = tmpl.readline()
1983 continue
1984
1985
1986
1987
1988
1989 if ((not direct_pythia_input) or
1990 (param.lower() in self.visible_params_to_always_write) or
1991 (param.lower() in self.user_set) or
1992 (param.lower() in self.system_set)):
1993 template = '%s=%s'
1994 else:
1995
1996
1997
1998 template = '!%s=%s'
1999
2000 output.write(template%(param_entry,
2001 value_entry.replace(value,new_value)))
2002
2003
2004 last_pos = tmpl.tell()
2005 line = tmpl.readline()
2006
2007
2008 if not add_missing:
2009 visible_param = []
2010 hidden_output_param = []
2011
2012
2013 if len(visible_param)>0 and not template is None:
2014 output.write(
2015 """!
2016 ! Additional general parameters%s.
2017 !
2018 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else ''))
2019 for param in visible_param:
2020 value = PY8Card.pythia8_formatting(self[param])
2021 output.write('%s=%s\n'%(param,value))
2022 if template is None:
2023 if param=='Main:subrun':
2024 output.write(
2025 """!
2026 ! Definition of subrun %d
2027 !
2028 """%self['Main:subrun'])
2029 elif param.lower() not in self.hidden_param:
2030 logger.debug('Adding parameter %s (missing in the template) to current '+\
2031 'pythia8 card (with value %s)',param, value)
2032
2033 if len(hidden_output_param)>0 and not template is None:
2034 output.write(
2035 """!
2036 ! Additional technical parameters%s set by MG5_aMC.
2037 !
2038 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else ''))
2039 for param in hidden_output_param:
2040 if param.lower() in self.comments:
2041 comment = '\n'.join('! %s'%c for c in
2042 self.comments[param.lower()].split('\n'))
2043 output.write(comment+'\n')
2044 output.write('%s=%s\n'%(param,PY8Card.pythia8_formatting(self[param])))
2045
2046
2047
2048 if read_subrun:
2049 output_file.write(output.getvalue())
2050 return
2051
2052
2053 for subrunID in subruns:
2054 new_subrun = StringIO.StringIO()
2055 self.subruns[subrunID].write(new_subrun,None,read_subrun=True)
2056 subruns_to_write[subrunID] = new_subrun
2057
2058
2059 for subrunID in sorted(subruns_to_write):
2060 output.write(subruns_to_write[subrunID].getvalue())
2061
2062
2063
2064 if 'LHEFInputs:nSubruns'.lower() not in self.user_set and \
2065 len(subruns_to_write)>0 and 'LHEFInputs:nSubruns' in self\
2066 and self['LHEFInputs:nSubruns']<max(subruns_to_write.keys()):
2067 logger.info("Updating PY8 parameter 'LHEFInputs:nSubruns' to "+
2068 "%d so as to cover all defined subruns."%max(subruns_to_write.keys()))
2069 self['LHEFInputs:nSubruns'] = max(subruns_to_write.keys())
2070 output = StringIO.StringIO()
2071 self.write(output,template,print_only_visible=print_only_visible)
2072
2073
2074 if isinstance(output_file, str):
2075 out = open(output_file,'w')
2076 out.write(output.getvalue())
2077 out.close()
2078 else:
2079 output_file.write(output.getvalue())
2080
2081 - def read(self, file_input, read_subrun=False, setter='default'):
2082 """Read the input file, this can be a path to a file,
2083 a file object, a str with the content of the file.
2084 The setter option choses the authority that sets potential
2085 modified/new parameters. It can be either:
2086 'default' or 'user' or 'system'"""
2087 if isinstance(file_input, str):
2088 if "\n" in file_input:
2089 finput = StringIO.StringIO(file_input)
2090 elif os.path.isfile(file_input):
2091 finput = open(file_input)
2092 else:
2093 raise Exception, "File input '%s' not found." % file_input
2094 elif isinstance(file_input, (StringIO.StringIO, file)):
2095 finput = file_input
2096 else:
2097 raise MadGraph5Error("Incorrect type for argument 'file_input': %s"%
2098 file_input.__class__.__name__)
2099
2100
2101 last_pos = finput.tell()
2102 line = finput.readline()
2103 started_subrun_reading = False
2104 while line!='':
2105
2106 if line.strip().startswith('!') or line.strip()=='':
2107
2108 last_pos = finput.tell()
2109 line = finput.readline()
2110 continue
2111
2112 try:
2113 param, value = line.split('=',1)
2114 param = param.strip()
2115 value = value.strip()
2116 except ValueError:
2117 line = line.replace('\n','')
2118 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\
2119 line
2120 if '!' in value:
2121 value,_ = value.split('!',1)
2122
2123
2124 if param=='Main:subrun':
2125 if read_subrun:
2126 if not started_subrun_reading:
2127
2128 started_subrun_reading = True
2129 else:
2130
2131 finput.seek(last_pos)
2132 return
2133 else:
2134
2135 finput.seek(last_pos)
2136 if int(value) in self.subruns:
2137 self.subruns[int(value)].read(finput,read_subrun=True,
2138 setter=setter)
2139 else:
2140
2141 NewSubrun=PY8SubRun()
2142 NewSubrun.read(finput,read_subrun=True, setter=setter)
2143 self.add_subrun(NewSubrun)
2144
2145
2146 last_pos = finput.tell()
2147 line = finput.readline()
2148 continue
2149
2150
2151
2152
2153
2154 if setter == 'user':
2155 self.userSet(param,value)
2156 elif setter == 'system':
2157 self.systemSet(param,value)
2158 else:
2159 self.defaultSet(param,value)
2160
2161
2162 last_pos = finput.tell()
2163 line = finput.readline()
2164
2166 """ Class to characterize a specific PY8 card subrun section. """
2167
2169 """ Overloading of the homonym function called in the __init__ of PY8Card.
2170 The initialization of the self.subruns attribute should of course not
2171 be performed in PY8SubRun."""
2172 pass
2173
2175 """ Initialize a subrun """
2176
2177
2178 subrunID = -1
2179 if 'subrun_id' in opts:
2180 subrunID = opts.pop('subrun_id')
2181
2182 super(PY8SubRun, self).__init__(*args, **opts)
2183 self['Main:subrun']=subrunID
2184
2186 """Sets up the list of available PY8SubRun parameters."""
2187
2188
2189 super(PY8SubRun, self).default_setup()
2190
2191 self.hidden_param = [k.lower() for k in self.keys()]
2192 self.hidden_params_to_always_write = set()
2193 self.visible_params_to_always_write = set()
2194
2195
2196 self.add_param("Main:subrun", -1)
2197 self.add_param("Beams:LHEF", "events.lhe.gz")
2198
2199
2200
2201 runblock = collections.namedtuple('block', ('name', 'fields', 'template_on', 'template_off'))
2203
2204 filename = 'run_card'
2205 blocks = []
2206
2207 - def __new__(cls, finput=None, **opt):
2208 if cls is RunCard:
2209 if not finput:
2210 target_class = RunCardLO
2211 elif isinstance(finput, cls):
2212 target_class = finput.__class__
2213 elif isinstance(finput, str):
2214 if '\n' not in finput:
2215 finput = open(finput).read()
2216 if 'req_acc_FO' in finput:
2217 target_class = RunCardNLO
2218 else:
2219 target_class = RunCardLO
2220 else:
2221 return None
2222 return super(RunCard, cls).__new__(target_class, finput, **opt)
2223 else:
2224 return super(RunCard, cls).__new__(cls, finput, **opt)
2225
2227
2228
2229
2230
2231 self.hidden_param = []
2232
2233 self.includepath = collections.defaultdict(list)
2234
2235 self.fortran_name = {}
2236
2237 self.legacy_parameter = {}
2238
2239 self.cuts_parameter = []
2240
2241 self.system_default = {}
2242
2243 self.display_block = []
2244 self.warned=False
2245
2246
2247 super(RunCard, self).__init__(*args, **opts)
2248
2249 - def add_param(self, name, value, fortran_name=None, include=True,
2250 hidden=False, legacy=False, cut=False, system=False, sys_default=None,
2251 **opts):
2252 """ add a parameter to the card. value is the default value and
2253 defines the type (int/float/bool/str) of the input.
2254 fortran_name defines what is the associate name in the f77 code
2255 include defines if we have to put the value in the include file
2256 hidden defines if the parameter is expected to be define by the user.
2257 legacy:Parameter which is not used anymore (raise a warning if not default)
2258 cut: defines the list of cut parameter to allow to set them all to off.
2259 sys_default: default used if the parameter is not in the card
2260
2261 options of **opts:
2262 - allowed: list of valid options. '*' means anything else should be allowed.
2263 empty list means anything possible as well.
2264 - comment: add comment for writing/help
2265 - typelist: type of the list if default is empty
2266 """
2267
2268 super(RunCard, self).add_param(name, value, system=system,**opts)
2269 name = name.lower()
2270 if fortran_name:
2271 self.fortran_name[name] = fortran_name
2272 if legacy:
2273 self.legacy_parameter[name] = value
2274 include = False
2275 self.includepath[include].append(name)
2276 if hidden or system:
2277 self.hidden_param.append(name)
2278 if cut:
2279 self.cuts_parameter.append(name)
2280 if sys_default is not None:
2281 self.system_default[name] = sys_default
2282
2283
2284
2285 - def read(self, finput, consistency=True):
2286 """Read the input file, this can be a path to a file,
2287 a file object, a str with the content of the file."""
2288
2289 if isinstance(finput, str):
2290 if "\n" in finput:
2291 finput = finput.split('\n')
2292 elif os.path.isfile(finput):
2293 finput = open(finput)
2294 else:
2295 raise Exception, "No such file %s" % finput
2296
2297 for line in finput:
2298 line = line.split('#')[0]
2299 line = line.split('!')[0]
2300 line = line.rsplit('=',1)
2301 if len(line) != 2:
2302 continue
2303 value, name = line
2304 name = name.lower().strip()
2305 if name not in self and ('min' in name or 'max' in name):
2306
2307 self.add_param(name, float(value), hidden=True, cut=True)
2308 else:
2309 self.set( name, value, user=True)
2310
2311 if consistency:
2312 try:
2313 self.check_validity()
2314 except InvalidRunCard, error:
2315 if consistency == 'warning':
2316 logger.warning(str(error))
2317 else:
2318 raise
2319
2320
2321 - def write(self, output_file, template=None, python_template=False,
2322 write_hidden=False):
2323 """Write the run_card in output_file according to template
2324 (a path to a valid run_card)"""
2325
2326 to_write = set(self.user_set)
2327 written = set()
2328 if not template:
2329 raise Exception
2330
2331
2332 write_block= []
2333 for b in self.blocks:
2334 name = b.name
2335
2336 if name not in self.display_block and \
2337 not any(f in self.user_set for f in b.fields):
2338 continue
2339 write_block.append(b.name)
2340
2341 if python_template and not to_write:
2342 import string
2343 text = file(template,'r').read()
2344 if self.blocks:
2345 text = string.Template(text)
2346 mapping = {}
2347 for b in self.blocks:
2348 if b.name in write_block:
2349 mapping[b.name] = b.template_on
2350 else:
2351 mapping[b.name] = b.template_off
2352 text = text.substitute(mapping)
2353
2354 if not self.list_parameter:
2355 text = text % self
2356 else:
2357 data = dict(self)
2358 for name in self.list_parameter:
2359 if self.list_parameter[name] != str:
2360 data[name] = ', '.join(str(v) for v in data[name])
2361 else:
2362 data[name] = "['%s']" % "', '".join(str(v) for v in data[name])
2363 text = text % data
2364 else:
2365 text = ""
2366 for line in file(template,'r'):
2367 nline = line.split('#')[0]
2368 nline = nline.split('!')[0]
2369 comment = line[len(nline):]
2370 nline = nline.split('=')
2371 if python_template and nline[0].startswith('$'):
2372 block_name = nline[0][1:]
2373 this_group = [b for b in self.blocks if b.name == block_name]
2374 if not this_group:
2375 logger.debug("block %s not defined", block_name)
2376 continue
2377 else:
2378 this_group = this_group[0]
2379 if block_name in write_block:
2380 text += this_group.template_on % self
2381 for name in this_group.fields:
2382 written.add(name)
2383 if name in to_write:
2384 to_write.remove(name)
2385 else:
2386 text += this_group.template_off % self
2387
2388 elif len(nline) != 2:
2389 text += line
2390 elif nline[1].strip() in self:
2391 name = nline[1].strip().lower()
2392 value = self[name]
2393 if name in self.list_parameter:
2394 if self.list_parameter[name] != str:
2395 value = ', '.join([str(v) for v in value])
2396 else:
2397 value = "['%s']" % "', '".join(str(v) for v in value)
2398 if python_template:
2399 text += line % {nline[1].strip():value, name:value}
2400 written.add(name)
2401 else:
2402 if not comment or comment[-1]!='\n':
2403 endline = '\n'
2404 else:
2405 endline = ''
2406 text += ' %s\t= %s %s%s' % (value, name, comment, endline)
2407 written.add(name)
2408
2409 if name in to_write:
2410 to_write.remove(name)
2411 else:
2412 logger.info('Adding missing parameter %s to current %s (with default value)',
2413 (name, self.filename))
2414 written.add(name)
2415 text += line
2416
2417 for b in self.blocks:
2418 if b.name not in write_block:
2419 continue
2420
2421 if all(f in written for f in b.fields):
2422 continue
2423
2424 to_add = []
2425 for line in b.template_on.split('\n'):
2426 nline = line.split('#')[0]
2427 nline = nline.split('!')[0]
2428 nline = nline.split('=')
2429 if len(nline) != 2:
2430 to_add.append(line)
2431 elif nline[1].strip() in self:
2432 name = nline[1].strip().lower()
2433 value = self[name]
2434 if name in self.list_parameter:
2435 value = ', '.join([str(v) for v in value])
2436 if name in written:
2437 continue
2438 else:
2439 to_add.append(line % {nline[1].strip():value, name:value})
2440 written.add(name)
2441
2442 if name in to_write:
2443 to_write.remove(name)
2444 else:
2445 raise Exception
2446
2447 if b.template_off in text:
2448 text = text.replace(b.template_off, '\n'.join(to_add))
2449 else:
2450 text += '\n'.join(to_add)
2451
2452 if to_write or write_hidden:
2453 text+="""#*********************************************************************
2454 # Additional hidden parameters
2455 #*********************************************************************
2456 """
2457 if write_hidden:
2458
2459
2460
2461 if python_template:
2462 written = written.union(set(re.findall('\%\((\w*)\)s', file(template,'r').read(), re.M)))
2463 to_write = to_write.union(set(self.hidden_param))
2464 to_write = to_write.difference(written)
2465
2466 for key in to_write:
2467 if key in self.system_only:
2468 continue
2469
2470 comment = self.comments.get(key,'hidden_parameter').replace('\n','\n#')
2471 text += ' %s\t= %s # %s\n' % (self[key], key, comment)
2472
2473 if isinstance(output_file, str):
2474 fsock = open(output_file,'w')
2475 fsock.write(text)
2476 fsock.close()
2477 else:
2478 output_file.write(text)
2479
2480
2481 - def get_default(self, name, default=None, log_level=None):
2482 """return self[name] if exist otherwise default. log control if we
2483 put a warning or not if we use the default value"""
2484
2485 lower_name = name.lower()
2486 if lower_name not in self.user_set:
2487 if log_level is None:
2488 if lower_name in self.system_only:
2489 log_level = 5
2490 elif lower_name in self.auto_set:
2491 log_level = 5
2492 elif lower_name in self.hidden_param:
2493 log_level = 10
2494 else:
2495 log_level = 20
2496 if not default:
2497 default = dict.__getitem__(self, name.lower())
2498
2499 logger.log(log_level, '%s missed argument %s. Takes default: %s'
2500 % (self.filename, name, default))
2501 self[name] = default
2502 return default
2503 else:
2504 return self[name]
2505
2506
2507 @staticmethod
2556
2557
2558
2560 """check that parameter missing in the card are set to the expected value"""
2561
2562 for name, value in self.system_default.items():
2563 self.set(name, value, changeifuserset=False)
2564
2565
2566 for name in self.includepath[False]:
2567 to_bypass = self.hidden_param + self.legacy_parameter.keys()
2568 if name not in to_bypass:
2569 self.get_default(name, log_level=log_level)
2570
2571 for name in self.legacy_parameter:
2572 if self[name] != self.legacy_parameter[name]:
2573 logger.warning("The parameter %s is not supported anymore this parameter will be ignored." % name)
2574
2575 default_include_file = 'run_card.inc'
2576
2578 """update hidden system only parameter for the correct writtin in the
2579 include"""
2580 return
2581
2583 """Write the various include file in output_dir.
2584 The entry True of self.includepath will be written in run_card.inc
2585 The entry False will not be written anywhere"""
2586
2587
2588 self.check_validity()
2589
2590
2591 self.update_system_parameter_for_include()
2592
2593 for incname in self.includepath:
2594 if incname is True:
2595 pathinc = self.default_include_file
2596 elif incname is False:
2597 continue
2598 else:
2599 pathinc = incname
2600
2601 fsock = file_writers.FortranWriter(pjoin(output_dir,pathinc))
2602 for key in self.includepath[incname]:
2603
2604 if key in self.fortran_name:
2605 fortran_name = self.fortran_name[key]
2606 else:
2607 fortran_name = key
2608
2609
2610 value = self.get_default(key)
2611
2612
2613 if isinstance(value, list):
2614
2615
2616
2617 targettype = self.list_parameter[key]
2618 if targettype is bool:
2619 pass
2620 elif targettype is int:
2621 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(len(value)))
2622 fsock.writelines(line)
2623 elif targettype is float:
2624 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(float(len(value))))
2625 fsock.writelines(line)
2626
2627 for i,v in enumerate(value):
2628 line = '%s(%s) = %s \n' % (fortran_name, i+1, self.f77_formatting(v))
2629 fsock.writelines(line)
2630 elif isinstance(value, dict):
2631 for fortran_name, onevalue in value.items():
2632 line = '%s = %s \n' % (fortran_name, self.f77_formatting(onevalue))
2633 fsock.writelines(line)
2634 else:
2635 line = '%s = %s \n' % (fortran_name, self.f77_formatting(value))
2636 fsock.writelines(line)
2637 fsock.close()
2638
2639 @staticmethod
2641 """return the particle colliding pdg code"""
2642 if lpp in (1,2, -1,-2):
2643 return math.copysign(2212, lpp)
2644 elif lpp in (3,-3):
2645 return math.copysign(11, lpp)
2646 elif lpp == 0:
2647
2648 return 0
2649 else:
2650 return lpp
2651
2666
2668 if pdf == "lhapdf":
2669 lhaid = self["lhaid"]
2670 if isinstance(lhaid, list):
2671 return lhaid[0]
2672 else:
2673 return lhaid
2674 else:
2675 return {'none': 0,
2676 'cteq6_m':10000,'cteq6_l':10041,'cteq6l1':10042,
2677 'nn23lo':246800,'nn23lo1':247000,'nn23nlo':244800
2678 }[pdf]
2679
2682
2684 """remove all the cut"""
2685
2686 for name in self.cuts_parameter:
2687 targettype = type(self[name])
2688 if targettype == bool:
2689 self[name] = False
2690 elif 'min' in name:
2691 self[name] = 0
2692 elif 'max' in name:
2693 self[name] = -1
2694 elif 'eta' in name:
2695 self[name] = -1
2696 else:
2697 self[name] = 0
2698
2700 """an object to handle in a nice way the run_card information"""
2701
2702 blocks = [
2703
2704 runblock(name='ion_pdf', fields=('nb_neutron1', 'nb_neutron2','nb_proton1','nb_proton2','mass_ion1', 'mass_ion2'),
2705 template_on=\
2706 """#*********************************************************************
2707 # Heavy ion PDF / rescaling of PDF *
2708 #*********************************************************************
2709 %(nb_proton1)s = nb_proton1 # number of proton for the first beam
2710 %(nb_neutron1)s = nb_neutron1 # number of neutron for the first beam
2711 %(mass_ion1)s = mass_ion1 # mass of the heavy ion (first beam)
2712 # Note that seting differently the two beams only work if you use
2713 # group_subprocess=False when generating your matrix-element
2714 %(nb_proton2)s = nb_proton2 # number of proton for the second beam
2715 %(nb_neutron2)s = nb_neutron2 # number of neutron for the second beam
2716 %(mass_ion2)s = mass_ion2 # mass of the heavy ion (second beam)
2717 """,
2718 template_off='# To see heavy ion options: type "update ion_pdf"'),
2719
2720
2721
2722 runblock(name='beam_pol', fields=('polbeam1','polbeam2'),
2723 template_on=\
2724 """#*********************************************************************
2725 # Beam polarization from -100 (left-handed) to 100 (right-handed) *
2726 #*********************************************************************
2727 %(polbeam1)s = polbeam1 ! beam polarization for beam 1
2728 %(polbeam2)s = polbeam2 ! beam polarization for beam 2
2729 """,
2730 template_off='# To see polarised beam options: type "update beam_pol"'),
2731
2732
2733 runblock(name='syscalc', fields=('sys_scalefact', 'sys_alpsfact','sys_matchscale','sys_pdf'),
2734 template_on=\
2735 """#**************************************
2736 # Parameter below of the systematics study
2737 # will be used by SysCalc (if installed)
2738 #**************************************
2739 #
2740 %(sys_scalefact)s = sys_scalefact # factorization/renormalization scale factor
2741 %(sys_alpsfact)s = sys_alpsfact # \alpha_s emission scale factors
2742 %(sys_matchscale)s = sys_matchscale # variation of merging scale
2743 # PDF sets and number of members (0 or none for all members).
2744 %(sys_pdf)s = sys_pdf # list of pdf sets. (errorset not valid for syscalc)
2745 # MSTW2008nlo68cl.LHgrid 1 = sys_pdf
2746 #
2747 """,
2748 template_off= '# Syscalc is deprecated but to see the associate options type\'update syscalc\''),
2749 ]
2750
2751
2752
2754 """default value for the run_card.dat"""
2755
2756 self.add_param("run_tag", "tag_1", include=False)
2757 self.add_param("gridpack", False)
2758 self.add_param("time_of_flight", -1.0, include=False)
2759 self.add_param("nevents", 10000)
2760 self.add_param("iseed", 0)
2761 self.add_param("python_seed", -1, 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")
2762 self.add_param("lpp1", 1, fortran_name="lpp(1)", allowed=[-1,1,0,2,3,9, -2,-3],
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("lpp2", 1, fortran_name="lpp(2)", allowed=[-1,1,0,2,3,9],
2765 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')
2766 self.add_param("ebeam1", 6500.0, fortran_name="ebeam(1)")
2767 self.add_param("ebeam2", 6500.0, fortran_name="ebeam(2)")
2768 self.add_param("polbeam1", 0.0, fortran_name="pb1", hidden=True,
2769 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--")
2770 self.add_param("polbeam2", 0.0, fortran_name="pb2", hidden=True,
2771 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--")
2772 self.add_param('nb_proton1', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(1)",
2773 comment='For heavy ion physics nb of proton in the ion (for both beam but if group_subprocess was False)')
2774 self.add_param('nb_proton2', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(2)",
2775 comment='For heavy ion physics nb of proton in the ion (used for beam 2 if group_subprocess was False)')
2776 self.add_param('nb_neutron1', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(1)",
2777 comment='For heavy ion physics nb of neutron in the ion (for both beam but if group_subprocess was False)')
2778 self.add_param('nb_neutron2', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(2)",
2779 comment='For heavy ion physics nb of neutron in the ion (of beam 2 if group_subprocess was False )')
2780 self.add_param('mass_ion1', -1.0, hidden=True, fortran_name="mass_ion(1)",
2781 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'],
2782 comment='For heavy ion physics mass in GeV of the ion (of beam 1)')
2783 self.add_param('mass_ion2', -1.0, hidden=True, fortran_name="mass_ion(2)",
2784 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'],
2785 comment='For heavy ion physics mass in GeV of the ion (of beam 2)')
2786
2787 self.add_param("pdlabel", "nn23lo1", allowed=['lhapdf', 'cteq6_m','cteq6_l', 'cteq6l1','nn23lo', 'nn23lo1', 'nn23nlo']),
2788 self.add_param("lhaid", 230000, hidden=True)
2789 self.add_param("fixed_ren_scale", False)
2790 self.add_param("fixed_fac_scale", False)
2791 self.add_param("scale", 91.1880)
2792 self.add_param("dsqrt_q2fact1", 91.1880, fortran_name="sf1")
2793 self.add_param("dsqrt_q2fact2", 91.1880, fortran_name="sf2")
2794 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",
2795 allowed=[-1,0,1,2,3,4])
2796
2797
2798 self.add_param("bias_module", 'None', include=False)
2799 self.add_param('bias_parameters', {'__type__':1.0}, include='BIAS/bias.inc')
2800
2801
2802 self.add_param("scalefact", 1.0)
2803 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.")
2804 self.add_param("highestmult", 1, fortran_name="nhmult", hidden=True)
2805 self.add_param("ktscheme", 1, hidden=True)
2806 self.add_param("alpsfact", 1.0)
2807 self.add_param("chcluster", False, hidden=True)
2808 self.add_param("pdfwgt", True, hidden=True)
2809 self.add_param("asrwgtflavor", 5, comment = 'highest quark flavor for a_s reweighting in MLM')
2810 self.add_param("clusinfo", True)
2811 self.add_param("lhe_version", 3.0)
2812 self.add_param("event_norm", "average", allowed=['sum','average', 'unity'],
2813 include=False, sys_default='sum')
2814
2815 self.add_param("auto_ptj_mjj", False)
2816 self.add_param("bwcutoff", 15.0)
2817 self.add_param("cut_decays", False)
2818 self.add_param("nhel", 0, include=False)
2819
2820 self.add_param("ptj", 20.0, cut=True)
2821 self.add_param("ptb", 0.0, cut=True)
2822 self.add_param("pta", 10.0, cut=True)
2823 self.add_param("ptl", 10.0, cut=True)
2824 self.add_param("misset", 0.0, cut=True)
2825 self.add_param("ptheavy", 0.0, cut=True, comment='this cut apply on particle heavier than 10 GeV')
2826 self.add_param("ptonium", 1.0, legacy=True)
2827 self.add_param("ptjmax", -1.0, cut=True)
2828 self.add_param("ptbmax", -1.0, cut=True)
2829 self.add_param("ptamax", -1.0, cut=True)
2830 self.add_param("ptlmax", -1.0, cut=True)
2831 self.add_param("missetmax", -1.0, cut=True)
2832
2833 self.add_param("ej", 0.0, cut=True)
2834 self.add_param("eb", 0.0, cut=True)
2835 self.add_param("ea", 0.0, cut=True)
2836 self.add_param("el", 0.0, cut=True)
2837 self.add_param("ejmax", -1.0, cut=True)
2838 self.add_param("ebmax", -1.0, cut=True)
2839 self.add_param("eamax", -1.0, cut=True)
2840 self.add_param("elmax", -1.0, cut=True)
2841
2842 self.add_param("etaj", 5.0, cut=True)
2843 self.add_param("etab", -1.0, cut=True)
2844 self.add_param("etaa", 2.5, cut=True)
2845 self.add_param("etal", 2.5, cut=True)
2846 self.add_param("etaonium", 0.6, legacy=True)
2847 self.add_param("etajmin", 0.0, cut=True)
2848 self.add_param("etabmin", 0.0, cut=True)
2849 self.add_param("etaamin", 0.0, cut=True)
2850 self.add_param("etalmin", 0.0, cut=True)
2851
2852 self.add_param("drjj", 0.4, cut=True)
2853 self.add_param("drbb", 0.0, cut=True)
2854 self.add_param("drll", 0.4, cut=True)
2855 self.add_param("draa", 0.4, cut=True)
2856 self.add_param("drbj", 0.0, cut=True)
2857 self.add_param("draj", 0.4, cut=True)
2858 self.add_param("drjl", 0.4, cut=True)
2859 self.add_param("drab", 0.0, cut=True)
2860 self.add_param("drbl", 0.0, cut=True)
2861 self.add_param("dral", 0.4, cut=True)
2862 self.add_param("drjjmax", -1.0, cut=True)
2863 self.add_param("drbbmax", -1.0, cut=True)
2864 self.add_param("drllmax", -1.0, cut=True)
2865 self.add_param("draamax", -1.0, cut=True)
2866 self.add_param("drbjmax", -1.0, cut=True)
2867 self.add_param("drajmax", -1.0, cut=True)
2868 self.add_param("drjlmax", -1.0, cut=True)
2869 self.add_param("drabmax", -1.0, cut=True)
2870 self.add_param("drblmax", -1.0, cut=True)
2871 self.add_param("dralmax", -1.0, cut=True)
2872
2873 self.add_param("mmjj", 0.0, cut=True)
2874 self.add_param("mmbb", 0.0, cut=True)
2875 self.add_param("mmaa", 0.0, cut=True)
2876 self.add_param("mmll", 0.0, cut=True)
2877 self.add_param("mmjjmax", -1.0, cut=True)
2878 self.add_param("mmbbmax", -1.0, cut=True)
2879 self.add_param("mmaamax", -1.0, cut=True)
2880 self.add_param("mmllmax", -1.0, cut=True)
2881 self.add_param("mmnl", 0.0, cut=True)
2882 self.add_param("mmnlmax", -1.0, cut=True)
2883
2884 self.add_param("ptllmin", 0.0, cut=True)
2885 self.add_param("ptllmax", -1.0, cut=True)
2886 self.add_param("xptj", 0.0, cut=True)
2887 self.add_param("xptb", 0.0, cut=True)
2888 self.add_param("xpta", 0.0, cut=True)
2889 self.add_param("xptl", 0.0, cut=True)
2890
2891 self.add_param("ptj1min", 0.0, cut=True)
2892 self.add_param("ptj1max", -1.0, cut=True)
2893 self.add_param("ptj2min", 0.0, cut=True)
2894 self.add_param("ptj2max", -1.0, cut=True)
2895 self.add_param("ptj3min", 0.0, cut=True)
2896 self.add_param("ptj3max", -1.0, cut=True)
2897 self.add_param("ptj4min", 0.0, cut=True)
2898 self.add_param("ptj4max", -1.0, cut=True)
2899 self.add_param("cutuse", 0, cut=True)
2900
2901 self.add_param("ptl1min", 0.0, cut=True)
2902 self.add_param("ptl1max", -1.0, cut=True)
2903 self.add_param("ptl2min", 0.0, cut=True)
2904 self.add_param("ptl2max", -1.0, cut=True)
2905 self.add_param("ptl3min", 0.0, cut=True)
2906 self.add_param("ptl3max", -1.0, cut=True)
2907 self.add_param("ptl4min", 0.0, cut=True)
2908 self.add_param("ptl4max", -1.0, cut=True)
2909
2910 self.add_param("htjmin", 0.0, cut=True)
2911 self.add_param("htjmax", -1.0, cut=True)
2912 self.add_param("ihtmin", 0.0, cut=True)
2913 self.add_param("ihtmax", -1.0, cut=True)
2914 self.add_param("ht2min", 0.0, cut=True)
2915 self.add_param("ht3min", 0.0, cut=True)
2916 self.add_param("ht4min", 0.0, cut=True)
2917 self.add_param("ht2max", -1.0, cut=True)
2918 self.add_param("ht3max", -1.0, cut=True)
2919 self.add_param("ht4max", -1.0, cut=True)
2920
2921 self.add_param("ptgmin", 0.0, cut=True)
2922 self.add_param("r0gamma", 0.4)
2923 self.add_param("xn", 1.0)
2924 self.add_param("epsgamma", 1.0)
2925 self.add_param("isoem", True)
2926 self.add_param("xetamin", 0.0, cut=True)
2927 self.add_param("deltaeta", 0.0, cut=True)
2928 self.add_param("ktdurham", -1.0, fortran_name="kt_durham", cut=True)
2929 self.add_param("dparameter", 0.4, fortran_name="d_parameter", cut=True)
2930 self.add_param("ptlund", -1.0, fortran_name="pt_lund", cut=True)
2931 self.add_param("pdgs_for_merging_cut", [21, 1, 2, 3, 4, 5, 6])
2932 self.add_param("maxjetflavor", 4)
2933 self.add_param("xqcut", 0.0, cut=True)
2934 self.add_param("use_syst", True)
2935 self.add_param('systematics_program', 'systematics', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics, syscalc')
2936 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.')
2937
2938 self.add_param("sys_scalefact", "0.5 1 2", include=False, hidden=True)
2939 self.add_param("sys_alpsfact", "None", include=False, hidden=True)
2940 self.add_param("sys_matchscale", "auto", include=False, hidden=True)
2941 self.add_param("sys_pdf", "errorset", include=False, hidden=True)
2942 self.add_param("sys_scalecorrelation", -1, include=False, hidden=True)
2943
2944
2945 self.add_param('gridrun', False, hidden=True)
2946 self.add_param('fixed_couplings', True, hidden=True)
2947 self.add_param('mc_grouped_subproc', True, hidden=True)
2948 self.add_param('xmtcentral', 0.0, hidden=True, fortran_name="xmtc")
2949 self.add_param('d', 1.0, hidden=True)
2950 self.add_param('gseed', 0, hidden=True, include=False)
2951 self.add_param('issgridfile', '', hidden=True)
2952
2953 self.add_param('job_strategy', 0, hidden=True, include=False, allowed=[0,1,2], comment='see appendix of 1507.00020 (page 26)')
2954 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.")
2955 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")
2956 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)")
2957
2958
2959
2960 self.add_param('pt_min_pdg',{'__type__':0.}, include=False)
2961 self.add_param('pt_max_pdg',{'__type__':0.}, include=False)
2962 self.add_param('E_min_pdg',{'__type__':0.}, include=False)
2963 self.add_param('E_max_pdg',{'__type__':0.}, include=False)
2964 self.add_param('eta_min_pdg',{'__type__':0.}, include=False)
2965 self.add_param('eta_max_pdg',{'__type__':0.}, include=False)
2966 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
2967 self.add_param('mxx_only_part_antipart', {'default':False}, include=False)
2968
2969 self.add_param('pdg_cut',[0], system=True)
2970 self.add_param('ptmin4pdg',[0.], system=True)
2971 self.add_param('ptmax4pdg',[-1.], system=True)
2972 self.add_param('Emin4pdg',[0.], system=True)
2973 self.add_param('Emax4pdg',[-1.], system=True)
2974 self.add_param('etamin4pdg',[0.], system=True)
2975 self.add_param('etamax4pdg',[-1.], system=True)
2976 self.add_param('mxxmin4pdg',[-1.], system=True)
2977 self.add_param('mxxpart_antipart', [False], system=True)
2978
2979
2981 """ """
2982
2983 super(RunCardLO, self).check_validity()
2984
2985
2986
2987
2988 if 'nhel' not in self.user_set:
2989 raise InvalidRunCard, "Parameter nhel is not defined in the run_card."
2990 if self['nhel'] not in [1,0]:
2991 raise InvalidRunCard, "Parameter nhel can only be '0' or '1', "+\
2992 "not %s." % self['nhel']
2993 if int(self['maxjetflavor']) > 6:
2994 raise InvalidRunCard, 'maxjetflavor should be lower than 5! (6 is partly supported)'
2995
2996 if len(self['pdgs_for_merging_cut']) > 1000:
2997 raise InvalidRunCard, "The number of elements in "+\
2998 "'pdgs_for_merging_cut' should not exceed 1000."
2999
3000
3001 if self['ptgmin'] > 0:
3002 if self['pta'] > 0:
3003 logger.warning('pta cut discarded since photon isolation is used')
3004 self['pta'] = 0.0
3005 if self['draj'] > 0:
3006 logger.warning('draj cut discarded since photon isolation is used')
3007 self['draj'] = 0.0
3008
3009
3010 if self['gridrun']:
3011 self['iseed'] = self['gseed']
3012
3013
3014 if self['use_syst']:
3015 if self['scalefact'] != 1.0:
3016 logger.warning('Since use_syst=T, We change the value of \'scalefact\' to 1')
3017 self['scalefact'] = 1.0
3018
3019
3020 if self['ickkw'] > 0:
3021 if self['ickkw'] != 1:
3022 logger.critical('ickkw >1 is pure alpha and only partly implemented.')
3023 import madgraph.interface.extended_cmd as basic_cmd
3024 answer = basic_cmd.smart_input('Do you really want to continue', allow_arg=['y','n'], default='n')
3025 if answer !='y':
3026 raise InvalidRunCard, 'ickkw>1 is still in alpha'
3027 if self['use_syst']:
3028
3029 if self['alpsfact'] != 1.0:
3030 logger.warning('Since use_syst=T, We change the value of \'alpsfact\' to 1')
3031 self['alpsfact'] =1.0
3032 if self['maxjetflavor'] == 6:
3033 raise InvalidRunCard, 'maxjetflavor at 6 is NOT supported for matching!'
3034 if self['ickkw'] == 2:
3035
3036 self.get_default('highestmult', log_level=20)
3037 self.get_default('issgridfile', 'issudgrid.dat', log_level=20)
3038 if self['xqcut'] > 0:
3039 if self['ickkw'] == 0:
3040 logger.error('xqcut>0 but ickkw=0. Potentially not fully consistent setup. Be carefull')
3041 import time
3042 time.sleep(5)
3043 if self['drjj'] != 0:
3044 logger.warning('Since icckw>0, We change the value of \'drjj\' to 0')
3045 self['drjj'] = 0
3046 if self['drjl'] != 0:
3047 logger.warning('Since icckw>0, We change the value of \'drjl\' to 0')
3048 self['drjl'] = 0
3049 if not self['auto_ptj_mjj']:
3050 if self['mmjj'] > self['xqcut']:
3051 logger.warning('mmjj > xqcut (and auto_ptj_mjj = F). MMJJ set to 0')
3052 self['mmjj'] = 0.0
3053
3054
3055 if self['pdlabel'] == 'lhapdf':
3056
3057 self.get_default('lhaid', log_level=20)
3058
3060
3061
3062 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys() +
3063 self['e_min_pdg'].keys() +self['e_max_pdg'].keys() +
3064 self['eta_min_pdg'].keys() +self['eta_max_pdg'].keys()+
3065 self['mxx_min_pdg'].keys() + self['mxx_only_part_antipart'].keys())
3066 pdg_to_cut.discard('__type__')
3067 pdg_to_cut.discard('default')
3068 if len(pdg_to_cut)>25:
3069 raise Exception, "Maximum 25 different pdgs are allowed for pdg specific cut"
3070
3071 if any(int(pdg)<0 for pdg in pdg_to_cut):
3072 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes')
3073 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative pdg code'
3074
3075
3076 if any(pdg in pdg_to_cut for pdg in [1,2,3,4,5,21,22,11,13,15]):
3077 raise Exception, "Can not use PDG related cut for light quark/b quark/lepton/gluon/photon"
3078
3079 if pdg_to_cut:
3080 self['pdg_cut'] = list(pdg_to_cut)
3081 self['ptmin4pdg'] = []
3082 self['Emin4pdg'] = []
3083 self['etamin4pdg'] =[]
3084 self['ptmax4pdg'] = []
3085 self['Emax4pdg'] = []
3086 self['etamax4pdg'] =[]
3087 self['mxxmin4pdg'] =[]
3088 self['mxxpart_antipart'] = []
3089 for pdg in self['pdg_cut']:
3090 for var in ['pt','e','eta', 'Mxx']:
3091 for minmax in ['min', 'max']:
3092 if var in ['Mxx'] and minmax =='max':
3093 continue
3094 new_var = '%s%s4pdg' % (var, minmax)
3095 old_var = '%s_%s_pdg' % (var, minmax)
3096 default = 0. if minmax=='min' else -1.
3097 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3098
3099 old_var = 'mxx_only_part_antipart'
3100 new_var = 'mxxpart_antipart'
3101 if 'default' in self[old_var]:
3102 default = self[old_var]['default']
3103 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3104 else:
3105 if str(pdg) not in self[old_var]:
3106 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg))
3107 self[new_var].append(self[old_var][str(pdg)])
3108 else:
3109 self['pdg_cut'] = [0]
3110 self['ptmin4pdg'] = [0.]
3111 self['Emin4pdg'] = [0.]
3112 self['etamin4pdg'] =[0.]
3113 self['ptmax4pdg'] = [-1.]
3114 self['Emax4pdg'] = [-1.]
3115 self['etamax4pdg'] =[-1.]
3116 self['mxxmin4pdg'] =[0.]
3117 self['mxxpart_antipart'] = [False]
3118
3119
3120
3122 """Rules
3123 process 1->N all cut set on off.
3124 loop_induced -> MC over helicity
3125 e+ e- beam -> lpp:0 ebeam:500
3126 p p beam -> set maxjetflavor automatically
3127 more than one multiplicity: ickkw=1 xqcut=30 use_syst=F
3128 """
3129
3130 if proc_characteristic['loop_induced']:
3131 self['nhel'] = 1
3132 self['pdgs_for_merging_cut'] = proc_characteristic['colored_pdgs']
3133
3134 if proc_characteristic['ninitial'] == 1:
3135
3136 self.remove_all_cut()
3137 self['use_syst'] = False
3138 else:
3139
3140 beam_id = set()
3141 for proc in proc_def:
3142 for oneproc in proc:
3143 for leg in oneproc['legs']:
3144 if not leg['state']:
3145 beam_id.add(leg['id'])
3146 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]):
3147 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7])
3148 self['maxjetflavor'] = maxjetflavor
3149 self['asrwgtflavor'] = maxjetflavor
3150 pass
3151 elif 11 in beam_id or -11 in beam_id:
3152 self['lpp1'] = 0
3153 self['lpp2'] = 0
3154 self['ebeam1'] = 500
3155 self['ebeam2'] = 500
3156 self['use_syst'] = False
3157 else:
3158 self['lpp1'] = 0
3159 self['lpp2'] = 0
3160 self['use_syst'] = False
3161
3162
3163 min_particle = 99
3164 max_particle = 0
3165 for proc in proc_def:
3166 min_particle = min(len(proc[0]['legs']), min_particle)
3167 max_particle = max(len(proc[0]['legs']), max_particle)
3168 if min_particle != max_particle:
3169
3170 for procmin in proc_def:
3171 if len(procmin[0]['legs']) != min_particle:
3172 continue
3173 else:
3174 idsmin = [l['id'] for l in procmin[0]['legs']]
3175 break
3176 matching = False
3177 for procmax in proc_def:
3178 if len(procmax[0]['legs']) != max_particle:
3179 continue
3180 idsmax = [l['id'] for l in procmax[0]['legs']]
3181 for i in idsmin:
3182 if i not in idsmax:
3183 continue
3184 else:
3185 idsmax.remove(i)
3186 for j in idsmax:
3187 if j not in [1,-1,2,-2,3,-3,4,-4,5,-5,21]:
3188 break
3189 else:
3190
3191 matching=True
3192 break
3193
3194 if matching:
3195 self['ickkw'] = 1
3196 self['xqcut'] = 30
3197
3198 self['drjj'] = 0
3199 self['drjl'] = 0
3200 self['sys_alpsfact'] = "0.5 1 2"
3201
3202
3203
3204 no_systematics = False
3205 for proc in proc_def:
3206 for oneproc in proc:
3207 if '^2' in oneproc.nice_string():
3208 no_systematics = True
3209 break
3210 else:
3211 continue
3212 break
3213 if no_systematics:
3214 self['use_syst'] = False
3215 self['systematics_program'] = 'none'
3216
3217 - def write(self, output_file, template=None, python_template=False,
3218 **opt):
3219 """Write the run_card in output_file according to template
3220 (a path to a valid run_card)"""
3221
3222 if not template:
3223 if not MADEVENT:
3224 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards',
3225 'run_card.dat')
3226 python_template = True
3227 else:
3228 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat')
3229 python_template = False
3230
3231 super(RunCardLO, self).write(output_file, template=template,
3232 python_template=python_template, **opt)
3233
3237
3239 """ A class to store a MadAnalysis5 card. Very basic since it is basically
3240 free format."""
3241
3242 _MG5aMC_escape_tag = '@MG5aMC'
3243
3244 _default_hadron_inputs = ['*.hepmc', '*.hep', '*.stdhep', '*.lhco','*.root']
3245 _default_parton_inputs = ['*.lhe']
3246 _skip_analysis = False
3247
3248 @classmethod
3250 """ Checks from the type of an event file whether it can be reconstructed or not."""
3251 return not (file_path.endswith('.lhco') or file_path.endswith('.lhco.gz') or \
3252 file_path.endswith('.root') or file_path.endswith('.root.gz'))
3253
3254 @classmethod
3256 """ A method returning the structure of an empty analysis """
3257 return {'commands':[],
3258 'reconstructions':[]}
3259
3260 @classmethod
3262 """ A method returning the structure of an empty reconstruction """
3263 return {'commands':[],
3264 'reco_output':'lhe'}
3265
3267 """define the default value"""
3268 self['mode'] = 'parton'
3269 self['inputs'] = []
3270
3271 self['stdout_lvl'] = None
3272
3273
3274
3275
3276
3277
3278
3279 self['analyses'] = {}
3280
3281
3282 self['recasting'] = {'commands':[],'card':[]}
3283
3284
3285 self['reconstruction'] = {'lhco_input':
3286 MadAnalysis5Card.empty_reconstruction(),
3287 'root_input':
3288 MadAnalysis5Card.empty_reconstruction()}
3289 self['reconstruction']['lhco_input']['reco_output']='lhco'
3290 self['reconstruction']['root_input']['reco_output']='root'
3291
3292
3293 self['order'] = []
3294
3295 - def __init__(self, finput=None,mode=None):
3296 if isinstance(finput, self.__class__):
3297 dict.__init__(self, finput)
3298 assert finput.__dict__.keys()
3299 for key in finput.__dict__:
3300 setattr(self, key, copy.copy(getattr(finput, key)) )
3301 return
3302 else:
3303 dict.__init__(self)
3304
3305
3306 self.default_setup()
3307 if not mode is None:
3308 self['mode']=mode
3309
3310
3311 if isinstance(finput, (file, str, StringIO.StringIO)):
3312 self.read(finput, mode=mode)
3313
3314 - def read(self, input, mode=None):
3315 """ Read an MA5 card"""
3316
3317 if mode not in [None,'parton','hadron']:
3318 raise MadGraph5Error('A MadAnalysis5Card can be read online the modes'+
3319 "'parton' or 'hadron'")
3320 card_mode = mode
3321
3322 if isinstance(input, (file, StringIO.StringIO)):
3323 input_stream = input
3324 elif isinstance(input, str):
3325 if not os.path.isfile(input):
3326 raise InvalidMadAnalysis5Card("Cannot read the MadAnalysis5 card."+\
3327 "File '%s' not found."%input)
3328 if mode is None and 'hadron' in input:
3329 card_mode = 'hadron'
3330 input_stream = open(input,'r')
3331 else:
3332 raise MadGraph5Error('Incorrect input for the read function of'+\
3333 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(input)))
3334
3335
3336 self.__init__()
3337 current_name = 'default'
3338 current_type = 'analyses'
3339 for line in input_stream:
3340
3341 if line.startswith('#'):
3342 continue
3343 if line.endswith('\n'):
3344 line = line[:-1]
3345 if line.strip()=='':
3346 continue
3347 if line.startswith(self._MG5aMC_escape_tag):
3348 try:
3349 option,value = line[len(self._MG5aMC_escape_tag):].split('=')
3350 value = value.strip()
3351 except ValueError:
3352 option = line[len(self._MG5aMC_escape_tag):]
3353 option = option.strip()
3354
3355 if option=='inputs':
3356 self['inputs'].extend([v.strip() for v in value.split(',')])
3357
3358 elif option == 'skip_analysis':
3359 self._skip_analysis = True
3360
3361 elif option=='stdout_lvl':
3362 try:
3363 self['stdout_lvl']=int(value)
3364 except ValueError:
3365 try:
3366 self['stdout_lvl']=eval(value)
3367 except:
3368 try:
3369 self['stdout_lvl']=eval('logging.%s'%value)
3370 except:
3371 raise InvalidMadAnalysis5Card(
3372 "MA5 output level specification '%s' is incorrect."%str(value))
3373
3374 elif option=='analysis_name':
3375 current_type = 'analyses'
3376 current_name = value
3377 if current_name in self[current_type]:
3378 raise InvalidMadAnalysis5Card(
3379 "Analysis '%s' already defined in MadAnalysis5 card"%current_name)
3380 else:
3381 self[current_type][current_name] = MadAnalysis5Card.empty_analysis()
3382
3383 elif option=='set_reconstructions':
3384 try:
3385 reconstructions = eval(value)
3386 if not isinstance(reconstructions, list):
3387 raise
3388 except:
3389 raise InvalidMadAnalysis5Card("List of reconstructions"+\
3390 " '%s' could not be parsed in MadAnalysis5 card."%value)
3391 if current_type!='analyses' and current_name not in self[current_type]:
3392 raise InvalidMadAnalysis5Card("A list of reconstructions"+\
3393 "can only be defined in the context of an "+\
3394 "analysis in a MadAnalysis5 card.")
3395 self[current_type][current_name]['reconstructions']=reconstructions
3396 continue
3397
3398 elif option=='reconstruction_name':
3399 current_type = 'reconstruction'
3400 current_name = value
3401 if current_name in self[current_type]:
3402 raise InvalidMadAnalysis5Card(
3403 "Reconstruction '%s' already defined in MadAnalysis5 hadron card"%current_name)
3404 else:
3405 self[current_type][current_name] = MadAnalysis5Card.empty_reconstruction()
3406
3407 elif option=='reco_output':
3408 if current_type!='reconstruction' or current_name not in \
3409 self['reconstruction']:
3410 raise InvalidMadAnalysis5Card(
3411 "Option '%s' is only available within the definition of a reconstruction"%option)
3412 if not value.lower() in ['lhe','root']:
3413 raise InvalidMadAnalysis5Card(
3414 "Option '%s' can only take the values 'lhe' or 'root'"%option)
3415 self['reconstruction'][current_name]['reco_output'] = value.lower()
3416
3417 elif option.startswith('recasting'):
3418 current_type = 'recasting'
3419 try:
3420 current_name = option.split('_')[1]
3421 except:
3422 raise InvalidMadAnalysis5Card('Malformed MA5 recasting option %s.'%option)
3423 if len(self['recasting'][current_name])>0:
3424 raise InvalidMadAnalysis5Card(
3425 "Only one recasting can be defined in MadAnalysis5 hadron card")
3426
3427 else:
3428 raise InvalidMadAnalysis5Card(
3429 "Unreckognized MG5aMC instruction in MadAnalysis5 card: '%s'"%option)
3430
3431 if option in ['analysis_name','reconstruction_name'] or \
3432 option.startswith('recasting'):
3433 self['order'].append((current_type,current_name))
3434 continue
3435
3436
3437
3438 if current_name == 'default' and current_type == 'analyses' and\
3439 'default' not in self['analyses']:
3440 self['analyses']['default'] = MadAnalysis5Card.empty_analysis()
3441 self['order'].append(('analyses','default'))
3442
3443 if current_type in ['recasting']:
3444 self[current_type][current_name].append(line)
3445 elif current_type in ['reconstruction']:
3446 self[current_type][current_name]['commands'].append(line)
3447 elif current_type in ['analyses']:
3448 self[current_type][current_name]['commands'].append(line)
3449
3450 if 'reconstruction' in self['analyses'] or len(self['recasting']['card'])>0:
3451 if mode=='parton':
3452 raise InvalidMadAnalysis5Card(
3453 "A parton MadAnalysis5 card cannot specify a recombination or recasting.")
3454 card_mode = 'hadron'
3455 elif mode is None:
3456 card_mode = 'parton'
3457
3458 self['mode'] = card_mode
3459 if self['inputs'] == []:
3460 if self['mode']=='hadron':
3461 self['inputs'] = self._default_hadron_inputs
3462 else:
3463 self['inputs'] = self._default_parton_inputs
3464
3465
3466
3467 if self['mode']=='hadron':
3468 for analysis_name, analysis in self['analyses'].items():
3469 if len(analysis['reconstructions'])==0:
3470 raise InvalidMadAnalysis5Card('Hadron-level analysis '+\
3471 "'%s' is not specified any reconstruction(s)."%analysis_name)
3472 if any(reco not in self['reconstruction'] for reco in \
3473 analysis['reconstructions']):
3474 raise InvalidMadAnalysis5Card('A reconstructions specified in'+\
3475 " analysis '%s' is not defined."%analysis_name)
3476
3477 - def write(self, output):
3478 """ Write an MA5 card."""
3479
3480 if isinstance(output, (file, StringIO.StringIO)):
3481 output_stream = output
3482 elif isinstance(output, str):
3483 output_stream = open(output,'w')
3484 else:
3485 raise MadGraph5Error('Incorrect input for the write function of'+\
3486 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(output)))
3487
3488 output_lines = []
3489 if self._skip_analysis:
3490 output_lines.append('%s skip_analysis'%self._MG5aMC_escape_tag)
3491 output_lines.append('%s inputs = %s'%(self._MG5aMC_escape_tag,','.join(self['inputs'])))
3492 if not self['stdout_lvl'] is None:
3493 output_lines.append('%s stdout_lvl=%s'%(self._MG5aMC_escape_tag,self['stdout_lvl']))
3494 for definition_type, name in self['order']:
3495
3496 if definition_type=='analyses':
3497 output_lines.append('%s analysis_name = %s'%(self._MG5aMC_escape_tag,name))
3498 output_lines.append('%s set_reconstructions = %s'%(self._MG5aMC_escape_tag,
3499 str(self['analyses'][name]['reconstructions'])))
3500 elif definition_type=='reconstruction':
3501 output_lines.append('%s reconstruction_name = %s'%(self._MG5aMC_escape_tag,name))
3502 elif definition_type=='recasting':
3503 output_lines.append('%s recasting_%s'%(self._MG5aMC_escape_tag,name))
3504
3505 if definition_type in ['recasting']:
3506 output_lines.extend(self[definition_type][name])
3507 elif definition_type in ['reconstruction']:
3508 output_lines.append('%s reco_output = %s'%(self._MG5aMC_escape_tag,
3509 self[definition_type][name]['reco_output']))
3510 output_lines.extend(self[definition_type][name]['commands'])
3511 elif definition_type in ['analyses']:
3512 output_lines.extend(self[definition_type][name]['commands'])
3513
3514 output_stream.write('\n'.join(output_lines))
3515
3516 return
3517
3518 - def get_MA5_cmds(self, inputs_arg, submit_folder, run_dir_path=None,
3519 UFO_model_path=None, run_tag=''):
3520 """ Returns a list of tuples ('AnalysisTag',['commands']) specifying
3521 the commands of the MadAnalysis runs required from this card.
3522 At parton-level, the number of such commands is the number of analysis
3523 asked for. In the future, the idea is that the entire card can be
3524 processed in one go from MA5 directly."""
3525
3526 if isinstance(inputs_arg, list):
3527 inputs = inputs_arg
3528 elif isinstance(inputs_arg, str):
3529 inputs = [inputs_arg]
3530 else:
3531 raise MadGraph5Error("The function 'get_MA5_cmds' can only take "+\
3532 " a string or a list for the argument 'inputs_arg'")
3533
3534 if len(inputs)==0:
3535 raise MadGraph5Error("The function 'get_MA5_cmds' must have "+\
3536 " at least one input specified'")
3537
3538 if run_dir_path is None:
3539 run_dir_path = os.path.dirname(inputs_arg)
3540
3541 cmds_list = []
3542
3543 UFO_load = []
3544
3545 if UFO_model_path:
3546 UFO_load.append('import %s'%UFO_model_path)
3547
3548 def get_import(input, type=None):
3549 """ Generates the MA5 import commands for that event file. """
3550 dataset_name = os.path.basename(input).split('.')[0]
3551 res = ['import %s as %s'%(input, dataset_name)]
3552 if not type is None:
3553 res.append('set %s.type = %s'%(dataset_name, type))
3554 return res
3555
3556 fifo_status = {'warned_fifo':False,'fifo_used_up':False}
3557 def warn_fifo(input):
3558 if not input.endswith('.fifo'):
3559 return False
3560 if not fifo_status['fifo_used_up']:
3561 fifo_status['fifo_used_up'] = True
3562 return False
3563 else:
3564 if not fifo_status['warned_fifo']:
3565 logger.warning('Only the first MA5 analysis/reconstructions can be run on a fifo. Subsequent runs will skip fifo inputs.')
3566 fifo_status['warned_fifo'] = True
3567 return True
3568
3569
3570 inputs_load = []
3571 for input in inputs:
3572 inputs_load.extend(get_import(input))
3573
3574 submit_command = 'submit %s'%submit_folder+'_%s'
3575
3576
3577
3578
3579 reconstruction_outputs = {
3580 'lhco_input':[f for f in inputs if
3581 f.endswith('.lhco') or f.endswith('.lhco.gz')],
3582 'root_input':[f for f in inputs if
3583 f.endswith('.root') or f.endswith('.root.gz')]}
3584
3585
3586 recasting_card_path = pjoin(run_dir_path,
3587 '_'.join([run_tag,os.path.basename(submit_folder),'recasting_card.dat']))
3588
3589
3590 for definition_type, name in self['order']:
3591 if definition_type == 'reconstruction':
3592 analysis_cmds = list(self['reconstruction'][name]['commands'])
3593 reco_outputs = []
3594 for i_input, input in enumerate(inputs):
3595
3596 if not MadAnalysis5Card.events_can_be_reconstructed(input):
3597 continue
3598
3599 if warn_fifo(input):
3600 continue
3601 analysis_cmds.append('import %s as reco_events'%input)
3602 if self['reconstruction'][name]['reco_output']=='lhe':
3603 reco_outputs.append('%s_%s.lhe.gz'%(os.path.basename(
3604 input).replace('_events','').split('.')[0],name))
3605 analysis_cmds.append('set main.outputfile=%s'%reco_outputs[-1])
3606 elif self['reconstruction'][name]['reco_output']=='root':
3607 reco_outputs.append('%s_%s.root'%(os.path.basename(
3608 input).replace('_events','').split('.')[0],name))
3609 analysis_cmds.append('set main.fastsim.rootfile=%s'%reco_outputs[-1])
3610 analysis_cmds.append(
3611 submit_command%('reco_%s_%d'%(name,i_input+1)))
3612 analysis_cmds.append('remove reco_events')
3613
3614 reconstruction_outputs[name]= [pjoin(run_dir_path,rec_out)
3615 for rec_out in reco_outputs]
3616 if len(reco_outputs)>0:
3617 cmds_list.append(('_reco_%s'%name,analysis_cmds))
3618
3619 elif definition_type == 'analyses':
3620 if self['mode']=='parton':
3621 cmds_list.append( (name, UFO_load+inputs_load+
3622 self['analyses'][name]['commands']+[submit_command%name]) )
3623 elif self['mode']=='hadron':
3624
3625 for reco in self['analyses'][name]['reconstructions']+\
3626 ['lhco_input','root_input']:
3627 if len(reconstruction_outputs[reco])==0:
3628 continue
3629 if self['reconstruction'][reco]['reco_output']=='lhe':
3630
3631 analysis_cmds = ['set main.mode = parton']
3632 else:
3633 analysis_cmds = []
3634 analysis_cmds.extend(sum([get_import(rec_out) for
3635 rec_out in reconstruction_outputs[reco]],[]))
3636 analysis_cmds.extend(self['analyses'][name]['commands'])
3637 analysis_cmds.append(submit_command%('%s_%s'%(name,reco)))
3638 cmds_list.append( ('%s_%s'%(name,reco),analysis_cmds) )
3639
3640 elif definition_type == 'recasting':
3641 if len(self['recasting']['card'])==0:
3642 continue
3643 if name == 'card':
3644
3645 open(recasting_card_path,'w').write('\n'.join(self['recasting']['card']))
3646 if name == 'commands':
3647 recasting_cmds = list(self['recasting']['commands'])
3648
3649 n_inputs = 0
3650 for input in inputs:
3651 if not MadAnalysis5Card.events_can_be_reconstructed(input):
3652 continue
3653
3654 if warn_fifo(input):
3655 continue
3656 recasting_cmds.extend(get_import(input,'signal'))
3657 n_inputs += 1
3658
3659 recasting_cmds.append('set main.recast.card_path=%s'%recasting_card_path)
3660 recasting_cmds.append(submit_command%'Recasting')
3661 if n_inputs>0:
3662 cmds_list.append( ('Recasting',recasting_cmds))
3663
3664 return cmds_list
3665
3667 """A class object for the run_card for a (aMC@)NLO pocess"""
3668
3670 """define the default value"""
3671
3672 self.add_param('run_tag', 'tag_1', include=False)
3673 self.add_param('nevents', 10000)
3674 self.add_param('req_acc', -1.0, include=False)
3675 self.add_param('nevt_job', -1, include=False)
3676 self.add_param('event_norm', 'average')
3677
3678 self.add_param('req_acc_fo', 0.01, include=False)
3679 self.add_param('npoints_fo_grid', 5000, include=False)
3680 self.add_param('niters_fo_grid', 4, include=False)
3681 self.add_param('npoints_fo', 10000, include=False)
3682 self.add_param('niters_fo', 6, include=False)
3683
3684 self.add_param('iseed', 0)
3685 self.add_param('lpp1', 1, fortran_name='lpp(1)')
3686 self.add_param('lpp2', 1, fortran_name='lpp(2)')
3687 self.add_param('ebeam1', 6500.0, fortran_name='ebeam(1)')
3688 self.add_param('ebeam2', 6500.0, fortran_name='ebeam(2)')
3689 self.add_param('pdlabel', 'nn23nlo', allowed=['lhapdf', 'cteq6_m','cteq6_d','cteq6_l','cteq6l1', 'nn23lo','nn23lo1','nn23nlo','ct14q00','ct14q07','ct14q14','ct14q21'])
3690 self.add_param('lhaid', [244600],fortran_name='lhaPDFid')
3691 self.add_param('lhapdfsetname', ['internal_use_only'], system=True)
3692
3693 self.add_param('parton_shower', 'HERWIG6', fortran_name='shower_mc')
3694 self.add_param('shower_scale_factor',1.0)
3695 self.add_param('fixed_ren_scale', False)
3696 self.add_param('fixed_fac_scale', False)
3697 self.add_param('mur_ref_fixed', 91.118)
3698 self.add_param('muf1_ref_fixed', -1.0, hidden=True)
3699 self.add_param('muf_ref_fixed', 91.118)
3700 self.add_param('muf2_ref_fixed', -1.0, hidden=True)
3701 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")
3702 self.add_param('fixed_qes_scale', False, hidden=True)
3703 self.add_param('qes_ref_fixed', -1.0, hidden=True)
3704 self.add_param('mur_over_ref', 1.0)
3705 self.add_param('muf_over_ref', 1.0)
3706 self.add_param('muf1_over_ref', -1.0, hidden=True)
3707 self.add_param('muf2_over_ref', -1.0, hidden=True)
3708 self.add_param('qes_over_ref', -1.0, hidden=True)
3709 self.add_param('reweight_scale', [True], fortran_name='lscalevar')
3710 self.add_param('rw_rscale_down', -1.0, hidden=True)
3711 self.add_param('rw_rscale_up', -1.0, hidden=True)
3712 self.add_param('rw_fscale_down', -1.0, hidden=True)
3713 self.add_param('rw_fscale_up', -1.0, hidden=True)
3714 self.add_param('rw_rscale', [1.0,2.0,0.5], fortran_name='scalevarR')
3715 self.add_param('rw_fscale', [1.0,2.0,0.5], fortran_name='scalevarF')
3716 self.add_param('reweight_pdf', [False], fortran_name='lpdfvar')
3717 self.add_param('pdf_set_min', 244601, hidden=True)
3718 self.add_param('pdf_set_max', 244700, hidden=True)
3719 self.add_param('store_rwgt_info', False)
3720 self.add_param('systematics_program', 'none', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics')
3721 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.')
3722
3723
3724 self.add_param('ickkw', 0)
3725 self.add_param('bwcutoff', 15.0)
3726
3727 self.add_param('jetalgo', 1.0)
3728 self.add_param('jetradius', 0.7)
3729 self.add_param('ptj', 10.0 , cut=True)
3730 self.add_param('etaj', -1.0, cut=True)
3731 self.add_param('gamma_is_j', 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('rphreco', 0.1)
3739 self.add_param('etaphreco', -1.0)
3740 self.add_param('lepphreco', True)
3741 self.add_param('quarkphreco', True)
3742 self.add_param('ptgmin', 20.0, cut=True)
3743 self.add_param('etagamma', -1.0)
3744 self.add_param('r0gamma', 0.4)
3745 self.add_param('xn', 1.0)
3746 self.add_param('epsgamma', 1.0)
3747 self.add_param('isoem', True)
3748 self.add_param('maxjetflavor', 4, hidden=True)
3749 self.add_param('iappl', 0)
3750 self.add_param('lhe_version', 3, hidden=True, include=False)
3751
3752
3753 self.add_param('FO_LHE_weight_ratio',1e-3, hidden=True, system=True)
3754 self.add_param('FO_LHE_postprocessing',['grouping','random'],
3755 hidden=True, system=True, include=False)
3756
3757
3758 self.add_param('pt_min_pdg',{'__type__':0.}, include=False)
3759 self.add_param('pt_max_pdg',{'__type__':0.}, include=False)
3760 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
3761 self.add_param('mxx_only_part_antipart', {'default':False}, include=False, hidden=True)
3762
3763
3764 self.add_param('pdg_cut',[0], hidden=True, system=True)
3765 self.add_param('ptmin4pdg',[0.], hidden=True, system=True)
3766 self.add_param('ptmax4pdg',[-1.], hidden=True, system=True)
3767 self.add_param('mxxmin4pdg',[0.], hidden=True, system=True)
3768 self.add_param('mxxpart_antipart', [False], hidden=True, system=True)
3769
3771 """check the validity of the various input"""
3772
3773 super(RunCardNLO, self).check_validity()
3774
3775
3776 if self['lpp1']==0 and self['lpp2']==0:
3777 if self['pdlabel']!='nn23nlo' or self['reweight_pdf']:
3778 self['pdlabel']='nn23nlo'
3779 self['reweight_pdf']=[False]
3780 logger.info('''Lepton-lepton collisions: ignoring PDF related parameters in the run_card.dat (pdlabel, lhaid, reweight_pdf, ...)''')
3781
3782
3783 if self['ickkw'] == 3:
3784
3785 scales=['fixed_ren_scale','fixed_fac_scale','fixed_QES_scale']
3786 for scale in scales:
3787 if self[scale]:
3788 logger.warning('''For consistency in the FxFx merging, \'%s\' has been set to false'''
3789 % scale,'$MG:BOLD')
3790 self[scale]= False
3791
3792 if len(self["dynamical_scale_choice"]) > 1 or self["dynamical_scale_choice"][0] != -1:
3793 self["dynamical_scale_choice"] = [-1]
3794 self["reweight_scale"]=[self["reweight_scale"][0]]
3795 logger.warning('''For consistency in the FxFx merging, dynamical_scale_choice has been set to -1 (default)'''
3796 ,'$MG:BOLD')
3797
3798
3799 jetparams=['jetradius','jetalgo']
3800 for jetparam in jetparams:
3801 if float(self[jetparam]) != 1.0:
3802 logger.info('''For consistency in the FxFx merging, \'%s\' has been set to 1.0'''
3803 % jetparam ,'$MG:BOLD')
3804 self[jetparam] = 1.0
3805 elif self['ickkw'] == -1 and (self["dynamical_scale_choice"][0] != -1 or
3806 len(self["dynamical_scale_choice"]) > 1):
3807 self["dynamical_scale_choice"] = [-1]
3808 self["reweight_scale"]=[self["reweight_scale"][0]]
3809 logger.warning('''For consistency with the jet veto, the scale which will be used is ptj. dynamical_scale_choice will be set at -1.'''
3810 ,'$MG:BOLD')
3811
3812
3813 if self['iappl'] != 0 and self['pdlabel'].lower() != 'lhapdf':
3814 raise InvalidRunCard('APPLgrid generation only possible with the use of LHAPDF')
3815 if self['iappl'] != 0 and not self['reweight_scale']:
3816 raise InvalidRunCard('APPLgrid generation only possible with including' +\
3817 ' the reweighting to get scale dependence')
3818
3819
3820 if self['qes_ref_fixed'] == -1.0:
3821 self['qes_ref_fixed']=self['mur_ref_fixed']
3822 if self['qes_over_ref'] == -1.0:
3823 self['qes_over_ref']=self['mur_over_ref']
3824 if self['muf1_over_ref'] != -1.0 and self['muf1_over_ref'] == self['muf2_over_ref']:
3825 self['muf_over_ref']=self['muf1_over_ref']
3826 if self['muf1_over_ref'] == -1.0:
3827 self['muf1_over_ref']=self['muf_over_ref']
3828 if self['muf2_over_ref'] == -1.0:
3829 self['muf2_over_ref']=self['muf_over_ref']
3830 if self['muf1_ref_fixed'] != -1.0 and self['muf1_ref_fixed'] == self['muf2_ref_fixed']:
3831 self['muf_ref_fixed']=self['muf1_ref_fixed']
3832 if self['muf1_ref_fixed'] == -1.0:
3833 self['muf1_ref_fixed']=self['muf_ref_fixed']
3834 if self['muf2_ref_fixed'] == -1.0:
3835 self['muf2_ref_fixed']=self['muf_ref_fixed']
3836
3837 if (self['rw_rscale_down'] != -1.0 and ['rw_rscale_down'] not in self['rw_rscale']) or\
3838 (self['rw_rscale_up'] != -1.0 and ['rw_rscale_up'] not in self['rw_rscale']):
3839 self['rw_rscale']=[1.0,self['rw_rscale_up'],self['rw_rscale_down']]
3840 if (self['rw_fscale_down'] != -1.0 and ['rw_fscale_down'] not in self['rw_fscale']) or\
3841 (self['rw_fscale_up'] != -1.0 and ['rw_fscale_up'] not in self['rw_fscale']):
3842 self['rw_fscale']=[1.0,self['rw_fscale_up'],self['rw_fscale_down']]
3843
3844
3845 if any(self['reweight_pdf']):
3846
3847 if self['pdlabel'] != "lhapdf":
3848 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.'
3849
3850
3851 if self['pdlabel'] != "lhapdf":
3852 self['reweight_pdf']=[self['reweight_pdf'][0]]
3853 self['lhaid']=[self['lhaid'][0]]
3854
3855
3856 if self['fixed_ren_scale'] and self['fixed_fac_scale']:
3857 self['reweight_scale']=[self['reweight_scale'][0]]
3858 self['dynamical_scale_choice']=[0]
3859
3860
3861
3862
3863 if len(self['reweight_pdf']) == 1 and len(self['lhaid']) != 1:
3864 self['reweight_pdf']=self['reweight_pdf']*len(self['lhaid'])
3865 logger.warning("Setting 'reweight_pdf' for all 'lhaid' to %s" % self['reweight_pdf'][0])
3866 if len(self['reweight_scale']) == 1 and len(self['dynamical_scale_choice']) != 1:
3867 self['reweight_scale']=self['reweight_scale']*len(self['dynamical_scale_choice'])
3868 logger.warning("Setting 'reweight_scale' for all 'dynamical_scale_choice' to %s" % self['reweight_pdf'][0])
3869
3870
3871 if len(self['lhaid']) != len(set(self['lhaid'])):
3872 raise InvalidRunCard, "'lhaid' has two or more identical entries. They have to be all different for the code to work correctly."
3873 if len(self['dynamical_scale_choice']) != len(set(self['dynamical_scale_choice'])):
3874 raise InvalidRunCard, "'dynamical_scale_choice' has two or more identical entries. They have to be all different for the code to work correctly."
3875
3876
3877 if len(self['reweight_pdf']) != len(self['lhaid']):
3878 raise InvalidRunCard, "'reweight_pdf' and 'lhaid' lists should have the same length"
3879 if len(self['reweight_scale']) != len(self['dynamical_scale_choice']):
3880 raise InvalidRunCard, "'reweight_scale' and 'dynamical_scale_choice' lists should have the same length"
3881 if len(self['dynamical_scale_choice']) > 10 :
3882 raise InvalidRunCard, "Length of list for 'dynamical_scale_choice' too long: max is 10."
3883 if len(self['lhaid']) > 25 :
3884 raise InvalidRunCard, "Length of list for 'lhaid' too long: max is 25."
3885 if len(self['rw_rscale']) > 9 :
3886 raise InvalidRunCard, "Length of list for 'rw_rscale' too long: max is 9."
3887 if len(self['rw_fscale']) > 9 :
3888 raise InvalidRunCard, "Length of list for 'rw_fscale' too long: max is 9."
3889
3890 if 1.0 not in self['rw_rscale']:
3891 logger.warning("'1.0' has to be part of 'rw_rscale', adding it")
3892 self['rw_rscale'].insert(0,1.0)
3893 if 1.0 not in self['rw_fscale']:
3894 logger.warning("'1.0' has to be part of 'rw_fscale', adding it")
3895 self['rw_fscale'].insert(0,1.0)
3896 if self['rw_rscale'][0] != 1.0 and 1.0 in self['rw_rscale']:
3897 a=self['rw_rscale'].index(1.0)
3898 self['rw_rscale'][0],self['rw_rscale'][a]=self['rw_rscale'][a],self['rw_rscale'][0]
3899 if self['rw_fscale'][0] != 1.0 and 1.0 in self['rw_fscale']:
3900 a=self['rw_fscale'].index(1.0)
3901 self['rw_fscale'][0],self['rw_fscale'][a]=self['rw_fscale'][a],self['rw_fscale'][0]
3902
3903 if len(self['rw_rscale']) != len(set(self['rw_rscale'])):
3904 raise InvalidRunCard, "'rw_rscale' has two or more identical entries. They have to be all different for the code to work correctly."
3905 if len(self['rw_fscale']) != len(set(self['rw_fscale'])):
3906 raise InvalidRunCard, "'rw_fscale' has two or more identical entries. They have to be all different for the code to work correctly."
3907
3908
3910
3911
3912 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys()+
3913 self['mxx_min_pdg'].keys()+ self['mxx_only_part_antipart'].keys())
3914 pdg_to_cut.discard('__type__')
3915 pdg_to_cut.discard('default')
3916 if len(pdg_to_cut)>25:
3917 raise Exception, "Maximum 25 different PDGs are allowed for PDG specific cut"
3918
3919 if any(int(pdg)<0 for pdg in pdg_to_cut):
3920 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes')
3921 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative PDG codes'
3922
3923
3924 if any(pdg in pdg_to_cut for pdg in [21,22,11,13,15]+ range(self['maxjetflavor']+1)):
3925
3926 raise Exception, "Can not use PDG related cuts for massless SM particles/leptons"
3927 if pdg_to_cut:
3928 self['pdg_cut'] = list(pdg_to_cut)
3929 self['ptmin4pdg'] = []
3930 self['ptmax4pdg'] = []
3931 self['mxxmin4pdg'] = []
3932 self['mxxpart_antipart'] = []
3933 for pdg in self['pdg_cut']:
3934 for var in ['pt','mxx']:
3935 for minmax in ['min', 'max']:
3936 if var == 'mxx' and minmax == 'max':
3937 continue
3938 new_var = '%s%s4pdg' % (var, minmax)
3939 old_var = '%s_%s_pdg' % (var, minmax)
3940 default = 0. if minmax=='min' else -1.
3941 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3942
3943 old_var = 'mxx_only_part_antipart'
3944 new_var = 'mxxpart_antipart'
3945 if 'default' in self[old_var]:
3946 default = self[old_var]['default']
3947 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3948 else:
3949 if str(pdg) not in self[old_var]:
3950 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg))
3951 self[new_var].append(self[old_var][str(pdg)])
3952 else:
3953 self['pdg_cut'] = [0]
3954 self['ptmin4pdg'] = [0.]
3955 self['ptmax4pdg'] = [-1.]
3956 self['mxxmin4pdg'] = [0.]
3957 self['mxxpart_antipart'] = [False]
3958
3959 - def write(self, output_file, template=None, python_template=False, **opt):
3960 """Write the run_card in output_file according to template
3961 (a path to a valid run_card)"""
3962
3963 if not template:
3964 if not MADEVENT:
3965 template = pjoin(MG5DIR, 'Template', 'NLO', 'Cards',
3966 'run_card.dat')
3967 python_template = True
3968 else:
3969 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat')
3970 python_template = False
3971
3972 super(RunCardNLO, self).write(output_file, template=template,
3973 python_template=python_template, **opt)
3974
3975
3977 """Rules
3978 e+ e- beam -> lpp:0 ebeam:500
3979 p p beam -> set maxjetflavor automatically
3980 """
3981
3982
3983 beam_id = set()
3984 for proc in proc_def:
3985 for leg in proc['legs']:
3986 if not leg['state']:
3987 beam_id.add(leg['id'])
3988 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]):
3989 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7])
3990 self['maxjetflavor'] = maxjetflavor
3991 pass
3992 elif 11 in beam_id or -11 in beam_id:
3993 self['lpp1'] = 0
3994 self['lpp2'] = 0
3995 self['ebeam1'] = 500
3996 self['ebeam2'] = 500
3997 else:
3998 self['lpp1'] = 0
3999 self['lpp2'] = 0
4000
4001 if proc_characteristic['ninitial'] == 1:
4002
4003 self.remove_all_cut()
4004
4008 """ a class for storing/dealing with the file MadLoopParam.dat
4009 contains a parser to read it, facilities to write a new file,...
4010 """
4011
4012 _ID_reduction_tool_map = {1:'CutTools',
4013 2:'PJFry++',
4014 3:'IREGI',
4015 4:'Golem95',
4016 5:'Samurai',
4017 6:'Ninja',
4018 7:'COLLIER'}
4019
4021 """initialize the directory to the default value"""
4022
4023 self.add_param("MLReductionLib", "6|7|1")
4024 self.add_param("IREGIMODE", 2)
4025 self.add_param("IREGIRECY", True)
4026 self.add_param("CTModeRun", -1)
4027 self.add_param("MLStabThres", 1e-3)
4028 self.add_param("NRotations_DP", 0)
4029 self.add_param("NRotations_QP", 0)
4030 self.add_param("ImprovePSPoint", 2)
4031 self.add_param("CTLoopLibrary", 2)
4032 self.add_param("CTStabThres", 1e-2)
4033 self.add_param("CTModeInit", 1)
4034 self.add_param("CheckCycle", 3)
4035 self.add_param("MaxAttempts", 10)
4036 self.add_param("ZeroThres", 1e-9)
4037 self.add_param("OSThres", 1.0e-8)
4038 self.add_param("DoubleCheckHelicityFilter", True)
4039 self.add_param("WriteOutFilters", True)
4040 self.add_param("UseLoopFilter", False)
4041 self.add_param("HelicityFilterLevel", 2)
4042 self.add_param("LoopInitStartOver", False)
4043 self.add_param("HelInitStartOver", False)
4044 self.add_param("UseQPIntegrandForNinja", True)
4045 self.add_param("UseQPIntegrandForCutTools", True)
4046 self.add_param("COLLIERMode", 1)
4047 self.add_param("COLLIERComputeUVpoles", True)
4048 self.add_param("COLLIERComputeIRpoles", True)
4049 self.add_param("COLLIERRequiredAccuracy", 1.0e-8)
4050 self.add_param("COLLIERCanOutput",False)
4051 self.add_param("COLLIERGlobalCache",-1)
4052 self.add_param("COLLIERUseCacheForPoles",False)
4053 self.add_param("COLLIERUseInternalStabilityTest",True)
4054
4055 - def read(self, finput):
4056 """Read the input file, this can be a path to a file,
4057 a file object, a str with the content of the file."""
4058
4059 if isinstance(finput, str):
4060 if "\n" in finput:
4061 finput = finput.split('\n')
4062 elif os.path.isfile(finput):
4063 finput = open(finput)
4064 else:
4065 raise Exception, "No such file %s" % input
4066
4067 previous_line= ''
4068 for line in finput:
4069 if previous_line.startswith('#'):
4070 name = previous_line[1:].split()[0]
4071 value = line.strip()
4072 if len(value) and value[0] not in ['#', '!']:
4073 self.__setitem__(name, value, change_userdefine=True)
4074 previous_line = line
4075
4076
4077 - def write(self, outputpath, template=None,commentdefault=False):
4078
4079 if not template:
4080 if not MADEVENT:
4081 template = pjoin(MG5DIR, 'Template', 'loop_material', 'StandAlone',
4082 'Cards', 'MadLoopParams.dat')
4083 else:
4084 template = pjoin(MEDIR, 'Cards', 'MadLoopParams_default.dat')
4085 fsock = open(template, 'r')
4086 template = fsock.readlines()
4087 fsock.close()
4088
4089 if isinstance(outputpath, str):
4090 output = open(outputpath, 'w')
4091 else:
4092 output = outputpath
4093
4094 def f77format(value):
4095 if isinstance(value, bool):
4096 if value:
4097 return '.true.'
4098 else:
4099 return '.false.'
4100 elif isinstance(value, int):
4101 return value
4102 elif isinstance(value, float):
4103 tmp ='%e' % value
4104 return tmp.replace('e','d')
4105 elif isinstance(value, str):
4106 return value
4107 else:
4108 raise Exception, "Can not format input %s" % type(value)
4109
4110 name = ''
4111 done = set()
4112 for line in template:
4113 if name:
4114 done.add(name)
4115 if commentdefault and name.lower() not in self.user_set :
4116 output.write('!%s\n' % f77format(self[name]))
4117 else:
4118 output.write('%s\n' % f77format(self[name]))
4119 name=''
4120 continue
4121 elif line.startswith('#'):
4122 name = line[1:].split()[0]
4123 output.write(line)
4124