1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 from __future__ import division
16
17 from __future__ import absolute_import
18 from __future__ import print_function
19 from six.moves import range
20 from six.moves import zip
21 if __name__ == "__main__":
22 import sys
23 import os
24 root = os.path.dirname(__file__)
25 if __package__ is None:
26 if os.path.basename(root) == 'internal':
27 __package__ = "internal"
28 sys.path.append(os.path.dirname(root))
29 import internal
30 else:
31 __package__ = "madgraph.various"
32
33
34
35 from . import lhe_parser
36 from . import banner
37 from . import banner as banner_mod
38 import itertools
39 from . import misc
40 import math
41 import os
42 import re
43 import sys
44 import time
45 from six import StringIO
46
47 pjoin = os.path.join
48 root = os.path.dirname(__file__)
49
52
54
55 - def __init__(self, input_file, output_file,
56 start_event=0, stop_event=sys.maxsize, write_banner=False,
57 mur=[0.5,1,2],
58 muf=[0.5,1,2],
59 alps=[1],
60 pdf='errorset',
61 dyn=[-1,1,2,3,4],
62 together=[('mur', 'muf', 'dyn')],
63 remove_wgts=[],
64 keep_wgts=[],
65 start_id=None,
66 lhapdf_config=misc.which('lhapdf-config'),
67 log=lambda x: sys.stdout.write(str(x)+'\n'),
68 only_beam=False,
69 ion_scaling=True,
70 weight_format=None,
71 weight_info=None,
72 ):
73
74
75
76 if isinstance(input_file, str):
77 self.input = lhe_parser.EventFile(input_file)
78 else:
79 self.input = input_file
80 self.output_path = output_file
81 self.weight_format = weight_format
82 self.weight_info_format = weight_info
83 if output_file != None:
84 if isinstance(output_file, str):
85 if output_file == input_file:
86 directory,name = os.path.split(output_file)
87 new_name = pjoin(directory, '.tmp_'+name)
88 self.output = lhe_parser.EventFile(new_name, 'w')
89 else:
90 self.output = lhe_parser.EventFile(output_file, 'w')
91 else:
92 self.output = output_file
93 self.log = log
94
95
96 self.banner = banner_mod.Banner(self.input.banner)
97 self.force_write_banner = bool(write_banner)
98 self.orig_dyn = self.banner.get('run_card', 'dynamical_scale_choice')
99 self.orig_pdf = self.banner.run_card.get_lhapdf_id()
100 matching_mode = self.banner.get('run_card', 'ickkw')
101
102
103 beam1, beam2 = self.banner.get_pdg_beam()
104 if abs(beam1) != 2212 and abs(beam2) != 2212:
105 self.b1 = 0
106 self.b2 = 0
107 pdf = 'central'
108
109 elif abs(beam1) != 2212:
110 self.b1 = 0
111 self.b2 = beam2//2212
112 elif abs(beam2) != 2212:
113 self.b1 = beam1//2212
114 self.b2 = 0
115 else:
116 self.b1 = beam1//2212
117 self.b2 = beam2//2212
118
119 self.orig_ion_pdf = False
120 self.ion_scaling = ion_scaling
121 self.only_beam = only_beam
122 if isinstance(self.banner.run_card, banner_mod.RunCardLO):
123 self.is_lo = True
124 if not self.banner.run_card['use_syst']:
125 raise SystematicsError('The events have not been generated with use_syst=True. Cannot evaluate systematics error on these events.')
126
127 if self.banner.run_card['nb_neutron1'] != 0 or \
128 self.banner.run_card['nb_neutron2'] != 0 or \
129 self.banner.run_card['nb_proton1'] != 1 or \
130 self.banner.run_card['nb_proton2'] != 1:
131 self.orig_ion_pdf = True
132 else:
133 self.is_lo = False
134 if not self.banner.run_card['store_rwgt_info']:
135 raise SystematicsError('The events have not been generated with store_rwgt_info=True. Cannot evaluate systematics error on these events.')
136
137
138 if isinstance(mur, str):
139 mur = mur.split(',')
140 self.mur=[float(i) for i in mur]
141 if isinstance(muf, str):
142 muf = muf.split(',')
143 self.muf=[float(i) for i in muf]
144
145 if isinstance(alps, str):
146 alps = alps.split(',')
147 self.alps=[float(i) for i in alps]
148
149
150 if isinstance(dyn, str):
151 dyn = dyn.split(',')
152 self.dyn=[int(i) for i in dyn]
153
154 if matching_mode == 3:
155 self.dyn = [-1]
156
157 if 4 in self.dyn and self.b1 and self.b2 and not self.is_lo:
158 self.dyn.remove(4)
159
160 if isinstance(together, str):
161 self.together = together.split(',')
162 else:
163 self.together = together
164
165
166 self.start_event=int(start_event)
167 self.stop_event=int(stop_event)
168 if start_event != 0:
169 self.log( "#starting from event #%s" % start_event)
170 if stop_event != sys.maxsize:
171 self.log( "#stopping at event #%s" % stop_event)
172
173
174 if isinstance(lhapdf_config, list):
175 lhapdf_config = lhapdf_config[0]
176 lhapdf = misc.import_python_lhapdf(lhapdf_config)
177 if not lhapdf:
178 log('fail to load lhapdf: doe not perform systematics')
179 return
180 lhapdf.setVerbosity(0)
181 self.pdfsets = {}
182 if isinstance(pdf, str):
183 pdf = pdf.split(',')
184
185 if isinstance(pdf,list) and isinstance(pdf[0],(str,int)):
186 self.pdf = []
187 for data in pdf:
188 if data == 'errorset':
189 data = '%s' % self.orig_pdf
190 if data == 'central':
191 data = '%s@0' % self.orig_pdf
192 if '@' in data:
193
194 name, arg = data.rsplit('@',1)
195 if int(arg) == 0:
196 if name.isdigit():
197 self.pdf.append(lhapdf.mkPDF(int(name)))
198 else:
199 self.pdf.append(lhapdf.mkPDF(name))
200 elif name.isdigit():
201 try:
202 self.pdf.append(lhapdf.mkPDF(int(name)+int(arg)))
203 except:
204 raise Exception('Individual error sets need to be called with LHAPDF NAME not with LHAGLUE NUMBER')
205 else:
206 self.pdf.append(lhapdf.mkPDF(name, int(arg)))
207 else:
208 if data.isdigit():
209 pdfset = lhapdf.mkPDF(int(data)).set()
210 else:
211 pdfset = lhapdf.mkPDF(data).set()
212 self.pdfsets[pdfset.lhapdfID] = pdfset
213 self.pdf += pdfset.mkPDFs()
214 else:
215 self.pdf = pdf
216
217 for p in self.pdf:
218 if p.lhapdfID == self.orig_pdf:
219 self.orig_pdf = p
220 break
221 else:
222 self.orig_pdf = lhapdf.mkPDF(self.orig_pdf)
223 if not self.b1 == 0 == self.b2:
224 self.log( "# events generated with PDF: %s (%s)" %(self.orig_pdf.set().name,self.orig_pdf.lhapdfID ))
225
226 self.get_all_fct()
227
228
229 if self.b1 == 0 == self.b2:
230 try:
231 from models.model_reader import Alphas_Runner
232 except ImportError:
233 root_path = pjoin(root, os.pardir, os.pardir)
234 try:
235 import internal.madevent_interface as me_int
236 cmd = me_int.MadEventCmd(root_path,force_run=True)
237 except ImportError:
238 import internal.amcnlo_run_interface as me_int
239 cmd = me_int.Cmd(root_path,force_run=True)
240 if 'mg5_path' in cmd.options and cmd.options['mg5_path']:
241 sys.path.append(cmd.options['mg5_path'])
242 from models.model_reader import Alphas_Runner
243
244 if not hasattr(self.banner, 'param_card'):
245 param_card = self.banner.charge_card('param_card')
246 else:
247 param_card = self.banner.param_card
248
249 asmz = param_card.get_value('sminputs', 3, 0.13)
250 nloop =2
251 zmass = param_card.get_value('mass', 23, 91.188)
252 cmass = param_card.get_value('mass', 4, 1.4)
253 if cmass == 0:
254 cmass = 1.4
255 bmass = param_card.get_value('mass', 5, 4.7)
256 if bmass == 0:
257 bmass = 4.7
258 self.alpsrunner = Alphas_Runner(asmz, nloop, zmass, cmass, bmass)
259
260
261 self.remove_wgts = []
262 for id in remove_wgts:
263 if id == 'all':
264 self.remove_wgts = ['all']
265 break
266 elif ',' in id:
267 min_value, max_value = [int(v) for v in id.split(',')]
268 self.remove_wgts += [i for i in range(min_value, max_value+1)]
269 else:
270 self.remove_wgts.append(id)
271 self.keep_wgts = []
272 for id in keep_wgts:
273 if id == 'all':
274 self.keep_wgts = ['all']
275 break
276 elif ',' in id:
277 min_value, max_value = [int(v) for v in id.split(',')]
278 self.remove_wgts += [i for i in range(min_value, max_value+1)]
279 else:
280 self.remove_wgts.append(id)
281
282
283 self.start_wgt_id = int(start_id[0]) if (start_id is not None) else None
284 self.has_wgts_pattern = False
285
286
288 """ determine if we have to keep/remove such weight """
289
290 if 'all' in self.keep_wgts or not self.remove_wgts:
291 return True
292
293
294 if name in self.keep_wgts:
295 return True
296
297
298 if not self.has_wgts_pattern:
299 pat = r'|'.join(w for w in self.keep_wgts if any(letter in w for letter in '*?.([+\\'))
300 if pat:
301 self.keep_wgts_pattern = re.compile(pat)
302 else:
303 self.keep_wgts_pattern = None
304 pat = r'|'.join(w for w in self.remove_wgts if any(letter in w for letter in '*?.([+\\'))
305 if pat:
306 self.rm_wgts_pattern = re.compile(pat)
307 else:
308 self.rm_wgts_pattern = None
309 self.has_wgts_pattern=True
310
311 if self.keep_wgts_pattern and re.match(self.keep_wgts_pattern,name):
312 return True
313
314
315 if 'all' in self.remove_wgts:
316 return False
317 elif name in self.remove_wgts:
318 return False
319 elif self.rm_wgts_pattern and re.match(self.rm_wgts_pattern, name):
320 return False
321 else:
322 return True
323
332
333
334 - def run(self, stdout=sys.stdout):
335 """ """
336 start_time = time.time()
337 if self.start_event == 0 or self.force_write_banner:
338 lowest_id = self.write_banner(self.output)
339 else:
340 lowest_id = self.get_id()
341
342 ids = [self.get_wgt_name(*self.args[i][:5], cid=lowest_id+i) for i in range(len(self.args)-1)]
343
344 all_cross = [0 for i in range(len(self.args))]
345
346 self.input.parsing = False
347 for nb_event,event in enumerate(self.input):
348 if nb_event < self.start_event:
349 continue
350 elif nb_event == self.start_event:
351 self.input.parsing = True
352 event = lhe_parser.Event(event)
353 elif nb_event >= self.stop_event:
354 if self.force_write_banner:
355 self.output.write('</LesHouchesEvents>\n')
356 break
357
358 if self.is_lo:
359 if (nb_event-self.start_event)>=0 and (nb_event-self.start_event) % 2500 ==0:
360 self.log( '# currently at event %s [elapsed time: %.2g s]' % (nb_event, time.time()-start_time))
361 else:
362 if (nb_event-self.start_event)>=0 and (nb_event-self.start_event) % 1000 ==0:
363 self.log( '# currently at event %i [elapsed time: %.2g s]' % (nb_event, time.time()-start_time))
364
365 self.new_event()
366 self.remove_old_wgts(event)
367 if self.is_lo:
368 wgts = [self.get_lo_wgt(event, *arg) for arg in self.args]
369 else:
370 wgts = [self.get_nlo_wgt(event, *arg) for arg in self.args]
371
372 if wgts[0] == 0:
373 print(wgts)
374 print(event)
375 raise Exception
376
377 wgt = [event.wgt*wgts[i]/wgts[0] for i in range(1,len(wgts))]
378 all_cross = [(all_cross[j] + event.wgt*wgts[j]/wgts[0]) for j in range(len(wgts))]
379
380 rwgt_data = event.parse_reweight()
381 rwgt_data.update(list(zip(ids, wgt)))
382 event.reweight_order += ids
383
384 self.output.write(str(event))
385 else:
386 self.output.write('</LesHouchesEvents>\n')
387 self.output.close()
388 self.print_cross_sections(all_cross, min(nb_event,self.stop_event)-self.start_event+1, stdout)
389
390 if self.output.name != self.output_path:
391
392 if not os.path.exists(self.output.name) and os.path.exists('%s.gz' % self.output.name):
393 to_check = '%s.gz' % self.output.name
394 else:
395 to_check = self.output.name
396
397 if to_check != self.output_path:
398 if '%s.gz' % to_check == self.output_path:
399 misc.gzip(to_check)
400 else:
401 import shutil
402 shutil.move(to_check, self.output_path)
403
404 return all_cross
405
407 """print the cross-section."""
408
409 norm = self.banner.get('run_card', 'event_norm', default='sum')
410
411
412
413 max_scale, min_scale = 0,sys.maxsize
414 max_alps, min_alps = 0, sys.maxsize
415 max_dyn, min_dyn = 0,sys.maxsize
416 pdfs = {}
417 dyns = {}
418
419 if norm == 'sum':
420 norm = 1
421 elif norm in ['average', 'bias']:
422 norm = 1./nb_event
423 elif norm == 'unity':
424 norm = 1
425
426 all_cross = [c*norm for c in all_cross]
427 stdout.write("# mur\t\tmuf\t\talpsfact\tdynamical_scale\tpdf\t\tcross-section\n")
428 for i,arg in enumerate(self.args):
429
430 to_print = list(arg)
431 to_print[4] = to_print[4].lhapdfID
432 to_print.append(all_cross[i])
433 to_report = []
434 stdout.write('%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\n' % tuple(to_print))
435
436 mur, muf, alps, dyn, pdf = arg[:5]
437 if pdf == self.orig_pdf and (dyn==self.orig_dyn or dyn==-1)\
438 and (mur!=1 or muf!=1 or alps!=1):
439 max_scale = max(max_scale,all_cross[i])
440 min_scale = min(min_scale,all_cross[i])
441 if pdf == self.orig_pdf and mur==1 and muf==1 and \
442 (dyn==self.orig_dyn or dyn==-1) and alps!=1:
443 max_alps = max(max_alps,all_cross[i])
444 min_alps = min(min_alps,all_cross[i])
445
446 if pdf == self.orig_pdf and mur==1 and muf==1 and alps==1:
447 max_dyn = max(max_dyn,all_cross[i])
448 min_dyn = min(min_dyn,all_cross[i])
449
450 if pdf == self.orig_pdf and (alps!=1 or mur!=1 or muf!=1) and \
451 (dyn!=self.orig_dyn or dyn!=-1):
452 if dyn not in dyns:
453 dyns[dyn] = {'max':0, 'min':sys.maxsize,'central':0}
454 curr = dyns[dyn]
455 curr['max'] = max(curr['max'],all_cross[i])
456 curr['min'] = min(curr['min'],all_cross[i])
457 if pdf == self.orig_pdf and (alps==1 and mur==1 and muf==1) and \
458 (dyn!=self.orig_dyn or dyn!=-1):
459 if dyn not in dyns:
460 dyns[dyn] = {'max':0, 'min':sys.maxsize,'central':all_cross[i]}
461 else:
462 dyns[dyn]['central'] = all_cross[i]
463
464 if alps==1 and mur==1 and muf==1 and (dyn==self.orig_dyn or dyn==-1):
465 pdfset = pdf.set()
466 if pdfset.lhapdfID in self.pdfsets:
467 if pdfset.lhapdfID not in pdfs :
468 pdfs[pdfset.lhapdfID] = [0] * pdfset.size
469 pdfs[pdfset.lhapdfID][pdf.memberID] = all_cross[i]
470 else:
471 to_report.append('# PDF %s : %s\n' % (pdf.lhapdfID, all_cross[i]))
472
473 stdout.write('\n')
474
475 resume = StringIO()
476
477 resume.write( '#***************************************************************************\n')
478 resume.write( "#\n")
479 resume.write( '# original cross-section: %s\n' % all_cross[0])
480 if max_scale:
481 resume.write( '# scale variation: +%2.3g%% -%2.3g%%\n' % ((max_scale-all_cross[0])/all_cross[0]*100,(all_cross[0]-min_scale)/all_cross[0]*100))
482 if max_alps:
483 resume.write( '# emission scale variation: +%2.3g%% -%2.3g%%\n' % ((max_alps-all_cross[0])/all_cross[0]*100,(max_alps-min_scale)/all_cross[0]*100))
484 if max_dyn and (max_dyn!= all_cross[0] or min_dyn != all_cross[0]):
485 resume.write( '# central scheme variation: +%2.3g%% -%2.3g%%\n' % ((max_dyn-all_cross[0])/all_cross[0]*100,(all_cross[0]-min_dyn)/all_cross[0]*100))
486 if self.orig_pdf.lhapdfID in pdfs:
487 lhapdfid = self.orig_pdf.lhapdfID
488 values = pdfs[lhapdfid]
489 pdfset = self.pdfsets[lhapdfid]
490 try:
491 pdferr = pdfset.uncertainty(values)
492 except RuntimeError:
493 resume.write( '# PDF variation: missing combination\n')
494 else:
495 resume.write( '# PDF variation: +%2.3g%% -%2.3g%%\n' % (pdferr.errplus*100/all_cross[0], pdferr.errminus*100/all_cross[0]))
496
497 resume.write( "#\n")
498 for lhapdfid,values in pdfs.items():
499 if lhapdfid == self.orig_pdf.lhapdfID:
500 continue
501 if len(values) == 1 :
502 continue
503 pdfset = self.pdfsets[lhapdfid]
504
505 if pdfset.errorType == 'unknown' :
506
507
508
509 continue
510 try:
511 pdferr = pdfset.uncertainty(values)
512 except RuntimeError:
513
514 pass
515 else:
516 resume.write( '#PDF %s: %g +%2.3g%% -%2.3g%%\n' % (pdfset.name, pdferr.central,pdferr.errplus*100/all_cross[0], pdferr.errminus*100/all_cross[0]))
517
518 dyn_name = {1: '\sum ET', 2:'\sum\sqrt{m^2+pt^2}', 3:'0.5 \sum\sqrt{m^2+pt^2}',4:'\sqrt{\hat s}' }
519 for key, curr in dyns.items():
520 if key ==-1:
521 continue
522 central, maxvalue, minvalue = curr['central'], curr['max'], curr['min']
523 if central == 0:
524 continue
525 if maxvalue == 0:
526 resume.write("# dynamical scheme # %s : %g # %s\n" %(key, central, dyn_name[key]))
527 else:
528 resume.write("# dynamical scheme # %s : %g +%2.3g%% -%2.3g%% # %s\n" %(key, central, (maxvalue-central)/central*100,(central-minvalue)/central*100, dyn_name[key]))
529
530 resume.write('\n'.join(to_report))
531
532 resume.write( '#***************************************************************************\n')
533
534 stdout.write(resume.getvalue())
535 self.log(resume.getvalue())
536
537
539 """create the new banner with the information of the weight"""
540
541 cid = self.get_id()
542 lowest_id = cid
543
544 in_scale = False
545 in_pdf = False
546 in_alps = False
547
548 text = ''
549
550 default = self.args[0]
551 for arg in self.args[1:]:
552 mur, muf, alps, dyn, pdf = arg[:5]
553 if pdf == self.orig_pdf and alps ==1 and (mur!=1 or muf!=1 or dyn!=-1):
554 if not in_scale:
555 text += "<weightgroup name=\"Central scale variation\" combine=\"envelope\">\n"
556 in_scale=True
557 elif in_scale:
558 if (pdf == self.orig_pdf and alps ==1) and arg != default:
559 pass
560 else:
561 text += "</weightgroup> # scale\n"
562 in_scale = False
563
564 if pdf == self.orig_pdf and mur == muf == 1 and dyn==-1 and alps!=1:
565 if not in_alps:
566 text += "<weightgroup name=\"Emission scale variation\" combine=\"envelope\">\n"
567 in_alps=True
568 elif in_alps:
569 text += "</weightgroup> # ALPS\n"
570 in_alps=False
571
572 if mur == muf == 1 and dyn==-1 and alps ==1:
573
574 if pdf.lhapdfID in self.pdfsets:
575 if in_pdf:
576 text += "</weightgroup> # PDFSET to PDFSET\n"
577 pdfset = self.pdfsets[pdf.lhapdfID]
578 descrip = pdfset.description.replace('=>',';').replace('>','.gt.').replace('<','.lt.')
579 text +="<weightgroup name=\"%s\" combine=\"%s\"> # %s: %s\n" %\
580 (pdfset.name, pdfset.errorType,pdfset.lhapdfID, descrip)
581 in_pdf=pdf.lhapdfID
582 elif pdf.memberID == 0 and (pdf.lhapdfID - pdf.memberID) in self.pdfsets:
583 if in_pdf:
584 text += "</weightgroup> # PDFSET to PDFSET\n"
585 pdfset = self.pdfsets[pdf.lhapdfID - 1]
586 descrip = pdfset.description.replace('=>',';').replace('>','.gt.').replace('<','.lt.')
587 text +="<weightgroup name=\"%s\" combine=\"%s\"> # %s: %s\n" %\
588 (pdfset.name, pdfset.errorType,pdfset.lhapdfID, descrip)
589 in_pdf=pdfset.lhapdfID
590 elif in_pdf and pdf.lhapdfID - pdf.memberID != in_pdf:
591 text += "</weightgroup> # PDFSET to PDF\n"
592 in_pdf = False
593 elif in_pdf:
594 text += "</weightgroup> PDF \n"
595 in_pdf=False
596
597
598
599 tag, info = '',''
600 if mur!=1.:
601 tag += 'MUR="%s" ' % mur
602 info += 'MUR=%s ' % mur
603 else:
604 tag += 'MUR="%s" ' % mur
605 if muf!=1.:
606 tag += 'MUF="%s" ' % muf
607 info += 'MUF=%s ' % muf
608 else:
609 tag += 'MUF="%s" ' % muf
610
611 if alps!=1.:
612 tag += 'ALPSFACT="%s" ' % alps
613 info += 'alpsfact=%s ' % alps
614 if dyn!=-1.:
615 tag += 'DYN_SCALE="%s" ' % dyn
616 info += 'dyn_scale_choice=%s ' % {1:'sum pt', 2:'HT',3:'HT/2',4:'sqrts'}[dyn]
617
618 if pdf != self.orig_pdf:
619 tag += 'PDF="%s" ' % pdf.lhapdfID
620 info += 'PDF=%s MemberID=%s' % (pdf.lhapdfID-pdf.memberID, pdf.memberID)
621 else:
622 tag += 'PDF="%s" ' % pdf.lhapdfID
623
624 wgt_name = self.get_wgt_name(mur, muf, alps, dyn, pdf, cid)
625 tag = self.get_wgt_tag(mur, muf, alps, dyn, pdf, cid)
626 info = self.get_wgt_info(mur, muf, alps, dyn, pdf, cid)
627 text +='<weight id="%s" %s> %s </weight>\n' % (wgt_name, tag, info)
628 cid+=1
629
630 if in_scale or in_alps or in_pdf:
631 text += "</weightgroup>\n"
632
633 if 'initrwgt' in self.banner:
634 if not self.remove_wgts:
635 self.banner['initrwgt'] += text
636 else:
637
638
639 wgt_in_group=0
640 tmp_group_txt =[]
641 out =[]
642 keep_last = False
643 for line in self.banner['initrwgt'].split('\n'):
644 sline = line.strip()
645 if sline.startswith('</weightgroup'):
646 if wgt_in_group:
647 out += tmp_group_txt
648 out.append('</weightgroup>')
649 if '<weightgroup' in line:
650 wgt_in_group=0
651 tmp_group_txt = [line[line.index('<weightgroup'):]]
652 elif sline.startswith('<weightgroup'):
653 wgt_in_group=0
654 tmp_group_txt = [line]
655 elif sline.startswith('<weight'):
656 name = re.findall(r'\bid=[\'\"]([^\'\"]*)[\'\"]', sline)
657 if self.is_wgt_kept(name[0]):
658 tmp_group_txt.append(line)
659 keep_last = True
660 wgt_in_group +=1
661 else:
662 keep_last = False
663 elif keep_last:
664 tmp_group_txt.append(line)
665 out.append(text)
666 self.banner['initrwgt'] = '\n'.join(out)
667 else:
668 self.banner['initrwgt'] = text
669
670
671 self.banner.write(self.output, close_tag=False)
672
673 return lowest_id
674
676
677 if self.weight_format:
678 wgt_name = self.weight_format[0] % {'mur': mur, 'muf':muf, 'alps': alps, 'pdf':pdf.lhapdfID, 'dyn':dyn, 'id': cid}
679 else:
680 wgt_name = cid
681 return wgt_name
682
684
685 if self.weight_info_format:
686 info = self.weight_info_format[0] % {'mur': mur, 'muf':muf, 'alps': alps, 'pdf':pdf.lhapdfID, 'dyn':dyn, 'id': cid, 's':' ', 'n':'\n'}
687 else:
688 info = ''
689 if mur!=1.:
690 info += 'MUR=%s ' % mur
691 if muf!=1.:
692 info += 'MUF=%s ' % muf
693 if alps!=1.:
694 info += 'alpsfact=%s ' % alps
695 if dyn!=-1.:
696 info += 'dyn_scale_choice=%s ' % {1:'sum pt', 2:'HT',3:'HT/2',4:'sqrts'}[dyn]
697 if pdf != self.orig_pdf:
698 info += 'PDF=%s MemberID=%s' % (pdf.lhapdfID-pdf.memberID, pdf.memberID)
699
700 return info
701
702 - def get_wgt_tag (self, mur, muf, alps, dyn, pdf, cid=0):
703 tags = []
704 tags.append('MUR="%s" ' % mur)
705 tags.append('MUF="%s" ' % muf)
706 if alps!=1.:
707 tags.append('ALPSFACT="%s" ' % alps)
708 if dyn!=-1.:
709 tags.append('DYN_SCALE="%s" ' % dyn)
710 tags.append('PDF="%s" ' % pdf.lhapdfID)
711 return " ".join(tags)
712
713
715
716 if self.start_wgt_id is not None:
717 return int(self.start_wgt_id)
718
719 if 'initrwgt' in self.banner:
720 pattern = re.compile('<weight id=(?:\'|\")([_\w]+)(?:\'|\")', re.S+re.I+re.M)
721 matches = pattern.findall(self.banner['initrwgt'])
722 matches.append('0')
723 return max([int(wid) for wid in matches if wid.isdigit()])+1
724 else:
725 return 1
726
727
729
730 all_args = []
731 default = [1.,1.,1.,-1,self.orig_pdf]
732
733 pos = {'mur':0, 'muf':1, 'alps':2, 'dyn':3, 'pdf':4}
734 done = set()
735 for one_block in self.together:
736 for name in one_block:
737 done.add(name)
738 for together in itertools.product(*[getattr(self,name) for name in one_block]):
739 new_args = list(default)
740 for name,value in zip(one_block, together):
741 new_args[pos[name]] = value
742 all_args.append(new_args)
743 for name in pos:
744 if name in done:
745 continue
746 for value in getattr(self, name):
747 new_args = list(default)
748 new_args[pos[name]] = value
749 all_args.append(new_args)
750
751 self.args = [default] + [arg for arg in all_args if arg!= default]
752
753
754 pdfplusone = [pdf for pdf in self.pdf if pdf.lhapdfID == self.orig_pdf.lhapdfID+1]
755 if pdfplusone:
756 pdfplusone = default[:-1] + [pdfplusone[0]]
757 index = self.args.index(pdfplusone)
758 self.args.insert(index, default)
759
760 self.log( "#Will Compute %s weights per event." % (len(self.args)-1))
761 return
762
764 self.alphas = {}
765 self.pdfQ2 = {}
766
767
768 - def get_pdfQ(self, pdf, pdg, x, scale, beam=1):
769
770 if pdg in [-21,-22]:
771 pdg = abs(pdg)
772 elif pdg == 0:
773 return 1
774
775 if self.only_beam and self.only_beam!= beam and pdf.lhapdfID != self.orig_pdf:
776 return self.getpdfQ(self.pdfsets[self.orig_pdf], pdg, x, scale, beam)
777
778 if self.orig_ion_pdf and (self.ion_scaling or pdf.lhapdfID == self.orig_pdf):
779 nb_p = self.banner.run_card["nb_proton%s" % beam]
780 nb_n = self.banner.run_card["nb_neutron%s" % beam]
781
782
783 if pdg in [1,2]:
784 pdf1 = pdf.xfxQ(1, x, scale)/x
785 pdf2 = pdf.xfxQ(2, x, scale)/x
786 if pdg == 1:
787 f = nb_p * pdf1 + nb_n * pdf2
788 else:
789 f = nb_p * pdf2 + nb_n * pdf1
790 elif pdg in [-1,-2]:
791 pdf1 = pdf.xfxQ(-1, x, scale)/x
792 pdf2 = pdf.xfxQ(-2, x, scale)/x
793 if pdg == -1:
794 f = nb_p * pdf1 + nb_n * pdf2
795 else:
796 f = nb_p * pdf2 + nb_n * pdf1
797 else:
798 f = (nb_p + nb_n) * pdf.xfxQ(pdg, x, scale)/x
799
800 f = f * (nb_p+nb_n)
801 else:
802 f = pdf.xfxQ(pdg, x, scale)/x
803
804
805
806
807 return f
808
809 - def get_pdfQ2(self, pdf, pdg, x, scale, beam=1):
810
811 if pdg in [-21,-22]:
812 pdg = abs(pdg)
813 elif pdg == 0:
814 return 1
815
816 if (pdf, pdg,x,scale, beam) in self.pdfQ2:
817 return self.pdfQ2[(pdf, pdg,x,scale,beam)]
818
819 if self.orig_ion_pdf and (self.ion_scaling or pdf.lhapdfID == self.orig_pdf):
820 nb_p = self.banner.run_card["nb_proton%s" % beam]
821 nb_n = self.banner.run_card["nb_neutron%s" % beam]
822
823
824 if pdg in [1,2]:
825 pdf1 = pdf.xfxQ2(1, x, scale)/x
826 pdf2 = pdf.xfxQ2(2, x, scale)/x
827 if pdg == 1:
828 f = nb_p * pdf1 + nb_n * pdf2
829 else:
830 f = nb_p * pdf2 + nb_n * pdf1
831 elif pdg in [-1,-2]:
832 pdf1 = pdf.xfxQ2(-1, x, scale)/x
833 pdf2 = pdf.xfxQ2(-2, x, scale)/x
834 if pdg == -1:
835 f = nb_p * pdf1 + nb_n * pdf2
836 else:
837 f = nb_p * pdf2 + nb_n * pdf1
838 else:
839 f = (nb_p + nb_n) * pdf.xfxQ2(pdg, x, scale)/x
840
841 f = f * (nb_p+nb_n)
842 else:
843 f = pdf.xfxQ2(pdg, x, scale)/x
844 self.pdfQ2[(pdf, pdg,x,scale,beam)] = f
845 return f
846
847
848
849
850 if f == 0 and pdf.memberID ==0:
851
852
853
854 pdfset = pdf.set()
855 allnumber= [0] + [self.get_pdfQ2(p, pdg, x, scale) for p in pdfset.mkPDFs()[1:]]
856 f = pdfset.uncertainty(allnumber).central
857 self.pdfQ2[(pdf, pdg,x,scale)] = f
858 return f
859
860 - def get_lo_wgt(self,event, Dmur, Dmuf, Dalps, dyn, pdf):
861 """
862 pdf is a lhapdf object!"""
863
864 loinfo = event.parse_lo_weight()
865
866 if dyn == -1:
867 mur = loinfo['ren_scale']
868 if self.b1 != 0 and loinfo['pdf_pdg_code1']:
869 muf1 = loinfo['pdf_q1'][-1]
870 else:
871 muf1 =0
872 if self.b2 != 0 and loinfo['pdf_pdg_code2']:
873 muf2 = loinfo['pdf_q2'][-1]
874 else:
875 muf2 =0
876 else:
877 if dyn == 1:
878 mur = event.get_et_scale(1.)
879 elif dyn == 2:
880 mur = event.get_ht_scale(1.)
881 elif dyn == 3:
882 mur = event.get_ht_scale(0.5)
883 elif dyn == 4:
884 mur = event.get_sqrts_scale(1.)
885 if math.isnan(mur):
886 return mur
887 muf1 = mur
888 muf2 = mur
889 loinfo = dict(loinfo)
890
891 if not loinfo['pdf_pdg_code1']:
892 muf1 = 0
893 else:
894 loinfo['pdf_q1'] = loinfo['pdf_q1'] [:-1] + [mur]
895 if not loinfo['pdf_pdg_code2']:
896 muf2 = 0
897 else:
898 loinfo['pdf_q2'] = loinfo['pdf_q2'] [:-1] + [mur]
899
900
901
902
903 if self.b1 == 0 == self.b2:
904 if loinfo['n_qcd'] != 0:
905 wgt = self.alpsrunner(Dmur*mur)**loinfo['n_qcd']
906 else:
907 wgt = 1.0
908 else:
909 wgt = pdf.alphasQ(Dmur*mur)**loinfo['n_qcd']
910
911
912 if self.b1 and muf1:
913 wgt *= self.get_pdfQ(pdf, self.b1*loinfo['pdf_pdg_code1'][-1], loinfo['pdf_x1'][-1], Dmuf*muf1, beam=1)
914 if self.b2 and muf2:
915 wgt *= self.get_pdfQ(pdf, self.b2*loinfo['pdf_pdg_code2'][-1], loinfo['pdf_x2'][-1], Dmuf*muf2, beam=2)
916
917 for scale in loinfo['asrwt']:
918 if self.b1 == 0 == self.b2:
919 wgt = self.alpsrunner(Dalps*scale)
920 else:
921 wgt *= pdf.alphasQ(Dalps*scale)
922
923
924 for i in range(loinfo['n_pdfrw1']-1):
925 scale = min(Dalps*loinfo['pdf_q1'][i], Dmuf*muf1)
926 wgt *= self.get_pdfQ(pdf, self.b1*loinfo['pdf_pdg_code1'][i], loinfo['pdf_x1'][i], scale, beam=1)
927 wgt /= self.get_pdfQ(pdf, self.b1*loinfo['pdf_pdg_code1'][i], loinfo['pdf_x1'][i+1], scale, beam=1)
928
929 for i in range(loinfo['n_pdfrw2']-1):
930 scale = min(Dalps*loinfo['pdf_q2'][i], Dmuf*muf2)
931 wgt *= self.get_pdfQ(pdf, self.b2*loinfo['pdf_pdg_code2'][i], loinfo['pdf_x2'][i], scale, beam=2)
932 wgt /= self.get_pdfQ(pdf, self.b2*loinfo['pdf_pdg_code2'][i], loinfo['pdf_x2'][i+1], scale, beam=2)
933
934 return wgt
935
936 - def get_nlo_wgt(self,event, Dmur, Dmuf, Dalps, dyn, pdf):
937 """return the new weight for NLO event --with weight information-- """
938
939 wgt = 0
940 nloinfo = event.parse_nlo_weight(real_type=(1,11,12,13))
941 for cevent in nloinfo.cevents:
942 if dyn == 1:
943 mur2 = max(1.0, cevent.get_et_scale(1.)**2)
944 elif dyn == 2:
945 mur2 = max(1.0, cevent.get_ht_scale(1.)**2)
946 elif dyn == 3:
947 mur2 = max(1.0, cevent.get_ht_scale(0.5)**2)
948 elif dyn == 4:
949 mur2 = cevent.get_sqrts_scale(event,1)**2
950 else:
951 mur2 = 0
952 muf2 = mur2
953
954 for onewgt in cevent.wgts:
955 if not __debug__ and (dyn== -1 and Dmur==1 and Dmuf==1 and pdf==self.orig_pdf):
956 wgt += onewgt.ref_wgt
957 continue
958
959 if dyn == -1:
960 mur2 = onewgt.scales2[1]
961 muf2 = onewgt.scales2[2]
962 Q2 = onewgt.scales2[0]
963
964 wgtpdf = self.get_pdfQ2(pdf, self.b1*onewgt.pdgs[0], onewgt.bjks[0],
965 Dmuf**2 * muf2)
966 wgtpdf *= self.get_pdfQ2(pdf, self.b2*onewgt.pdgs[1], onewgt.bjks[1],
967 Dmuf**2 * muf2)
968
969 tmp = onewgt.pwgt[0]
970 tmp += onewgt.pwgt[1] * math.log(Dmur**2 * mur2/ Q2)
971 tmp += onewgt.pwgt[2] * math.log(Dmuf**2 * muf2/ Q2)
972
973 if self.b1 == 0 == self.b2:
974 alps = self.alpsrunner(Dmur*math.sqrt(mur2))
975 else:
976 alps = pdf.alphasQ2(Dmur**2*mur2)
977
978 tmp *= math.sqrt(4*math.pi*alps)**onewgt.qcdpower
979
980 if wgtpdf == 0:
981 key = (self.b1*onewgt.pdgs[0], self.b2*onewgt.pdgs[1], onewgt.bjks[0],onewgt.bjks[1], muf2)
982 if dyn== -1 and Dmuf==1 and Dmur==1 and pdf==self.orig_pdf:
983 wgtpdf = onewgt.ref_wgt / tmp
984 self.pdfQ2[key] = wgtpdf
985 elif key in self.pdfQ2:
986 wgtpdf = self.pdfQ2[key]
987 else:
988
989 wgtpdf = 0
990
991 tmp *= wgtpdf
992 wgt += tmp
993
994
995 if __debug__ and dyn== -1 and Dmur==1 and Dmuf==1 and pdf==self.orig_pdf:
996 if not misc.equal(tmp, onewgt.ref_wgt, sig_fig=2):
997 misc.sprint(tmp, onewgt.ref_wgt, (tmp-onewgt.ref_wgt)/tmp)
998 misc.sprint(onewgt)
999 misc.sprint(cevent)
1000 misc.sprint(mur2,muf2)
1001 raise Exception('not enough agreement between stored value and computed one')
1002
1003 return wgt
1004
1005
1008 """calling systematics from a list of arguments"""
1009
1010
1011 input, output = args[0:2]
1012
1013 start_opts = 2
1014 if output and output.startswith('-'):
1015 start_opts = 1
1016 output = input
1017
1018 opts = {}
1019 for arg in args[start_opts:]:
1020 if '=' in arg:
1021 key,values= arg.split('=')
1022 key = key.replace('-','')
1023 values = values.strip()
1024 if values[0] in ["'",'"'] and values[-1]==values[0]:
1025 values = values[1:-1]
1026 values = values.split(',')
1027 if key == 'together':
1028 if key in opts:
1029 opts[key].append(tuple(values))
1030 else:
1031 opts[key]=[tuple(values)]
1032 elif key == 'result':
1033 result = open(values[0],'w')
1034 elif key in ['start_event', 'stop_event', 'only_beam']:
1035 opts[key] = banner_mod.ConfigFile.format_variable(values[0], int, key)
1036 elif key in ['write_banner', 'ion_scalling']:
1037 opts[key] = banner_mod.ConfigFile.format_variable(values[0], bool, key)
1038 else:
1039 if key in opts:
1040 opts[key] += values
1041 else:
1042 opts[key] = values
1043 else:
1044 raise SystematicsError("unknow argument %s" % arg)
1045
1046
1047 if 'from_card' in opts:
1048 if opts['from_card'] != ['internal']:
1049 card = banner.RunCard(opts['from_card'][0])
1050 else:
1051 for i in range(10):
1052 try:
1053 lhe = lhe_parser.EventFile(input)
1054 break
1055 except OSError as error:
1056 print(error)
1057 time.sleep(15*(i+1))
1058 else:
1059 raise
1060
1061 card = banner.RunCard(banner.Banner(lhe.banner)['mgruncard'])
1062 lhe.close()
1063
1064 if isinstance(card, banner.RunCardLO):
1065
1066 if 'systematics_arguments' in card.user_set:
1067 return call_systematics([input, output] + card['systematics_arguments']
1068 , result=result, running=running,
1069 log=log)
1070
1071 else:
1072 opts['mur'] = [float(x) for x in card['sys_scalefact'].split()]
1073 opts['muf'] = opts['mur']
1074 if card['sys_alpsfact'] != 'None':
1075 opts['alps'] = [float(x) for x in card['sys_alpsfact'].split()]
1076 else:
1077 opts['alps'] = [1.0]
1078 opts['together'] = [('mur','muf','alps','dyn')]
1079 if '&&' in card['sys_pdf']:
1080 pdfs = card['sys_pdf'].split('&&')
1081 else:
1082 data = card['sys_pdf'].split()
1083 pdfs = []
1084 for d in data:
1085 if not d.isdigit():
1086 pdfs.append(d)
1087 elif int(d) > 500:
1088 pdfs.append(d)
1089 else:
1090 pdfs[-1] = '%s %s' % (pdfs[-1], d)
1091
1092 opts['dyn'] = [-1,1,2,3,4]
1093 opts['pdf'] = []
1094 for pdf in pdfs:
1095 split = pdf.split()
1096 if len(split)==1:
1097 opts['pdf'].append('%s' %pdf)
1098 else:
1099 pdf,nb = split
1100 for i in range(int(nb)):
1101 opts['pdf'].append('%s@%s' % (pdf, i))
1102 if not opts['pdf']:
1103 opts['pdf'] = 'central'
1104 else:
1105
1106 if 'systematics_arguments' in card.user_set:
1107 return call_systematics([input, output] + card['systematics_arguments']
1108 , result=result, running=running,
1109 log=log)
1110 else:
1111 raise Exception
1112 del opts['from_card']
1113
1114
1115 obj = Systematics(input, output, log=log, **opts)
1116 if running and obj:
1117 obj.run(result)
1118 return obj
1119
1120 if __name__ == "__main__":
1121
1122 sys_args = sys.argv[1:]
1123 for i, arg in enumerate(list(sys_args)) :
1124 if arg.startswith('--lhapdf_config=') :
1125 lhapdf = misc.import_python_lhapdf(arg[len('--lhapdf_config='):])
1126 del sys_args[i]
1127 break
1128
1129 if 'lhapdf' not in globals():
1130 lhapdf = misc.import_python_lhapdf('lhapdf-config')
1131
1132 if not lhapdf:
1133 sys.exit('Can not run systematics since can not link python to lhapdf, specify --lhapdf_config=')
1134 call_systematics(sys_args)
1135