From 48dae9a2c5fd333d8ad809a38828d4abd3c223f0 Mon Sep 17 00:00:00 2001 From: Aaron Viets <aaron.viets@ligo.org> Date: Thu, 20 Sep 2018 22:29:44 -0700 Subject: [PATCH] gstlal_compute_strain: fixed hoft_clean state vector bits. --- gstlal-calibration/bin/gstlal_compute_strain | 4 +- .../gst/lal/gstlal_transferfunction.c | 40 ++++---- .../gst/lal/gstlal_transferfunction.h | 1 + .../python/calibration_parts.py | 7 +- gstlal-calibration/tests/rms_test.py | 95 +++++++++++++++++++ 5 files changed, 124 insertions(+), 23 deletions(-) create mode 100755 gstlal-calibration/tests/rms_test.py diff --git a/gstlal-calibration/bin/gstlal_compute_strain b/gstlal-calibration/bin/gstlal_compute_strain index 37facaa350..bc04e1fdef 100755 --- a/gstlal-calibration/bin/gstlal_compute_strain +++ b/gstlal-calibration/bin/gstlal_compute_strain @@ -2194,8 +2194,8 @@ if remove_cal_lines or remove_power_lines or witness_channel_list is not None: # if compute_calib_statevector and (remove_cal_lines or remove_power_lines or witness_channel_list is not None): - low_rms_rate = pow(2, int(numpy.log(cleaning_check_range_low_max) / numpy.log(2) + 1.1)) - mid_rms_rate = pow(2, int(numpy.log(cleaning_check_range_mid_max) / numpy.log(2) + 1.1)) + low_rms_rate = pow(2, int(numpy.log(2 * cleaning_check_range_low_max) / numpy.log(2) + 1.01)) + mid_rms_rate = pow(2, int(numpy.log(2 * cleaning_check_range_mid_max) / numpy.log(2) + 1.01)) # Compute the RMS of the uncleaned strain in a low-frequency range to test subtraction of actuation lines strain_rms_lowfreq = calibration_parts.compute_rms(pipeline, straintee, low_rms_rate, cleaning_check_rms_time, f_min = cleaning_check_range_low_min, f_max = cleaning_check_range_low_max, filter_latency = filter_latency_factor, rate_out = calibstate_sr, td = td) diff --git a/gstlal-calibration/gst/lal/gstlal_transferfunction.c b/gstlal-calibration/gst/lal/gstlal_transferfunction.c index 6b249ba7a5..9a80f146c1 100644 --- a/gstlal-calibration/gst/lal/gstlal_transferfunction.c +++ b/gstlal-calibration/gst/lal/gstlal_transferfunction.c @@ -183,11 +183,11 @@ DEFINE_MAXIMUM(32); DEFINE_MAXIMUM(64); -static void write_transfer_functions(complex double *tfs, char *element_name, double df, gint64 rows, int columns, gboolean write_to_screen, char *filename, gboolean free_name) { +static void write_transfer_functions(complex double *tfs, char *element_name, double df, gint64 rows, int columns, double t_start, double t_finish, gboolean write_to_screen, char *filename, gboolean free_name) { gint64 i; int j, j_stop; if(write_to_screen) { - g_print("\n\n==================== Transfer functions computed by %s ====================\nfrequency\t\t ", element_name); + g_print("\n\n==================== Transfer functions computed by %s from %f until %f ====================\nfrequency\t\t ", element_name, t_start, t_finish); for(j = 1; j < columns; j++) g_print("ch%d -> ch0\t\t\t\t ", j); g_print("ch%d -> ch0\n\n", columns); @@ -212,7 +212,7 @@ static void write_transfer_functions(complex double *tfs, char *element_name, do if(filename) { FILE *fp; fp = fopen(filename, "a"); - g_fprintf(fp, "==================== Transfer functions computed by %s ====================\nfrequency\t\t ", element_name); + g_fprintf(fp, "==================== Transfer functions computed by %s from %f until %f ====================\nfrequency\t\t ", element_name, t_start, t_finish); for(j = 1; j < columns; j++) g_fprintf(fp, "ch%d -> ch0\t\t\t\t ", j); g_fprintf(fp, "ch%d -> ch0\n\n", columns); @@ -239,11 +239,11 @@ static void write_transfer_functions(complex double *tfs, char *element_name, do } -static void write_fir_filters(double *filters, char *element_name, gint64 rows, int columns, gboolean write_to_screen, char *filename, gboolean free_name) { +static void write_fir_filters(double *filters, char *element_name, gint64 rows, int columns, double t_start, double t_finish, gboolean write_to_screen, char *filename, gboolean free_name) { gint64 i; int j, j_stop; if(write_to_screen) { - g_print("================== FIR filters computed by %s ==================\n", element_name); + g_print("================== FIR filters computed by %s from %f until %f ==================\n", element_name, t_start, t_finish); for(j = 1; j < columns; j++) g_print("ch%d -> ch0\t", j); g_print("ch%d -> ch0\n\n", columns); @@ -260,7 +260,7 @@ static void write_fir_filters(double *filters, char *element_name, gint64 rows, if(filename) { FILE *fp; fp = fopen(filename, "a"); - g_fprintf(fp, "================== FIR filters computed by %s ==================\n", element_name); + g_fprintf(fp, "================== FIR filters computed by %s from %f until %f ==================\n", element_name, t_start, t_finish); for(j = 1; j < columns; j++) g_fprintf(fp, "ch%d -> ch0\t", j); g_fprintf(fp, "ch%d -> ch0\n\n", columns); @@ -837,14 +837,14 @@ static gboolean find_transfer_functions_ ## DTYPE(GSTLALTransferFunction *elemen } \ } \ } \ - success &= update_transfer_functions_ ## DTYPE(element->workspace.w ## S_OR_D ## pf.autocorrelation_matrix, num_tfs, fd_fft_length, fd_tf_length, element->workspace.w ## S_OR_D ## pf.sinc_table, element->workspace.w ## S_OR_D ## pf.sinc_length, element->workspace.w ## S_OR_D ## pf.sinc_taps_per_df, element->use_median ? 1 : element->num_ffts - element->workspace.w ## S_OR_D ## pf.num_ffts_dropped, element->workspace.w ## S_OR_D ## pf.transfer_functions_at_f, element->workspace.w ## S_OR_D ## pf.transfer_functions_solved_at_f, element->workspace.w ## S_OR_D ## pf.autocorrelation_matrix_at_f, element->workspace.w ## S_OR_D ## pf.permutation, element->transfer_functions); \ + success &= update_transfer_functions_ ## DTYPE(element->workspace.w ## S_OR_D ## pf.autocorrelation_matrix, num_tfs, fd_fft_length, fd_tf_length, element->workspace.w ## S_OR_D ## pf.sinc_table, element->workspace.w ## S_OR_D ## pf.sinc_length, element->workspace.w ## S_OR_D ## pf.sinc_taps_per_df, element->use_median ? 1 : element->workspace.w ## S_OR_D ## pf.num_ffts_in_avg - element->workspace.w ## S_OR_D ## pf.num_ffts_dropped, element->workspace.w ## S_OR_D ## pf.transfer_functions_at_f, element->workspace.w ## S_OR_D ## pf.transfer_functions_solved_at_f, element->workspace.w ## S_OR_D ## pf.autocorrelation_matrix_at_f, element->workspace.w ## S_OR_D ## pf.permutation, element->transfer_functions); \ if(success) { \ GST_INFO_OBJECT(element, "Just computed new transfer functions"); \ /* Let other elements know about the update */ \ g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_TRANSFER_FUNCTIONS]); \ /* Write transfer functions to the screen or a file if we want */ \ if(element->write_to_screen || element->filename) \ - write_transfer_functions(element->transfer_functions, gst_element_get_name(element), element->rate / 2.0 / (fd_tf_length - 1.0), fd_tf_length, num_tfs, element->write_to_screen, element->filename, TRUE); \ + write_transfer_functions(element->transfer_functions, gst_element_get_name(element), element->rate / 2.0 / (fd_tf_length - 1.0), fd_tf_length, num_tfs, element->t_start_tf, element->t_start_tf + (double) (element->workspace.w ## S_OR_D ## pf.num_ffts_in_avg * stride + element->fft_overlap) / element->rate, element->write_to_screen, element->filename, TRUE); \ /* If this is this first transfer function after a gap, we may wish to store it */ \ if(element->use_first_after_gap && !element->num_tfs_since_gap) { \ for(i = 0; i < num_tfs * fd_tf_length; i++) \ @@ -871,7 +871,7 @@ static gboolean find_transfer_functions_ ## DTYPE(GSTLALTransferFunction *elemen g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_FIR_FILTERS]); \ /* Write FIR filters to the screen or a file if we want */ \ if(element->write_to_screen || element->filename) \ - write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, num_tfs, element->write_to_screen, element->filename, TRUE); \ + write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, num_tfs, element->t_start_tf, element->t_start_tf + (double) (element->workspace.w ## S_OR_D ## pf.num_ffts_in_avg * stride + element->fft_overlap) / element->rate, element->write_to_screen, element->filename, TRUE); \ /* If this is this first FIR filter after a gap, we may wish to store it */ \ if(element->use_first_after_gap && element->num_tfs_since_gap == 1) { \ for(i = 0; i < num_tfs * element->fir_length; i++) \ @@ -1018,7 +1018,7 @@ static gboolean event(GstBaseSink *sink, GstEvent *event) { g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_TRANSFER_FUNCTIONS]); /* Write transfer functions to the screen or a file if we want */ if(element->write_to_screen || element->filename) - write_transfer_functions(element->transfer_functions, gst_element_get_name(element), element->rate / 2.0 / (fd_tf_length - 1.0), fd_tf_length, num_tfs, element->write_to_screen, element->filename, TRUE); + write_transfer_functions(element->transfer_functions, gst_element_get_name(element), element->rate / 2.0 / (fd_tf_length - 1.0), fd_tf_length, num_tfs, element->t_start_tf, element->t_start_tf + (double) (element->workspace.wspf.num_ffts_in_avg * (element->fft_length - element->fft_overlap) + element->fft_overlap) / element->rate, element->write_to_screen, element->filename, TRUE); } else GST_WARNING_OBJECT(element, "Transfer function(s) computation failed. No transfer functions will be produced."); /* Update FIR filters if we want */ @@ -1030,7 +1030,7 @@ static gboolean event(GstBaseSink *sink, GstEvent *event) { g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_FIR_FILTERS]); /* Write FIR filters to the screen or a file if we want */ if(element->write_to_screen || element->filename) - write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, num_tfs, element->write_to_screen, element->filename, TRUE); + write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, num_tfs, element->t_start_tf, element->t_start_tf + (double) (element->workspace.wspf.num_ffts_in_avg * (element->fft_length - element->fft_overlap) + element->fft_overlap) / element->rate, element->write_to_screen, element->filename, TRUE); } else GST_WARNING_OBJECT(element, "FIR filter(s) computation failed. No FIR filters will be produced."); } @@ -1093,7 +1093,7 @@ static gboolean event(GstBaseSink *sink, GstEvent *event) { g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_TRANSFER_FUNCTIONS]); /* Write transfer functions to the screen or a file if we want */ if(element->write_to_screen || element->filename) - write_transfer_functions(element->transfer_functions, gst_element_get_name(element), element->rate / 2.0 / (fd_tf_length - 1.0), fd_tf_length, num_tfs, element->write_to_screen, element->filename, TRUE); + write_transfer_functions(element->transfer_functions, gst_element_get_name(element), element->rate / 2.0 / (fd_tf_length - 1.0), fd_tf_length, num_tfs, element->t_start_tf, element->t_start_tf + (double) (element->workspace.wdpf.num_ffts_in_avg * (element->fft_length - element->fft_overlap) + element->fft_overlap) / element->rate, element->write_to_screen, element->filename, TRUE); } else GST_WARNING_OBJECT(element, "Transfer function(s) computation failed. No transfer functions will be produced."); /* Update FIR filters if we want */ @@ -1105,7 +1105,7 @@ static gboolean event(GstBaseSink *sink, GstEvent *event) { g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_FIR_FILTERS]); /* Write FIR filters to the screen or a file if we want */ if(element->write_to_screen || element->filename) - write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, num_tfs, element->write_to_screen, element->filename, TRUE); + write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, num_tfs, element->t_start_tf, element->t_start_tf + (double) (element->workspace.wdpf.num_ffts_in_avg * (element->fft_length - element->fft_overlap) + element->fft_overlap) / element->rate, element->write_to_screen, element->filename, TRUE); } else GST_WARNING_OBJECT(element, "FIR filter(s) computation failed. No FIR filters will be produced."); } @@ -1763,7 +1763,7 @@ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer) { g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_TRANSFER_FUNCTIONS]); /* Write transfer functions to the screen or a file if we want */ if(element->write_to_screen || element->filename) - write_transfer_functions(element->transfer_functions, gst_element_get_name(element), (double) element->rate / element->fir_length, element->fir_length / 2 + 1, element->channels - 1, element->write_to_screen, element->filename, TRUE); + write_transfer_functions(element->transfer_functions, gst_element_get_name(element), (double) element->rate / element->fir_length, element->fir_length / 2 + 1, element->channels - 1, 0, 0, element->write_to_screen, element->filename, TRUE); if(element->make_fir_filters) { for(i = 0; i < (element->channels - 1) * element->fir_length; i++) element->fir_filters[i] = element->post_gap_fir_filters[i]; @@ -1772,7 +1772,7 @@ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer) { g_object_notify_by_pspec(G_OBJECT(element), properties[ARG_FIR_FILTERS]); /* Write FIR filters to the screen or a file if we want */ if(element->write_to_screen || element->filename) - write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, element->channels - 1, element->write_to_screen, element->filename, TRUE); + write_fir_filters(element->fir_filters, gst_element_get_name(element), element->fir_length, element->channels - 1, 0, 0, element->write_to_screen, element->filename, TRUE); } } @@ -1812,16 +1812,18 @@ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer) { gboolean success; if(element->data_type == GSTLAL_TRANSFERFUNCTION_F32) { /* If we are just beginning to compute new transfer functions with this data, initialize memory that we will fill to zero */ - if(!element->workspace.wspf.num_ffts_in_avg) + if(!element->workspace.wspf.num_ffts_in_avg) { memset(element->workspace.wspf.autocorrelation_matrix, 0, element->channels * (element->channels - 1) * (element->fft_length / 2 + 1) * sizeof(*element->workspace.wspf.autocorrelation_matrix)); - + element->t_start_tf = (double) (gst_util_uint64_scale_int_round(GST_BUFFER_PTS(buffer) + GST_BUFFER_DURATION(buffer), element->rate, GST_SECOND) - element->sample_count + element->update_samples) / element->rate; + } /* Send the data to a function to compute fft's and transfer functions */ success = find_transfer_functions_float(element, (float *) mapinfo.data, mapinfo.size, GST_BUFFER_PTS(buffer)); } else { /* If we are just beginning to compute new transfer functions with this data, initialize memory that we will fill to zero */ - if(!element->workspace.wdpf.num_ffts_in_avg) + if(!element->workspace.wdpf.num_ffts_in_avg) { memset(element->workspace.wdpf.autocorrelation_matrix, 0, element->channels * (element->channels - 1) * (element->fft_length / 2 + 1) * sizeof(*element->workspace.wdpf.autocorrelation_matrix)); - + element->t_start_tf = (double) (gst_util_uint64_scale_int_round(GST_BUFFER_PTS(buffer) + GST_BUFFER_DURATION(buffer), element->rate, GST_SECOND) - element->sample_count + element->update_samples) / element->rate; + } /* Send the data to a function to compute fft's and transfer functions */ success = find_transfer_functions_double(element, (double *) mapinfo.data, mapinfo.size, GST_BUFFER_PTS(buffer)); } diff --git a/gstlal-calibration/gst/lal/gstlal_transferfunction.h b/gstlal-calibration/gst/lal/gstlal_transferfunction.h index acf5aaac4f..1ecec76b18 100644 --- a/gstlal-calibration/gst/lal/gstlal_transferfunction.h +++ b/gstlal-calibration/gst/lal/gstlal_transferfunction.h @@ -78,6 +78,7 @@ struct _GSTLALTransferFunction { /* Internal state */ gboolean computed_full_tfs; + double t_start_tf; /* transfer function work space */ union { diff --git a/gstlal-calibration/python/calibration_parts.py b/gstlal-calibration/python/calibration_parts.py index cb60d588ed..e3d1713122 100644 --- a/gstlal-calibration/python/calibration_parts.py +++ b/gstlal-calibration/python/calibration_parts.py @@ -379,9 +379,9 @@ def compute_rms(pipeline, head, rate, average_time, f_min = None, f_max = None, if (f_min is not None) and (f_max is not None): head = bandpass(pipeline, head, rate, f_low = f_min, f_high = f_max, filter_latency = filter_latency, td = td) elif f_min is not None: - head = highpass(pipeline, head, fcut = f_min, filter_latency = filter_latency, td = td) + head = highpass(pipeline, head, rate, fcut = f_min, filter_latency = filter_latency, td = td) elif f_max is not None: - head = lowpass(pipeline, head, fcut = f_max, filter_latency = filter_latency, td = td) + head = lowpass(pipeline, head, rate, fcut = f_max, filter_latency = filter_latency, td = td) # Square it head = mkpow(pipeline, head, exponent = 2.0) @@ -392,6 +392,9 @@ def compute_rms(pipeline, head, rate, average_time, f_min = None, f_max = None, # Compute running average head = pipeparts.mkgeneric(pipeline, head, "lal_smoothkappas", default_kappa_re = 0.0, array_size = 1, avg_array_size = average_time * rate_out, filter_latency = filter_latency) + # Take the square root + head = mkpow(pipeline, head, exponent = 0.5) + return head # diff --git a/gstlal-calibration/tests/rms_test.py b/gstlal-calibration/tests/rms_test.py new file mode 100755 index 0000000000..b37259af0e --- /dev/null +++ b/gstlal-calibration/tests/rms_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# Copyright (C) 2018 Aaron Viets +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# +# ============================================================================= +# +# Preamble +# +# ============================================================================= +# + + +import numpy +import sys +from gstlal import pipeparts +from gstlal import calibration_parts +from gstlal import test_common +from gi.repository import Gst + + +# +# ============================================================================= +# +# Pipelines +# +# ============================================================================= +# + +def rms_01(pipeline, name): + + # + # This test passes a random series of integers through rms + # + + rate_in = 2048 # Hz + buffer_length = 1.0 # seconds + test_duration = 50.0 # seconds + + # + # build pipeline + # + + head = test_common.test_src(pipeline, buffer_length = buffer_length, rate = rate_in, width = 64, test_duration = test_duration, wave = 5, freq = 0) + white_noise = pipeparts.mktee(pipeline, head) + white_noise_over10 = pipeparts.mkaudioamplify(pipeline, white_noise, 0.1) + white_noise_bp100to150 = calibration_parts.bandpass(pipeline, white_noise, 2048, length = 1.0, f_low = 100, f_high = 150) + white_noise_bp250to300 = calibration_parts.bandpass(pipeline, white_noise, 2048, length = 1.0, f_low = 250, f_high = 300) + white_noise_bp450to500 = calibration_parts.bandpass(pipeline, white_noise, 2048, length = 1.0, f_low = 450, f_high = 500) + white_noise_bp400to500 = calibration_parts.bandpass(pipeline, white_noise, 2048, length = 1.0, f_low = 400, f_high = 500) + rms = calibration_parts.compute_rms(pipeline, white_noise, 1024, 1.0, f_min = 100, f_max = 500) + rms_over10 = calibration_parts.compute_rms(pipeline, white_noise_over10, 1024, 1.0, f_min = 100, f_max = 500) + rms_bp100to150 = calibration_parts.compute_rms(pipeline, white_noise_bp100to150, 1024, 1.0, f_min = 100, f_max = 500) + rms_bp250to300 = calibration_parts.compute_rms(pipeline, white_noise_bp250to300, 1024, 1.0, f_min = 100, f_max = 500) + rms_bp450to500 = calibration_parts.compute_rms(pipeline, white_noise_bp450to500, 1024, 1.0, f_min = 100, f_max = 500) + rms_bp400to500 = calibration_parts.compute_rms(pipeline, white_noise_bp400to500, 1024, 1.0, f_min = 100, f_max = 500) + pipeparts.mknxydumpsink(pipeline, rms, "rms.txt") + pipeparts.mknxydumpsink(pipeline, rms_over10, "rms_over10.txt") + pipeparts.mknxydumpsink(pipeline, rms_bp100to150, "rms_bp100to150.txt") + pipeparts.mknxydumpsink(pipeline, rms_bp250to300, "rms_bp250to300.txt") + pipeparts.mknxydumpsink(pipeline, rms_bp450to500, "rms_bp450to500.txt") + pipeparts.mknxydumpsink(pipeline, rms_bp400to500, "rms_bp400to500.txt") + + # + # done + # + + return pipeline + + +# +# ============================================================================= +# +# Main +# +# ============================================================================= +# + + +test_common.build_and_run(rms_01, "rms_01") + + -- GitLab