From d5a7b856fc855eda2848560b4df2ca1d1f878bb6 Mon Sep 17 00:00:00 2001 From: Patrick Godwin <patrick.godwin@ligo.org> Date: Thu, 23 Aug 2018 09:23:08 -0700 Subject: [PATCH] fxtools/multirate_datasource.py: replace resample with interpolator elem for downsampling, update firbank elem for whitening with tdwhiten elem, update comments, add check for GstAudio 1.0 --- .../python/fxtools/multirate_datasource.py | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/gstlal-burst/python/fxtools/multirate_datasource.py b/gstlal-burst/python/fxtools/multirate_datasource.py index 198b638f81..ffa242a068 100644 --- a/gstlal-burst/python/fxtools/multirate_datasource.py +++ b/gstlal-burst/python/fxtools/multirate_datasource.py @@ -33,6 +33,7 @@ import numpy import gi gi.require_version('Gst', '1.0') +gi.require_version('GstAudio', '1.0') from gi.repository import GObject, Gst, GstAudio GObject.threads_init() Gst.init(None) @@ -47,6 +48,7 @@ from gstlal import datasource # FIXME: Find a better way than using global variables. PSD_FFT_LENGTH = 32 PSD_DROP_TIME = 16 * PSD_FFT_LENGTH +NATIVE_RATE_CUTOFF = 128 # FIXME: this Gstreamer graph is outdated, need to update it ## #### produced whitened h(t) at (possibly) multiple sample rates @@ -137,11 +139,14 @@ def mkwhitened_multirate_src(pipeline, src, rates, native_rate, instrument, psd raise ValueError("psd_fft_length must be an integer") psd_fft_length = int(psd_fft_length) + # # down-sample to highest of target sample rates. - quality = 9 + # + + quality = 10 # set by interpolator max_rate = max(rates) head = pipeparts.mkcapsfilter(pipeline, src, "audio/x-raw, rate=[%d,MAX]" % max_rate) - head = pipeparts.mkresample(pipeline, head, quality = quality) + head = pipeparts.mkinterpolator(pipeline, head) # # construct whitener. @@ -152,19 +157,27 @@ def mkwhitened_multirate_src(pipeline, src, rates, native_rate, instrument, psd whiten = pipeparts.mkwhiten(pipeline, head, fft_length = psd_fft_length, zero_pad = 0, average_samples = 64, median_samples = 7, expand_gaps = True, name = "%s_%s_lalwhiten" % (instrument, channel_name)) pipeparts.mkfakesink(pipeline, whiten) + # # high pass filter + # + block_stride = block_duration * max_rate // Gst.SECOND - # FIXME: don't hardcode native rate cutoff for high-pass filtering - if native_rate >= 128: + if native_rate >= NATIVE_RATE_CUTOFF: kernel = reference_psd.one_second_highpass_kernel(max_rate, cutoff = 12) assert len(kernel) % 2 == 1, "high-pass filter length is not odd" head = pipeparts.mkfirbank(pipeline, head, fir_matrix = numpy.array(kernel, ndmin = 2), block_stride = block_stride, time_domain = False, latency = (len(kernel) - 1) // 2) + # # FIR filter for whitening kernel - head = pipeparts.mkfirbank(pipeline, head, fir_matrix = numpy.zeros((1, 1 + max_rate * psd_fft_length), dtype=numpy.float64), block_stride = block_stride, time_domain = False, latency = 0) + # + + head = pipeparts.mktdwhiten(pipeline, head, kernel = numpy.zeros(1 + max_rate * psd_fft_length, dtype=numpy.float64), latency = 0) + # # compute whitening kernel from PSD - def set_fir_psd(whiten, pspec, firbank, psd_fir_kernel): + # + + def set_fir_psd(whiten, pspec, firelem, psd_fir_kernel): psd_data = numpy.array(whiten.get_property("mean-psd")) psd = lal.CreateREAL8FrequencySeries( name = "psd", @@ -178,15 +191,19 @@ def mkwhitened_multirate_src(pipeline, src, rates, native_rate, instrument, psd kernel, latency, sample_rate = psd_fir_kernel.psd_to_linear_phase_whitening_fir_kernel(psd) kernel, theta = psd_fir_kernel.linear_phase_fir_kernel_to_minimum_phase_whitening_fir_kernel(kernel, sample_rate) kernel -= numpy.mean(kernel) # subtract DC offset from signal - firbank.set_property("fir-matrix", numpy.array(kernel, ndmin = 2)) + firelem.set_property("kernel", kernel) whiten.connect_after("notify::mean-psd", set_fir_psd, head, reference_psd.PSDFirKernel()) + # # Drop initial data to let the PSD settle + # + head = pipeparts.mkdrop(pipeline, head, drop_samples = PSD_DROP_TIME * max_rate) # # enable/disable PSD tracking # + whiten.set_property("psd-mode", 0 if track_psd else 1) # @@ -232,13 +249,17 @@ def mkwhitened_multirate_src(pipeline, src, rates, native_rate, instrument, psd head = datasource.mksegmentsrcgate(pipeline, head, veto_segments, invert_output=True) # - # tee for highest sample rate stream + # if segments are specified to dump whitened timeseries, do so # tee = pipeparts.mktee(pipeline, head) if nxydump_segment: pipeparts.mknxydumpsink(pipeline, pipeparts.mkqueue(pipeline, tee), "whitenedtimeseries_%s.txt" % channel_name, segment = nxydump_segment) + # + # tee for highest sample rate stream + # + head = {rate: None for rate in rates} head[max_rate] = pipeparts.mkqueue(pipeline, tee, max_size_buffers = 0, max_size_bytes = 0, max_size_time = Gst.SECOND * 8) @@ -249,11 +270,10 @@ def mkwhitened_multirate_src(pipeline, src, rates, native_rate, instrument, psd for rate in sorted(set(rates))[:-1]: head[rate] = pipeparts.mkqueue(pipeline, tee, max_size_buffers = 0, max_size_bytes = 0, max_size_time = Gst.SECOND * 8) head[rate] = pipeparts.mkaudioamplify(pipeline, head[rate], 1. / math.sqrt(pipeparts.audioresample_variance_gain(quality, max_rate, rate))) - head[rate] = pipeparts.mkcapsfilter(pipeline, pipeparts.mkresample(pipeline, head[rate], quality = quality), caps = "audio/x-raw, rate=%d" % rate) + head[rate] = pipeparts.mkcapsfilter(pipeline, pipeparts.mkinterpolator(pipeline, head[rate]), caps = "audio/x-raw, rate=%d" % rate) # - # done. return value is a dictionary of tee elements indexed by - # sample rate + # return value is a dictionary of elements indexed by sample rate # return head -- GitLab