1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """ Command interface for MadSpin """
16 from __future__ import division
17 import difflib
18 import logging
19 import math
20 import os
21 import re
22 import shutil
23 import sys
24 import tempfile
25 import time
26 import subprocess
27 from subprocess import Popen, PIPE, STDOUT
28
29
30 pjoin = os.path.join
31
32 import madgraph.interface.extended_cmd as extended_cmd
33 import madgraph.interface.madgraph_interface as mg_interface
34 import madgraph.interface.master_interface as master_interface
35 import madgraph.interface.common_run_interface as common_run_interface
36 import madgraph.iolibs.files as files
37 import MadSpin.interface_madspin as madspin_interface
38 import madgraph.various.misc as misc
39 import madgraph.various.banner as banner
40 import madgraph.various.lhe_parser as lhe_parser
41 import madgraph.various.combine_plots as combine_plots
42 import madgraph.various.cluster as cluster
43 import madgraph.fks.fks_common as fks_common
44
45 import models.import_ufo as import_ufo
46 import models.check_param_card as check_param_card
47 import MadSpin.decay as madspin
48
49
50 logger = logging.getLogger('decay.stdout')
51 logger_stderr = logging.getLogger('decay.stderr')
52 cmd_logger = logging.getLogger('cmdprint2')
53
54
55 dir_to_f2py_free_mod = {}
56 nb_f2py_module = 0
63 """Basic interface for reweighting operation"""
64
65 prompt = 'Reweight>'
66 debug_output = 'Reweight_debug'
67
68 @misc.mute_logger()
69 - def __init__(self, event_path=None, allow_madspin=False, *completekey, **stdin):
70 """initialize the interface with potentially an event_path"""
71
72 if not event_path:
73 cmd_logger.info('************************************************************')
74 cmd_logger.info('* *')
75 cmd_logger.info('* Welcome to Reweight Module *')
76 cmd_logger.info('* *')
77 cmd_logger.info('************************************************************')
78 extended_cmd.Cmd.__init__(self, *completekey, **stdin)
79
80 self.model = None
81 self.has_standalone_dir = False
82
83 self.options = {'curr_dir': os.path.realpath(os.getcwd())}
84
85 self.events_file = None
86 self.processes = {}
87 self.second_model = None
88 self.second_process = None
89 self.mg5cmd = master_interface.MasterCmd()
90 self.seed = None
91 self.output_type = "default"
92 self.helicity_reweighting = True
93 self.rwgt_dir = None
94
95 if event_path:
96 logger.info("Extracting the banner ...")
97 self.do_import(event_path, allow_madspin=allow_madspin)
98
99
100 self.calculator = {}
101 self.calculator_nbcall = {}
102
103
104 self.all_cross_section = {}
105
106 - def do_import(self, inputfile, allow_madspin=False):
107 """import the event file"""
108
109 args = self.split_arg(inputfile)
110 if not args:
111 return self.InvalidCmd, 'import requires arguments'
112
113
114 self.options['curr_dir'] = os.path.realpath(os.path.dirname(inputfile))
115 if os.path.basename(os.path.dirname(os.path.dirname(inputfile))) == 'Events':
116 self.options['curr_dir'] = pjoin(self.options['curr_dir'],
117 os.path.pardir, os.pardir)
118
119
120 if not os.path.exists(inputfile):
121 if inputfile.endswith('.gz'):
122 if not os.path.exists(inputfile[:-3]):
123 raise self.InvalidCmd('No such file or directory : %s' % inputfile)
124 else:
125 inputfile = inputfile[:-3]
126 elif os.path.exists(inputfile + '.gz'):
127 inputfile = inputfile + '.gz'
128 else:
129 raise self.InvalidCmd('No such file or directory : %s' % inputfile)
130
131 if inputfile.endswith('.gz'):
132 misc.gunzip(inputfile)
133 inputfile = inputfile[:-3]
134
135
136 self.lhe_input = lhe_parser.EventFile(os.path.realpath(inputfile))
137 if not self.lhe_input.banner:
138 value = self.ask("What is the path to banner", 0, [0], "please enter a path", timeout=0)
139 self.lhe_input.banner = open(value).read()
140 self.banner = self.lhe_input.get_banner()
141
142
143 if 'init' not in self.banner:
144 raise self.InvalidCmd('Event file does not contain init information')
145 for line in self.banner['init'].split('\n'):
146 split = line.split()
147 if len(split) == 4:
148 cross, error = float(split[0]), float(split[1])
149 self.orig_cross = (cross, error)
150
151
152
153
154 if 'slha' not in self.banner:
155 misc.sprint(self.banner)
156 self.events_file = None
157 raise self.InvalidCmd('Event file does not contain model information')
158 elif 'mg5proccard' not in self.banner:
159 self.events_file = None
160 raise self.InvalidCmd('Event file does not contain generation information')
161
162 if 'madspin' in self.banner and not allow_madspin:
163 raise self.InvalidCmd('Reweight should be done before running MadSpin')
164
165
166
167 process = self.banner.get_detail('proc_card', 'generate')
168 if '[' in process:
169 logger.warning("Remember that the reweighting is performed at Leading Order. NLO precision is not guarantee.")
170
171 if not process:
172 msg = 'Invalid proc_card information in the file (no generate line):\n %s' % self.banner['mg5proccard']
173 raise Exception, msg
174 process, option = mg_interface.MadGraphCmd.split_process_line(process)
175 self.proc_option = option
176
177 logger.info("process: %s" % process)
178 logger.info("options: %s" % option)
179
180
182 """return the LO definitions of the process corresponding to the born/real"""
183
184
185 process, order, final = re.split('\[\s*(.*)\s*\]', proc)
186
187 commandline="add process %s %s --no_warning=duplicate;" % (process, final)
188 if not order:
189
190 return proc
191 elif not order.startswith(('virt=','loonly=','noborn=')):
192
193 if '=' in order:
194
195 order = order.split('=',1)[1]
196
197
198 pert = fks_common.find_pert_particles_interactions(self.model,
199 pert_order = order)['soft_particles']
200 commandline += "define pert_%s = %s;" % (order.replace(' ',''), ' '.join(map(str,pert)) )
201
202
203 if '%s=' % order in process:
204 result=re.split(' ',process)
205 process=''
206 for r in result:
207 if '%s=' % order in r:
208 ior=re.split('=',r)
209 r='QCD=%i' % (int(ior[1])+1)
210 process=process+r+' '
211
212 result = re.split('([/$@]|\w+=\w+)', process, 1)
213 if len(result) ==3:
214 process, split, rest = result
215 commandline+="add process %s pert_%s %s%s %s --no_warning=duplicate;" % (process, order.replace(' ','') ,split, rest, final)
216 else:
217 commandline +='add process %s pert_%s %s --no_warning=duplicate;' % (process,order.replace(' ',''), final)
218 elif order.startswith(('noborn=')):
219
220 return "add process %s " % proc.replace('noborn=', 'sqrvirt=')
221
222 else:
223
224 return "add process %s " % proc
225 return commandline
226
227
229 """Check some basic property of the events file"""
230
231 sum_of_weight = 0
232 sum_of_abs_weight = 0
233 negative_event = 0
234 positive_event = 0
235
236 start = time.time()
237 for event_nb,event in enumerate(self.lhe_input):
238
239 if (event_nb % max(int(10**int(math.log10(float(event_nb)+1))),10)==0):
240 running_time = misc.format_timer(time.time()-start)
241 logger.info('Event nb %s %s' % (event_nb, running_time))
242 if (event_nb==10001): logger.info('reducing number of print status. Next status update in 10000 events')
243
244 event.check()
245
246 sum_of_weight += event.wgt
247 sum_of_abs_weight += abs(event.wgt)
248 if event.wgt < 0 :
249 negative_event +=1
250 else:
251 positive_event +=1
252
253 logger.info("total cross-section: %s" % sum_of_weight)
254 logger.info("total abs cross-section: %s" % sum_of_abs_weight)
255 logger.info("fraction of negative event %s", negative_event/(negative_event+positive_event))
256 logger.info("total number of events %s", (negative_event+positive_event))
257 logger.info("negative event %s", negative_event)
258
259
260
261
262 @extended_cmd.debug()
264 "Complete the import command"
265
266 args=self.split_arg(line[0:begidx])
267
268 if len(args) == 1:
269 base_dir = '.'
270 else:
271 base_dir = args[1]
272
273 return self.path_completion(text, base_dir)
274
275
276 if os.path.sep in args[-1] + text:
277 return self.path_completion(text,
278 pjoin(*[a for a in args if \
279 a.endswith(os.path.sep)]))
280
282 """help for change command"""
283
284 print "change model X :use model X for the reweighting"
285 print "change process p p > e+ e-: use a new process for the reweighting"
286 print "change process p p > mu+ mu- --add : add one new process to existing ones"
287
289 """allow to define a second model/processes"""
290
291 global nb_f2py_module
292
293 args = self.split_arg(line)
294 if len(args)<2:
295 logger.critical("not enough argument (need at least two). Discard line")
296 if args[0] == "model":
297 nb_f2py_module += 1
298 self.second_model = " ".join(args[1:])
299 if self.has_standalone_dir:
300 self.terminate_fortran_executables()
301 self.has_standalone_dir = False
302 elif args[0] == "process":
303 nb_f2py_module += 1
304 if self.has_standalone_dir:
305 self.terminate_fortran_executables()
306 self.has_standalone_dir = False
307 if args[-1] == "--add":
308 self.second_process.append(" ".join(args[1:-1]))
309 else:
310 self.second_process = [" ".join(args[1:])]
311 elif args[0] == "output":
312 if args[1] in ['default', '2.0', 'unweight']:
313 self.output_type = args[1]
314 elif args[0] == "helicity":
315 self.helicity_reweighting = banner.ConfigFile.format_variable(args[1], bool, "helicity")
316 elif args[0] == "rwgt_dir":
317 self.rwgt_dir = args[1]
318 if not os.path.exists(self.rwgt_dir):
319 os.mkdir(self.rwgt_dir)
320 else:
321 logger.critical("unknown option! %s. Discard line." % args[0])
322
323
325 """check the validity of the launch command"""
326
327 if not self.lhe_input:
328 if isinstance(self.lhe_input, lhe_parser.EventFile):
329 self.lhe_input = lhe_parser.EventFile(self.lhe_input.name)
330 else:
331 raise self.InvalidCmd("No events files defined.")
332
334 """help for the launch command"""
335
336 logger.info('''Add to the loaded events a weight associated to a
337 new param_card (to be define). The weight returned is the ratio of the
338 square matrix element by the squared matrix element of production.
339 All scale are kept fix for this re-weighting.''')
340
341
342
344 """end of the configuration launched the code"""
345
346 args = self.split_arg(line)
347 self.check_launch(args)
348
349 model_line = self.banner.get('proc_card', 'full_model_line')
350
351 if not self.has_standalone_dir:
352 if self.rwgt_dir and os.path.exists(pjoin(self.rwgt_dir,'rw_me','rwgt.pkl')):
353 self.load_from_pickle()
354 self.me_dir = self.rwgt_dir
355 else:
356 self.create_standalone_directory()
357
358 if self.rwgt_dir:
359 path_me =self.rwgt_dir
360 else:
361 path_me = self.me_dir
362
363 if self.second_model or self.second_process:
364 rw_dir = pjoin(path_me, 'rw_me_second')
365 else:
366 rw_dir = pjoin(path_me, 'rw_me')
367
368 ff = open(pjoin(rw_dir,'Cards', 'param_card.dat'), 'w')
369 ff.write(self.banner['slha'])
370 ff.close()
371 ff = open(pjoin(path_me, 'rw_me','Cards', 'param_card_orig.dat'), 'w')
372 ff.write(self.banner['slha'])
373 ff.close()
374 cmd = common_run_interface.CommonRunCmd.ask_edit_card_static(cards=['param_card.dat'],
375 ask=self.ask, pwd=rw_dir, first_cmd=self.stored_line)
376 self.stored_line = None
377
378 new_card = open(pjoin(rw_dir, 'Cards', 'param_card.dat')).read()
379
380 if "auto" in new_card.lower():
381 self.mother.check_param_card(pjoin(path_me, 'rw_me', 'Cards', 'param_card.dat'))
382 new_card = open(pjoin(rw_dir, 'Cards', 'param_card.dat')).read()
383
384
385 if 'initrwgt' in self.banner:
386 if 'type=\'mg_reweighting\'' in self.banner['initrwgt']:
387 blockpat = re.compile(r'''<weightgroup type=\'mg_reweighting\'\s*>(?P<text>.*?)</weightgroup>''', re.I+re.M+re.S)
388 before, content, after = blockpat.split(self.banner['initrwgt'])
389 header_rwgt_other = before + after
390 pattern = re.compile('<weight id=\'mg_reweight_(?P<id>\d+)\'>(?P<info>[^<]*)</weight>', re.S+re.I+re.M)
391 mg_rwgt_info = pattern.findall(content)
392 maxid = 0
393 for i, diff in mg_rwgt_info:
394 if int(i) > maxid:
395 maxid = int(i)
396 maxid += 1
397 rewgtid = maxid
398 else:
399 header_rwgt_other = self.banner['initrwgt']
400 mg_rwgt_info = []
401 rewgtid = 1
402 else:
403 self.banner['initrwgt'] = ''
404 header_rwgt_other = ''
405 mg_rwgt_info = []
406 rewgtid = 1
407
408
409
410 s_orig = self.banner['slha']
411 s_new = new_card
412 if not self.second_model:
413 old_param = check_param_card.ParamCard(s_orig.splitlines())
414 new_param = check_param_card.ParamCard(s_new.splitlines())
415 card_diff = old_param.create_diff(new_param)
416 if card_diff == '' and not self.second_process:
417 logger.warning(' REWEIGHTING: original card and new card are identical. Bypass this run')
418 return
419
420 try:
421 if old_param['sminputs'].get(3)- new_param['sminputs'].get(3) > 1e-3 * new_param['sminputs'].get(3):
422 logger.warning("We found different value of alpha_s. Note that the value of alpha_s used is the one associate with the event and not the one from the cards.")
423 except Exception, error:
424 logger.debug("error in check of alphas: %s" % str(error))
425 pass
426 if not self.second_process:
427 mg_rwgt_info.append((str(rewgtid), card_diff))
428 else:
429 str_proc = "\n change process ".join([""]+self.second_process)
430 mg_rwgt_info.append((str(rewgtid), str_proc + '\n'+ card_diff))
431 else:
432 str_info = "change model %s" % self.second_model
433 if self.second_process:
434 str_info += "\n change process ".join([""]+self.second_process)
435 card_diff = str_info
436 str_info += '\n' + s_new
437 mg_rwgt_info.append((str(rewgtid), str_info))
438
439
440 self.banner['initrwgt'] = header_rwgt_other
441 self.banner['initrwgt'] += '\n<weightgroup type=\'mg_reweighting\'>\n'
442 for tag, diff in mg_rwgt_info:
443 self.banner['initrwgt'] += '<weight id=\'mg_reweight_%s\'>%s</weight>\n' % \
444 (tag, diff)
445 self.banner['initrwgt'] += '\n</weightgroup>\n'
446 self.banner['initrwgt'] = self.banner['initrwgt'].replace('\n\n', '\n')
447
448 output = open( self.lhe_input.name +'rw', 'w')
449
450
451 logger.info('starts to compute weight for events with the following modification to the param_card:')
452 logger.info(card_diff)
453
454
455 self.banner.write(output, close_tag=False)
456
457 if self.mother:
458 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe')
459 output2 = open(out_path, 'w')
460 lha_strategy = self.banner.get_lha_strategy()
461 self.banner.set_lha_strategy(4*lha_strategy/abs(lha_strategy))
462 self.banner.write(output2, close_tag=False)
463 self.banner.set_lha_strategy(lha_strategy)
464 new_banner = banner.Banner(self.banner)
465 if not hasattr(self, 'run_card'):
466 self.run_card = new_banner.charge_card('run_card')
467 self.run_card['run_tag'] = 'reweight_%s' % rewgtid
468 new_banner['slha'] = s_new
469 del new_banner['initrwgt']
470 assert 'initrwgt' in self.banner
471 ff = open(pjoin(self.mother.me_dir,'Events',self.mother.run_name, '%s_%s_banner.txt' % \
472 (self.mother.run_name, self.run_card['run_tag'])),'w')
473 new_banner.write(ff)
474 ff.close()
475
476
477 tag_name = 'mg_reweight_%s' % rewgtid
478 start = time.time()
479 cross = 0
480 ratio, ratio_square = 0, 0
481
482 os.environ['GFORTRAN_UNBUFFERED_ALL'] = 'y'
483 if self.lhe_input.closed:
484 misc.sprint("using", self.lhe_input.name)
485 self.lhe_input = lhe_parser.EventFile(self.lhe_input.name)
486
487
488 nb_core = 1
489
490
491
492 self.lhe_input.seek(0)
493 for event_nb,event in enumerate(self.lhe_input):
494
495 if (event_nb % max(int(10**int(math.log10(float(event_nb)+1))),10)==0):
496 running_time = misc.format_timer(time.time()-start)
497 logger.info('Event nb %s %s' % (event_nb, running_time))
498 if (event_nb==10001): logger.info('reducing number of print status. Next status update in 10000 events')
499
500 if nb_core > 1:
501
502 while 1:
503 if multicore.queue.qsize() < 100 * nb_core:
504 multicore.submit(self.write_reweighted_event, argument=[event, tag_name])
505 break
506
507
508 continue
509 else:
510 weight = self.calculate_weight(event)
511 cross += weight
512 ratio += weight/event.wgt
513 ratio_square += (weight/event.wgt)**2
514 if self.output_type == "default":
515 event.reweight_data[tag_name] = weight
516
517 output.write(str(event))
518 if self.mother:
519 event.wgt = weight
520 event.reweight_data = {}
521 output2.write(str(event))
522
523 else:
524 event.wgt = weight
525 event.reweight_data = {}
526 if self.mother:
527 output2.write(str(event))
528 else:
529 output.write(str(event))
530
531
532 if 'event_norm' in self.run_card:
533 if self.run_card['event_norm'] == 'average':
534 cross /= event_nb+1
535
536
537 running_time = misc.format_timer(time.time()-start)
538 logger.info('All event done (nb_event: %s) %s' % (event_nb+1, running_time))
539
540 output.write('</LesHouchesEvents>\n')
541 output.close()
542 os.environ['GFORTRAN_UNBUFFERED_ALL'] = 'n'
543 if self.mother:
544 output2.write('</LesHouchesEvents>\n')
545 output2.close()
546
547 if hasattr(self.mother, 'results'):
548 run_name = self.mother.run_name
549 results = self.mother.results
550 results.add_run(run_name, self.run_card, current=True)
551 results.add_detail('nb_event', event_nb+1)
552 results.add_detail('cross', cross)
553 event_nb +=1
554 variance = ratio_square/event_nb - (ratio/event_nb)**2
555 orig_cross, orig_error = self.orig_cross
556 error = variance/math.sqrt(event_nb) * orig_cross + ratio/event_nb * orig_error
557
558 results.add_detail('error', error)
559 self.mother.create_plot(mode='reweight', event_path=output2.name,
560 tag=self.run_card['run_tag'])
561
562 if 'plot' in results.current.reweight:
563 html_dir = pjoin(self.mother.me_dir, 'HTML', run_name)
564 td = pjoin(self.mother.options['td_path'], 'td')
565 MA = pjoin(self.mother.options['madanalysis_path'])
566 path1 = pjoin(html_dir, 'plots_parton')
567 path2 = pjoin(html_dir, 'plots_%s' % self.run_card['run_tag'])
568 outputplot = path2
569 combine_plots.merge_all_plots(path2, path1, outputplot, td, MA)
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584 self.lhe_input.close()
585 if not self.mother or self.output_type != "default" :
586 target = pjoin(self.mother.me_dir, 'Events', run_name, 'events.lhe')
587 else:
588 target = self.lhe_input.name
589
590 if self.output_type == "default":
591 files.mv(output.name, target)
592 elif self.output_type == "unweight":
593 output2.close()
594 lhe = lhe_parser.EventFile(output2.name)
595 nb_event = lhe.unweight(target)
596 if self.mother and hasattr(self.mother, 'results'):
597 results = self.mother.results
598 results.add_detail('nb_event', nb_event)
599 results.current.parton.append('lhe')
600
601 else:
602 files.mv(output2.name, self.lhe_input.name)
603 if self.mother and hasattr(self.mother, 'results'):
604 results = self.mother.results
605 results.current.parton.append('lhe')
606
607 logger.info('Event %s have now the additional weight' % self.lhe_input.name)
608 logger.info('new cross-section is : %g pb (indicative error: %g pb)' % (cross,error))
609 self.terminate_fortran_executables(new_card_only=True)
610
611 self.all_cross_section[rewgtid] = (cross, error)
612
614 "Not in help"
615
616 logger.warning("Invalid Syntax. The command 'set' should be placed after the 'launch' one. Continuing by adding automatically 'launch'")
617 self.stored_line = "set %s" % line
618 return self.exec_cmd("launch")
619
620 - def default(self, line, log=True):
621 """Default action if line is not recognized"""
622
623 if os.path.isfile(line):
624 if log:
625 logger.warning("Invalid Syntax. The path to a param_card' should be placed after the 'launch' command. Continuing by adding automatically 'launch'")
626 self.stored_line = line
627 return self.exec_cmd("launch")
628 else:
629 return super(ReweightInterface,self).default(line, log=log)
630
632 """a function for running in multicore"""
633
634 if not hasattr(opt['thread_space'], "calculator"):
635 opt['thread_space'].calculator = {}
636 opt['thread_space'].calculator_nbcall = {}
637 opt['thread_space'].cross = 0
638 opt['thread_space'].output = open( self.lhe_input.name +'rw.%s' % opt['thread_id'], 'w')
639 if self.mother:
640 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe.%s' % opt['thread_id'])
641 opt['thread_space'].output2 = open(out_path, 'w')
642
643 weight = self.calculate_weight(event, space=opt['thread_space'])
644 opt['thread_space'].cross += weight
645 if self.output_type == "default":
646 event.reweight_data[tag_name] = weight
647
648 opt['thread_space'].output.write(str(event))
649 if self.mother:
650 event.wgt = weight
651 event.reweight_data = {}
652 opt['thread_space'].output2.write(str(event))
653 else:
654 event.wgt = weight
655 event.reweight_data = {}
656 if self.mother:
657 opt['thread_space'].output2.write(str(event))
658 else:
659 opt['thread_space'].output.write(str(event))
660
661 return 0
662
664 """space defines where to find the calculator (in multicore)"""
665
666 if not space:
667 space = self
668
669 event.parse_reweight()
670
671 w_orig = self.calculate_matrix_element(event, 0, space)
672 w_new = self.calculate_matrix_element(event, 1, space)
673 if w_orig == 0:
674 tag, order = event.get_tag_and_order()
675 orig_order, Pdir, hel_dict = self.id_to_path[tag]
676 misc.sprint(w_orig, w_new)
677 misc.sprint(event)
678 raise Exception, "Invalid matrix element for original computation (weight=0)"
679 return w_new/w_orig*event.wgt
680
681 @staticmethod
683 """ fortran/C-python do not order table in the same order"""
684 new_p = []
685 for i in range(len(p[0])): new_p.append([0]*len(p))
686 for i, onep in enumerate(p):
687 for j, x in enumerate(onep):
688 new_p[j][i] = x
689 return new_p
690
691 @staticmethod
693 if tag == 2:
694 return
695 if os.path.exists(pjoin(Pdir, 'matrix%spy.so' % tag)):
696 return
697 else:
698 open(pjoin(Pdir, 'matrix%spy.so' % tag),'w').write(open(pjoin(Pdir, 'matrix2py.so')
699 ).read().replace('matrix2py', 'matrix%spy' % tag))
700
702 """routine to return the matrix element"""
703
704 tag, order = event.get_tag_and_order()
705
706 if (not self.second_model and not self.second_process) or hypp_id==0:
707 orig_order, Pdir, hel_dict = self.id_to_path[tag]
708 else:
709 orig_order, Pdir, hel_dict = self.id_to_path_second[tag]
710
711 run_id = (tag, hypp_id)
712
713
714 assert space == self
715 start = False
716 if run_id in space.calculator:
717 external = space.calculator[run_id]
718 elif (not self.second_model and not self.second_process) or hypp_id==0:
719
720 subdir = pjoin(self.me_dir,'rw_me ', 'SubProcesses')
721 if self.me_dir not in sys.path:
722 sys.path.insert(0,self.me_dir)
723 if self.rwgt_dir and self.rwgt_dir not in sys.path:
724 sys.path.insert(0,self.rwgt_dir)
725 Pname = os.path.basename(Pdir)
726 if hypp_id == 0:
727 if (Pdir, 0) not in dir_to_f2py_free_mod:
728 metag = 1
729 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module)
730 else:
731 metag, old_module = dir_to_f2py_free_mod[(Pdir,0)]
732 if old_module != nb_f2py_module:
733 metag += 1
734 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module)
735
736 os.environ['MENUM'] = '2'
737 misc.compile(['matrix2py.so'], cwd=Pdir)
738
739 self.rename_f2py_lib(Pdir, 2*metag)
740 with misc.chdir(Pdir):
741 mymod = __import__('rw_me.SubProcesses.%s.matrix%spy' % (Pname, 2*metag), globals(), locals(), [],-1)
742 S = mymod.SubProcesses
743 P = getattr(S, Pname)
744 mymod = getattr(P, 'matrix%spy' % (2*metag))
745 mymod.initialise('param_card_orig.dat')
746
747 if hypp_id == 1:
748
749 metag = dir_to_f2py_free_mod[(Pdir,0)][0]
750 newtag = 2*metag+1
751 self.rename_f2py_lib(Pdir, newtag)
752 try:
753 mymod = __import__('rw_me.SubProcesses.%s.matrix%spy' % (Pname, newtag), globals(), locals(), [],-1)
754 except Exception, error:
755 os.remove(pjoin(Pdir, 'matrix%spy.so' % newtag))
756 newtag = "L%s" % newtag
757 os.environ['MENUM'] = newtag
758 misc.compile(['matrix%spy.so' % newtag], cwd=Pdir)
759 mymod = __import__('rw_me.SubProcesses.%s.matrix%spy' % (Pname, newtag), globals(), locals(), [],-1)
760
761 S = mymod.SubProcesses
762 P = getattr(S, Pname)
763 mymod = getattr(P, 'matrix%spy' % newtag)
764 with misc.chdir(Pdir):
765 mymod.initialise('param_card.dat')
766 space.calculator[run_id] = mymod.get_me
767 external = space.calculator[run_id]
768 else:
769 subdir = pjoin(self.me_dir,'rw_me_second', 'SubProcesses')
770 if self.me_dir not in sys.path:
771 sys.path.append(self.me_dir)
772
773 assert hypp_id == 1
774 Pname = os.path.basename(Pdir)
775 os.environ['MENUM'] = '2'
776 misc.compile(['matrix2py.so'], cwd=pjoin(subdir, Pdir))
777 if (Pdir, 1) not in dir_to_f2py_free_mod:
778 metag = 1
779 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module)
780 else:
781 metag, old_module = dir_to_f2py_free_mod[(Pdir,1)]
782 if old_module != nb_f2py_module:
783 metag += 1
784 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module)
785 self.rename_f2py_lib(Pdir, metag)
786 with misc.chdir(Pdir):
787 try:
788 mymod = __import__("rw_me_second.SubProcesses.%s.matrix%spy" % (Pname, metag))
789 except ImportError:
790 os.remove(pjoin(Pdir, 'matrix%spy.so' % metag ))
791 metag = "L%s" % metag
792 os.environ['MENUM'] = str(metag)
793 misc.compile(['matrix%spy.so' % metag], cwd=pjoin(subdir, Pdir))
794 mymod = __import__("rw_me_second.SubProcesses.%s.matrix%spy" % (Pname, metag))
795
796 reload(mymod)
797 S = mymod.SubProcesses
798 P = getattr(S, Pname)
799 mymod = getattr(P, 'matrix%spy' % metag)
800 mymod.initialise('param_card.dat')
801 space.calculator[run_id] = mymod.get_me
802 external = space.calculator[run_id]
803
804
805 p = self.invert_momenta(event.get_momenta(orig_order))
806
807
808 hel_order = event.get_helicity(orig_order)
809 if self.helicity_reweighting and 9 not in hel_order:
810 nhel = hel_dict[tuple(hel_order)]
811 else:
812 nhel = 0
813
814 with misc.chdir(Pdir):
815 with misc.stdchannel_redirected(sys.stdout, os.devnull):
816 me_value = external(p,event.aqcd, nhel)
817
818 if isinstance(me_value, tuple):
819 me_value, code = me_value
820
821 hundred_value = (code % 1000) //100
822 if hundred_value in [4]:
823 me_value = 0.
824
825 return me_value
826
828 """routine to terminate all fortran executables"""
829
830 for (mode, production) in dict(self.calculator):
831
832 if new_card_only and production == 0:
833 continue
834 del self.calculator[(mode, production)]
835
857
860
861
863 """Adding one element to the list based on the matrix element"""
864
865
866
867
868
869
870 @misc.mute_logger()
872 """generate the various directory for the weight evaluation"""
873
874
875 if not self.rwgt_dir:
876 path_me = self.me_dir
877 else:
878 path_me = self.rwgt_dir
879 try:
880 shutil.rmtree(pjoin(path_me,'rw_me'))
881 except Exception:
882 pass
883
884
885 complex_mass = False
886 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''')
887 for line in self.banner.proc_card:
888 if line.startswith('set'):
889 self.mg5cmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False)
890 if has_cms.search(line):
891 complex_mass = True
892 elif line.startswith('define'):
893 try:
894 self.mg5cmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False)
895 except Exception:
896 pass
897
898 info = self.banner.get('proc_card', 'full_model_line')
899 if '-modelname' in info:
900 mg_names = False
901 else:
902 mg_names = True
903 model_name = self.banner.get('proc_card', 'model')
904 if model_name:
905 self.load_model(model_name, mg_names, complex_mass)
906 else:
907 raise self.InvalidCmd('Only UFO model can be loaded in this module.')
908
909 mgcmd = self.mg5cmd
910 modelpath = self.model.get('modelpath')
911 if os.path.basename(modelpath) != mgcmd._curr_model['name']:
912 name, restrict = mgcmd._curr_model['name'].rsplit('-',1)
913 if os.path.exists(pjoin(os.path.dirname(modelpath),name, 'restrict_%s.dat' % restrict)):
914 modelpath = pjoin(os.path.dirname(modelpath), mgcmd._curr_model['name'])
915
916 commandline="import model %s " % modelpath
917 mgcmd.exec_cmd(commandline)
918
919
920 processes = [line[9:].strip() for line in self.banner.proc_card
921 if line.startswith('generate')]
922 processes += [' '.join(line.split()[2:]) for line in self.banner.proc_card
923 if re.search('^\s*add\s+process', line)]
924 mgcmd.exec_cmd("set group_subprocesses False")
925
926 logger.info('generating the square matrix element for reweighting')
927 start = time.time()
928 commandline=''
929 for proc in processes:
930 if '[' not in proc:
931 commandline += "add process %s ;" % proc
932 else:
933 commandline += self.get_LO_definition_from_NLO(proc)
934
935 commandline = commandline.replace('add process', 'generate',1)
936 logger.info(commandline)
937 mgcmd.exec_cmd(commandline, precmd=True)
938 commandline = 'output standalone_rw %s' % pjoin(path_me,'rw_me')
939 mgcmd.exec_cmd(commandline, precmd=True)
940 logger.info('Done %.4g' % (time.time()-start))
941 self.has_standalone_dir = True
942
943
944
945 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements()
946
947 self.id_to_path = {}
948 for me in matrix_elements:
949 for proc in me.get('processes'):
950 initial = []
951 final = [l.get('id') for l in proc.get('legs')\
952 if l.get('state') or initial.append(l.get('id'))]
953 order = (initial, final)
954 tag = proc.get_initial_final_ids()
955 decay_finals = proc.get_final_ids_after_decay()
956
957 if tag[1] != decay_finals:
958 order = (initial, list(decay_finals))
959 decay_finals.sort()
960 tag = (tag[0], tuple(decay_finals))
961 Pdir = pjoin(path_me, 'rw_me', 'SubProcesses',
962 'P%s' % me.get('processes')[0].shell_string())
963 assert os.path.exists(Pdir), "Pdir %s do not exists" % Pdir
964 if tag in self.id_to_path:
965 if not Pdir == self.id_to_path[tag][1]:
966 misc.sprint(tag, Pdir, self.id_to_path[tag][1])
967 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation'
968 else:
969 continue
970
971 hel_nb = 0
972 hel_dict = {9:0}
973 for helicities in me.get_helicity_matrix():
974 hel_nb +=1
975 hel_dict[tuple(helicities)] = hel_nb
976
977 self.id_to_path[tag] = [order, Pdir, hel_dict]
978
979
980 if self.second_model or self.second_process:
981 self.create_second_standalone_directory()
982
983 @misc.mute_logger()
985 """generate the various directory for the weight evaluation"""
986
987
988 path_me = self.me_dir
989 try:
990 shutil.rmtree(pjoin(path_me,'rw_me_second'))
991 except Exception:
992 pass
993
994 mgcmd = self.mg5cmd
995
996 if self.second_model:
997 use_mgdefault= True
998 complex_mass = False
999 if ' ' in self.second_model:
1000 args = self.second_model.split()
1001 if '--modelname' in args:
1002 use_mgdefault = False
1003 model_name = args[0]
1004 else:
1005 model_name = self.second_model
1006 self.load_model(model_name, use_mgdefault, complex_mass)
1007
1008 modelpath = self.model.get('modelpath')
1009 if os.path.basename(modelpath) != mgcmd._curr_model['name']:
1010 name, restrict = mgcmd._curr_model['name'].rsplit('-',1)
1011 if os.path.exists(pjoin(os.path.dirname(modelpath),name, 'restrict_%s.dat' % restrict)):
1012 modelpath = pjoin(os.path.dirname(modelpath), mgcmd._curr_model['name'])
1013
1014 commandline="import model %s " % modelpath
1015 if not use_mgdefault:
1016 commandline += ' -modelname '
1017 mgcmd.exec_cmd(commandline)
1018
1019
1020 if self.second_process:
1021 processes = self.second_process
1022 else:
1023 processes = [line[9:].strip() for line in self.banner.proc_card
1024 if line.startswith('generate')]
1025 processes += [' '.join(line.split()[2:]) for line in self.banner.proc_card
1026 if re.search('^\s*add\s+process', line)]
1027 mgcmd.exec_cmd("set group_subprocesses False")
1028
1029 logger.info('generating the square matrix element for reweighting')
1030 start = time.time()
1031 commandline=''
1032 for proc in processes:
1033 if '[' not in proc:
1034 commandline+="add process %s ;" % proc
1035 elif 'sqrvirt' in proc:
1036 commandline+="add process %s ;" % proc
1037 else:
1038 raise self.InvalidCmd('NLO processes can\'t be reweight (for Loop induced reweighting use [sqrvirt =])')
1039
1040 commandline = commandline.replace('add process', 'generate',1)
1041 logger.info(commandline)
1042 mgcmd.exec_cmd(commandline, precmd=True)
1043
1044 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements()
1045
1046 commandline = 'output standalone_rw %s' % pjoin(path_me,'rw_me_second')
1047 mgcmd.exec_cmd(commandline, precmd=True)
1048 logger.info('Done %.4g' % (time.time()-start))
1049
1050
1051 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements()
1052
1053 self.id_to_path_second = {}
1054 to_check = []
1055 for me in matrix_elements:
1056 for proc in me.get('processes'):
1057 initial = []
1058 final = [l.get('id') for l in proc.get('legs')\
1059 if l.get('state') or initial.append(l.get('id'))]
1060 order = (initial, final)
1061 tag = proc.get_initial_final_ids()
1062 decay_finals = proc.get_final_ids_after_decay()
1063
1064 if tag[1] != decay_finals:
1065 order = (initial, list(decay_finals))
1066 decay_finals.sort()
1067 tag = (tag[0], tuple(decay_finals))
1068 Pdir = pjoin(path_me, 'rw_me_second', 'SubProcesses',
1069 'P%s' % me.get('processes')[0].shell_string())
1070 if not os.path.exists(Pdir):
1071 to_check.append(tag)
1072 continue
1073 if tag in self.id_to_path_second:
1074 if not Pdir == self.id_to_path_second[tag][1]:
1075 misc.sprint(tag, Pdir, self.id_to_path_second[tag][1])
1076 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation'
1077 else:
1078 continue
1079
1080
1081 hel_nb = 0
1082 hel_dict = {9:0}
1083 for helicities in me.get_helicity_matrix():
1084 hel_nb +=1
1085 hel_dict[tuple(helicities)] = hel_nb
1086 self.id_to_path_second[tag] = [order, Pdir, hel_dict]
1087
1088 for tag in to_check:
1089 if tag not in self.id_to_path:
1090 logger.warning("no valid path for %s" % (tag,))
1091
1092
1093
1094 if os.path.exists(pjoin(path_me, 'rw_me_second', 'Cards', 'MadLoopParams.dat')):
1095 MLCard = banner.MadLoopParam(pjoin(path_me, 'rw_me_second', 'Cards', 'MadLoopParams.dat'))
1096 MLCard.set('WriteOutFilters', False)
1097 MLCard.set('UseLoopFilter', False)
1098 MLCard.set("DoubleCheckHelicityFilter", False)
1099 MLCard.set("HelicityFilterLevel", 0)
1100 MLCard.write(pjoin(path_me, 'rw_me_second', 'SubProcesses', 'MadLoopParams.dat'),
1101 pjoin(path_me, 'rw_me_second', 'Cards', 'MadLoopParams.dat'),
1102 commentdefault=False)
1103
1104
1105
1106
1107
1108
1109 - def load_model(self, name, use_mg_default, complex_mass=False):
1129
1130
1132 import madgraph.iolibs.save_load_object as save_load_object
1133
1134 to_save = {}
1135 to_save['id_to_path'] = self.id_to_path
1136 if hasattr(self, 'id_to_path_second'):
1137 to_save['id_to_path_second'] = self.id_to_path_second
1138 else:
1139 to_save['id_to_path_second'] = {}
1140 to_save['all_cross_section'] = self.all_cross_section
1141 to_save['processes'] = self.processes
1142 to_save['second_process'] = self.second_process
1143 if self.second_model:
1144 to_save['second_model'] =True
1145 else:
1146 to_save['second_model'] = None
1147 to_save['rwgt_dir'] = self.rwgt_dir
1148
1149 name = pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl')
1150 save_load_object.save_to_file(name, to_save)
1151
1153 import madgraph.iolibs.save_load_object as save_load_object
1154
1155 obj = save_load_object.load_from_file( pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl'))
1156
1157 self.has_standalone_dir = True
1158 self.options = {'curr_dir': os.path.realpath(os.getcwd())}
1159
1160 old_rwgt = obj['rwgt_dir']
1161
1162
1163 self.id_to_path = {}
1164 for key , (order, Pdir, hel_dict) in obj['id_to_path'].items():
1165 new_P = Pdir.replace(old_rwgt, self.rwgt_dir)
1166 self.id_to_path[key] = [order, new_P, hel_dict]
1167
1168
1169 self.id_to_path_second = {}
1170 for key , (order, Pdir, hel_dict) in obj['id_to_path_second'].items():
1171 new_P = Pdir.replace(old_rwgt, self.rwgt_dir)
1172 self.id_to_path_second[key] = [order, new_P, hel_dict]
1173
1174 self.all_cross_section = obj['all_cross_section']
1175 self.processes = obj['processes']
1176 self.second_process = obj['second_process']
1177 self.second_model = obj['second_model']
1178