gstlal 1.13.0
Loading...
Searching...
No Matches
gstlal_fake_frames
1#!/usr/bin/env python3
2#
3# Copyright (C) 2011 Kipp Cannon, Chad Hanna, Drew Keppel
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the
7# Free Software Foundation; either version 2 of the License, or (at your
8# option) any later version.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13# Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19import numpy
20from optparse import OptionParser
21import os
22import sys
23
24import lal
25
26from gstlal import kernels
27from gstlal import pipeparts
28from gstlal import datasource
29from gstlal.psd import read_psd
30from gstlal.stream import Stream
31
32
166
167
168
171def parse_command_line():
172 parser = OptionParser(description = __doc__)
173
174 #
175 # Append data source options
176 #
177
178 datasource.append_options(parser)
179
180 #
181 # Append program specific options
182 #
183
184 parser.add_option("--shift", metavar = "ns", help = "Number of nanoseconds to delay (negative) or advance (positive) the time stream", type = "int")
185 parser.add_option("--sample-rate", metavar = "Hz", default = 16384, type = "int", help = "Sample rate at which to generate the data, should be less than or equal to the sample rate of the measured psds provided, default = 16384 Hz, max 16384 Hz")
186 parser.add_option("--whiten-reference-psd", metavar = "name", help = "Set the name of psd xml file to whiten the data with")
187 parser.add_option("--whiten-track-psd", action = "store_true", help = "Whiten the data by tracking PSD changes, can be combined with --whiten-reference-psd to seed the process.")
188 parser.add_option("--color-psd", metavar = "name", help = "Set the name of psd xml file to color the data with")
189 parser.add_option("--output-path", metavar = "name", default = ".", help = "Path to output frame files (default = \".\").")
190 parser.add_option("--output-channel-name", metavar = "name", help = "The name of the channel in the output frames. The default is the same as the channel name")
191 parser.add_option("--output-frame-type", metavar = "name", help = "Frame type, required")
192 parser.add_option("--output-frame-duration", metavar = "s", default = 16, type = "int", help = "Set the duration of the output frames. The duration of the frame file will be multiplied by --frames-per-file. Default: 16s")
193 parser.add_option("--output-frames-per-file", metavar = "n", default = 256, type = "int", help = "Set the number of frames per file. Default: 256")
194 parser.add_option("-v", "--verbose", action = "store_true", help = "Be verbose (optional).")
195
196 #
197 # Parse options
198 #
199
200 options, filenames = parser.parse_args()
201
202 if options.sample_rate > 16384:
203 raise ValueError("--sample-rate must be <= 16384")
204
205 if options.output_frame_type is None:
206 raise ValueError("--frame-type is required")
207
208
209 return options, filenames
210
211
212#
213# Main
214#
215
216options, filenames = parse_command_line()
217
218
219os.makedirs(options.output_path, exist_ok=True)
220
221
222gw_data_source = datasource.DataSourceInfo.from_optparse(options)
223
224
225instrument = list(gw_data_source.channel_dict.keys())[0]
226
227# set default output channel if not set by user
228if options.output_channel_name is None:
229 options.output_channel_name = gw_data_source.channel_dict[instrument]
230
231# do not do injections in datasource, we will do them later
232injections, gw_data_source.injection_filename = options.injection_file, None
233
234
236gw_data_source.block_size = 8 * options.sample_rate
237stream = Stream.from_datasource(
238 gw_data_source,
239 instrument,
240 name=os.path.split(sys.argv[0])[1],
241 verbose=options.verbose
242)
243
244
245if options.verbose:
246 stream = stream.progressreport("frames")
247
248if options.shift is not None:
249
250 stream = stream.shift(shift=options.shift)
251
252
253 stream = stream.progressreport("frames_shifted")
254
255if options.whiten_reference_psd:
256
257 wpsd = read_psd(options.whiten_reference_psd, verbose = options.verbose)[instrument]
258else:
259
260 wpsd = None
261
262if options.whiten_reference_psd or options.whiten_track_psd:
263
264 stream = stream.condition(options.sample_rate, instrument, psd=wpsd, track_psd=options.whiten_track_psd)
265else:
266
267 stream = stream.resample(quality=9).capsfilter(f"audio/x-raw, rate={options.sample_rate}")
268 # FIXME this is a bit hacky, should datasource.mkbasicsrc be patched to change the sample rate?
269 # FIXME don't hardcode sample rate (though this is what datasource generates for all fake data, period
270 # Renormalize if datasource is "white"
271 if options.data_source == "white":
272 renormalize_factor = 1.0 / (pipeparts.audioresample_variance_gain(9, 16384, options.sample_rate))**.5
273 stream = stream.audioamplify(renormalize_factor)
274
275# Apply a coloring filter
276if options.color_psd:
277
278
279 rpsd = read_psd(options.color_psd, verbose = options.verbose)[instrument]
280
281
282 max_sample = int(round(1.0 / rpsd.deltaF * options.sample_rate / 2.0)) + 1
283
284 # Truncate to requested output sample rate, if it is higher than the psd provides an assert will fail later
285 rpsd_data = numpy.array(rpsd.data.data[:max_sample])
286 if len(rpsd_data) < max_sample: # FIXME this is off by one sample, but shouldn't be.
287 rpsd_data = numpy.append(rpsd_data, numpy.zeros(max_sample - len(rpsd_data)))
288
289 rpsd = lal.CreateCOMPLEX16FrequencySeries(name = rpsd.name, epoch = rpsd.epoch, f0 = rpsd.f0, deltaF = rpsd.deltaF, length = max_sample, sampleUnits = rpsd.sampleUnits)
290 rpsd.data.data = rpsd_data
291
292 # create the coloring FIR kernel from reference_psd.psd_to_fir_kernel()
293 FIRKernel = kernels.PSDFirKernel()
294 fir_matrix, latency, measured_sample_rate = FIRKernel.psd_to_linear_phase_whitening_fir_kernel(rpsd, invert = False)
295
296
297 stream = stream.firbank(latency=latency, fir_matrix=[fir_matrix], block_stride=(1 * options.sample_rate))
298
299
300
301tagstr = f"units=strain,channel-name={options.output_channel_name},instrument={instrument}"
302
303
304stream = stream.taginject(tagstr)
305
306
307if injections is not None:
308 stream = stream.injections(injections)
309
310
311stream = stream.framecppchannelmux(
312 channels=f"{instrument}:{options.output_channel_name}",
313 frame_duration=options.output_frame_duration,
314 frames_per_file=options.output_frames_per_file
315)
316
317
318framesink = stream.framecppfilesink(frame_type=options.output_frame_type)
319
320# Put O(100000 s) frames in each directory
321framesink.connect("notify::timestamp", pipeparts.framecpp_filesink_ldas_path_handler, (options.output_path, 5))
322
323# Run it
324stream.start()