3 from optparse
import OptionParser
5 from scipy.linalg
import solve_triangular
11 def _block_slices(dim_size, block_size):
12 """Generator that yields slice objects for indexing into
13 sequential blocks of an array along a particular axis
17 yield slice(count, count + block_size, 1)
22 def blockwise_dot(A, B, deltaF, max_elements=int(2**27), out=
None):
24 Computes the dot product of two matrices in a block-wise fashion.
25 Only blocks of `A` with a maximum size of `max_elements` will be
26 processed simultaneously.
33 raise ValueError(
'matrices are not aligned')
35 if A.flags.f_contiguous:
37 max_cols =
max(1, max_elements // m)
38 max_rows = max_elements // max_cols
42 max_rows =
max(1, max_elements // n)
43 max_cols = max_elements // max_rows
46 out = np.empty((m, o), dtype=np.result_type(A, B))
47 elif out.shape != (m, o):
48 raise ValueError(
'output array has incorrect dimensions')
50 for mm
in _block_slices(m, max_rows):
52 for nn
in _block_slices(n, max_cols):
53 A_block = A[mm, nn].copy()
54 out[mm, :] += np.dot(A_block, B[nn, :]) * 4 * deltaF
60 """Return a unit vector whose j-th component is 1"""
61 ehat = np.zeros(length)
66 """Calculate interpolation nodes following the Algorithm 5 in J Sci Comput
72 ndarray whose i-th row is the i-th basis vector
79 ndarray whose i-th row is the weight for the i-th frequency node.
81 vec_num, vec_len = basis.shape
83 j = abs(basis[0]).argmax()
85 UT = np.zeros(shape=(vec_num, vec_len), dtype=complex)
86 PT = np.zeros(shape=(vec_num, vec_len))
88 PT[0] =
ehat(j, vec_len)
89 PTU = np.zeros(shape=(vec_num, vec_num), dtype=complex)
92 for i
in range(vec_num - 1):
96 PTU[i-1][:i:] = np.array([UT[k][nodes[i-1]]
for k
in range(i)])
98 PTU[:i:, :i:], np.array([ei[node]
for node
in nodes]),
99 lower=
True, check_finite=
False)
101 r = ei - c.dot(UT[:i:])
106 PT[i] =
ehat(j, vec_len)
111 B = np.linalg.inv(VT.dot(PT.transpose())).
dot(VT)
114 B = np.array([B[i]
for i
in np.argsort(nodes)])
120 selected_params, flow, fhigh, deltaF, approximant, quadratic
122 """Construct frequency nodes and weights from parameter values selected by greedy algorithm.
126 selected_params : ndarray
127 ndarray whose i-th row is the i-th parameter set selected by greedy
134 construct nodes for products of waveforms when this is True
139 interpolation frequency nodes
141 ndarray whose i-th roq is the weight for the i-th frequency node.
144 start_index =
int(flow / deltaF)
145 def _waveform(param):
147 m1, m2, a1z, a2z = param
148 hp, _ = lalsimulation.SimInspiralChooseFDWaveform(
149 m1 * lal.MSUN_SI, m2 * lal.MSUN_SI,
150 0.0, 0.0, a1z, 0.0, 0.0, a2z,
151 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
152 deltaF, flow, fhigh, flow,
None,
153 lalsimulation.GetApproximantFromString(approximant)
155 hp = hp.data.data[start_index::]
157 return np.conj(hp) * hp
160 basis = np.array([_waveform(param)
for param
in selected_params]).transpose()
163 basis, _ = np.linalg.qr(basis)
164 basis = basis.transpose()
167 nodes, B =
DEIM(basis)
168 return np.array([flow + deltaF * node
for node
in nodes]), B
175 parser = OptionParser(usage=
"usage: %prog [options]",
177 parser.add_option(
"-d",
"--data", type=
'string',
181 parser.add_option(
"-p",
"--psd", type=
'string',
185 parser.add_option(
"-t",
"--time_prior", type=float,
188 help=
"width of time prior",)
189 parser.add_option(
"-i",
"--ifo", type=
'string',
192 help=
"list of ifos",)
193 parser.add_option(
"-a",
"--approx", type=
'string',
196 help=
"approximant name",)
197 parser.add_option(
"-s",
"--seglen", type=float,
200 help=
"segment length",)
201 parser.add_option(
"-f",
"--fLow", type=float,
204 help=
"low frequency cut off",)
205 parser.add_option(
"-u",
"--fHigh", type=float,
208 help=
"high frequency cut off",)
209 parser.add_option(
"-T",
"--delta_tc", type=float,
212 help=
"width of tc subdomain",)
213 parser.add_option(
"-B",
"--basis-set", type=
'string',
215 dest=
"b_matrix_directory",
216 help=
"B matrix directory",)
217 parser.add_option(
"-o",
"--out", type=
'string',
223 (options, args) = parser.parse_args()
225 basis_params = np.loadtxt(os.path.join(options.b_matrix_directory,
"params.dat")).T
226 flow_in_params, fhigh_in_params, deltaF_in_params = basis_params[0], basis_params[1], 1. / basis_params[2]
228 B_linear_path = os.path.join(options.b_matrix_directory,
"B_linear.npy")
229 B_quadratic_path = os.path.join(options.b_matrix_directory,
"B_quadratic.npy")
230 fnodes_linear_path = os.path.join(options.b_matrix_directory,
"fnodes_linear.npy")
231 fnodes_quadratic_path = os.path.join(options.b_matrix_directory,
"fnodes_quadratic.npy")
232 params_linear_path = os.path.join(options.b_matrix_directory,
"selected_params_linear.npy")
233 params_quadratic_path = os.path.join(options.b_matrix_directory,
"selected_params_quadratic.npy")
234 if os.path.exists(B_linear_path)
and os.path.exists(B_quadratic_path)
and \
235 os.path.exists(fnodes_linear_path)
and os.path.exists(fnodes_quadratic_path):
236 B_linear = np.load(B_linear_path)
237 B_quadratic = np.load(B_quadratic_path)
238 fnodes_linear = np.load(fnodes_linear_path)
239 fnodes_quadratic = np.load(fnodes_quadratic_path)
240 elif os.path.exists(params_linear_path)
and os.path.exists(params_quadratic_path):
241 selected_params_linear = np.load(params_linear_path)
242 selected_params_quadratic = np.load(params_quadratic_path)
243 fnodes_linear, B_linear =
construct_nodes(selected_params_linear, flow_in_params, fhigh_in_params, deltaF_in_params, options.approximant,
False)
244 fnodes_quadratic, B_quadratic =
construct_nodes(selected_params_linear, flow_in_params, fhigh_in_params, deltaF_in_params, options.approximant,
True)
246 print(
"No ROQ data found. Please make sure that you have B_(linear, quadratic).npy "
247 "and fnodes_(linear, quadratic).npy, or selected_params_(linear, quadratic).npy")
252 ''' for a data array and reduced basis compute roq weights
254 B: (reduced basis element)*invV (the inverse Vandermonde matrix)
256 PSD: detector noise power spectral density (must be same shape as data)
257 deltaF: integration element df
260 weights = np.dot(data, B.conjugate()) * deltaF * 4.
265 relative_tc_shift = options.seglen - 2.
272 for ifo
in options.IFOs:
274 dat_file = np.column_stack( np.loadtxt(options.data_file[i]) )
275 data = dat_file[1] + 1j*dat_file[2]
276 fseries = dat_file[0]
278 deltaF = 1./options.seglen
280 deltaF = fseries[1] - fseries[0]
282 fHigh = options.fHigh
285 fHigh_index =
int(fHigh / deltaF)
287 print(
'Desired fHigh is', fHigh,
', actual fHigh is', fseries[fHigh_index])
291 scale_factor = flow_in_params / fLow
294 fLow = flow_in_params
295 assert fHigh == fhigh_in_params
296 fLow_index =
int(fLow / deltaF)
298 print(
'Desired fLow is', fLow,
', actual fLow is', fseries[fLow_index])
300 fseries = fseries[fLow_index:fHigh_index]
301 data = data[fLow_index:fHigh_index]
303 psdfile = np.column_stack( np.loadtxt(options.psd_file[i]) )
306 psd[-1] = psd[-1 -1 ]
307 psd = psd[fLow_index:fHigh_index]
311 B_linear = B_linear.T[0:(fHigh_index - fLow_index)][:].T
312 B_quadratic = B_quadratic.T[0:(fHigh_index-fLow_index)][:].T
313 print(B_linear.shape[1], B_quadratic.shape[1], len(data), len(psd))
314 assert len(data) == len(psd) == B_linear.shape[1] == B_quadratic.shape[1]
319 B_linear = B_linear.T
320 B_quadratic = B_quadratic.T
322 for k
in range(len(data)):
323 if np.isnan(data[k].real):
327 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) )
330 tc_shifted_data = np.zeros([len(tcs), len(fseries)], dtype=complex)
332 print(
"time steps = "+
str(len(tcs)))
333 for j
in range(len(tcs)):
339 tc_shifted_data[j] = data * np.exp(1j*2.*np.pi*fseries*tc)
346 print(
"Computing weights for "+ifo)
347 weights_path_linear = os.path.join(options.outpath,
"weights_linear_%s.dat"%ifo)
348 weights_file_linear = open(weights_path_linear,
"wb")
350 max_block_gigabytes = 4
351 max_elements =
int((max_block_gigabytes * 2 ** 30) / 8)
353 weights_linear =
blockwise_dot(tc_shifted_data, B_linear.conjugate(), deltaF, max_elements).T
355 (weights_linear).tofile(weights_file_linear)
356 weights_file_linear.close()
361 weights_path_quadratic = os.path.join(options.outpath,
"weights_quadratic_%s.dat"%ifo)
362 weights_file_quadratic = open(weights_path_quadratic,
"wb")
365 (weights_quadratic).tofile(weights_file_quadratic)
366 weights_file_quadratic.close()
367 size_file_path = os.path.join(options.outpath,
"roq_sizes.dat")
371 B_linear = B_linear.T
372 B_quadratic = B_quadratic.T
374 np.savetxt(size_file_path,np.array((len(tcs),B_linear.shape[0],B_quadratic.shape[0],B_linear.shape[1])),fmt=
'%u')
375 print(
"Weights have been computed for "+ifo)
382 print(
"scale factor = %f"%scale_factor)
383 fnodes_linear /= scale_factor
384 fnodes_quadratic /= scale_factor
387 fnodes_linear_path = os.path.join(options.outpath,
"fnodes_linear.dat")
388 fnodes_linear_file = open(fnodes_linear_path,
"wb")
390 fnodes_linear.tofile(fnodes_linear_file)
391 fnodes_linear_file.close()
393 fnodes_quadratic_path = os.path.join(options.outpath,
"fnodes_quadratic.dat")
394 fnodes_quadratic_file = open(fnodes_quadratic_path,
"wb")
396 fnodes_quadratic.tofile(fnodes_quadratic_file)
397 fnodes_quadratic_file.close()
399 tcs_file_path = os.path.join(options.outpath,
"tcs.dat")
400 tcs_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.