Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInference 4.1.9.1-00ddc7f
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cbcBayesPostProc.py
Go to the documentation of this file.
1##python
2# -*- coding: utf-8 -*-
3#
4# cbcBayesPostProc.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 socket
37import pickle
38from time import strftime
39
40#related third party imports
41import numpy as np
42from numpy import (exp, cos, sin, size, cov, unique, hsplit, log, squeeze)
43
44import matplotlib
45matplotlib.use("Agg")
46from matplotlib import pyplot as plt
47
48# Default font properties
49fig_width_pt = 246 # Get this from LaTeX using \showthe\columnwidth
50inches_per_pt = 1.0/72.27 # Convert pt to inch
51golden_mean = (2.236-1.0)/2.0 # Aesthetic ratio
52fig_width = fig_width_pt*inches_per_pt # width in inches
53fig_height = fig_width*golden_mean # height in inches
54fig_size = [fig_width,fig_height]
55matplotlib.rcParams.update(
56 {'axes.labelsize': 16,
57 'font.size': 16,
58 'legend.fontsize': 16,
59 'xtick.labelsize': 16,
60 'ytick.labelsize': 16,
61 'text.usetex': False,
62 'figure.figsize': fig_size,
63 'font.family': "serif",
64 'font.serif': ['Times','Palatino','New Century Schoolbook','Bookman','Computer Modern Roman','Times New Roman','Liberation Serif'],
65 'font.weight':'normal',
66 'font.size':16,
67 'savefig.dpi': 120
68 })
69
70#local application/library specific imports
72from lalinference import bayespputils as bppu
73from lalinference import git_version
74
75from igwn_ligolw import lsctables
76from igwn_ligolw import utils
77
78__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>"
79__version__= "git id %s"%git_version.id
80__date__= git_version.date
81
82from lalinference.lalinference_pipe_utils import guess_url
83
84def email_notify(address,path):
85 import subprocess
86 USER = os.environ['USER']
87 HOST = socket.getfqdn()
88 address=address.split(',')
89 FROM=USER+'@'+HOST
90 SUBJECT="LALInference result is ready at "+HOST+"!"
91 # Guess the web space path for the clusters
92 fslocation=os.path.abspath(path)
93 webpath='posplots.html'
94 url = guess_url(os.path.join(fslocation,webpath))
95 TEXT="Hi "+USER+",\nYou have a new parameter estimation result on "+HOST+".\nYou can view the result at "+url+"\n"
96 cmd='echo "%s" | mail -s "%s" "%s"'%(TEXT,SUBJECT,', '.join(address))
97 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True)
98 (out, err) = proc.communicate()
99 #print "program output %s error %s:"%(out,err)
100
101def pickle_to_file(obj,fname):
102 """
103 Pickle/serialize 'obj' into 'fname'.
104 """
105 filed=open(fname,'w')
106 pickle.dump(obj,filed)
107 filed.close()
108
109def oneD_dict_to_file(dict,fname):
110 filed=open(fname,'w')
111 for key,value in dict.items():
112 filed.write("%s %s\n"%(str(key),str(value)) )
113
114def multipleFileCB(opt, opt_str, value, parser):
115 args=[]
116
117 def floatable(str):
118 try:
119 float(str)
120 return True
121 except ValueError:
122 return False
123
124 for arg in parser.rargs:
125 # stop on --foo like options
126 if arg[:2] == "--" and len(arg) > 2:
127 break
128 # stop on -a, but not on -3 or -3.0
129 if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
130 break
131 args.append(arg)
132
133 del parser.rargs[:len(args)]
134 #Append new files to list if some already specified
135 if getattr(parser.values, opt.dest):
136 oldargs = getattr(parser.values, opt.dest)
137 oldargs.extend(args)
138 args = oldargs
139 setattr(parser.values, opt.dest, args)
140
141def dict2html(d,parent=None):
142 if not d: return ""
143 out=bppu.htmlChunk('div',parent=parent)
144 tab=out.tab()
145 row=out.insert_row(tab)
146 for key in d.keys():
147 out.insert_td(row,str(key))
148 row2=out.insert_row(tab)
149 for val in d.values():
150 out.insert_td(row2,str(val))
151 return out
152
153def extract_hdf5_metadata(h5grp,parent=None):
154 import h5py
155 #out=bppu.htmlChunk('div',parent=parent)
156 sec=bppu.htmlSection(h5grp.name,htmlElement=parent)
157 dict2html(h5grp.attrs,parent=sec)
158 for group in h5grp:
159 if(isinstance(h5grp[group],h5py.Group)):
160 extract_hdf5_metadata(h5grp[group],sec)
161 return h5grp
162
163
165 outdir,data,oneDMenus,twoDGreedyMenu,GreedyRes,
166 confidence_levels,twoDplots,
167 #misc. optional
168 injfile=None,eventnum=None,
169 trigfile=None,trignum=None,
170 skyres=None,
171 #direct integration evidence
172 dievidence=False,boxing=64,difactor=1.0,
173 #elliptical evidence
174 ellevidence=False,
175 #manual input of bayes factors optional.
176 bayesfactornoise=None,bayesfactorcoherent=None,
177 #manual input for SNR in the IFOs, optional.
178 snrfactor=None,
179 #nested sampling options
180 ns_flag=False,ns_Nlive=None,
181 #spinspiral/mcmc options
182 ss_flag=False,ss_spin_flag=False,
183 #lalinferenceMCMC options
184 li_flag=False,deltaLogP=None,fixedBurnins=None,nDownsample=None,oldMassConvention=False,
185 #followupMCMC options
186 fm_flag=False,
187 #spin frame for the injection
188 inj_spin_frame='OrbitalL',
189 # on ACF?
190 noacf=False,
191 #Turn on 2D kdes
192 twodkdeplots=False,
193 #Turn on R convergence tests
194 RconvergenceTests=False,
195 # Save PDF figures?
196 savepdfs=True,
197 #List of covariance matrix csv files used as analytic likelihood
198 covarianceMatrices=None,
199 #List of meanVector csv files used, one csv file for each covariance matrix
200 meanVectors=None,
201 #header file
202 header=None,
203 psd_files=None,
204 greedy=True ## If true will use greedy bin for 1-d credible regions. Otherwise use 2-steps KDE
205 ):
206 """
207 This is a demonstration script for using the functionality/data structures
208 contained in lalinference.bayespputils . It will produce a webpage from a file containing
209 posterior samples generated by the parameter estimation codes with 1D/2D plots
210 and stats from the marginal posteriors for each parameter/set of parameters.
211 """
212 if eventnum is not None and injfile is None:
213 print("You specified an event number but no injection file. Ignoring!")
214
215 if trignum is not None and trigfile is None:
216 print("You specified a trigger number but no trigger file. Ignoring!")
217
218 if trignum is None and trigfile is not None:
219 print("You specified a trigger file but no trigger number. Taking first entry (the case for GraceDB events).")
220 trignum=0
221
222 if data is None:
223 raise RuntimeError('You must specify an input data file')
224 #
225 if outdir is None:
226 raise RuntimeError("You must specify an output directory.")
227
228 if not os.path.isdir(outdir):
229 os.makedirs(outdir)
230 #
231 if fm_flag:
232 peparser=bppu.PEOutputParser('fm')
233 commonResultsObj=peparser.parse(data)
234
235 elif ns_flag and not ss_flag:
236 peparser=bppu.PEOutputParser('ns')
237 commonResultsObj=peparser.parse(data,Nlive=ns_Nlive)
238
239 elif ss_flag and not ns_flag:
240 peparser=bppu.PEOutputParser('mcmc_burnin')
241 commonResultsObj=peparser.parse(data,spin=ss_spin_flag,deltaLogP=deltaLogP)
242
243 elif li_flag:
244 peparser=bppu.PEOutputParser('inf_mcmc')
245 commonResultsObj=peparser.parse(data,outdir=outdir,deltaLogP=deltaLogP,fixedBurnins=fixedBurnins,nDownsample=nDownsample,oldMassConvention=oldMassConvention)
246
247 elif ss_flag and ns_flag:
248 raise RuntimeError("Undefined input format. Choose only one of:")
249
250 elif '.hdf' in data[0] or '.h5' in data[0]:
251 if len(data) > 1:
252 peparser = bppu.PEOutputParser('hdf5s')
253 commonResultsObj=peparser.parse(data,deltaLogP=deltaLogP,fixedBurnins=fixedBurnins,nDownsample=nDownsample)
254 else:
255 fixedBurnins = fixedBurnins if fixedBurnins is not None else None
256 peparser = bppu.PEOutputParser('hdf5')
257 commonResultsObj=peparser.parse(data[0],deltaLogP=deltaLogP,fixedBurnins=fixedBurnins,nDownsample=nDownsample)
258 else:
259 peparser=bppu.PEOutputParser('common')
260 commonResultsObj=peparser.parse(open(data[0],'r'),info=[header,None])
261 # check if Nest (through nest2post) has produced an header file with git and CL info. If yes copy in outdir
262 if os.path.isfile(data[0]+"_header.txt"):
263 import shutil
264 shutil.copy2(data[0]+"_header.txt", os.path.join(outdir,'nest_headers.txt'))
265
266 #Extract f_ref from CRO if present. This is needed to calculate orbital angular momentum
267 # when converting spin parameters. Ideally this info will be provided in the
268 # SimInspiralTable in the near future.
269 ps,samps = commonResultsObj
270 try:
271 f_refIdx = ps.index('f_ref')
272 injFref = unique(samps[:,f_refIdx])
273 if len(injFref) > 1:
274 print("ERROR: Expected f_ref to be constant for all samples. Can't tell which value was injected!")
275 print(injFref)
276 injFref = None
277 else:
278 injFref = injFref[0]
279 except ValueError:
280 injFref = None
281
282 #Select injections using tc +/- 0.1s if it exists or eventnum from the injection file
283 injection=None
284 if injfile and eventnum is not None:
285 print('Looking for event %i in %s\n'%(eventnum,injfile))
286 xmldoc = utils.load_filename(injfile)
287 siminspiraltable=lsctables.SimInspiralTable.get_table(xmldoc)
288 injection=siminspiraltable[eventnum]
289
290 #Get trigger
291 triggers = None
292 if trigfile is not None and trignum is not None:
293 triggers = bppu.readCoincXML(trigfile, trignum)
294
295 ## Load Bayes factors ##
296 # Add Bayes factor information to summary file #
297 if bayesfactornoise is not None:
298 bfile=open(bayesfactornoise,'r')
299 BSN=bfile.read()
300 bfile.close()
301 if(len(BSN.split())!=1):
302 BSN=BSN.split()[0]
303 print('BSN: %s'%BSN)
304 if bayesfactorcoherent is not None:
305 bfile=open(bayesfactorcoherent,'r')
306 BCI=bfile.read()
307 bfile.close()
308 print('BCI: %s'%BCI)
309
310 if snrfactor is not None:
311 if not os.path.isfile(snrfactor):
312 print("No snr file provided or wrong path to snr file\n")
313 snrfactor=None
314 else:
315 snrstring=""
316 snrfile=open(snrfactor,'r')
317 snrs=snrfile.readlines()
318 snrfile.close()
319 for snr in snrs:
320 if snr=="\n":
321 continue
322 snrstring=snrstring +" "+str(snr[0:-1])+" ,"
323 snrstring=snrstring[0:-1]
324
325 #Create an instance of the posterior class using the posterior values loaded
326 #from the file and any injection information (if given).
327 pos = bppu.Posterior(commonResultsObj,SimInspiralTableEntry=injection,inj_spin_frame=inj_spin_frame, injFref=injFref,SnglInspiralList=triggers)
328
329 #Create analytic likelihood functions if covariance matrices and mean vectors were given
330 analyticLikelihood = None
331 if covarianceMatrices and meanVectors:
332 analyticLikelihood = bppu.AnalyticLikelihood(covarianceMatrices, meanVectors)
333
334 #Plot only analytic parameters
335 oneDMenu = analyticLikelihood.names
336 if twoDGreedyMenu:
337 twoDGreedyMenu = []
338 for i in range(len(oneDMenu)):
339 for j in range(i+1,len(oneDMenu)):
340 twoDGreedyMenu.append([oneDMenu[i],oneDMenu[j]])
341 twoDplots = twoDGreedyMenu
342
343 if eventnum is None and injfile is not None:
344 import itertools
345 injections = lsctables.SimInspiralTable.get_table(utils.load_filename(injfile))
346
347 if(len(injections)<1):
348 try:
349 print('Warning: Cannot find injection with end time %f' %(pos['time'].mean))
350 except KeyError:
351 print("Warning: No 'time' column!")
352
353 else:
354 try:
355 injection = itertools.ifilter(lambda a: abs(float(a.get_end()) - pos['time'].mean) < 0.1, injections).next()
356 pos.set_injection(injection)
357 except KeyError:
358 print("Warning: No 'time' column!")
359
360 pos.extend_posterior()
361 # create list of names in oneDMenus dic
362 oneDMenu=[]
363 for i in oneDMenus.keys():
364 oneDMenu+=oneDMenus[i]
365 #Perform necessary mappings
366 functions = {'cos':cos,'sin':sin,'exp':exp,'log':log}
367 for pos_name in oneDMenu:
368 if pos_name not in pos.names:
369 for func in functions.keys():
370 old_pos_name = pos_name.replace(func,'')
371 if pos_name.find(func)==0 and old_pos_name in pos.names:
372 print("Taking %s of %s ..."% (func,old_pos_name))
373 pos.append_mapping(pos_name,functions[func],old_pos_name)
374
375 #Remove samples with NaNs in requested params
376 requested_params = set(pos.names).intersection(set(oneDMenu))
377 pos.delete_NaN_entries(requested_params)
378
379 #Remove non-analytic parameters if analytic likelihood is given:
380 if analyticLikelihood:
381 dievidence_names = ['post','posterior','logl','prior','likelihood','cycle','chain']
382 [pos.pop(param) for param in pos.names if param not in analyticLikelihood.names and param not in dievidence_names]
383
384 ##Print some summary stats for the user...##
385 #Number of samples
386 print("Number of posterior samples: %i"%len(pos))
387 # Means
388 print('Means:')
389 print(str(pos.means))
390 #Median
391 print('Median:')
392 print(str(pos.medians))
393 #maxL
394 print('maxL:')
395 max_pos,max_pos_co=pos.maxL
396 print(max_pos_co)
397
398 # Save posterior samples
399 posfilename=os.path.join(outdir,'posterior_samples.dat')
400 pos.write_to_file(posfilename)
401
402 #==================================================================#
403 #Create web page
404 #==================================================================#
405
406 html=bppu.htmlPage('Posterior PDFs',css=bppu.__default_css_string,javascript=bppu.__default_javascript_string)
407
408 #Create a section for meta-data/run information
409 html_meta=html.add_section('Summary')
410 table=html_meta.tab()
411 row=html_meta.insert_row(table,label='thisrow')
412 td=html_meta.insert_td(row,'',label='Samples')
413 SampsStats=html.add_section_to_element('Samples',td)
414 SampsStats.p('Produced from '+str(len(pos))+' posterior samples.')
415 if 'chain' in pos.names:
416 acceptedChains = unique(pos['chain'].samples)
417 acceptedChainText = '%i of %i chains accepted: %i'%(len(acceptedChains),len(data),acceptedChains[0])
418 if len(acceptedChains) > 1:
419 for chain in acceptedChains[1:]:
420 acceptedChainText += ', %i'%(chain)
421 SampsStats.p(acceptedChainText)
422 if 'cycle' in pos.names:
423 SampsStats.p('Longest chain has '+str(pos.longest_chain_cycles())+' cycles.')
424 filenames='Samples read from %s'%(data[0])
425 if len(data) > 1:
426 for fname in data[1:]:
427 filenames+=', '+str(fname)
428 SampsStats.p(filenames)
429 td=html_meta.insert_td(row,'',label='SummaryLinks')
430 legend=html.add_section_to_element('Sections',td)
431
432 # Create a section for HDF5 metadata if available
433 if '.h5' in data[0] or '.hdf' in data[0]:
434 html_hdf=html.add_section('Metadata',legend=legend)
435 import h5py
436 with h5py.File(data[0],'r') as h5grp:
437 extract_hdf5_metadata(h5grp,parent=html_hdf)
438
439 #Create a section for model selection results (if they exist)
440 if bayesfactorcoherent is not None or bayesfactornoise is not None:
441 html_model=html.add_section('Model selection',legend=legend)
442 if bayesfactornoise is not None:
443 html_model.p('log Bayes factor ( coherent vs gaussian noise) = %s, Bayes factor=%f'%(BSN,exp(float(BSN))))
444 if bayesfactorcoherent is not None:
445 html_model.p('log Bayes factor ( coherent vs incoherent OR noise ) = %s, Bayes factor=%f'%(BCI,exp(float(BCI))))
446
447 if dievidence:
448 html_model=html.add_section('Direct Integration Evidence',legend=legend)
449 log_ev = log(difactor) + pos.di_evidence(boxing=boxing)
450 ev=exp(log_ev)
451 evfilename=os.path.join(outdir,"evidence.dat")
452 evout=open(evfilename,"w")
453 evout.write(str(ev))
454 evout.write(" ")
455 evout.write(str(log_ev))
456 evout.close()
457 print("Computing direct integration evidence = %g (log(Evidence) = %g)"%(ev, log_ev))
458 html_model.p('Direct integration evidence is %g, or log(Evidence) = %g. (Boxing parameter = %d.)'%(ev,log_ev,boxing))
459 if 'logl' in pos.names:
460 log_ev=pos.harmonic_mean_evidence()
461 html_model.p('Compare to harmonic mean evidence of %g (log(Evidence) = %g).'%(exp(log_ev),log_ev))
462
463 if ellevidence:
464 try:
465 html_model=html.add_section('Elliptical Evidence',legend=legend)
466 log_ev = pos.elliptical_subregion_evidence()
467 ev = exp(log_ev)
468 evfilename=os.path.join(outdir, 'ellevidence.dat')
469 evout=open(evfilename, 'w')
470 evout.write(str(ev) + ' ' + str(log_ev))
471 evout.close()
472 print('Computing elliptical region evidence = %g (log(ev) = %g)'%(ev, log_ev))
473 html_model.p('Elliptical region evidence is %g, or log(Evidence) = %g.'%(ev, log_ev))
474
475 if 'logl' in pos.names:
476 log_ev=pos.harmonic_mean_evidence()
477 html_model.p('Compare to harmonic mean evidence of %g (log(Evidence = %g))'%(exp(log_ev), log_ev))
478 except IndexError:
479 print('Warning: Sample size too small to compute elliptical evidence!')
480
481 #Create a section for SNR, if a file is provided
482 if snrfactor is not None:
483 html_snr=html.add_section('Signal to noise ratio(s)',legend=legend)
484 html_snr.p('%s'%snrstring)
485
486 # Create a section for the DIC
487 html_dic = html.add_section('Deviance Information Criterion', legend=legend)
488 html_dic.p('DIC = %.1f'%pos.DIC)
489 dicout = open(os.path.join(outdir, 'dic.dat'), 'w')
490 try:
491 dicout.write('%.1f\n'%pos.DIC)
492 finally:
493 dicout.close()
494
495 #Create a section for summary statistics
496 # By default collapse section are collapsed when the page is opened or reloaded. Use start_closed=False option as here below to change this
497 tabid='statstable'
498 html_stats=html.add_collapse_section('Summary statistics',legend=legend,innertable_id=tabid,start_closed=False)
499 html_stats.write(str(pos))
500 statfilename=os.path.join(outdir,"summary_statistics.dat")
501 statout=open(statfilename,"w")
502 statout.write("\tmaP\tmaxL\tKL\tstdev\tmean\tmedian\tstacc\tinjection\tvalue\n")
503
504 warned_about_kl = False
505 for statname,statoned_pos in pos:
506
507 statmax_pos,max_i=pos._posMaxL()
508 statmaxL=statoned_pos.samples[max_i][0]
509 try:
510 statKL = statoned_pos.KL()
511 except ValueError:
512 if not warned_about_kl:
513 print("Unable to compute KL divergence")
514 warned_about_kl = True
515 statKL = None
516
517 statmax_pos,max_j=pos._posMap()
518 statmaxP=statoned_pos.samples[max_j][0]
519 statmean=str(statoned_pos.mean)
520 statstdev=str(statoned_pos.stdev)
521 statmedian=str(squeeze(statoned_pos.median))
522 statstacc=str(statoned_pos.stacc)
523 statinjval=str(statoned_pos.injval)
524
525 statarray=[str(i) for i in [statname,statmaxP,statmaxL,statKL,statstdev,statmean,statmedian,statstacc,statinjval]]
526 statout.write("\t".join(statarray))
527 statout.write("\n")
528
529 statout.close()
530
531 #==================================================================#
532 #Generate sky map, WF, and PSDs
533 #==================================================================#
534
535 skyreses=None
536 sky_injection_cl=None
537 inj_position=None
538 tabid='skywftable'
539 html_wf=html.add_collapse_section('Sky Localization and Waveform',innertable_id=tabid)
540
541 table=html_wf.tab(idtable=tabid)
542 row=html_wf.insert_row(table,label='SkyandWF')
543 skytd=html_wf.insert_td(row,'',label='SkyMap',legend=legend)
544 html_sky=html.add_section_to_element('SkyMap',skytd)
545 #If sky resolution parameter has been specified try and create sky map...
546 if skyres is not None and \
547 ('ra' in pos.names and 'dec' in pos.names):
548
549 if pos['dec'].injval is not None and pos['ra'].injval is not None:
550 inj_position=[pos['ra'].injval,pos['dec'].injval]
551 else:
552 inj_position=None
553
554 hpmap = pos.healpix_map(float(skyres), nest=True)
555 bppu.plot_sky_map(hpmap, outdir, inj=inj_position, nest=True)
556
557 if inj_position is not None:
558 html_sky.p('Injection found at p = %g'%bppu.skymap_inj_pvalue(hpmap, inj_position, nest=True))
559
560 html_sky.write('<a href="skymap.png" target="_blank"><img src="skymap.png"/></a>')
561
562 html_sky_write='<table border="1" id="statstable"><tr><th>Confidence region</th><th>size (sq. deg)</th></tr>'
563
564 areas = bppu.skymap_confidence_areas(hpmap, confidence_levels)
565 for cl, area in zip(confidence_levels, areas):
566 html_sky_write+='<tr><td>%g</td><td>%g</td></tr>'%(cl, area)
567 html_sky_write+=('</table>')
568
569 html_sky.write(html_sky_write)
570 else:
571 html_sky.write('<b>No skymap generated!</b>')
572 wfdir=os.path.join(outdir,'Waveform')
573 if not os.path.isdir(wfdir):
574 os.makedirs(wfdir)
575 try:
576 wfpointer= bppu.plot_waveform(pos=pos,siminspiral=injfile,event=eventnum,path=wfdir)
577 except Exception as e:
578 wfpointer = None
579 print("Could not create WF plot. The error was: %s\n"%str(e))
580 wftd=html_wf.insert_td(row,'',label='Waveform',legend=legend)
581 wfsection=html.add_section_to_element('Waveforms',wftd)
582 if wfpointer is not None:
583 wfsection.write('<a href="Waveform/WF_DetFrame.png" target="_blank"><img src="Waveform/WF_DetFrame.png"/></a>')
584 else:
585 print("Could not create WF plot.\n")
586 wfsection.write("<b>No Waveform generated!</b>")
587
588 wftd=html_wf.insert_td(row,'',label='PSDs',legend=legend)
589 wfsection=html.add_section_to_element('PSDs',wftd)
590 if psd_files is not None:
591 psd_files=list(psd_files.split(','))
592 psddir=os.path.join(outdir,'PSDs')
593 if not os.path.isdir(psddir):
594 os.makedirs(psddir)
595 try:
596 if 'flow' in pos.names:
597 f_low = pos['flow'].samples.min()
598 else:
599 f_low = 30.
600 bppu.plot_psd(psd_files,outpath=psddir, f_min=f_low)
601 wfsection.write('<a href="PSDs/PSD.png" target="_blank"><img src="PSDs/PSD.png"/></a>')
602 except Exception as e:
603 print("Could not create PSD plot. The error was: %s\n"%str(e))
604 wfsection.write("<b>PSD plotting failed</b>")
605 else:
606 wfsection.write("<b>No PSD files provided</b>")
607
608 # Add plots for calibration estimates
609 if np.any(['spcal_amp' in param for param in pos.names]) or np.any(['spcal_phase' in param for param in pos.names]):
610 wftd=html_wf.insert_td(row,'',label='Calibration',legend=legend)
611 wfsection=html.add_section_to_element('Calibration',wftd)
612 bppu.plot_calibration_pos(pos, outpath=outdir)
613 wfsection.write('<a href="calibration.png" target="_blank"><img src="calibration.png"/></a>')
614 # if precessing spins do spin disk
615 allin=1.0
616 if set(['a1','a2','tilt1','tilt2']).issubset(pos.names):
617 wftd=html_wf.insert_td(row,'',label='DiskPlot',legend=legend)
618 wfsection=html.add_section_to_element('DiskPlot',wftd)
619 lalinference.plot.make_disk_plot(pos, outpath=outdir)
620 wfsection.write('<a href="comp_spin_pos.png" target="_blank"><img src="comp_spin_pos.png"/></a>')
621
622 #==================================================================#
623 #1D posteriors
624 #==================================================================#
625 onepdfdir=os.path.join(outdir,'1Dpdf')
626 if not os.path.isdir(onepdfdir):
627 os.makedirs(onepdfdir)
628
629 sampsdir=os.path.join(outdir,'1Dsamps')
630 if not os.path.isdir(sampsdir):
631 os.makedirs(sampsdir)
632 reses={}
633
634 for i in oneDMenus.keys():
635 rss=bppu.make_1d_table(html,legend,i,pos,oneDMenus[i],noacf,GreedyRes,onepdfdir,sampsdir,savepdfs,greedy,analyticLikelihood,nDownsample)
636 reses.update(rss)
637
638
639
640
641 tabid='onedconftable'
642 html_ogci=html.add_collapse_section('1D confidence intervals (greedy binning)',legend=legend,innertable_id=tabid)
643 html_ogci_write='<table id="%s" border="1"><tr><th/>'%tabid
644 clasciiout="#parameter \t"
645 confidence_levels.sort()
646 for cl in confidence_levels:
647 html_ogci_write+='<th>%f</th>'%cl
648 clasciiout+="%s\t"%('%.02f'%cl)
649 if injection:
650 html_ogci_write+='<th>Injection Confidence Level</th>'
651 html_ogci_write+='<th>Injection Confidence Interval</th>'
652 clasciiout+="Injection_Confidence_Level\t"
653 clasciiout+="Injection_Confidence_Interval"
654 clasciiout+='\n'
655 html_ogci_write+='</tr>'
656 #Generate new BCI html table row
657 printed=0
658 for par_name in oneDMenu:
659 par_name=par_name.lower()
660 try:
661 pos[par_name.lower()]
662 except KeyError:
663 #print "No input chain for %s, skipping binning."%par_name
664 continue
665 try:
666 par_bin=GreedyRes[par_name]
667 except KeyError:
668 print("Bin size is not set for %s, skipping binning."%par_name)
669 continue
670 binParams={par_name:par_bin}
671 injection_area=None
672 if greedy:
673 if printed==0:
674 print("Using greedy 1-d binning credible regions\n")
675 printed=1
676 toppoints,injectionconfidence,reses,injection_area,cl_intervals=bppu.greedy_bin_one_param(pos,binParams,confidence_levels)
677 else:
678 if printed==0:
679 print("Using 2-step KDE 1-d credible regions\n")
680 printed=1
681 if pos[par_name].injval is None:
682 injCoords=None
683 else:
684 injCoords=[pos[par_name].injval]
685 _,reses,injstats=bppu.kdtree_bin2Step(pos,[par_name],confidence_levels,injCoords=injCoords)
686 if injstats is not None:
687 injectionconfidence=injstats[3]
688 injection_area=injstats[4]
689
690 BCItableline='<tr><td>%s</td>'%(par_name)
691 clasciiout+="%s\t"%par_name
692 cls=list(reses.keys())
693 cls.sort()
694
695 for cl in cls:
696 BCItableline+='<td>%f</td>'%reses[cl]
697 clasciiout+="%f\t"%reses[cl]
698 if injection is not None:
699 if injectionconfidence is not None and injection_area is not None:
700
701 BCItableline+='<td>%f</td>'%injectionconfidence
702 BCItableline+='<td>%f</td>'%injection_area
703 clasciiout+="%f\t"%injectionconfidence
704 clasciiout+="%f"%injection_area
705
706 else:
707 BCItableline+='<td/>'
708 BCItableline+='<td/>'
709 clasciiout+="nan\t"
710 clasciiout+="nan"
711 BCItableline+='</tr>'
712 clasciiout+="\n"
713 #Append new table line to section html
714 html_ogci_write+=BCItableline
715
716 html_ogci_write+='</table>'
717 html_ogci.write(html_ogci_write)
718
719 #===============================#
720 # Corner plots
721 #===============================#
722 cornerdir=os.path.join(outdir,'corner')
723 if not os.path.isdir(cornerdir):
724 os.makedirs(cornerdir)
725 massParams=['mtotal','m1','m2','mc']
726 distParams=['distance','distMPC','dist','distance_maxl']
727 incParams=['iota','inclination','theta_jn']
728 polParams=['psi','polarisation','polarization']
729 skyParams=['ra','rightascension','declination','dec']
730 timeParams=['time']
731 spininducedquadParams = ['dquadmon1', 'dquadmon2','dquadmons','dquadmona']
732 spinParams=['spin1','spin2','a1','a2','a1z','a2z','phi1','theta1','phi2','theta2','chi','effectivespin','chi_eff','chi_tot','chi_p','beta','tilt1','tilt2','phi_jl','theta_jn','phi12']
733 sourceParams=['m1_source','m2_source','mtotal_source','mc_source','redshift']
734 intrinsicParams=massParams+spinParams
735 extrinsicParams=incParams+distParams+polParams+skyParams
736 sourceFrameParams=sourceParams+distParams
737 try:
738 myfig=bppu.plot_corner(pos,[0.05,0.5,0.95],parnames=intrinsicParams)
739 except:
740 myfig=None
741 tabid='CornerTable'
742 html_corner=''
743 got_any=0
744 if myfig:
745 html_corner+='<tr><td width="100%"><a href="corner/intrinsic.png" target="_blank"><img width="70%" src="corner/intrinsic.png"/></a></td></tr>'
746 myfig.savefig(os.path.join(cornerdir,'intrinsic.png'))
747 myfig.savefig(os.path.join(cornerdir,'intrinsic.pdf'))
748 got_any+=1
749 try:
750 myfig=bppu.plot_corner(pos,[0.05,0.5,0.95],parnames=extrinsicParams)
751 except:
752 myfig=None
753
754 if myfig:
755 myfig.savefig(os.path.join(cornerdir,'extrinsic.png'))
756 myfig.savefig(os.path.join(cornerdir,'extrinsic.pdf'))
757 html_corner+='<tr><td width="100%"><a href="corner/extrinsic.png" target="_blank"><img width="70%" src="corner/extrinsic.png"/></a></td></tr>'
758 got_any+=1
759 try:
760 myfig=bppu.plot_corner(pos,[0.05,0.5,0.95],parnames=sourceFrameParams)
761 except:
762 myfig=None
763
764 if myfig:
765 myfig.savefig(os.path.join(cornerdir,'sourceFrame.png'))
766 myfig.savefig(os.path.join(cornerdir,'sourceFrame.pdf'))
767 html_corner+='<tr><td width="100%"><a href="corner/sourceFrame.png" target="_blank"><img width="70%" src="corner/sourceFrame.png"/></a></td></tr>'
768 got_any+=1
769
770 if got_any>0:
771 html_corner='<table id="%s" border="1">'%tabid+html_corner
772 html_corner+='</table>'
773 if html_corner!='':
774 html_co=html.add_collapse_section('Corner plots',legend=legend,innertable_id=tabid)
775 html_co.write(html_corner)
776 if clasciiout:
777 fout=open(os.path.join(outdir,'confidence_levels.txt'),'w')
778 fout.write(clasciiout)
779 fout.close()
780 #==================================================================#
781 #2D posteriors
782 #==================================================================#
783
784 #Loop over parameter pairs in twoDGreedyMenu and bin the sample pairs
785 #using a greedy algorithm . The ranked pixels (toppoints) are used
786 #to plot 2D histograms and evaluate Bayesian confidence intervals.
787
788 #Make a folder for the 2D kde plots
789 margdir=os.path.join(outdir,'2Dkde')
790 if not os.path.isdir(margdir):
791 os.makedirs(margdir)
792
793 twobinsdir=os.path.join(outdir,'2Dbins')
794 if not os.path.isdir(twobinsdir):
795 os.makedirs(twobinsdir)
796
797 greedytwobinsdir=os.path.join(outdir,'greedy2Dbins')
798 if not os.path.isdir(greedytwobinsdir):
799 os.makedirs(greedytwobinsdir)
800
801 #Add a section to the webpage for a table of the confidence interval
802 #results.
803 tabid='2dconftable'
804 html_tcig=html.add_collapse_section('2D confidence intervals (greedy binning)',legend=legend,innertable_id=tabid)
805 #Generate the top part of the table
806 html_tcig_write='<table id="%s" border="1"><tr><th/>'%tabid
807 confidence_levels.sort()
808 for cl in confidence_levels:
809 html_tcig_write+='<th>%f</th>'%cl
810 if injection:
811 html_tcig_write+='<th>Injection Confidence Level</th>'
812 html_tcig_write+='<th>Injection Confidence Interval</th>'
813 html_tcig_write+='</tr>'
814
815
816 #= Add a section for a table of 2D marginal PDFs (kde)
817 twodkdeplots_flag=twodkdeplots
818 if twodkdeplots_flag:
819 tabid='2dmargtable'
820 html_tcmp=html.add_collapse_section('2D Marginal PDFs',legend=legend,innertable_id=tabid)
821 #Table matter
822 html_tcmp_write='<table border="1" id="%s">'%tabid
823
824 tabid='2dgreedytable'
825 html_tgbh=html.add_collapse_section('2D Greedy Bin Histograms',legend=legend,innertable_id=tabid)
826 html_tgbh_write='<table border="1" id="%s">'%tabid
827
828 row_count=0
829 row_count_gb=0
830
831 for par1_name,par2_name in twoDGreedyMenu:
832 par1_name=par1_name.lower()
833 par2_name=par2_name.lower()
834 # Don't plot a parameter against itself!
835 if par1_name == par2_name: continue
836 try:
837 pos[par1_name.lower()]
838 except KeyError:
839 #print "No input chain for %s, skipping binning."%par1_name
840 continue
841 try:
842 pos[par2_name.lower()]
843 except KeyError:
844 #print "No input chain for %s, skipping binning."%par2_name
845 continue
846 #Bin sizes
847 try:
848 par1_bin=GreedyRes[par1_name]
849 except KeyError:
850 print("Bin size is not set for %s, skipping %s/%s binning."%(par1_name,par1_name,par2_name))
851 continue
852 try:
853 par2_bin=GreedyRes[par2_name]
854 except KeyError:
855 print("Bin size is not set for %s, skipping %s/%s binning."%(par2_name,par1_name,par2_name))
856 continue
857
858 # Skip any fixed parameters to avoid matrix inversion problems
859 par1_pos=pos[par1_name].samples
860 par2_pos=pos[par2_name].samples
861 if (size(unique(par1_pos))<2 or size(unique(par2_pos))<2):
862 continue
863
864 #print "Binning %s-%s to determine confidence levels ..."%(par1_name,par2_name)
865 #Form greedy binning input structure
866 greedy2Params={par1_name:par1_bin,par2_name:par2_bin}
867
868 #Greedy bin the posterior samples
869 toppoints,injection_cl,reses,injection_area=\
870 bppu.greedy_bin_two_param(pos,greedy2Params,confidence_levels)
871
872 print("BCI %s-%s:"%(par1_name,par2_name))
873 print(reses)
874
875 #Generate new BCI html table row
876 BCItableline='<tr><td>%s-%s</td>'%(par1_name,par2_name)
877 cls=list(reses.keys())
878 cls.sort()
879
880 for cl in cls:
881 BCItableline+='<td>%f</td>'%reses[cl]
882
883 if injection is not None:
884 if injection_cl is not None:
885 BCItableline+='<td>%f</td>'%injection_cl
886 BCItableline+='<td>'+str(injection_area)+'</td>'
887
888 else:
889 BCItableline+='<td/>'
890 BCItableline+='<td/>'
891
892 BCItableline+='</tr>'
893
894 #Append new table line to section html
895 html_tcig_write+=BCItableline
896
897
898 #= Plot 2D histograms of greedily binned points =#
899
900 #greedy2ContourPlot=bppu.plot_two_param_greedy_bins_contour({'Result':pos},greedy2Params,[0.67,0.9,0.95],{'Result':'k'})
901 greedy2ContourPlot=bppu.plot_two_param_kde_greedy_levels({'Result':pos},greedy2Params,[0.67,0.9,0.95],{'Result':'k'})
902 greedy2contourpath=os.path.join(greedytwobinsdir,'%s-%s_greedy2contour.png'%(par1_name,par2_name))
903 if greedy2ContourPlot is not None:
904 greedy2ContourPlot.savefig(greedy2contourpath)
905 if(savepdfs): greedy2ContourPlot.savefig(greedy2contourpath.replace('.png','.pdf'))
906 plt.close(greedy2ContourPlot)
907
908 greedy2HistFig=bppu.plot_two_param_greedy_bins_hist(pos,greedy2Params,confidence_levels)
909 greedy2histpath=os.path.join(greedytwobinsdir,'%s-%s_greedy2.png'%(par1_name,par2_name))
910 greedy2HistFig.savefig(greedy2histpath)
911 if(savepdfs): greedy2HistFig.savefig(greedy2histpath.replace('.png','.pdf'))
912 plt.close(greedy2HistFig)
913
914 greedyFile = open(os.path.join(twobinsdir,'%s_%s_greedy_stats.txt'%(par1_name,par2_name)),'w')
915
916 #= Write out statistics for greedy bins
917 for cl in cls:
918 greedyFile.write("%lf %lf\n"%(cl,reses[cl]))
919 greedyFile.close()
920
921 if [par1_name,par2_name] in twoDplots or [par2_name,par1_name] in twoDplots :
922 print('Generating %s-%s greedy hist plot'%(par1_name,par2_name))
923
924 par1_pos=pos[par1_name].samples
925 par2_pos=pos[par2_name].samples
926
927 if (size(unique(par1_pos))<2 or size(unique(par2_pos))<2):
928 continue
929 head,figname=os.path.split(greedy2histpath)
930 head,figname_c=os.path.split(greedy2contourpath)
931 if row_count_gb==0:
932 html_tgbh_write+='<tr>'
933 html_tgbh_write+='<td width="30%"><img width="100%" src="greedy2Dbins/'+figname+'"/>[<a href="greedy2Dbins/'+figname_c+'">contour</a>]</td>'
934 row_count_gb+=1
935 if row_count_gb==3:
936 html_tgbh_write+='</tr>'
937 row_count_gb=0
938
939 #= Generate 2D kde plots =#
940
941 if twodkdeplots_flag is True:
942 if [par1_name,par2_name] in twoDplots or [par2_name,par1_name] in twoDplots :
943 print('Generating %s-%s plot'%(par1_name,par2_name))
944
945 par1_pos=pos[par1_name].samples
946 par2_pos=pos[par2_name].samples
947
948 if (size(unique(par1_pos))<2 or size(unique(par2_pos))<2):
949 continue
950
951 plot2DkdeParams={par1_name:50,par2_name:50}
952 myfig=bppu.plot_two_param_kde(pos,plot2DkdeParams)
953
954 figname=par1_name+'-'+par2_name+'_2Dkernel.png'
955 twoDKdePath=os.path.join(margdir,figname)
956
957 if row_count==0:
958 html_tcmp_write+='<tr>'
959 html_tcmp_write+='<td width="30%"><img width="100%" src="2Dkde/'+figname+'"/></td>'
960 row_count+=1
961 if row_count==3:
962 html_tcmp_write+='</tr>'
963 row_count=0
964
965 if myfig:
966 myfig.savefig(twoDKdePath)
967 if(savepdfs): myfig.savefig(twoDKdePath.replace('.png','.pdf'))
968 plt.close(myfig)
969 else:
970 print('Unable to generate 2D kde levels for %s-%s'%(par1_name,par2_name))
971
972
973 #Finish off the BCI table and write it into the etree
974 html_tcig_write+='</table>'
975 html_tcig.write(html_tcig_write)
976
977 if twodkdeplots_flag is True:
978 #Finish off the 2D kde plot table
979 while row_count!=0:
980 html_tcmp_write+='<td/>'
981 row_count+=1
982 if row_count==3:
983 row_count=0
984 html_tcmp_write+='</tr>'
985 html_tcmp_write+='</table>'
986 html_tcmp.write(html_tcmp_write)
987 #Add a link to all plots
988 html_tcmp.a("2Dkde/",'All 2D marginal PDFs (kde)')
989
990 #Finish off the 2D greedy histogram plot table
991 while row_count_gb!=0:
992 html_tgbh_write+='<td/>'
993 row_count_gb+=1
994 if row_count_gb==3:
995 row_count_gb=0
996 html_tgbh_write+='</tr>'
997 html_tgbh_write+='</table>'
998 html_tgbh.write(html_tgbh_write)
999 #Add a link to all plots
1000 html_tgbh.a("greedy2Dbins/",'All 2D Greedy Bin Histograms')
1001
1002 if RconvergenceTests is True:
1003 convergenceResults=bppu.convergenceTests(pos,gelman=False)
1004
1005 if convergenceResults is not None:
1006 tabid='convtable'
1007 html_conv_test=html.add_collapse_section('Convergence tests',legend=legend,innertable_id=tabid)
1008 data_found=False
1009 for test,test_data in convergenceResults.items():
1010
1011 if test_data:
1012 data_found=True
1013 html_conv_test.h3(test)
1014
1015 html_conv_table_rows={}
1016 html_conv_table_header=''
1017 for chain,chain_data in test_data.items():
1018 html_conv_table_header+='<th>%s</th>'%chain
1019
1020
1021 for data in chain_data:
1022 if len(data)==2:
1023 try:
1024 html_conv_table_rows[data[0]]+='<td>'+data[1]+'</td>'
1025 except KeyError:
1026 html_conv_table_rows[data[0]]='<td>'+data[1]+'</td>'
1027
1028 html_conv_table='<table id="%s"><tr><th>Chain</th>'%tabid+html_conv_table_header+'</tr>'
1029 for row_name,row in html_conv_table_rows.items():
1030 html_conv_table+='<tr><td>%s</td>%s</tr>'%(row_name,row)
1031 html_conv_table+='</table>'
1032 html_conv_test.write(html_conv_table)
1033 if data_found is False:
1034 html_conv_test.p('No convergence diagnostics generated!')
1035
1036 #Create a section for the covariance matrix
1037 tabid='covtable'
1038 html_stats_cov=html.add_collapse_section('Covariance matrix',legend=legend,innertable_id=tabid)
1039 pos_samples,table_header_string=pos.samples()
1040
1041 #calculate cov matrix
1042 try:
1043 cov_matrix=cov(pos_samples,rowvar=0,bias=1)
1044
1045 #Create html table
1046 table_header_list=table_header_string.split()
1047 cov_table_string='<table border="1" id="%s"><tr><th/>'%tabid
1048 for header in table_header_list:
1049 cov_table_string+='<th>%s</th>'%header
1050 cov_table_string+='</tr>'
1051
1052 cov_column_list=hsplit(cov_matrix,cov_matrix.shape[1])
1053
1054 for cov_column,cov_column_name in zip(cov_column_list,table_header_list):
1055 cov_table_string+='<tr><th>%s</th>'%cov_column_name
1056 for cov_column_element in cov_column:
1057 cov_table_string+='<td>%.3e</td>'%(cov_column_element[0])
1058 cov_table_string+='</tr>'
1059 cov_table_string+='</table>'
1060 html_stats_cov.write(cov_table_string)
1061
1062 except:
1063 print('Unable to compute the covariance matrix.')
1064
1065
1066 html_footer=html.add_section('')
1067 html_footer.p('Produced using cbcBayesPostProc.py at '+strftime("%Y-%m-%d %H:%M:%S")+' .')
1068
1069 cc_args=''
1070 for arg in sys.argv:
1071 cc_args+=arg+' '
1072
1073 html_footer.p('Command line: %s'%cc_args)
1074 html_footer.p(git_version.verbose_msg)
1075
1076 #Save results page
1077 resultspage=open(os.path.join(outdir,'posplots.html'),'w')
1078 resultspage.write(str(html))
1079
1080
1081 #Close files
1082 resultspage.close()
1083
1084USAGE='''%prog [options] datafile.dat [datafile2.dat ...]
1085Generate a web page displaying results of parameter estimation based on the contents
1086of one or more datafiles containing samples from one of the bayesian algorithms (MCMC, nested sampling).
1087Options specify which extra statistics to compute and allow specification of additional information.
1088'''
1089
1090if __name__=='__main__':
1091
1092 from optparse import OptionParser
1093 parser=OptionParser(USAGE)
1094 parser.add_option("-o","--outpath", dest="outpath",help="make page and plots in DIR", metavar="DIR")
1095 parser.add_option("-d","--data",dest="data",action="callback",callback=multipleFileCB,help="datafile")
1096 #Optional (all)
1097 parser.add_option("-i","--inj",dest="injfile",help="SimInsipral injection file",metavar="INJ.XML",default=None)
1098 parser.add_option("-t","--trig",dest="trigfile",help="Coinc XML file",metavar="COINC.XML",default=None)
1099 parser.add_option("--skyres",dest="skyres",help="Sky resolution to use to calculate sky box size",default=None)
1100 parser.add_option("--eventnum",dest="eventnum",action="store",default=None,help="event number in SimInspiral file of this signal",type="int",metavar="NUM")
1101 parser.add_option("--trignum",dest="trignum",action="store",default=None,help="trigger number in CoincTable",type="int",metavar="NUM")
1102 parser.add_option("--bsn",action="store",default=None,help="Optional file containing the bayes factor signal against noise",type="string")
1103 parser.add_option("--bci",action="store",default=None,help="Optional file containing the bayes factor coherent signal model against incoherent signal model.",type="string")
1104 parser.add_option("--snr",action="store",default=None,help="Optional file containing the SNRs of the signal in each IFO",type="string")
1105 parser.add_option("--dievidence",action="store_true",default=False,help="Calculate the direct integration evidence for the posterior samples")
1106 parser.add_option("--boxing",action="store",default=64,help="Boxing parameter for the direct integration evidence calculation",type="int",dest="boxing")
1107 parser.add_option("--evidenceFactor",action="store",default=1.0,help="Overall factor (normalization) to apply to evidence",type="float",dest="difactor",metavar="FACTOR")
1108
1109 parser.add_option('--ellipticEvidence', action='store_true', default=False,help='Estimate the evidence by fitting ellipse to highest-posterior points.', dest='ellevidence')
1110
1111 parser.add_option("--plot-2d", action="store_true", default=False,help="Make individual 2-D plots.")
1112 parser.add_option("--header",action="store",default=None,help="Optional file containing the header line for posterior samples",type="string")
1113 #NS
1114 parser.add_option("--ns",action="store_true",default=False,help="(inspnest) Parse input as if it was output from parallel nested sampling runs.")
1115 parser.add_option("--Nlive",action="store",default=None,help="(inspnest) Number of live points used in each parallel nested sampling run.",type="int")
1116 parser.add_option("--xflag",action="store_true",default=False,help="(inspnest) Convert x to iota.")
1117 #SS
1118 parser.add_option("--ss",action="store_true",default=False,help="(SPINspiral) Parse input as if it was output from SPINspiral.")
1119 parser.add_option("--spin",action="store_true",default=False,help="(SPINspiral) Specify spin run (15 parameters). ")
1120 #LALInf
1121 parser.add_option("--lalinfmcmc",action="store_true",default=False,help="(LALInferenceMCMC) Parse input from LALInferenceMCMC.")
1122 parser.add_option("--inj-spin-frame",default='OrbitalL', help="The reference frame used for the injection (default: OrbitalL)")
1123 parser.add_option("--downsample",action="store",default=None,help="(LALInferenceMCMC) approximate number of samples to record in the posterior",type="int")
1124 parser.add_option("--deltaLogL",action="store",default=None,help="(LALInferenceMCMC) Difference in logL to use for convergence test. (DEPRECATED)",type="float")
1125 parser.add_option("--deltaLogP",action="store",default=None,help="(LALInferenceMCMC) Difference in logpost to use for burnin criteria.",type="float")
1126 parser.add_option("--fixedBurnin",dest="fixedBurnin",action="callback",callback=multipleFileCB,help="(LALInferenceMCMC) Fixed number of iteration for burnin.")
1127 parser.add_option("--oldMassConvention",action="store_true",default=False,help="(LALInferenceMCMC) if activated, m2 > m1; otherwise m1 > m2 in PTMCMC.output.*.00")
1128 #FM
1129 parser.add_option("--fm",action="store_true",default=False,help="(followupMCMC) Parse input as if it was output from followupMCMC.")
1130 # ACF plots off?
1131 parser.add_option("--no-acf", action="store_true", default=False, dest="noacf")
1132 # Turn on 2D kdes
1133 parser.add_option("--twodkdeplots", action="store_true", default=False, dest="twodkdeplots")
1134 # Turn on R convergence tests
1135 parser.add_option("--RconvergenceTests", action="store_true", default=False, dest="RconvergenceTests")
1136 parser.add_option("--nopdfs",action="store_false",default=True,dest="nopdfs")
1137 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.")
1138 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.")
1139 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.")
1140 parser.add_option("--archive",action="store",default=None,type="string",metavar="results.tar.gz",help="Create the given tarball with all results")
1141 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")
1142 parser.add_option("--kdecredibleregions",action="store_true",default=False,help="If given, will use 2-step KDE trees to estimate 1-d credible regions [default false: use greedy binning]")
1143 parser.add_option("--noplot-source-frame", action="store_true", default=False,help="Don't make 1D plots of source-frame masses")
1144 (opts,args)=parser.parse_args()
1145
1146 datafiles=[]
1147 if args:
1148 datafiles=datafiles+args
1149 if opts.data:
1150 datafiles=datafiles + opts.data
1151
1152 if opts.fixedBurnin:
1153 # If only one value for multiple chains, assume it's to be applied to all chains
1154 if len(opts.fixedBurnin) == 1:
1155 fixedBurnins = [int(opts.fixedBurnin[0]) for df in datafiles]
1156 else:
1157 fixedBurnins = [int(fixedBurnin) for fixedBurnin in opts.fixedBurnin]
1158 else:
1159 fixedBurnins = None
1160 from lalinference.bayespputils import massParams,spinParams,cosmoParam,strongFieldParams,distParams,incParams,polParams,skyParams,phaseParams,timeParams,endTimeParams,statsParams,calibParams,snrParams,tidalParams,fourPiecePolyParams,spectralParams
1161
1162
1163 oneDMenus={'Masses':None,'SourceFrame':None,'Timing':None,'Extrinsic':None,'Spins':None,'StrongField':None,'Others':None}
1164
1165 oneDMenus['Masses']= massParams
1166 oneDMenus['Extrinsic']=incParams+distParams+polParams+skyParams+phaseParams
1167 oneDMenus['Spins']= spinParams
1168 oneDMenus['Timing']=timeParams+endTimeParams
1169 oneDMenus['StrongField']= strongFieldParams
1170 oneDMenus['Others']=snrParams+statsParams+calibParams
1171 oneDMenus['SourceFrame']= cosmoParam
1172
1173 if opts.noplot_source_frame:
1174 oneDMenus['SourceFrame']= []
1175
1176 ifos_menu=['h1','l1','v1']
1177 from itertools import combinations
1178 for ifo1,ifo2 in combinations(ifos_menu,2):
1179 oneDMenus['Timing'].append(ifo1+ifo2+'_delay')
1180 #oneDMenu=[]
1181 twoDGreedyMenu=[]
1182 if opts.plot_2d:
1183 for mp1,mp2 in combinations(massParams,2):
1184 twoDGreedyMenu.append([mp1, mp2])
1185 for mp in massParams:
1186 for d in distParams:
1187 twoDGreedyMenu.append([mp,d])
1188 for mp in massParams:
1189 for sp in spinParams:
1190 twoDGreedyMenu.append([mp,sp])
1191 for mp in massParams:
1192 for dchi in bppu.tigerParams:
1193 twoDGreedyMenu.append([mp,dchi])
1194 for mp in massParams:
1195 for lvp in bppu.lorentzInvarianceViolationParams:
1196 twoDGreedyMenu.append([mp,lvp])
1197 for sp in spinParams:
1198 for lvp in bppu.lorentzInvarianceViolationParams:
1199 twoDGreedyMenu.append([sp,lvp])
1200 for dchi in bppu.tigerParams:
1201 for lvp in bppu.lorentzInvarianceViolationParams:
1202 twoDGreedyMenu.append([dchi, lvp])
1203 for eg in bppu.energyParams:
1204 for lvp in bppu.lorentzInvarianceViolationParams:
1205 twoDGreedyMenu.append([eg, lvp])
1206 for dp in distParams:
1207 for lvp in bppu.lorentzInvarianceViolationParams:
1208 twoDGreedyMenu.append([dp, lvp])
1209 for dp in distParams:
1210 for sp in snrParams:
1211 twoDGreedyMenu.append([dp,sp])
1212 for dp in distParams:
1213 for ip in incParams:
1214 twoDGreedyMenu.append([dp,ip])
1215 for dp in distParams:
1216 for sp in skyParams:
1217 twoDGreedyMenu.append([dp,sp])
1218 for dp in distParams:
1219 for sp in spinParams:
1220 twoDGreedyMenu.append([dp,sp])
1221 for ip in incParams:
1222 for sp in skyParams:
1223 twoDGreedyMenu.append([ip,sp])
1224 for ip in incParams:
1225 for sp in spinParams:
1226 twoDGreedyMenu.append([ip,sp])
1227 for phip in phaseParams:
1228 twoDGreedyMenu.append([ip,phip])
1229 for psip in polParams:
1230 twoDGreedyMenu.append([ip,psip])
1231 for sp1 in skyParams:
1232 for sp2 in skyParams:
1233 if not (sp1 == sp2):
1234 twoDGreedyMenu.append([sp1, sp2])
1235 for sp1,sp2 in combinations(spinParams,2):
1236 twoDGreedyMenu.append([sp1, sp2])
1237 for dc1,dc2 in combinations(bppu.tigerParams,2):
1238 twoDGreedyMenu.append([dc1,dc2])
1239 for mp in massParams:
1240 for tp in tidalParams:
1241 if not (mp == tp):
1242 twoDGreedyMenu.append([mp, tp])
1243 for tp in fourPiecePolyParams:
1244 if not (mp == tp):
1245 twoDGreedyMenu.append([mp, tp])
1246 for tp in spectralParams:
1247 if not (mp == tp):
1248 twoDGreedyMenu.append([mp, tp])
1249 for sp1,sp2 in combinations(snrParams,2):
1250 twoDGreedyMenu.append([sp1,sp2])
1251 twoDGreedyMenu.append(['lambda1','lambda2'])
1252 twoDGreedyMenu.append(['lam_tilde','dlam_tilde'])
1253 twoDGreedyMenu.append(['lambdat','dlambdat'])
1254 twoDGreedyMenu.append(['logp1','gamma1','gamma2','gamma3'])
1255 twoDGreedyMenu.append(['SDgamma0','SDgamma1','SDgamma2','SDgamma3'])
1256 for psip in polParams:
1257 for phip in phaseParams:
1258 twoDGreedyMenu.append([psip,phip])
1259 for sp in skyParams:
1260 twoDGreedyMenu.append([psip,sp])
1261 for sp in spinParams:
1262 twoDGreedyMenu.append([psip,sp])
1263
1264 for i in calibParams[3:]:
1265 twoDGreedyMenu.append([i,'distance'])
1266
1267 #twoDGreedyMenu=[['mc','eta'],['mchirp','eta'],['m1','m2'],['mtotal','eta'],['distance','iota'],['dist','iota'],['dist','m1'],['ra','dec']]
1268 #Bin size/resolution for binning. Need to match (converted) column names.
1269 greedyBinSizes=bppu.greedyBinSizes
1270
1271
1272 if opts.plot_2d:
1273 for dt1,dt2 in combinations(['h1_end_time','l1_end_time','v1_end_time'],2):
1274 twoDGreedyMenu.append([dt1,dt2])
1275 for dt1,dt2 in combinations( ['h1l1_delay','l1v1_delay','h1v1_delay'],2):
1276 twoDGreedyMenu.append([dt1,dt2])
1277
1278 if opts.deltaLogL and not opts.deltaLogP:
1279 print("DEPRECATION WARNING: --deltaLogL has been replaced by --deltaLogP. Using the posterior to define burnin criteria")
1280 deltaLogP = opts.deltaLogL
1281 else:
1282 deltaLogP = opts.deltaLogP
1283
1284 confidenceLevels=bppu.confidenceLevels
1285 #2D plots list
1286 #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']]
1287 twoDplots=twoDGreedyMenu
1289 opts.outpath,datafiles,oneDMenus,twoDGreedyMenu,
1290 greedyBinSizes,confidenceLevels,twoDplots,
1291 #optional
1292 injfile=opts.injfile,eventnum=opts.eventnum,
1293 trigfile=opts.trigfile,trignum=opts.trignum,
1294 skyres=opts.skyres,
1295 # direct integration evidence
1296 dievidence=opts.dievidence,boxing=opts.boxing,difactor=opts.difactor,
1297 # Ellipitical evidence
1298 ellevidence=opts.ellevidence,
1299 #manual bayes factor entry
1300 bayesfactornoise=opts.bsn,bayesfactorcoherent=opts.bci,
1301 #manual input for SNR in the IFOs, optional.
1302 snrfactor=opts.snr,
1303 #nested sampling options
1304 ns_flag=opts.ns,ns_Nlive=opts.Nlive,
1305 #spinspiral/mcmc options
1306 ss_flag=opts.ss,ss_spin_flag=opts.spin,
1307 #LALInferenceMCMC options
1308 li_flag=opts.lalinfmcmc,deltaLogP=deltaLogP,fixedBurnins=fixedBurnins,nDownsample=opts.downsample,oldMassConvention=opts.oldMassConvention,
1309 #followupMCMC options
1310 fm_flag=opts.fm,
1311 #injected spin frame
1312 inj_spin_frame=opts.inj_spin_frame,
1313 # Turn of ACF?
1314 noacf=opts.noacf,
1315 #Turn on 2D kdes
1316 twodkdeplots=opts.twodkdeplots,
1317 #Turn on R convergence tests
1318 RconvergenceTests=opts.RconvergenceTests,
1319 # Also save PDFs?
1320 savepdfs=opts.nopdfs,
1321 #List of covariance matrix csv files used as analytic likelihood
1322 covarianceMatrices=opts.covarianceMatrices,
1323 #List of meanVector csv files used, one csv file for each covariance matrix
1324 meanVectors=opts.meanVectors,
1325 #header file for parameter names in posterior samples
1326 header=opts.header,
1327 # ascii files (one per IFO) containing freq - PSD columns
1328 psd_files=opts.psdfiles,
1329 greedy=not(opts.kdecredibleregions)
1330 )
1331
1332 if opts.archive is not None:
1333 import subprocess
1334 subprocess.call(["tar","cvzf",opts.archive,opts.outpath])
1335
1336 # Send an email, useful for keeping track of dozens of jobs!
1337 # Will only work if the local host runs a mail daemon
1338 # that can send mail to the internet
1339 if opts.email:
1340 try:
1341 email_notify(opts.email,opts.outpath)
1342 except Exception as e:
1343 print('Unable to send notification email')
1344 print("The error was %s\n"%str(e))
1345#
def oneD_dict_to_file(dict, fname)
def cbcBayesPostProc(outdir, data, oneDMenus, 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, deltaLogP=None, fixedBurnins=None, nDownsample=None, oldMassConvention=False, fm_flag=False, inj_spin_frame='OrbitalL', noacf=False, twodkdeplots=False, RconvergenceTests=False, savepdfs=True, covarianceMatrices=None, meanVectors=None, header=None, psd_files=None, greedy=True ## If true will use greedy bin for 1-d credible regions. Otherwise use 2-steps KDE)
This is a demonstration script for using the functionality/data structures contained in lalinference....
def pickle_to_file(obj, fname)
Pickle/serialize 'obj' into 'fname'.
multipleFileCB
def email_notify(address, path)
def dict2html(d, parent=None)
def extract_hdf5_metadata(h5grp, parent=None)
def guess_url(fslocation)
Try to work out the web address of a given path.