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