4from optparse
import OptionParser
6from scipy.linalg
import solve_triangular
12def _block_slices(dim_size, block_size):
13 """Generator that yields slice objects for indexing into
14 sequential blocks of an array along a particular axis
18 yield slice(count, count + block_size, 1)
23def blockwise_dot(A, B, deltaF, max_elements=int(2**27), out=
None):
25 Computes the dot product of two matrices in a block-wise fashion.
26 Only blocks of `A`
with a maximum size of `max_elements` will be
27 processed simultaneously.
34 raise ValueError(
'matrices are not aligned')
36 if A.flags.f_contiguous:
38 max_cols =
max(1, max_elements // m)
39 max_rows = max_elements // max_cols
43 max_rows =
max(1, max_elements // n)
44 max_cols = max_elements // max_rows
47 out = np.empty((m, o), dtype=np.result_type(A, B))
48 elif out.shape != (m, o):
49 raise ValueError(
'output array has incorrect dimensions')
51 for mm
in _block_slices(m, max_rows):
53 for nn
in _block_slices(n, max_cols):
54 A_block = A[mm, nn].copy()
55 out[mm, :] += np.dot(A_block, B[nn, :]) * 4 * deltaF
61 """Return a unit vector whose j-th component is 1"""
62 ehat = np.zeros(length)
67 """Calculate interpolation nodes following the Algorithm 5 in J Sci Comput
73 ndarray whose i-th row is the i-th basis vector
80 ndarray whose i-th row
is the weight
for the i-th frequency node.
82 vec_num, vec_len = basis.shape
84 j = abs(basis[0]).argmax()
86 UT = np.zeros(shape=(vec_num, vec_len), dtype=complex)
87 PT = np.zeros(shape=(vec_num, vec_len))
89 PT[0] =
ehat(j, vec_len)
90 PTU = np.zeros(shape=(vec_num, vec_num), dtype=complex)
93 for i
in range(vec_num - 1):
97 PTU[i-1][:i:] = np.array([UT[k][nodes[i-1]]
for k
in range(i)])
99 PTU[:i:, :i:], np.array([ei[node]
for node
in nodes]),
100 lower=
True, check_finite=
False)
102 r = ei - c.dot(UT[:i:])
107 PT[i] =
ehat(j, vec_len)
112 B = np.linalg.inv(VT.dot(PT.transpose())).
dot(VT)
115 B = np.array([B[i]
for i
in np.argsort(nodes)])
121 selected_params, flow, fhigh, deltaF, approximant, quadratic
123 """Construct frequency nodes and weights from parameter values selected by greedy algorithm.
127 selected_params : ndarray
128 ndarray whose i-th row is the i-th parameter set selected by greedy
135 construct nodes
for products of waveforms when this
is True
140 interpolation frequency nodes
142 ndarray whose i-th roq
is the weight
for the i-th frequency node.
145 start_index =
int(flow / deltaF)
146 def _waveform(param):
148 m1, m2, a1z, a2z = param
149 hp, _ = lalsimulation.SimInspiralChooseFDWaveform(
150 m1 * lal.MSUN_SI, m2 * lal.MSUN_SI,
151 0.0, 0.0, a1z, 0.0, 0.0, a2z,
152 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
153 deltaF, flow, fhigh, flow,
None,
154 lalsimulation.GetApproximantFromString(approximant)
156 hp = hp.data.data[start_index::]
158 return np.conj(hp) * hp
161 basis = np.array([_waveform(param)
for param
in selected_params]).transpose()
164 basis, _ = np.linalg.qr(basis)
165 basis = basis.transpose()
168 nodes, B =
DEIM(basis)
169 return np.array([flow + deltaF * node
for node
in nodes]), B
176parser = OptionParser(usage=
"usage: %prog [options]",
178parser.add_option(
"-d",
"--data", type=
'string',
182parser.add_option(
"-p",
"--psd", type=
'string',
186parser.add_option(
"-t",
"--time_prior", type=float,
189 help=
"width of time prior",)
190parser.add_option(
"-i",
"--ifo", type=
'string',
193 help=
"list of ifos",)
194parser.add_option(
"-a",
"--approx", type=
'string',
197 help=
"approximant name",)
198parser.add_option(
"-s",
"--seglen", type=float,
201 help=
"segment length",)
202parser.add_option(
"-f",
"--fLow", type=float,
205 help=
"low frequency cut off",)
206parser.add_option(
"-u",
"--fHigh", type=float,
209 help=
"high frequency cut off",)
210parser.add_option(
"-T",
"--delta_tc", type=float,
213 help=
"width of tc subdomain",)
214parser.add_option(
"-B",
"--basis-set", type=
'string',
216 dest=
"b_matrix_directory",
217 help=
"B matrix directory",)
218parser.add_option(
"-o",
"--out", type=
'string',
224(options, args) = parser.parse_args()
226basis_params = np.loadtxt(os.path.join(options.b_matrix_directory,
"params.dat")).T
227flow_in_params, fhigh_in_params, deltaF_in_params = basis_params[0], basis_params[1], 1. / basis_params[2]
229B_linear_path = os.path.join(options.b_matrix_directory,
"B_linear.npy")
230B_quadratic_path = os.path.join(options.b_matrix_directory,
"B_quadratic.npy")
231fnodes_linear_path = os.path.join(options.b_matrix_directory,
"fnodes_linear.npy")
232fnodes_quadratic_path = os.path.join(options.b_matrix_directory,
"fnodes_quadratic.npy")
233params_linear_path = os.path.join(options.b_matrix_directory,
"selected_params_linear.npy")
234params_quadratic_path = os.path.join(options.b_matrix_directory,
"selected_params_quadratic.npy")
235if os.path.exists(B_linear_path)
and os.path.exists(B_quadratic_path)
and \
236 os.path.exists(fnodes_linear_path)
and os.path.exists(fnodes_quadratic_path):
237 B_linear = np.load(B_linear_path)
238 B_quadratic = np.load(B_quadratic_path)
239 fnodes_linear = np.load(fnodes_linear_path)
240 fnodes_quadratic = np.load(fnodes_quadratic_path)
241elif os.path.exists(params_linear_path)
and os.path.exists(params_quadratic_path):
242 selected_params_linear = np.load(params_linear_path)
243 selected_params_quadratic = np.load(params_quadratic_path)
244 fnodes_linear, B_linear =
construct_nodes(selected_params_linear, flow_in_params, fhigh_in_params, deltaF_in_params, options.approximant,
False)
245 fnodes_quadratic, B_quadratic =
construct_nodes(selected_params_quadratic, flow_in_params, fhigh_in_params, deltaF_in_params, options.approximant,
True)
247 print(
"No ROQ data found. Please make sure that you have B_(linear, quadratic).npy "
248 "and fnodes_(linear, quadratic).npy, or selected_params_(linear, quadratic).npy")
253 ''' for a data array and reduced basis compute roq weights
255 B: (reduced basis element)*invV (the inverse Vandermonde matrix)
257 PSD: detector noise power spectral density (must be same shape as data)
258 deltaF: integration element df
261 weights = np.dot(data, B.conjugate()) * deltaF * 4.
266relative_tc_shift = options.seglen - 2.
273for ifo
in options.IFOs:
275 dat_file = np.column_stack( np.loadtxt(options.data_file[i]) )
276 data = dat_file[1] + 1j*dat_file[2]
277 fseries = dat_file[0]
279 deltaF = 1./options.seglen
281 deltaF = fseries[1] - fseries[0]
283 fHigh = options.fHigh
286 fHigh_index =
int(fHigh / deltaF)
288 print(
'Desired fHigh is', fHigh,
', actual fHigh is', fseries[fHigh_index])
292 scale_factor = flow_in_params / fLow
295 fLow = flow_in_params
296 assert fHigh == fhigh_in_params
297 fLow_index =
int(fLow / deltaF)
299 print(
'Desired fLow is', fLow,
', actual fLow is', fseries[fLow_index])
301 fseries = fseries[fLow_index:fHigh_index]
302 data = data[fLow_index:fHigh_index]
304 psdfile = np.column_stack( np.loadtxt(options.psd_file[i]) )
307 psd[-1] = psd[-1 -1 ]
308 psd = psd[fLow_index:fHigh_index]
312 B_linear = B_linear.T[0:(fHigh_index - fLow_index)][:].T
313 B_quadratic = B_quadratic.T[0:(fHigh_index-fLow_index)][:].T
314 print(B_linear.shape[1], B_quadratic.shape[1], len(data), len(psd))
315 assert len(data) == len(psd) == B_linear.shape[1] == B_quadratic.shape[1]
320 B_linear = B_linear.T
321 B_quadratic = B_quadratic.T
323 for k
in range(len(data)):
324 if np.isnan(data[k].real):
328 tcs = np.linspace(relative_tc_shift - options.dt - 0.045, relative_tc_shift + options.dt + 0.045, ceil(2.*(options.dt+0.045) / options.delta_tc) )
331 tc_shifted_data = np.zeros([len(tcs), len(fseries)], dtype=complex)
333 print(
"time steps = "+
str(len(tcs)))
334 for j
in range(len(tcs)):
340 tc_shifted_data[j] = data * np.exp(1j*2.*np.pi*fseries*tc)
347 print(
"Computing weights for "+ifo)
348 weights_path_linear = os.path.join(options.outpath,
"weights_linear_%s.dat"%ifo)
349 weights_file_linear = open(weights_path_linear,
"wb")
351 max_block_gigabytes = 4
352 max_elements =
int((max_block_gigabytes * 2 ** 30) / 8)
354 weights_linear =
blockwise_dot(tc_shifted_data, B_linear.conjugate(), deltaF, max_elements).T
356 (weights_linear).tofile(weights_file_linear)
357 weights_file_linear.close()
362 weights_path_quadratic = os.path.join(options.outpath,
"weights_quadratic_%s.dat"%ifo)
363 weights_file_quadratic = open(weights_path_quadratic,
"wb")
366 (weights_quadratic).tofile(weights_file_quadratic)
367 weights_file_quadratic.close()
368 size_file_path = os.path.join(options.outpath,
"roq_sizes.dat")
372 B_linear = B_linear.T
373 B_quadratic = B_quadratic.T
375 np.savetxt(size_file_path,np.array((len(tcs),B_linear.shape[0],B_quadratic.shape[0],B_linear.shape[1])),fmt=
'%u')
376 print(
"Weights have been computed for "+ifo)
383 print(
"scale factor = %f"%scale_factor)
384 fnodes_linear /= scale_factor
385 fnodes_quadratic /= scale_factor
388fnodes_linear_path = os.path.join(options.outpath,
"fnodes_linear.dat")
389fnodes_linear_file = open(fnodes_linear_path,
"wb")
391fnodes_linear.tofile(fnodes_linear_file)
392fnodes_linear_file.close()
394fnodes_quadratic_path = os.path.join(options.outpath,
"fnodes_quadratic.dat")
395fnodes_quadratic_file = open(fnodes_quadratic_path,
"wb")
397fnodes_quadratic.tofile(fnodes_quadratic_file)
398fnodes_quadratic_file.close()
400tcs_file_path = os.path.join(options.outpath,
"tcs.dat")
401tcs_file = open(tcs_file_path,
"wb")
static REAL8 dot(const REAL8 v[3], const REAL8 w[3])
def construct_nodes(selected_params, flow, fhigh, deltaF, approximant, quadratic)
Construct frequency nodes and weights from parameter values selected by greedy algorithm.
def DEIM(basis)
Calculate interpolation nodes following the Algorithm 5 in J Sci Comput (2013) 57:604-637.
def BuildWeights(data, B, deltaF)
for a data array and reduced basis compute roq weights
def ehat(j, length)
Return a unit vector whose j-th component is 1.
def blockwise_dot(A, B, deltaF, max_elements=int(2 **27), out=None)
Computes the dot product of two matrices in a block-wise fashion.