LALInference  4.1.6.1-89842e6
lalinference_coherence_test.py
Go to the documentation of this file.
1 '''
2 This program simply computes the bayes factor between the coherent and incoherent models
3 given as input the B files for the run.
4 '''
5 
6 from __future__ import print_function
7 
8 from optparse import OptionParser
9 import sys
10 import os
11 import matplotlib
12 matplotlib.use("Agg")
13 from pylab import loadtxt
14 from math import log,exp
15 
16 usage='''%prog [options] coherent_B.txt incoherent1_B.txt incoherent2_B.txt ... incoherentN_B.txt
17 %prog takes a list of arguments which specify FIRST the coherent B.txt file, followed by all the
18 B.txt files from the individual runs on each IFO. The coherent file must be specified first.
19 
20 The code will then perform either the test of coherent vs incoherent signal models, i.e.
21 B_{CI} = Z_co / Z_1 * Z_2 * Z_3
22 
23 or a test of coherent vs incoherent
24 B_{CIN} = Z_co / (Z_1 * Z_2 * Z_3 + N_{123})
25 
26 or the test of coherent vs ( incoherent signal or noise ) models, i.e.
27 B_{CIN} = Z_co / Z_{inc OR noise}
28 with Z_{inc OR noise} = sum over all permutations of the signal and noise hypotheses in each detector
29 e.g. for 2 detectors:
30 Z_{inc OR noise} =
31 see also https://dcc.ligo.org/LIGO-T1600068
32 
33 Output will be written to stdout, and to a text file specified by the --outfile option.
34 
35 '''
36 
37 parser=OptionParser(usage)
38 parser.add_option("-c","--coherent-incoherent",action="store_true",dest="ci",help="Perform coherence test of Coherent signal vs incoherent signal",default=False )
39 parser.add_option("-n","--coherent-incoherent-noise", dest="cin", action="store_true", help="Perform coherence test of coherent signal vs incoherent signal or noise", default=False )
40 parser.add_option("-b","--new-coherent-incoherent-noise", dest="cin_or_n", action="store_true", help="Perform coherence test of coherent signal vs incoherent signal or noise using the most inclusive hypothesis", default=False )
41 parser.add_option("-o","--outfile",default=None, help="Optional output file name", metavar="OUTFILE.txt",type="string",action="store")
42 
43 (opts,args)=parser.parse_args()
44 
45 def get_metadata_hdf5(filename,key):
46  import h5py
47  with h5py.File(filename,'r') as hdf:
48  g=hdf['lalinference']
49  if(len(g.keys()))>1:
50  print('Error: multiple runs %s found in input file %s'%g.keys(),filename)
51  sys.exit(1)
52  # Descend into run group
53  g=g[list(g.keys())[0]]
54  return g.attrs[key]
55 
56 # Sanity check input arguments
57 if len(args)==0:
58  print('No input files specified')
59  sys.exit(1)
60 
61 if( sum([opts.ci,opts.cin,opts.cin_or_n])!=1):
62  print('Please specify one of -c, -n or -b. See help for details.')
63  sys.exit(1)
64 
65 cofile=args[0]
66 incofiles=args[1:]
67 
68 if len(incofiles)<2:
69  print('Cannot perform coherence test on less than 2 IFOs')
70  sys.exit(0)
71 
72 if len(incofiles)==0:
73  print('Error: You must specify incoherent input files')
74  sys.exit(1)
75 
76 def logadd(a,b):
77  if(a>b): (a,b)=(b,a)
78  return (b+log(1+exp(a-b)))
79 
80 def get_metadata_old(Bfile,key):
81  print('Looking for '+Bfile)
82  if os.access(Bfile,os.R_OK):
83  outstat = loadtxt(Bfile)
84  if key=='log_evidence':
85  return outstat[1]
86  if key=='log_noise_evidence':
87  return outstat[2]
88  if key=='log_bayes_factor':
89  return outstat[0]
90  print('Unknown key %s'%(key))
91  return None
92  else:
93  return None
94 
95 def get_metadata(filename,key):
96  if '.h5' in filename or '.hdf' in filename:
97  return get_metadata_hdf5(filename,key)
98  else:
99  return get_metadata_old(filename,key)
100 
101 Zco = get_metadata(cofile,'log_evidence')
102 Zinco=0
103 Z_single_noise = [ get_metadata(inco,'log_noise_evidence') for inco in incofiles]
104 Z_single_signal = [ get_metadata(inco,'log_evidence') for inco in incofiles]
105 
106 # we compute now the evidence for the hypothesis "incoherent signal OR noise" as the
107 # sum over all posible permutations over mutually exclusive sub propositions
108 
109 from itertools import combinations
110 try:
111  from scipy.special import logsumexp
112 except ImportError: # scipy < 0.19.0
113  from scipy.misc import logsumexp
114 
115 def not_seen(t, seen=set()):
116  return False if t[0] in seen or t[1] in seen else seen.update(t) or True
117 
118 Z_incoherentORnoise = logsumexp([sum(p) for p in list(filter(lambda t, seen=set(): False if t[0] in seen or t[1] in seen else seen.update(t) or True, combinations(Z_single_signal+Z_single_noise, len(Z_single_signal))))])
119 
120 for inco in incofiles:
121  Zinco+=get_metadata(inco,'log_evidence')
122 Znoise = get_metadata(cofile,'log_noise_evidence')
123 
124 if(opts.outfile is not None):
125  out=open(opts.outfile,'w')
126 
127 if(opts.ci):
128  B=Zco-Zinco
129 if (opts.cin):
130  B=Zco-logadd(Zinco,Znoise)
131 if(opts.cin_or_n):
132  B=Zco-Z_incoherentORnoise
133 
134 print('%.3f'%(B))
135 
136 if(opts.outfile is not None ):
137  print('%.3f'%(B), file=out)
138  out.close()