Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInference 4.1.9.1-3a66518
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cbcBayesBurstPostProc.py
Go to the documentation of this file.
1##python
2# -*- coding: utf-8 -*-
3#
4# cbcBayesBurstPostProc.py
5#
6# Copyright 2010
7# Benjamin Aylott <benjamin.aylott@ligo.org>,
8# Benjamin Farr <bfarr@u.northwestern.edu>,
9# Will M. Farr <will.farr@ligo.org>,
10# John Veitch <john.veitch@ligo.org>
11# Vivien Raymond <vivien.raymond@ligo.org>
12# Salvatore Vitale <salvatore.vitale@ligo.org>
13#
14# This program is free software; you can redistribute it and/or modify
15# it under the terms of the GNU General Public License as published by
16# the Free Software Foundation; either version 2 of the License, or
17# (at your option) any later version.
18#
19# This program is distributed in the hope that it will be useful,
20# but WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22# GNU General Public License for more details.
23#
24# You should have received a copy of the GNU General Public License
25# along with this program; if not, write to the Free Software
26# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27# MA 02110-1301, USA.
28
29#===============================================================================
30# Preamble
31#===============================================================================
32
33#standard library imports
34import sys
35import os
36import pickle
37from time import strftime
38
39#related third party imports
40from numpy import (exp, cos, sin, size, cov, unique, hsplit, log, squeeze, sort)
41
42import matplotlib
43matplotlib.use("Agg")
44from matplotlib import pyplot as plt
45
46#local application/library specific imports
47from lalinference import bayespputils as bppu
48
49from lalinference import git_version
50from igwn_ligolw import table
51from igwn_ligolw import ligolw
52from igwn_ligolw import lsctables
53
54try:
55 os.environ['PATH'] = os.environ['PATH'] + ':/usr/texbin'
56except:
57 os.environ['PATH'] =':/usr/texbin'
58print(os.environ['PATH'])
59__author__="Ben Aylott <benjamin.aylott@ligo.org>, Ben Farr <bfarr@u.northwestern.edu>, Will M. Farr <will.farr@ligo.org>, John Veitch <john.veitch@ligo.org>"
60__version__= "git id %s"%git_version.id
61__date__= git_version.date
62
63def email_notify(address,path):
64 import smtplib
65 import subprocess
66 address=address.split(',')
67 SERVER="localhost"
68 USER=os.environ['USER']
69 HOST=subprocess.check_output(["hostname","-f"]).strip()
70 FROM=USER+'@'+HOST
71 SUBJECT="LALInference result is ready at "+HOST+"!"
72 # Guess the web space path for the clusters
73 fslocation=os.path.abspath(path)
74 webpath='posplots.html'
75 if 'public_html' in fslocation:
76 k='public_html'
77 elif 'WWW' in fslocation:
78 k='WWW'
79 else:
80 k=None
81 if k is not None:
82 (a,b)=(fslocation,'')
83 while a!=k:
84 (a,b)=fslocation.split(a)
85 webpath=os.path.join(b,webpath)
86 else: webpath=os.path.join(fslocation,'posplots.html')
87
88 if 'atlas.aei.uni-hannover.de' in HOST:
89 url="https://atlas1.atlas.aei.uni-hannover.de/"
90 elif 'ligo.caltech.edu' in HOST:
91 url="https://ldas-jobs.ligo.caltech.edu/"
92 elif 'ligo-wa.caltech.edu' in HOST:
93 url="https://ldas-jobs.ligo-wa.caltech.edu/"
94 elif 'ligo-la.caltech.edu' in HOST:
95 url="https://ldas-jobs.ligo-la.caltech.edu/"
96 elif 'phys.uwm.edu' in HOST:
97 url="https://ldas-jobs.phys.uwm.edu/"
98 elif 'phy.syr.edu' in HOST:
99 url="https://sugar-jobs.phy.syr.edu/"
100 else:
101 url=HOST+':'
102 url=url+webpath
103
104 TEXT="Hi "+USER+",\nYou have a new parameter estimation result on "+HOST+".\nYou can view the result at "+url
105 message="From: %s\nTo: %s\nSubject: %s\n\n%s"%(FROM,', '.join(address),SUBJECT,TEXT)
106 server=smtplib.SMTP(SERVER)
107 server.sendmail(FROM,address,message)
108 server.quit()
109
110
111class LIGOLWContentHandlerExtractSimInspiralTable(ligolw.LIGOLWContentHandler):
112 def __init__(self,document):
113 ligolw.LIGOLWContentHandler.__init__(self,document)
114 self.tabname=lsctables.SimInspiralTable.tableName
115 self.intable=False
117 def startElement(self,name,attrs):
118 if attrs.has_key('Name') and table.Table.TableName(attrs['Name'])==self.tabname:
119 self.tableElementName=name
120 # Got the right table, let's see if it's the right event
121 ligolw.LIGOLWContentHandler.startElement(self,name,attrs)
122 self.intable=True
123 elif self.intable: # We are in the correct table
124 ligolw.LIGOLWContentHandler.startElement(self,name,attrs)
125 def endElement(self,name):
126 if self.intable: ligolw.LIGOLWContentHandler.endElement(self,name)
127 if self.intable and name==self.tableElementName: self.intable=False
128
129class LIGOLWContentHandlerExtractSimBurstTable(ligolw.LIGOLWContentHandler):
130 def __init__(self,document):
131 ligolw.LIGOLWContentHandler.__init__(self,document)
132 self.tabname=lsctables.SimBurstTable.tableName
133 self.intable=False
135 def startElement(self,name,attrs):
136 if attrs.has_key('Name') and table.Table.TableName(attrs['Name'])==self.tabname:
137 self.tableElementName=name
138 # Got the right table, let's see if it's the right event
139 ligolw.LIGOLWContentHandler.startElement(self,name,attrs)
140 self.intable=True
141 elif self.intable: # We are in the correct table
142 ligolw.LIGOLWContentHandler.startElement(self,name,attrs)
143 def endElement(self,name):
144 if self.intable: ligolw.LIGOLWContentHandler.endElement(self,name)
145 if self.intable and name==self.tableElementName: self.intable=False
146
147def pickle_to_file(obj,fname):
148 """
149 Pickle/serialize 'obj' into 'fname'.
150 """
151 filed=open(fname,'w')
152 pickle.dump(obj,filed)
153 filed.close()
154
155def oneD_dict_to_file(dict,fname):
156 filed=open(fname,'w')
157 for key,value in dict.items():
158 filed.write("%s %s\n"%(str(key),str(value)) )
159
160def multipleFileCB(opt, opt_str, value, parser):
161 args=[]
162
163 def floatable(str):
164 try:
165 float(str)
166 return True
167 except ValueError:
168 return False
169
170 for arg in parser.rargs:
171 # stop on --foo like options
172 if arg[:2] == "--" and len(arg) > 2:
173 break
174 # stop on -a, but not on -3 or -3.0
175 if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
176 break
177 args.append(arg)
178
179 del parser.rargs[:len(args)]
180 #Append new files to list if some already specified
181 if getattr(parser.values, opt.dest):
182 oldargs = getattr(parser.values, opt.dest)
183 oldargs.extend(args)
184 args = oldargs
185 setattr(parser.values, opt.dest, args)
186def dict2html(d,parent=None):
187 if not d: return ""
188 out=bppu.htmlChunk('div',parent=parent)
189 tab=out.tab()
190 row=out.insert_row(tab)
191 for key in d.keys():
192 out.insert_td(row,str(key))
193 row2=out.insert_row(tab)
194 for val in d.values():
195 out.insert_td(row2,str(val))
196 return out
197
198def extract_hdf5_metadata(h5grp,parent=None):
199 import h5py
200 #out=bppu.htmlChunk('div',parent=parent)
201 sec=bppu.htmlSection(h5grp.name,htmlElement=parent)
202 dict2html(h5grp.attrs,parent=sec)
203 for group in h5grp:
204 if(isinstance(h5grp[group],h5py.Group)):
205 extract_hdf5_metadata(h5grp[group],sec)
206 return h5grp
207
209 outdir,data,oneDMenu,twoDGreedyMenu,GreedyRes,
210 confidence_levels,twoDplots,
211 #misc. optional
212 injfile=None,eventnum=None,
213 trigfile=None,trignum=None,
214 skyres=None,
215 #direct integration evidence
216 dievidence=False,boxing=64,difactor=1.0,
217 #elliptical evidence
218 ellevidence=False,
219 #manual input of bayes factors optional.
220 bayesfactornoise=None,bayesfactorcoherent=None,
221 #manual input for SNR in the IFOs, optional.
222 snrfactor=None,
223 #nested sampling options
224 ns_flag=False,ns_Nlive=None,
225 #spinspiral/mcmc options
226 ss_flag=False,ss_spin_flag=False,
227 #lalinferenceMCMC options
228 li_flag=False,deltaLogL=None,fixedBurnins=None,nDownsample=None,oldMassConvention=False,
229 #followupMCMC options
230 fm_flag=False,
231 # on ACF?
232 noacf=False,
233 #Turn on 2D kdes
234 twodkdeplots=False,
235 #Turn on R convergence tests
236 RconvergenceTests=False,
237 # Save PDF figures?
238 savepdfs=True,
239 #List of covariance matrix csv files used as analytic likelihood
240 covarianceMatrices=None,
241 #List of meanVector csv files used, one csv file for each covariance matrix
242 meanVectors=None,
243 #header file
244 header=None,
245 psd_files=None,
246 #only save stats about PDF and exit #
247 statsonly=False
248 ):
249 """
250 This is a demonstration script for using the functionality/data structures
251 contained in lalinference.bayespputils . It will produce a webpage from a file containing
252 posterior samples generated by the parameter estimation codes with 1D/2D plots
253 and stats from the marginal posteriors for each parameter/set of parameters.
254 """
255 got_inspiral_table=0
256 got_burst_table=0
257 votfile=None
258 if eventnum is not None and injfile is None:
259 print("You specified an event number but no injection file. Ignoring!")
260
261 if trignum is not None and trigfile is None:
262 print("You specified a trigger number but no trigger file. Ignoring!")
263
264 if trignum is None and trigfile is not None:
265 print("You specified a trigger file but no trigger number. Taking first entry (the case for GraceDB events).")
266 trignum=0
267
268 if data is None:
269 raise RuntimeError('You must specify an input data file')
270 #
271 if outdir is None:
272 raise RuntimeError("You must specify an output directory.")
273
274 if not os.path.isdir(outdir):
275 os.makedirs(outdir)
276 #
277 if fm_flag:
278 peparser=bppu.PEOutputParser('fm')
279 commonResultsObj=peparser.parse(data)
280
281 elif ns_flag and not ss_flag:
282 peparser=bppu.PEOutputParser('ns')
283 commonResultsObj=peparser.parse(data,Nlive=ns_Nlive)
284
285 elif ss_flag and not ns_flag:
286 peparser=bppu.PEOutputParser('mcmc_burnin')
287 commonResultsObj=peparser.parse(data,spin=ss_spin_flag,deltaLogL=deltaLogL)
288
289 elif li_flag:
290 peparser=bppu.PEOutputParser('inf_mcmc')
291 commonResultsObj=peparser.parse(data,outdir=outdir,deltaLogL=deltaLogL,fixedBurnins=fixedBurnins,nDownsample=nDownsample,oldMassConvention=oldMassConvention)
292
293 elif ss_flag and ns_flag:
294 raise RuntimeError("Undefined input format. Choose only one of:")
295
296 elif '.xml' in data[0]:
297 peparser=bppu.PEOutputParser('xml')
298 commonResultsObj=peparser.parse(data[0])
299 thefile=open(data[0],'r')
300 votfile=thefile.read()
301 elif '.hdf' in data[0] or '.h5' in data[0]:
302 peparser = bppu.PEOutputParser('hdf5')
303 commonResultsObj = peparser.parse(data[0])
304 else:
305 peparser=bppu.PEOutputParser('common')
306 commonResultsObj=peparser.parse(open(data[0],'r'),info=[header,None])
307
308 #Extract f_ref from CRO if present. This is needed to calculate orbital angular momentum
309 # when converting spin parameters. Ideally this info will be provided in the
310 # SimInspiralTable in the near future.
311 ps,samps = commonResultsObj
312 try:
313 f_refIdx = ps.index('f_ref')
314 injFref = unique(samps[:,f_refIdx])
315 if len(injFref) > 1:
316 print("ERROR: Expected f_ref to be constant for all samples. Can't tell which value was injected!")
317 print(injFref)
318 injFref = None
319 else:
320 injFref = injFref[0]
321 except ValueError:
322 injFref = None
323
324 #Select injections using tc +/- 0.1s if it exists or eventnum from the injection file
325 injection=None
326 if injfile and eventnum is not None:
327 print('Looking for event %i in %s\n'%(eventnum,injfile))
328 import itertools
329 from igwn_ligolw import ligolw
330 from igwn_ligolw import lsctables
331 from igwn_ligolw import utils
332 xmldoc = utils.load_filename(injfile,contenthandler=LIGOLWContentHandlerExtractSimBurstTable)
333 got_burst_table=1
334 try:
335 simtable=lsctables.SimBurstTable.get_table(xmldoc)
336 except ValueError:
337 simtable=lsctables.SimInspiralTable.get_table(xmldoc)
338 got_inspiral_table=1
339 got_burst_table=0
340
341 injection=simtable[eventnum]
342 #injections = SimInspiralUtils.ReadSimInspiralFromFiles([injfile])
343 #if(len(injections)!=1): raise RuntimeError('Error: something unexpected happened while loading the injection file!\n')
344 #injection=injections[0]
345
346 #Get trigger
347 triggers = None
348 if trigfile is not None and trignum is not None:
349 triggers = bppu.readCoincXML(trigfile, trignum)
350
351 ## Load Bayes factors ##
352 # Add Bayes factor information to summary file #
353 if bayesfactornoise is not None:
354 bfile=open(bayesfactornoise,'r')
355 BSN=bfile.read()
356 bfile.close()
357 if(len(BSN.split())!=1):
358 BSN=BSN.split()[0]
359 print('BSN: %s'%BSN)
360 if bayesfactorcoherent is not None:
361 bfile=open(bayesfactorcoherent,'r')
362 BCI=bfile.read()
363 bfile.close()
364 print('BCI: %s'%BCI)
365
366 if snrfactor is not None:
367 if not os.path.isfile(snrfactor):
368 print("No snr file provided or wrong path to snr file\n")
369 snrfactor=None
370 else:
371 snrstring=""
372 snrfile=open(snrfactor,'r')
373 snrs=snrfile.readlines()
374 snrfile.close()
375 for snr in snrs:
376 if snr=="\n":
377 continue
378 snrstring=snrstring +" "+str(snr[0:-1])+" ,"
379 snrstring=snrstring[0:-1]
380
381 #Create an instance of the posterior class using the posterior values loaded
382 #from the file and any injection information (if given).
383 if got_inspiral_table==1:
384 pos = bppu.Posterior(commonResultsObj,SimInspiralTableEntry=injection,injFref=injFref,SnglInspiralList=triggers)
385 else:
386 pos = bppu.BurstPosterior(commonResultsObj,SimBurstTableEntry=injection,injFref=injFref,SnglBurstList=triggers)
387 #Create analytic likelihood functions if covariance matrices and mean vectors were given
388 analyticLikelihood = None
389 if covarianceMatrices and meanVectors:
390 analyticLikelihood = bppu.AnalyticLikelihood(covarianceMatrices, meanVectors)
391
392 #Plot only analytic parameters
393 oneDMenu = analyticLikelihood.names
394 twoDGreedyMenu = []
395 for i in range(len(oneDMenu)):
396 for j in range(i+1,len(oneDMenu)):
397 twoDGreedyMenu.append([oneDMenu[i],oneDMenu[j]])
398 twoDplots = twoDGreedyMenu
399
400 if eventnum is None and injfile is not None:
401 import itertools
402 from igwn_ligolw import lsctables
403 from igwn_ligolw import utils
404 if got_inspiral_table==1:
405 injections = lsctables.SimInspiralTable.get_table(
406 utils.load_filename(injfile)
407 )
408
409 if(len(injections)<1):
410 try:
411 print('Warning: Cannot find injection with end time %f' %(pos['time'].mean))
412 except KeyError:
413 print("Warning: No 'time' column!")
414
415 else:
416 try:
417 injection = itertools.ifilter(lambda a: abs(float(a.get_end()) - pos['time'].mean) < 0.1, injections).next()
418 pos.set_injection(injection)
419 except KeyError:
420 print("Warning: No 'time' column!")
421 """
422 # Compute time delays from sky position
423 if ('ra' in pos.names or 'rightascension' in pos.names) \
424 and ('declination' in pos.names or 'dec' in pos.names) \
425 and 'time' in pos.names:
426 from lal import LIGOTimeGPS, TimeDelayFromEarthCenter
427 import itertools
428 detMap = {'H1': 'LHO_4k', 'H2': 'LHO_2k', 'L1': 'LLO_4k',
429 'G1': 'GEO_600', 'V1': 'VIRGO', 'T1': 'TAMA_300'}
430 if 'ra' in pos.names:
431 ra_name='ra'
432 else: ra_name='rightascension'
433 if 'dec' in pos.names:
434 dec_name='dec'
435 else: dec_name='declination'
436 ifo_times={}
437 my_ifos=['H1','L1','V1']
438 for ifo in my_ifos:
439 inj_time=None
440 if injection:
441 inj_time=float(injection.get_end(ifo[0]))
442 location=lal.cached_detectors_by_prefix[ifo].location
443 ifo_times[ifo]=array(map(lambda ra,dec,time: array([time[0]+TimeDelayFromEarthCenter(location,ra[0],dec[0],LIGOTimeGPS(float(time[0])))]), pos[ra_name].samples,pos[dec_name].samples,pos['time'].samples))
444 loc_end_time=bppu.PosteriorOneDPDF(ifo.lower()+'_end_time',ifo_times[ifo],injected_value=inj_time)
445 pos.append(loc_end_time)
446 for ifo1 in my_ifos:
447 for ifo2 in my_ifos:
448 if ifo1==ifo2: continue
449 delay_time=ifo_times[ifo2]-ifo_times[ifo1]
450 if injection:
451 inj_delay=float(injection.get_end(ifo2[0])-injection.get_end(ifo1[0]))
452 else:
453 inj_delay=None
454 time_delay=bppu.PosteriorOneDPDF(ifo1.lower()+ifo2.lower()+'_delay',delay_time,inj_delay)
455 pos.append(time_delay)
456
457 """
458 #Perform necessary mappings
459 functions = {'cos':cos,'sin':sin,'exp':exp,'log':log}
460 for pos_name in oneDMenu:
461 if pos_name not in pos.names:
462 for func in functions.keys():
463 old_pos_name = pos_name.replace(func,'')
464 if pos_name.find(func)==0 and old_pos_name in pos.names:
465 print("Taking %s of %s ..."% (func,old_pos_name))
466 pos.append_mapping(pos_name,functions[func],old_pos_name)
467
468 #Remove samples with NaNs in requested params
469 requested_params = set(pos.names).intersection(set(oneDMenu))
470 pos.delete_NaN_entries(requested_params)
471
472 #Remove non-analytic parameters if analytic likelihood is given:
473 if analyticLikelihood:
474 dievidence_names = ['post','posterior','logl','prior','likelihood','cycle','chain']
475 [pos.pop(param) for param in pos.names if param not in analyticLikelihood.names and param not in dievidence_names]
476
477 ##Print some summary stats for the user...##
478 #Number of samples
479 print("Number of posterior samples: %i"%len(pos))
480 # Means
481 print('Means:')
482 print(str(pos.means))
483 #Median
484 print('Median:')
485 print(str(pos.medians))
486 #maxL
487 print('maxL:')
488 max_pos,max_pos_co=pos.maxL
489 print(max_pos_co)
490
491 #==================================================================#
492 #Create web page
493 #==================================================================#
494
495 html=bppu.htmlPage('Posterior PDFs',css=bppu.__default_css_string,javascript=bppu.__default_javascript_string)
496
497 #Create a section for meta-data/run information
498 html_meta=html.add_section('Summary')
499 table=html_meta.tab()
500
501 row=html_meta.insert_row(table,label='thisrow')
502 td=html_meta.insert_td(row,'',label='Samples')
503 SampsStats=html.add_section_to_element('Samples',td)
504 SampsStats.p('Produced from '+str(len(pos))+' posterior samples.')
505 if 'chain' in pos.names:
506 acceptedChains = unique(pos['chain'].samples)
507 acceptedChainText = '%i of %i chains accepted: %i'%(len(acceptedChains),len(data),acceptedChains[0])
508 if len(acceptedChains) > 1:
509 for chain in acceptedChains[1:]:
510 acceptedChainText += ', %i'%(chain)
511 SampsStats.p(acceptedChainText)
512 if 'cycle' in pos.names:
513 SampsStats.p('Longest chain has '+str(pos.longest_chain_cycles())+' cycles.')
514 filenames='Samples read from %s'%(data[0])
515 if len(data) > 1:
516 for fname in data[1:]:
517 filenames+=', '+str(fname)
518 SampsStats.p(filenames)
519 td=html_meta.insert_td(row,'',label='SummaryLinks')
520 legend=html.add_section_to_element('Sections',td)
521
522 # Create a section for HDF5 metadata if available
523 if '.h5' in data[0] or '.hdf' in data[0]:
524 html_hdf=html.add_section('Metadata',legend=legend)
525 import h5py
526 with h5py.File(data[0],'r') as h5grp:
527 extract_hdf5_metadata(h5grp,parent=html_hdf)
528
529 #Create a section for model selection results (if they exist)
530
531 if bayesfactornoise is not None:
532 html_model=html.add_section('Model selection',legend=legend)
533 html_model.p('log Bayes factor ( coherent vs gaussian noise) = %s, Bayes factor=%f'%(BSN,exp(float(BSN))))
534 if bayesfactorcoherent is not None:
535 html_model.p('log Bayes factor ( coherent vs incoherent OR noise ) = %s, Bayes factor=%f'%(BCI,exp(float(BCI))))
536
537 if dievidence:
538 html_model=html.add_section('Direct Integration Evidence',legend=legend)
539 log_ev = log(difactor) + pos.di_evidence(boxing=boxing)
540 ev=exp(log_ev)
541 evfilename=os.path.join(outdir,"evidence.dat")
542 evout=open(evfilename,"w")
543 evout.write(str(ev))
544 evout.write(" ")
545 evout.write(str(log_ev))
546 evout.close()
547 print("Computing direct integration evidence = %g (log(Evidence) = %g)"%(ev, log_ev))
548 html_model.p('Direct integration evidence is %g, or log(Evidence) = %g. (Boxing parameter = %d.)'%(ev,log_ev,boxing))
549 if 'logl' in pos.names:
550 log_ev=pos.harmonic_mean_evidence()
551 html_model.p('Compare to harmonic mean evidence of %g (log(Evidence) = %g).'%(exp(log_ev),log_ev))
552
553 if ellevidence:
554 try:
555 html_model=html.add_section('Elliptical Evidence',legend=legend)
556 log_ev = pos.elliptical_subregion_evidence()
557 ev = exp(log_ev)
558 evfilename=os.path.join(outdir, 'ellevidence.dat')
559 evout=open(evfilename, 'w')
560 evout.write(str(ev) + ' ' + str(log_ev))
561 evout.close()
562 print('Computing elliptical region evidence = %g (log(ev) = %g)'%(ev, log_ev))
563 html_model.p('Elliptical region evidence is %g, or log(Evidence) = %g.'%(ev, log_ev))
564
565 if 'logl' in pos.names:
566 log_ev=pos.harmonic_mean_evidence()
567 html_model.p('Compare to harmonic mean evidence of %g (log(Evidence = %g))'%(exp(log_ev), log_ev))
568 except IndexError:
569 print('Warning: Sample size too small to compute elliptical evidence!')
570
571 #Create a section for SNR, if a file is provided
572 if snrfactor is not None:
573 html_snr=html.add_section('Signal to noise ratio(s)',legend=legend)
574 html_snr.p('%s'%snrstring)
575
576 #Create a section for summary statistics
577 tabid='statstable'
578 html_stats=html.add_collapse_section('Summary statistics',legend=legend,innertable_id=tabid)
579 html_stats.write(str(pos))
580 statfilename=os.path.join(outdir,"summary_statistics.dat")
581 statout=open(statfilename,"w")
582 statout.write("\tmaxP\tmaxL\tstdev\tmean\tmedian\tstacc\tinjection\tvalue\n")
583
584 for statname,statoned_pos in pos:
585
586 statmax_pos,max_i=pos._posMaxL()
587 statmaxL=statoned_pos.samples[max_i][0]
588 statmax_pos,max_j=pos._posMap()
589 statmaxP=statoned_pos.samples[max_j][0]
590 statmean=str(statoned_pos.mean)
591 statstdev=str(statoned_pos.stdev)
592 statmedian=str(squeeze(statoned_pos.median))
593 statstacc=str(statoned_pos.stacc)
594 statinjval=str(statoned_pos.injval)
595
596 statarray=[str(i) for i in [statname,statmaxP,statmaxL,statstdev,statmean,statmedian,statstacc,statinjval]]
597 statout.write("\t".join(statarray))
598 statout.write("\n")
599
600 statout.close()
601
602 #==================================================================#
603 #Generate sky map, WF, and PSDs
604 #==================================================================#
605
606 skyreses=None
607 sky_injection_cl=None
608 inj_position=None
609 tabid='skywftable'
610 html_wf=html.add_collapse_section('Sky Localization and Waveform',innertable_id=tabid)
611
612 table=html_wf.tab(idtable=tabid)
613 row=html_wf.insert_row(table,label='SkyandWF')
614 skytd=html_wf.insert_td(row,'',label='SkyMap',legend=legend)
615 html_sky=html.add_section_to_element('SkyMap',skytd)
616 #If sky resolution parameter has been specified try and create sky map...
617 if skyres is not None and \
618 ('ra' in pos.names and 'dec' in pos.names):
619
620 if pos['dec'].injval is not None and pos['ra'].injval is not None:
621 inj_position=[pos['ra'].injval,pos['dec'].injval]
622 else:
623 inj_position=None
624
625 hpmap = pos.healpix_map(float(skyres), nest=True)
626 bppu.plot_sky_map(hpmap, outdir, inj=inj_position, nest=True)
627
628 if inj_position is not None:
629 html_sky.p('Injection found at p = %g'%bppu.skymap_inj_pvalue(hpmap, inj_position, nest=True))
630
631 html_sky.write('<a href="skymap.png" target="_blank"><img src="skymap.png"/></a>')
632
633 html_sky_write='<table border="1" id="statstable"><tr><th>Confidence region</th><th>size (sq. deg)</th></tr>'
634
635 areas = bppu.skymap_confidence_areas(hpmap, confidence_levels)
636 for cl, area in zip(confidence_levels, areas):
637 html_sky_write+='<tr><td>%g</td><td>%g</td></tr>'%(cl, area)
638 html_sky_write+=('</table>')
639
640 html_sky.write(html_sky_write)
641 else:
642 html_sky.write('<b>No skymap generated!</b>')
643
644 wfdir=os.path.join(outdir,'Waveform')
645 if not os.path.isdir(wfdir):
646 os.makedirs(wfdir)
647 try:
648 wfpointer= bppu.plot_burst_waveform(pos=pos,simburst=injfile,event=eventnum,path=wfdir)
649 except:
650 wfpointer = None
651 wftd=html_wf.insert_td(row,'',label='Waveform',legend=legend)
652 wfsection=html.add_section_to_element('Waveforms',wftd)
653 if wfpointer is not None:
654 wfsection.write('<a href="Waveform/WF_DetFrame.png" target="_blank"><img src="Waveform/WF_DetFrame.png"/></a>')
655 else:
656 wfsection.write("<b>No Waveform generated!</b>")
657
658 wftd=html_wf.insert_td(row,'',label='PSDs',legend=legend)
659 wfsection=html.add_section_to_element('PSDs',wftd)
660 psd_pointer=None
661 if psd_files is not None:
662 psd_files=list(psd_files.split(','))
663 psddir=os.path.join(outdir,'PSDs')
664 if not os.path.isdir(psddir):
665 os.makedirs(psddir)
666 try:
667 psd_pointer=bppu.plot_psd(psd_files,outpath=psddir)
668 except:
669 psd_pointer=None
670 if psd_pointer:
671 wfsection.write('<a href="PSDs/PSD.png" target="_blank"><img src="PSDs/PSD.png"/></a>')
672 else:
673 wfsection.write("<b>No PSD file found!</b>")
674 if statsonly:
675 return 0
676 #==================================================================#
677 #1D posteriors
678 #==================================================================#
679
680 #Loop over each parameter and determine the contigious and greedy
681 #confidence levels and some statistics.
682
683 #Add section for 1D marginal PDFs and sample plots
684 tabid='onedmargtable'
685 html_ompdf=html.add_collapse_section('1D marginal posterior PDFs',legend=legend,innertable_id=tabid)
686 #Table matter
687 if not noacf:
688 html_ompdf_write= '<table id="%s"><tr><th>Histogram and Kernel Density Estimate</th><th>Samples used</th><th>Autocorrelation</th></tr>'%tabid
689 else:
690 html_ompdf_write= '<table id="%s"><tr><th>Histogram and Kernel Density Estimate</th><th>Samples used</th></tr>'%tabid
691 #Add section for 1D confidence intervals
692 tabid='onedconftable'
693 html_ogci=html.add_collapse_section('1D confidence intervals (greedy binning)',legend=legend,innertable_id=tabid)
694 html_ogci_write='<table id="%s" border="1"><tr><th/>'%tabid
695 confidence_levels.sort()
696 for cl in confidence_levels:
697 html_ogci_write+='<th>%f</th>'%cl
698 if injection:
699 html_ogci_write+='<th>Injection Confidence Level</th>'
700 html_ogci_write+='<th>Injection Confidence Interval</th>'
701 html_ogci_write+='</tr>'
702
703 onepdfdir=os.path.join(outdir,'1Dpdf')
704 if not os.path.isdir(onepdfdir):
705 os.makedirs(onepdfdir)
706
707 sampsdir=os.path.join(outdir,'1Dsamps')
708 if not os.path.isdir(sampsdir):
709 os.makedirs(sampsdir)
710 Nskip=0
711 if 'chain' in pos.names:
712 data,header=pos.samples()
713 par_index=pos.names.index('cycle')
714 chain_index=pos.names.index("chain")
715 chains=unique(pos["chain"].samples)
716 chainCycles = [sort(data[ data[:,chain_index] == chain, par_index ]) for chain in chains]
717 chainNcycles = [cycles[-1]-cycles[0] for cycles in chainCycles]
718 chainNskips = [cycles[1] - cycles[0] for cycles in chainCycles]
719 elif 'cycle' in pos.names:
720 cycles = sort(pos['cycle'].samples)
721 Ncycles = cycles[-1]-cycles[0]
722 Nskip = cycles[1]-cycles[0]
723
724 for par_name in oneDMenu:
725 par_name=par_name.lower()
726 try:
727 pos[par_name.lower()]
728 except KeyError:
729 #print "No input chain for %s, skipping binning."%par_name
730 continue
731 try:
732 par_bin=GreedyRes[par_name]
733 except KeyError:
734 print("Bin size is not set for %s, skipping binning."%par_name)
735 continue
736
737 #print "Binning %s to determine confidence levels ..."%par_name
738 binParams={par_name:par_bin}
739
740 toppoints,injectionconfidence,reses,injection_area,cl_intervals=bppu.greedy_bin_one_param(pos,binParams,confidence_levels)
741
742 #oneDContCL,oneDContInj = bppu.contigious_interval_one_param(pos,binParams,confidence_levels)
743
744 #Generate new BCI html table row
745 BCItableline='<tr><td>%s</td>'%(par_name)
746 cls=list(reses.keys())
747 cls.sort()
748
749 for cl in cls:
750 BCItableline+='<td>%f</td>'%reses[cl]
751
752 if injection is not None:
753 if injectionconfidence is not None and injection_area is not None:
754
755 BCItableline+='<td>%f</td>'%injectionconfidence
756 BCItableline+='<td>%f</td>'%injection_area
757
758 else:
759 BCItableline+='<td/>'
760 BCItableline+='<td/>'
761
762 BCItableline+='</tr>'
763
764 #Append new table line to section html
765 html_ogci_write+=BCItableline
766
767 #Generate 1D histogram/kde plots
768 print("Generating 1D plot for %s."%par_name)
769
770 #Get analytic description if given
771 pdf=cdf=None
772 if analyticLikelihood:
773 pdf = analyticLikelihood.pdf(par_name)
774 cdf = analyticLikelihood.cdf(par_name)
775
776 oneDPDFParams={par_name:50}
777 rbins,plotFig=bppu.plot_one_param_pdf(pos,oneDPDFParams,pdf,cdf,plotkde=False)
778
779 figname=par_name+'.png'
780 oneDplotPath=os.path.join(onepdfdir,figname)
781 plotFig.savefig(oneDplotPath)
782 if(savepdfs): plotFig.savefig(os.path.join(onepdfdir,par_name+'.pdf'))
783 plt.close(plotFig)
784
785 if rbins:
786 print("r of injected value of %s (bins) = %f"%(par_name, rbins))
787
788 ##Produce plot of raw samples
789 myfig=plt.figure(figsize=(4,3.5),dpi=200)
790 pos_samps=pos[par_name].samples
791 if not ("chain" in pos.names):
792 # If there is not a parameter named "chain" in the
793 # posterior, then just produce a plot of the samples.
794 plt.plot(pos_samps,'k.',linewidth=0.0, markeredgewidth=0,figure=myfig)
795 maxLen=len(pos_samps)
796 else:
797 # If there is a parameter named "chain", then produce a
798 # plot of the various chains in different colors, with
799 # smaller dots.
800 data,header=pos.samples()
801 par_index=pos.names.index(par_name)
802 chain_index=pos.names.index("chain")
803 chains=unique(pos["chain"].samples)
804 chainData=[data[ data[:,chain_index] == chain, par_index ] for chain in chains]
805 chainDataRanges=[range(len(cd)) for cd in chainData]
806 maxLen=max([len(cd) for cd in chainData])
807 for rng, data in zip(chainDataRanges, chainData):
808 plt.plot(rng, data, marker=',',linewidth=0.0, markeredgewidth=0,figure=myfig)
809 plt.title("Gelman-Rubin R = %g"%(pos.gelman_rubin(par_name)))
810
811 #dataPairs=[ [rng, data] for (rng,data) in zip(chainDataRanges, chainData)]
812 #flattenedData=[ item for pair in dataPairs for item in pair ]
813 #maxLen=max([len(data) for data in flattenedData])
814 #plt.plot(array(flattenedData),marker=',',linewidth=0.0,figure=myfig)
815
816
817 injpar=pos[par_name].injval
818
819 if injpar:
820 if min(pos_samps)<injpar and max(pos_samps)>injpar:
821 plt.axhline(injpar, color='r', linestyle='-.')
822 myfig.savefig(os.path.join(sampsdir,figname.replace('.png','_samps.png')))
823 if(savepdfs): myfig.savefig(os.path.join(sampsdir,figname.replace('.png','_samps.pdf')))
824 plt.close(myfig)
825 acfail=0
826 if not (noacf):
827 acffig=plt.figure(figsize=(4,3.5),dpi=200)
828 if not ("chain" in pos.names):
829 data=pos_samps[:,0]
830 try:
831 (Neff, acl, acf) = bppu.effectiveSampleSize(data, Nskip)
832 lines=plt.plot(acf, 'k,', marker=',',linewidth=0.0, markeredgewidth=0, figure=acffig)
833 # Give ACL info if not already downsampled according to it
834 if nDownsample is None:
835 plt.title('Autocorrelation Function')
836 elif 'cycle' in pos.names:
837 last_color = lines[-1].get_color()
838 plt.axvline(acl/Nskip, linestyle='-.', color=last_color)
839 plt.title('ACL = %i N = %i'%(acl,Neff))
840 except FloatingPointError:
841 # Ignore
842 acfail=1
843 pass
844 else:
845 try:
846 acls = []
847 Nsamps = 0.0;
848 for rng, data, Nskip, Ncycles in zip(chainDataRanges, chainData, chainNskips, chainNcycles):
849 (Neff, acl, acf) = bppu.effectiveSampleSize(data, Nskip)
850 acls.append(acl)
851 Nsamps += Neff
852 lines=plt.plot(acf,'k,', marker=',',linewidth=0.0, markeredgewidth=0, figure=acffig)
853 # Give ACL info if not already downsampled according to it
854 if nDownsample is not None:
855 last_color = lines[-1].get_color()
856 plt.axvline(acl/Nskip, linestyle='-.', color=last_color)
857 if nDownsample is None:
858 plt.title('Autocorrelation Function')
859 else:
860 plt.title('ACL = %i N = %i'%(max(acls),Nsamps))
861 except FloatingPointError:
862 # Ignore
863 acfail=1
864 pass
865
866 acffig.savefig(os.path.join(sampsdir,figname.replace('.png','_acf.png')))
867 if(savepdfs): acffig.savefig(os.path.join(sampsdir,figname.replace('.png','_acf.pdf')))
868 plt.close(acffig)
869
870 if not noacf:
871 if not acfail:
872 acfhtml='<td width="30%"><img width="100%" src="1Dsamps/'+figname.replace('.png', '_acf.png')+'"/></td>'
873 else:
874 acfhtml='<td>ACF generation failed!</td>'
875 html_ompdf_write+='<tr><td width="30%"><img width="100%" src="1Dpdf/'+figname+'"/></td><td width="30%"><img width="100%" src="1Dsamps/'+figname.replace('.png','_samps.png')+'"/></td>'+acfhtml+'</tr>'
876 else:
877 html_ompdf_write+='<tr><td width="30%"><img width="100%" src="1Dpdf/'+figname+'"/></td><td width="30%"><img width="100%" src="1Dsamps/'+figname.replace('.png','_samps.png')+'"/></td></tr>'
878
879
880 html_ompdf_write+='</table>'
881
882 html_ompdf.write(html_ompdf_write)
883
884 html_ogci_write+='</table>'
885 html_ogci.write(html_ogci_write)
886
887 #==================================================================#
888 #2D posteriors
889 #==================================================================#
890
891 #Loop over parameter pairs in twoDGreedyMenu and bin the sample pairs
892 #using a greedy algorithm . The ranked pixels (toppoints) are used
893 #to plot 2D histograms and evaluate Bayesian confidence intervals.
894
895 #Make a folder for the 2D kde plots
896 margdir=os.path.join(outdir,'2Dkde')
897 if not os.path.isdir(margdir):
898 os.makedirs(margdir)
899
900 twobinsdir=os.path.join(outdir,'2Dbins')
901 if not os.path.isdir(twobinsdir):
902 os.makedirs(twobinsdir)
903
904 greedytwobinsdir=os.path.join(outdir,'greedy2Dbins')
905 if not os.path.isdir(greedytwobinsdir):
906 os.makedirs(greedytwobinsdir)
907
908 #Add a section to the webpage for a table of the confidence interval
909 #results.
910 tabid='2dconftable'
911 html_tcig=html.add_collapse_section('2D confidence intervals (greedy binning)',legend=legend,innertable_id=tabid)
912 #Generate the top part of the table
913 html_tcig_write='<table id="%s" border="1"><tr><th/>'%tabid
914 confidence_levels.sort()
915 for cl in confidence_levels:
916 html_tcig_write+='<th>%f</th>'%cl
917 if injection:
918 html_tcig_write+='<th>Injection Confidence Level</th>'
919 html_tcig_write+='<th>Injection Confidence Interval</th>'
920 html_tcig_write+='</tr>'
921
922
923 #= Add a section for a table of 2D marginal PDFs (kde)
924 twodkdeplots_flag=twodkdeplots
925 if twodkdeplots_flag:
926 tabid='2dmargtable'
927 html_tcmp=html.add_collapse_section('2D Marginal PDFs',legend=legend,innertable_id=tabid)
928 #Table matter
929 html_tcmp_write='<table border="1" id="%s">'%tabid
930 tabid='2dgreedytable'
931 html_tgbh=html.add_collapse_section('2D Greedy Bin Histograms',legend=legend,innertable_id=tabid)
932 html_tgbh_write='<table border="1" id="%s">'%tabid
933
934 row_count=0
935 row_count_gb=0
936
937 for par1_name,par2_name in twoDGreedyMenu:
938 par1_name=par1_name.lower()
939 par2_name=par2_name.lower()
940 try:
941 pos[par1_name.lower()]
942 except KeyError:
943 #print "No input chain for %s, skipping binning."%par1_name
944 continue
945 try:
946 pos[par2_name.lower()]
947 except KeyError:
948 #print "No input chain for %s, skipping binning."%par2_name
949 continue
950 #Bin sizes
951 try:
952 par1_bin=GreedyRes[par1_name]
953 except KeyError:
954 print("Bin size is not set for %s, skipping %s/%s binning."%(par1_name,par1_name,par2_name))
955 continue
956 try:
957 par2_bin=GreedyRes[par2_name]
958 except KeyError:
959 print("Bin size is not set for %s, skipping %s/%s binning."%(par2_name,par1_name,par2_name))
960 continue
961
962 #print "Binning %s-%s to determine confidence levels ..."%(par1_name,par2_name)
963 #Form greedy binning input structure
964 greedy2Params={par1_name:par1_bin,par2_name:par2_bin}
965
966 #Greedy bin the posterior samples
967 try:
968 toppoints,injection_cl,reses,injection_area=\
969 bppu.greedy_bin_two_param(pos,greedy2Params,confidence_levels)
970 except:
971 # Failures may happen since some simburst set injval to nan
972 continue
973
974 print("BCI %s-%s:"%(par1_name,par2_name))
975 print(reses)
976
977 #Generate new BCI html table row
978 BCItableline='<tr><td>%s-%s</td>'%(par1_name,par2_name)
979 cls=list(reses.keys())
980 cls.sort()
981
982 for cl in cls:
983 BCItableline+='<td>%f</td>'%reses[cl]
984
985 if injection is not None:
986 if injection_cl is not None:
987 BCItableline+='<td>%f</td>'%injection_cl
988 BCItableline+='<td>'+str(injection_area)+'</td>'
989
990 else:
991 BCItableline+='<td/>'
992 BCItableline+='<td/>'
993
994 BCItableline+='</tr>'
995
996 #Append new table line to section html
997 html_tcig_write+=BCItableline
998
999
1000 #= Plot 2D histograms of greedily binned points =#
1001
1002 #greedy2ContourPlot=bppu.plot_two_param_greedy_bins_contour({'Result':pos},greedy2Params,[0.67,0.9,0.95],{'Result':'k'})
1003 try:
1004 greedy2ContourPlot=bppu.plot_two_param_kde_greedy_levels({'Result':pos},greedy2Params,[0.67,0.9,0.95],{'Result':'k'})
1005 greedy2contourpath=os.path.join(greedytwobinsdir,'%s-%s_greedy2contour.png'%(par1_name,par2_name))
1006 greedy2ContourPlot.savefig(greedy2contourpath)
1007 if(savepdfs): greedy2ContourPlot.savefig(greedy2contourpath.replace('.png','.pdf'))
1008 plt.close(greedy2ContourPlot)
1009
1010 greedy2HistFig=bppu.plot_two_param_greedy_bins_hist(pos,greedy2Params,confidence_levels)
1011 greedy2histpath=os.path.join(greedytwobinsdir,'%s-%s_greedy2.png'%(par1_name,par2_name))
1012 greedy2HistFig.savefig(greedy2histpath)
1013 if(savepdfs): greedy2HistFig.savefig(greedy2histpath.replace('.png','.pdf'))
1014 plt.close(greedy2HistFig)
1015 except:
1016 pass
1017 greedyFile = open(os.path.join(twobinsdir,'%s_%s_greedy_stats.txt'%(par1_name,par2_name)),'w')
1018
1019 #= Write out statistics for greedy bins
1020 for cl in cls:
1021 greedyFile.write("%lf %lf\n"%(cl,reses[cl]))
1022 greedyFile.close()
1023
1024 if [par1_name,par2_name] in twoDplots or [par2_name,par1_name] in twoDplots :
1025 print('Generating %s-%s greedy hist plot'%(par1_name,par2_name))
1026
1027 par1_pos=pos[par1_name].samples
1028 par2_pos=pos[par2_name].samples
1029
1030 if (size(unique(par1_pos))<2 or size(unique(par2_pos))<2):
1031 continue
1032 head,figname=os.path.split(greedy2histpath)
1033 head,figname_c=os.path.split(greedy2contourpath)
1034 if row_count_gb==0:
1035 html_tgbh_write+='<tr>'
1036 html_tgbh_write+='<td width="30%"><img width="100%" src="greedy2Dbins/'+figname+'"/>[<a href="greedy2Dbins/'+figname_c+'">contour</a>]</td>'
1037 row_count_gb+=1
1038 if row_count_gb==3:
1039 html_tgbh_write+='</tr>'
1040 row_count_gb=0
1041
1042 #= Generate 2D kde plots =#
1043
1044 if twodkdeplots_flag is True:
1045 if [par1_name,par2_name] in twoDplots or [par2_name,par1_name] in twoDplots :
1046 print('Generating %s-%s plot'%(par1_name,par2_name))
1047
1048 par1_pos=pos[par1_name].samples
1049 par2_pos=pos[par2_name].samples
1050
1051 if (size(unique(par1_pos))<2 or size(unique(par2_pos))<2):
1052 continue
1053
1054 plot2DkdeParams={par1_name:50,par2_name:50}
1055 myfig=bppu.plot_two_param_kde(pos,plot2DkdeParams)
1056
1057 figname=par1_name+'-'+par2_name+'_2Dkernel.png'
1058 twoDKdePath=os.path.join(margdir,figname)
1059
1060 if row_count==0:
1061 html_tcmp_write+='<tr>'
1062 html_tcmp_write+='<td width="30%"><img width="100%" src="2Dkde/'+figname+'"/></td>'
1063 row_count+=1
1064 if row_count==3:
1065 html_tcmp_write+='</tr>'
1066 row_count=0
1067
1068 myfig.savefig(twoDKdePath)
1069 if(savepdfs): myfig.savefig(twoDKdePath.replace('.png','.pdf'))
1070 plt.close(myfig)
1071
1072 #Finish off the BCI table and write it into the etree
1073 html_tcig_write+='</table>'
1074 html_tcig.write(html_tcig_write)
1075
1076 if twodkdeplots_flag is True:
1077 #Finish off the 2D kde plot table
1078 while row_count!=0:
1079 html_tcmp_write+='<td/>'
1080 row_count+=1
1081 if row_count==3:
1082 row_count=0
1083 html_tcmp_write+='</tr>'
1084 html_tcmp_write+='</table>'
1085 html_tcmp.write(html_tcmp_write)
1086 #Add a link to all plots
1087 html_tcmp.a("2Dkde/",'All 2D marginal PDFs (kde)')
1088
1089 #Finish off the 2D greedy histogram plot table
1090 while row_count_gb!=0:
1091 html_tgbh_write+='<td/>'
1092 row_count_gb+=1
1093 if row_count_gb==3:
1094 row_count_gb=0
1095 html_tgbh_write+='</tr>'
1096 html_tgbh_write+='</table>'
1097 html_tgbh.write(html_tgbh_write)
1098 #Add a link to all plots
1099 html_tgbh.a("greedy2Dbins/",'All 2D Greedy Bin Histograms')
1100
1101 if RconvergenceTests is True:
1102 convergenceResults=bppu.convergenceTests(pos,gelman=False)
1103
1104 if convergenceResults is not None:
1105 tabid='convtable'
1106 html_conv_test=html.add_collapse_section('Convergence tests',legend=legend,innertable_id=tabid)
1107 data_found=False
1108 for test,test_data in convergenceResults.items():
1109
1110 if test_data:
1111 data_found=True
1112 html_conv_test.h3(test)
1113
1114 html_conv_table_rows={}
1115 html_conv_table_header=''
1116 for chain,chain_data in test_data.items():
1117 html_conv_table_header+='<th>%s</th>'%chain
1118
1119
1120 for data in chain_data:
1121 if len(data)==2:
1122 try:
1123 html_conv_table_rows[data[0]]+='<td>'+data[1]+'</td>'
1124 except KeyError:
1125 html_conv_table_rows[data[0]]='<td>'+data[1]+'</td>'
1126
1127 html_conv_table='<table id="%s"><tr><th>Chain</th>'%tabid+html_conv_table_header+'</tr>'
1128 for row_name,row in html_conv_table_rows.items():
1129 html_conv_table+='<tr><td>%s</td>%s</tr>'%(row_name,row)
1130 html_conv_table+='</table>'
1131 html_conv_test.write(html_conv_table)
1132 if data_found is False:
1133 html_conv_test.p('No convergence diagnostics generated!')
1134 #Create a section for the covariance matrix
1135 tabid='covtable'
1136 html_stats_cov=html.add_collapse_section('Covariance matrix',legend=legend,innertable_id=tabid)
1137 pos_samples,table_header_string=pos.samples()
1138 #calculate cov matrix
1139 cov_matrix=cov(pos_samples,rowvar=0,bias=1)
1140
1141 #Create html table
1142 table_header_list=table_header_string.split()
1143
1144 cov_table_string='<table border="1" id="%s"><tr><th/>'%tabid
1145 for header in table_header_list:
1146 cov_table_string+='<th>%s</th>'%header
1147 cov_table_string+='</tr>'
1148
1149 cov_column_list=hsplit(cov_matrix,cov_matrix.shape[1])
1150
1151 for cov_column,cov_column_name in zip(cov_column_list,table_header_list):
1152 cov_table_string+='<tr><th>%s</th>'%cov_column_name
1153 for cov_column_element in cov_column:
1154 cov_table_string+='<td>%.3e</td>'%(cov_column_element[0])
1155 cov_table_string+='</tr>'
1156 cov_table_string+='</table>'
1157 html_stats_cov.write(cov_table_string)
1158
1159 html_footer=html.add_section('')
1160 html_footer.p('Produced using cbcBayesPostProc.py at '+strftime("%Y-%m-%d %H:%M:%S")+' .')
1161
1162 cc_args=''
1163 for arg in sys.argv:
1164 cc_args+=arg+' '
1165
1166 html_footer.p('Command line: %s'%cc_args)
1167 html_footer.p(git_version.verbose_msg)
1168
1169 #Save results page
1170 resultspage=open(os.path.join(outdir,'posplots.html'),'w')
1171 resultspage.write(str(html))
1172
1173 # Save posterior samples too...
1174 posfilename=os.path.join(outdir,'posterior_samples.dat')
1175 pos.write_to_file(posfilename)
1176
1177 #Close files
1178 resultspage.close()
1179
1180USAGE='''%prog [options] datafile.dat [datafile2.dat ...]
1181Generate a web page displaying results of parameter estimation based on the contents
1182of one or more datafiles containing samples from one of the bayesian algorithms (MCMC, nested sampling).
1183Options specify which extra statistics to compute and allow specification of additional information.
1184'''
1185
1186if __name__=='__main__':
1187
1188 from optparse import OptionParser
1189 parser=OptionParser(USAGE)
1190 parser.add_option("-o","--outpath", dest="outpath",help="make page and plots in DIR", metavar="DIR")
1191 parser.add_option("-d","--data",dest="data",action="callback",callback=multipleFileCB,help="datafile")
1192 #Optional (all)
1193 parser.add_option("-i","--inj",dest="injfile",help="SimBurst injection file",metavar="INJ.XML",default=None)
1194 parser.add_option("-t","--trig",dest="trigfile",help="Coinc XML file",metavar="COINC.XML",default=None)
1195 parser.add_option("--skyres",dest="skyres",help="Sky resolution to use to calculate sky box size",default=None)
1196 parser.add_option("--eventnum",dest="eventnum",action="store",default=None,help="event number in SimInspiral file of this signal",type="int",metavar="NUM")
1197 parser.add_option("--trignum",dest="trignum",action="store",default=None,help="trigger number in CoincTable",type="int",metavar="NUM")
1198 parser.add_option("--bsn",action="store",default=None,help="Optional file containing the bayes factor signal against noise",type="string")
1199 parser.add_option("--bci",action="store",default=None,help="Optional file containing the bayes factor coherent signal model against incoherent signal model.",type="string")
1200 parser.add_option("--snr",action="store",default=None,help="Optional file containing the SNRs of the signal in each IFO",type="string")
1201 parser.add_option("--dievidence",action="store_true",default=False,help="Calculate the direct integration evidence for the posterior samples")
1202 parser.add_option("--boxing",action="store",default=64,help="Boxing parameter for the direct integration evidence calculation",type="int",dest="boxing")
1203 parser.add_option("--evidenceFactor",action="store",default=1.0,help="Overall factor (normalization) to apply to evidence",type="float",dest="difactor",metavar="FACTOR")
1204
1205 parser.add_option('--ellipticEvidence', action='store_true', default=False,help='Estimate the evidence by fitting ellipse to highest-posterior points.', dest='ellevidence')
1206
1207 parser.add_option("--no2D",action="store_true",default=False,help="Skip 2-D plotting.")
1208 parser.add_option("--header",action="store",default=None,help="Optional file containing the header line for posterior samples",type="string")
1209 #NS
1210 parser.add_option("--ns",action="store_true",default=False,help="(inspnest) Parse input as if it was output from parallel nested sampling runs.")
1211 parser.add_option("--Nlive",action="store",default=None,help="(inspnest) Number of live points used in each parallel nested sampling run.",type="int")
1212 parser.add_option("--xflag",action="store_true",default=False,help="(inspnest) Convert x to iota.")
1213 #SS
1214 parser.add_option("--ss",action="store_true",default=False,help="(SPINspiral) Parse input as if it was output from SPINspiral.")
1215 parser.add_option("--spin",action="store_true",default=False,help="(SPINspiral) Specify spin run (15 parameters). ")
1216 #LALInf
1217 parser.add_option("--lalinfmcmc",action="store_true",default=False,help="(LALInferenceMCMC) Parse input from LALInferenceMCMC.")
1218 parser.add_option("--downsample",action="store",default=None,help="(LALInferenceMCMC) approximate number of samples to record in the posterior",type="int")
1219 parser.add_option("--deltaLogL",action="store",default=None,help="(LALInferenceMCMC) Difference in logL to use for convergence test.",type="float")
1220 parser.add_option("--fixedBurnin",dest="fixedBurnin",action="callback",callback=multipleFileCB,help="(LALInferenceMCMC) Fixed number of iteration for burnin.")
1221 parser.add_option("--oldMassConvention",action="store_true",default=False,help="(LALInferenceMCMC) if activated, m2 > m1; otherwise m1 > m2 in PTMCMC.output.*.00")
1222 #FM
1223 parser.add_option("--fm",action="store_true",default=False,help="(followupMCMC) Parse input as if it was output from followupMCMC.")
1224 # ACF plots off?
1225 parser.add_option("--no-acf", action="store_true", default=False, dest="noacf")
1226 # Turn on 2D kdes
1227 parser.add_option("--twodkdeplots", action="store_true", default=False, dest="twodkdeplots")
1228 # Turn on R convergence tests
1229 parser.add_option("--RconvergenceTests", action="store_true", default=False, dest="RconvergenceTests")
1230 parser.add_option("--nopdfs",action="store_false",default=True,dest="nopdfs")
1231 parser.add_option("-c","--covarianceMatrix",dest="covarianceMatrices",action="append",default=None,help="CSV file containing covariance (must give accompanying mean vector CSV. Can add more than one matrix.")
1232 parser.add_option("-m","--meanVectors",dest="meanVectors",action="append",default=None,help="Comma separated list of locations of the multivariate gaussian described by the correlation matrix. First line must be list of params in the order used for the covariance matrix. Provide one list per covariance matrix.")
1233 parser.add_option("--email",action="store",default=None,type="string",metavar="user@ligo.org",help="Send an e-mail to the given address with a link to the finished page.")
1234 parser.add_option("--stats_only",action="store_true",default=False,dest="stats_only")
1235 parser.add_option("--archive",action="store",default=None,type="string",metavar="results.tar.gz",help="Create the given tarball with all results")
1236 parser.add_option("--psdfiles",action="store",default=None,type="string",metavar="H1,L1,V1",help="comma separater list of ASCII files with PSDs, one per IFO")
1237 (opts,args)=parser.parse_args()
1238
1239 datafiles=[]
1240 if args:
1241 datafiles=datafiles+args
1242 if opts.data:
1243 datafiles=datafiles + opts.data
1244
1245 if opts.fixedBurnin:
1246 fixedBurnins = [int(fixedBurnin) for fixedBurnin in opts.fixedBurnin]
1247 else:
1248 fixedBurnins = None
1249 if opts.archive=='None':
1250 opts.archive=None
1251 #List of parameters to plot/bin . Need to match (converted) column names.
1252
1253 polParams=['psi','polarisation','polarization']
1254 skyParams=['ra','rightascension','declination','dec']
1255 timeParams=['time']
1256 ellParams=['alpha','polar_eccentricity','polar_angle']
1257 burstParams=['frequency','loghrss','quality','hrss','duration']
1258 phaseParams=['phase','phi_orb']
1259 #endTimeParams=['l1_end_time','h1_end_time','v1_end_time']
1260 endTimeParams=[]
1261 #statsParams=['logprior','logl','deltalogl','deltaloglh1','deltalogll1','deltaloglv1','deltaloglh2','deltaloglg1']
1262 statsParams=['logl']
1263 calibParams=['calpha_l1','calpha_h1','calamp_l1','calamp_h1']
1264 oneDMenu=polParams + skyParams + timeParams + statsParams+burstParams+ellParams+phaseParams+calibParams
1265
1266 ifos_menu=['h1','l1','v1']
1267 from itertools import combinations
1268 for ifo1,ifo2 in combinations(ifos_menu,2):
1269 oneDMenu.append(ifo1+ifo2+'_delay')
1270
1271 #oneDMenu=[]
1272 twoDGreedyMenu=[]
1273 if not opts.no2D:
1274 for b1,b2 in combinations(burstParams,2):
1275 twoDGreedyMenu.append([b1,b2])
1276 #for bu in burstParams:
1277 # for sp in skyParams:
1278 # twoDGreedyMenu.append([bu,sp])
1279 #for bu in burstParams:
1280 # for ti in timeParams:
1281 # twoDGreedyMenu.append([bu,ti])
1282
1283 twoDGreedyMenu.append(['phi_orb','psi'])
1284 twoDGreedyMenu.append(['alpha','psi'])
1285 twoDGreedyMenu.append(['phi_orb','alpha'])
1286 twoDGreedyMenu.append(['loghrss','psi'])
1287 twoDGreedyMenu.append(['alpha','loghrss'])
1288 for i in calibParams[2:]:
1289 twoDGreedyMenu.append([i,'loghrss'])
1290 twoDGreedyMenu.append(['calpha_h1','calpha_l1'])
1291 twoDGreedyMenu.append(['calamp_h1','calamp_l1'])
1292
1293 #twoDGreedyMenu=[['mc','eta'],['mchirp','eta'],['m1','m2'],['mtotal','eta'],['distance','iota'],['dist','iota'],['dist','m1'],['ra','dec']]
1294 #Bin size/resolution for binning. Need to match (converted) column names.
1295 greedyBinSizes={'time':1e-4,'ra':0.05,'dec':0.05,'polarisation':0.04,'rightascension':0.05,'declination':0.05, 'loghrss':0.01,'frequency':0.5,'quality':0.05,'phase':0.1,'phi_orb':0.1,'psi':0.04,'polarization':0.04,'alpha':0.01,'duration':0.0001,'calamp_l1':0.01,'calamp_h1':0.01,'calpha_h1':0.01,'calpha_l1':0.01,'polar_eccentricity':0.01}
1296 #for derived_time in ['h1_end_time','l1_end_time','v1_end_time','h1l1_delay','l1v1_delay','h1v1_delay']:
1297 # greedyBinSizes[derived_time]=greedyBinSizes['time']
1298 #if not opts.no2D:
1299 # for dt1,dt2 in combinations(['h1_end_time','l1_end_time','v1_end_time'],2):
1300 # twoDGreedyMenu.append([dt1,dt2])
1301 # for dt1,dt2 in combinations( ['h1l1_delay','l1v1_delay','h1v1_delay'],2):
1302 # twoDGreedyMenu.append([dt1,dt2])
1303
1304 #Confidence levels
1305 for loglname in ['logl','deltalogl','deltaloglh1','deltaloglv1','deltalogll1','logll1','loglh1','loglv1']:
1306 greedyBinSizes[loglname]=0.1
1307 confidenceLevels=[0.67,0.9,0.95,0.99]
1308 #2D plots list
1309 #twoDplots=[['mc','eta'],['mchirp','eta'],['mc', 'time'],['mchirp', 'time'],['m1','m2'],['mtotal','eta'],['distance','iota'],['dist','iota'],['RA','dec'],['ra', 'dec'],['m1','dist'],['m2','dist'],['mc', 'dist'],['psi','iota'],['psi','distance'],['psi','dist'],['psi','phi0'], ['a1', 'a2'], ['a1', 'iota'], ['a2', 'iota'],['eta','time'],['ra','iota'],['dec','iota'],['chi','iota'],['chi','mchirp'],['chi','eta'],['chi','distance'],['chi','ra'],['chi','dec'],['chi','psi']]
1310 twoDplots=twoDGreedyMenu
1312 opts.outpath,datafiles,oneDMenu,twoDGreedyMenu,
1313 greedyBinSizes,confidenceLevels,twoDplots,
1314 #optional
1315 injfile=opts.injfile,eventnum=opts.eventnum,
1316 trigfile=opts.trigfile,trignum=opts.trignum,
1317 skyres=opts.skyres,
1318 # direct integration evidence
1319 dievidence=opts.dievidence,boxing=opts.boxing,difactor=opts.difactor,
1320 # Ellipitical evidence
1321 ellevidence=opts.ellevidence,
1322 #manual bayes factor entry
1323 bayesfactornoise=opts.bsn,bayesfactorcoherent=opts.bci,
1324 #manual input for SNR in the IFOs, optional.
1325 snrfactor=opts.snr,
1326 #nested sampling options
1327 ns_flag=opts.ns,ns_Nlive=opts.Nlive,
1328 #spinspiral/mcmc options
1329 ss_flag=opts.ss,ss_spin_flag=opts.spin,
1330 #LALInferenceMCMC options
1331 li_flag=opts.lalinfmcmc,deltaLogL=opts.deltaLogL,fixedBurnins=fixedBurnins,nDownsample=opts.downsample,oldMassConvention=opts.oldMassConvention,
1332 #followupMCMC options
1333 fm_flag=opts.fm,
1334 # Turn of ACF?
1335 noacf=opts.noacf,
1336 #Turn on 2D kdes
1337 #twodkdeplots=opts.twodkdeplots,
1338 twodkdeplots=False,
1339 #Turn on R convergence tests
1340 RconvergenceTests=opts.RconvergenceTests,
1341 # Also save PDFs?
1342 savepdfs=opts.nopdfs,
1343 #List of covariance matrix csv files used as analytic likelihood
1344 covarianceMatrices=opts.covarianceMatrices,
1345 #List of meanVector csv files used, one csv file for each covariance matrix
1346 meanVectors=opts.meanVectors,
1347 #header file for parameter names in posterior samples
1348 header=opts.header,
1349 # ascii files (one per IFO) containing freq - PSD columns
1350 psd_files=opts.psdfiles,
1351 statsonly=opts.stats_only
1352 )
1353 if opts.archive is not None:
1354 import subprocess
1355 subprocess.call(["tar","cvzf",opts.archive,opts.outpath])
1356 # Send an email, useful for keeping track of dozens of jobs!
1357 # Will only work if the local host runs a mail daemon
1358 # that can send mail to the internet
1359 if opts.email:
1360 try:
1361 email_notify(opts.email,opts.outpath)
1362 except:
1363 print('Unable to send notification email')
1364#
#define max(a, b)
def __init__(self, document)
intable
def startElement(self, name, attrs)
tabname
def endElement(self, name)
tableElementName
intable
def __init__(self, document)
def endElement(self, name)
tableElementName
def startElement(self, name, attrs)
tabname
def oneD_dict_to_file(dict, fname)
def cbcBayesBurstPostProc(outdir, data, oneDMenu, twoDGreedyMenu, GreedyRes, confidence_levels, twoDplots, injfile=None, eventnum=None, trigfile=None, trignum=None, skyres=None, dievidence=False, boxing=64, difactor=1.0, ellevidence=False, bayesfactornoise=None, bayesfactorcoherent=None, snrfactor=None, ns_flag=False, ns_Nlive=None, ss_flag=False, ss_spin_flag=False, li_flag=False, deltaLogL=None, fixedBurnins=None, nDownsample=None, oldMassConvention=False, fm_flag=False, noacf=False, twodkdeplots=False, RconvergenceTests=False, savepdfs=True, covarianceMatrices=None, meanVectors=None, header=None, psd_files=None, statsonly=False)
This is a demonstration script for using the functionality/data structures contained in lalinference....
multipleFileCB
def dict2html(d, parent=None)
def extract_hdf5_metadata(h5grp, parent=None)
def email_notify(address, path)
def pickle_to_file(obj, fname)
Pickle/serialize 'obj' into 'fname'.