Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInference 4.1.9.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cbcBayesPosToSimInspiral.py
Go to the documentation of this file.
1##python
2# -*- coding: utf-8 -*-
3#
4# cbcBayesPosToSimInspiral.py
5#
6# Copyright 2013
7# Benjamin Farr <bfarr@u.northwestern.edu>,
8# Will M. Farr <will.farr@ligo.org>,
9# John Veitch <john.veitch@ligo.org>
10#
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25# MA 02110-1301, USA.
26"""
27Populate a sim_inspiral table with random draws from an ASCII table.
28"""
29from optparse import Option, OptionParser
30import numpy as np
31from igwn_ligolw import ligolw
32from igwn_ligolw import lsctables
33import igwn_ligolw.utils.process
34import matplotlib
35matplotlib.use("Agg") # Needed to run on the CIT cluster
36from lalinference import bayespputils as bppu
37
38# Create a datatype for all relavent fields to be filled in the sim_inspiral table
39sim_inspiral_dt = [
40 ('waveform','|S64'),
41 ('taper','|S64'),
42 ('f_lower', 'f8'),
43 ('mchirp', 'f8'),
44 ('eta', 'f8'),
45 ('mass1', 'f8'),
46 ('mass2', 'f8'),
47 ('geocent_end_time', 'f8'),
48 ('geocent_end_time_ns', 'f8'),
49 ('distance', 'f8'),
50 ('longitude', 'f8'),
51 ('latitude', 'f8'),
52 ('inclination', 'f8'),
53 ('coa_phase', 'f8'),
54 ('polarization', 'f8'),
55 ('spin1x', 'f8'),
56 ('spin1y', 'f8'),
57 ('spin1z', 'f8'),
58 ('spin2x', 'f8'),
59 ('spin2y', 'f8'),
60 ('spin2z', 'f8'),
61 ('amp_order', 'i4'),
62 ('numrel_data','|S64')
63]
64
65def get_input_filename(parser, args):
66 """Determine name of input: either the sole positional command line argument,
67 or /dev/stdin."""
68 if len(args) == 0:
69 infilename = '/dev/stdin'
70 elif len(args) == 1:
71 infilename = args[0]
72 else:
73 parser.error("Too many command line arguments.")
74 return infilename
75
76def standardize_param_name(params, possible_names, desired_name):
77 for name in possible_names:
78 if name in params: params[params.index(name)] = desired_name
79
81 standardize_param_name(params, ['m1'], 'm1')
82 standardize_param_name(params, ['m2'], 'm2')
83 standardize_param_name(params, ['mc', 'chirpmass'], 'mchirp')
84 standardize_param_name(params, ['massratio'], 'eta')
85 standardize_param_name(params, ['d', 'dist'], 'distance')
86 standardize_param_name(params, ['ra'], 'longitude')
87 standardize_param_name(params, ['dec'], 'latitude')
88 standardize_param_name(params, ['iota'], 'inclination')
89 standardize_param_name(params, ['phi', 'phase', 'phi0'], 'phi_orb')
90 standardize_param_name(params, ['psi', 'polarisation'], 'polarization')
91
92
94 params = samples.dtype.names
95 has_mc = 'mchirp' in params
96 has_eta = 'eta' in params
97 has_q = 'q' in params
98 has_ms = 'mass1' in params and 'mass2' in params
99 has_mtotal = 'mtotal' in params
100
101 if has_mc:
102 mc = samples['mchirp']
103 if not has_eta:
104 if has_q:
105 eta = bppu.q2eta(samples['q'])
106 else:
107 raise ValueError("Chirp mass given with no mass ratio.")
108 else:
109 eta = samples['eta']
110
111 if not has_ms:
112 m1, m2 = bppu.mc2ms(mc, eta)
113
114 mtotal = m1 + m2
115
116 elif has_ms:
117 m1 = samples['mass1']
118 m2 = samples['mass2']
119 mtotal = m1 + m2
120 eta = m1 * m2 / (mtotal * mtotal)
121 mc = mtotal * np.power(eta, 3./5.)
122
123 elif has_mtotal:
124 mtotal = samples['mtotal']
125 if has_eta:
126 eta = samples['eta']
127 mc = mtotal * np.power(eta, 3./5.)
128 m1, m2 = bppu.mc2ms(mc, eta)
129 elif has_q:
130 m1 = mtotal / (1 + samples['q'])
131 m2 = mtotal - m1
132 else:
133 raise ValueError("Chirp mass given with no mass ratio.")
134 return mc, eta, m1, m2, mtotal
135
136
137if __name__ == "__main__":
138 parser = OptionParser(
139 description = __doc__,
140 usage = "%prog [options] [INPUT]",
141 option_list = [
142 Option("-o", "--output", metavar="FILE.xml",
143 help="name of output XML file"),
144 Option("--num-of-injs", metavar="NUM", type=int, default=200,
145 help="number of injections"),
146 Option("--approx", metavar="APPROX", default="SpinTaylorT4threePointFivePN",
147 help="approximant to be injected"),
148 Option("--taper", metavar="TAPER", default="TAPER_NONE",
149 help="Taper methods for injections"),
150 Option("--flow", metavar="FLOW", type=float, default=None,
151 help="Taper methods for injections"),
152 Option("--amporder", metavar="AMPORDER", type=int, default=0,
153 help="pN order in amplitude for injection")
154 ]
155 )
156
157 opts, args = parser.parse_args()
158 infilename = get_input_filename(parser, args)
159
160 # Read in ASCII table, assuming column names are the first line
161 with open(infilename, 'r') as inp:
162 params = inp.readline().split()
164 samples = np.loadtxt(inp, dtype=[(p, np.float) for p in params])
165
166 N = opts.num_of_injs
167 if len(samples) < N:
168 raise ValueError("{} injections requested, but {} samples were provided.".format(N, len(samples)))
169
170 # Choose subset for sim_inspiral_table
171 selection = np.arange(len(samples))
172 np.random.shuffle(selection)
173 samples = samples[selection[:N]]
174
175 # Create an empty structured array with names indentical to sim_inspiral fields
176 injections = np.zeros((N,), dtype=sim_inspiral_dt)
177
178 # Determine all mass parameterizations
179 mc, eta, m1, m2, mtotal = compute_mass_parameterizations(samples)
180
181 # Get cycle numbers as simulation_ids
182 ids = range(N)
183
184 # Compute cartesian spins
185 if 'a1' in params and 'theta1' in params and 'phi1' in params:
186 s1x, s1y, s1z = bppu.sph2cart(samples['a1'], samples['theta1'], samples['phi1'])
187 elif 'a1z' in params:
188 s1z = samples['a1z']
189 s1x = np.zeros_like(s1z)
190 s1y = np.zeros_like(s1z)
191 else:
192 s1x = np.zeros_like(m1)
193 s1y = np.zeros_like(m1)
194 s1z = np.zeros_like(m1)
195
196
197 if 'a2' in params and 'theta2' in params and 'phi2' in params:
198 s2x, s2y, s2z = bppu.sph2cart(samples['a2'], samples['theta2'], samples['phi2'])
199 elif 'a2z' in params:
200 s2z = samples['a2z']
201 s2x = np.zeros_like(s2z)
202 s2y = np.zeros_like(s2z)
203 else:
204 s2x = np.zeros_like(m2)
205 s2y = np.zeros_like(m2)
206 s2z = np.zeros_like(m2)
207
208 system_frame_params = set([ \
209 'costheta_jn', \
210 'phi_jl', \
211 'tilt1', 'tilt2', \
212 'phi12', \
213 'a1','a2', \
214 'f_ref' \
215 ])
216 theta_jn=np.array([np.arccos(i) for i in samples['costheta_jn']])
217 if set(params).intersection(system_frame_params) == system_frame_params:
218 inclination, theta1, phi1, theta2, phi2, _ = bppu.physical2radiationFrame(
219 theta_jn,
220 samples['phi_jl'],
221 samples['tilt1'],
222 samples['tilt2'],
223 samples['phi12'],
224 samples['a1'],
225 samples['a2'],
226 m1, m2,
227 samples['f_ref'],
228 samples['phi_orb'])
229 inclination = inclination.flatten()
230 theta1 = theta1.flatten()
231 phi1 = phi1.flatten()
232 theta2 = theta2.flatten()
233 phi2 = phi2.flatten()
234 s1x, s1y, s1z = bppu.sph2cart(samples['a1'], theta1, phi1)
235 s2x, s2y, s2z = bppu.sph2cart(samples['a2'], theta2, phi2)
236 else:
237 inclination = theta_jn
238
239 print(s1x.shape)
240 # Check if f_low is given on the command line. If not, try to take if from 'samples'.
241 if opts.flow is None:
242 try:
243 flow = samples['flow']
244 except:
245 raise ValueError("No f_low found in input file or command line arguments.")
246 else:
247 try:
248 samples['flow']
249 except:
250 pass
251 else: # executed if no exception is raised
252 print(('f_low given in both input file and command line.'
253 ' Using command line argument: %r' % opts.flow))
254 flow = [opts.flow for i in range(N)]
255
256 # Populate structured array
257 injections['waveform'] = [opts.approx for i in range(N)]
258 injections['taper'] = [opts.taper for i in range(N)]
259 injections['f_lower'] = flow
260 injections['mchirp'] = mc
261 injections['eta'] = eta
262 injections['mass1'] = m1
263 injections['mass2'] = m2
264 injections['geocent_end_time'] = np.modf(samples['time'])[1]
265 injections['geocent_end_time_ns'] = np.modf(samples['time'])[0] * 10**9
266 injections['distance'] = samples['distance']
267 injections['longitude'] = samples['longitude']
268 injections['latitude'] = samples['latitude']
269 injections['inclination'] = inclination
270 injections['coa_phase'] = samples['phi_orb']
271 injections['polarization'] = samples['polarization']
272 injections['spin1x'] = s1x
273 injections['spin1y'] = s1y
274 injections['spin1z'] = s1z
275 injections['spin2x'] = s2x
276 injections['spin2y'] = s2y
277 injections['spin2z'] = s2z
278 injections['amp_order'] = [opts.amporder for i in range(N)]
279 injections['numrel_data'] = [ "" for _ in range(N)]
280
281 # Create a new XML document
282 xmldoc = ligolw.Document()
283 xmldoc.appendChild(ligolw.LIGO_LW())
284 proc = igwn_ligolw.utils.process.register_to_xmldoc(doc, sys.argv[0], {})
285 sim_table = lsctables.New(lsctables.SimInspiralTable)
286 xmldoc.childNodes[0].appendChild(sim_table)
287
288 # Add empty rows to the sim_inspiral table
289 for inj in range(N):
290 row = sim_table.RowType()
291 for slot in row.__slots__: setattr(row, slot, 0)
292 sim_table.append(row)
293
294 # Fill in IDs
295 for i,row in enumerate(sim_table):
296 row.process_id = proc.process_id
297 row.simulation_id = sim_table.get_next_id()
298
299 # Fill rows
300 for field in injections.dtype.names:
301 vals = injections[field]
302 for row, val in zip(sim_table, vals): setattr(row, field, val)
303
304 # Write file
305 output_file = open(opts.output, 'w')
306 xmldoc.write(output_file)
307 output_file.close()
def get_input_filename(parser, args)
Determine name of input: either the sole positional command line argument, or /dev/stdin.
def standardize_param_name(params, possible_names, desired_name)