From 2a59e4df3409f44a33b889f8eaa91bcc7bfd3cae Mon Sep 17 00:00:00 2001
From: Aaron Viets <aaron.viets@ligo.org>
Date: Fri, 14 Feb 2025 17:17:16 -0600
Subject: [PATCH 1/3] lal_smoothkappas:  When element is reset with a truncated
 median array, take filter latency into account

---
 gst/lal/gstlal_smoothkappas.c | 58 +++++++++++++++++++++--------------
 gst/lal/gstlal_smoothkappas.h |  1 +
 python/calibration_parts.py   | 15 +++++----
 3 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/gst/lal/gstlal_smoothkappas.c b/gst/lal/gstlal_smoothkappas.c
index 34ba73475..6155fe6a5 100644
--- a/gst/lal/gstlal_smoothkappas.c
+++ b/gst/lal/gstlal_smoothkappas.c
@@ -161,7 +161,7 @@ static void set_metadata(GSTLALSmoothKappas *element, GstBuffer *buf, guint64 ou
 }
 
 
-static void get_new_median(double new_element, double *fifo_array, double *current_median, gint array_size, int *index_re, int *index_im, gboolean array_is_imaginary, int samples_in_filter, gboolean no_default) {
+static void get_new_median(double new_element, double *fifo_array, double *current_median, gint array_size, int *index_re, int *index_im, gboolean array_is_imaginary, int samples_in_filter, gboolean no_default, int *future_unused) {
 	if(array_is_imaginary) {
 		fifo_array[*index_im] = new_element;
 		(*index_im)++;
@@ -180,7 +180,7 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 	greater = Greater = G_MAXDOUBLE;
 	less = Less = -G_MAXDOUBLE;
 	num_samples = (no_default && samples_in_filter < array_size) ? samples_in_filter : array_size;
-	j_start = (array_is_imaginary ? *index_im : *index_re) + array_size - num_samples;
+	j_start = (array_is_imaginary ? *index_im : *index_re) + array_size - num_samples - *future_unused;
 	for(j = j_start; j < j_start + num_samples; j++) {
 		jj = j % array_size;
 		if(fifo_array[jj] < *current_median) {
@@ -204,6 +204,8 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 		else
 			g_assert_not_reached();
 	}
+	if(*future_unused > 0)
+		(*future_unused)--;
 
 	g_assert_cmpint(number_less + number_equal + number_greater, ==, num_samples);
 
@@ -260,6 +262,15 @@ static double get_average(double new_element, double *fifo_array, gint array_siz
 
 
 static void reset(GSTLALSmoothKappas *element) {
+	/* Calculate number of samples currently in median array that are too new to be used yet.  We want the truncated array to contain samples with timestamps closest to that of the next output sample */
+	if(element->array_size * element->filter_latency < element->min_array_size / 2)
+		element->future_unused = 0;
+	else if(element->array_size * element->filter_latency > element->samples_in_filter - element->min_array_size / 2)
+		element->future_unused = element->samples_in_filter - element->min_array_size;
+	else
+		element->future_unused = (int) (element->array_size * element->filter_latency - element->min_array_size / 2);
+	g_assert_cmpint(element->future_unused, >=, 0);
+	/* Drop samples to make truncated array */
 	element->samples_in_filter = element->min_array_size;
 	int i, num_default, ii, i_start, i_stop, num_less, num_greater, num_equal;
 	double greater, less, replace_value_re, replace_value_im;
@@ -268,10 +279,10 @@ static void reset(GSTLALSmoothKappas *element) {
 	if(element->array_size > element->samples_in_filter) {
 		num_default = element->array_size - element->min_array_size;
 		/* Replace removed values with default values */
-		if(!element->default_to_median) {
-			for(i = element->index_re; i < element->index_re + num_default; i++)
+		if(!element->default_to_median && !element->no_default) {
+			for(i = element->index_re - element->future_unused + element->array_size; i < element->index_re - element->future_unused + element->array_size + num_default; i++)
 				element->fifo_array_re[i % element->array_size] = element->default_kappa_re;
-			for(i = element->index_im; i < element->index_im + num_default; i++)
+			for(i = element->index_im - element->future_unused + element->array_size; i < element->index_im - element->future_unused + element->array_size + num_default; i++)
 				element->fifo_array_im[i % element->array_size] = element->default_kappa_im;
 		}
 		/* Find new median */
@@ -285,7 +296,7 @@ static void reset(GSTLALSmoothKappas *element) {
 			num_less = 0;
 			num_equal = 0;
 			num_greater = 0;
-			i_start = (element->index_re + element->array_size - element->samples_in_filter) % element->array_size;
+			i_start = (element->index_re + 2 * element->array_size - element->samples_in_filter - element->future_unused) % element->array_size;
 			i_stop = i_start + (element->no_default ? element->samples_in_filter : element->array_size);
 			for(i = i_start; i < i_stop; i++) {
 				ii = i % element->array_size;
@@ -323,7 +334,7 @@ static void reset(GSTLALSmoothKappas *element) {
 			num_less = 0;
 			num_equal = 0;
 			num_greater = 0;
-			i_start = (element->index_im + element->array_size - element->samples_in_filter) % element->array_size;
+			i_start = (element->index_im + 2 * element->array_size - element->samples_in_filter - element->future_unused) % element->array_size;
 			i_stop = i_start + (element->no_default ? element->samples_in_filter : element->array_size);
 			for(i = i_start; i < i_stop; i++) {
 				ii = i % element->array_size;
@@ -351,11 +362,11 @@ static void reset(GSTLALSmoothKappas *element) {
 				element->current_median_im = less;
 			/* In all other cases, do nothing */
 		}
-		if(element->default_to_median) {
+		if(element->default_to_median && !element->no_default) {
 			/* Fill removed values with current median */
-			for(i = element->index_re; i < element->index_re + num_default; i++)
+			for(i = element->index_re - element->future_unused + element->array_size; i < element->index_re - element->future_unused + element->array_size + num_default; i++)
 				element->fifo_array_re[i % element->array_size] = element->current_median_re;
-			for(i = element->index_im; i < element->index_im + num_default; i++)
+			for(i = element->index_im - element->future_unused + element->array_size; i < element->index_im - element->future_unused + element->array_size + num_default; i++)
 				element->fifo_array_im[i % element->array_size] = element->current_median_im;
 		}
 	}
@@ -375,7 +386,7 @@ static void reset(GSTLALSmoothKappas *element) {
 
 
 #define DEFINE_SMOOTH_BUFFER(DTYPE) \
-static GstFlowReturn smooth_buffer_ ## DTYPE(const DTYPE *src, guint64 src_size, DTYPE *dst, guint64 dst_size, double *fifo_array, double *avg_array, double default_kappa, double *current_median, double maximum_offset, gint array_size, gint avg_array_size, int *index_re, int *index_im, int *avg_index_re, int *avg_index_im, int *num_bad_in_avg_re, gboolean gap, gboolean default_to_median, gboolean track_bad_kappa, int *samples_in_filter, gboolean no_default, guint64 *total_samples, gboolean reject_zeros) { \
+static GstFlowReturn smooth_buffer_ ## DTYPE(const DTYPE *src, guint64 src_size, DTYPE *dst, guint64 dst_size, double *fifo_array, double *avg_array, double default_kappa, double *current_median, double maximum_offset, gint array_size, gint avg_array_size, int *index_re, int *index_im, int *avg_index_re, int *avg_index_im, int *num_bad_in_avg_re, gboolean gap, gboolean default_to_median, gboolean track_bad_kappa, int *samples_in_filter, gboolean no_default, guint64 *total_samples, gboolean reject_zeros, int *future_unused) { \
 	guint64 i; \
 	double new_element; \
 	DTYPE new_avg; \
@@ -394,7 +405,7 @@ static GstFlowReturn smooth_buffer_ ## DTYPE(const DTYPE *src, guint64 src_size,
 		} \
  \
 		/* Compute new median */ \
-		get_new_median(new_element, fifo_array, current_median, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default); \
+		get_new_median(new_element, fifo_array, current_median, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default, future_unused); \
 		/* Compute new average */ \
 		new_avg = (DTYPE) get_average(*current_median, avg_array, avg_array_size, avg_index_re, avg_index_im, FALSE, *samples_in_filter + (int) i + 1, no_default); \
 		if (track_bad_kappa) { \
@@ -421,7 +432,7 @@ static GstFlowReturn smooth_buffer_ ## DTYPE(const DTYPE *src, guint64 src_size,
 
 
 #define DEFINE_SMOOTH_COMPLEX_BUFFER(DTYPE) \
-static GstFlowReturn smooth_complex_buffer_ ## DTYPE(const DTYPE complex *src, guint64 src_size, DTYPE complex *dst, guint64 dst_size, double *fifo_array_re, double *fifo_array_im, double *avg_array_re, double *avg_array_im, double default_kappa_re, double default_kappa_im, double *current_median_re, double *current_median_im, double maximum_offset_re, double maximum_offset_im, gint array_size, gint avg_array_size, int *index_re, int *index_im, int *avg_index_re, int *avg_index_im, int *num_bad_in_avg_re, int *num_bad_in_avg_im, gboolean gap, gboolean default_to_median, gboolean track_bad_kappa, int *samples_in_filter, gboolean no_default, guint64 *total_samples, gboolean reject_zeros) { \
+static GstFlowReturn smooth_complex_buffer_ ## DTYPE(const DTYPE complex *src, guint64 src_size, DTYPE complex *dst, guint64 dst_size, double *fifo_array_re, double *fifo_array_im, double *avg_array_re, double *avg_array_im, double default_kappa_re, double default_kappa_im, double *current_median_re, double *current_median_im, double maximum_offset_re, double maximum_offset_im, gint array_size, gint avg_array_size, int *index_re, int *index_im, int *avg_index_re, int *avg_index_im, int *num_bad_in_avg_re, int *num_bad_in_avg_im, gboolean gap, gboolean default_to_median, gboolean track_bad_kappa, int *samples_in_filter, gboolean no_default, guint64 *total_samples, gboolean reject_zeros, int *future_unused) { \
 	guint64 i; \
 	double new_element_re, new_element_im; \
 	DTYPE complex new_avg; \
@@ -452,8 +463,8 @@ static GstFlowReturn smooth_complex_buffer_ ## DTYPE(const DTYPE complex *src, g
 			*num_bad_in_avg_im = 0; \
 		} \
 		/* Compute new median */ \
-		get_new_median(new_element_re, fifo_array_re, current_median_re, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default); \
-		get_new_median(new_element_im, fifo_array_im, current_median_im, array_size, index_re, index_im, TRUE, *samples_in_filter + (int) i + 1, no_default); \
+		get_new_median(new_element_re, fifo_array_re, current_median_re, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default, future_unused); \
+		get_new_median(new_element_im, fifo_array_im, current_median_im, array_size, index_re, index_im, TRUE, *samples_in_filter + (int) i + 1, no_default, future_unused); \
 		/* Compute new average */ \
 		new_avg = (DTYPE) get_average(*current_median_re, avg_array_re, avg_array_size, avg_index_re, avg_index_im, FALSE, *samples_in_filter + (int) i + 1, no_default) + I * (DTYPE) get_average(*current_median_im, avg_array_im, avg_array_size, avg_index_re, avg_index_im, TRUE, *samples_in_filter + (int) i + 1, no_default); \
 		if(track_bad_kappa) { \
@@ -626,13 +637,13 @@ static gboolean sink_event(GstBaseTransform *trans, GstEvent *event) {
 		void *data = g_malloc(waste_samples * element->unit_size);
 		GstFlowReturn result;
 		if(element->data_type == GSTLAL_SMOOTHKAPPAS_F32) {
-			result = smooth_buffer_float((float *) fake, (guint64) waste_samples, (float *) data, (guint64) waste_samples, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+			result = smooth_buffer_float((float *) fake, (guint64) waste_samples, (float *) data, (guint64) waste_samples, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 		} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_F64) {
-			result = smooth_buffer_double((double *) fake, (guint64) waste_samples, (double *) data, (guint64) waste_samples, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+			result = smooth_buffer_double((double *) fake, (guint64) waste_samples, (double *) data, (guint64) waste_samples, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 		} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_Z64) {
-			result = smooth_complex_buffer_float((float complex *) fake, (guint64) waste_samples, (float complex *) data, (guint64) waste_samples, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+			result = smooth_complex_buffer_float((float complex *) fake, (guint64) waste_samples, (float complex *) data, (guint64) waste_samples, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 		} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_Z128) {
-			result = smooth_complex_buffer_double((double complex *) fake, (guint64) waste_samples, (double complex *) data, (guint64) waste_samples, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+			result = smooth_complex_buffer_double((double complex *) fake, (guint64) waste_samples, (double complex *) data, (guint64) waste_samples, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, TRUE, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 		} else {
 			result = GST_FLOW_ERROR;
 			success = FALSE;
@@ -799,13 +810,13 @@ static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuf
 
 	/* Process data in buffer */
 	if(element->data_type == GSTLAL_SMOOTHKAPPAS_F32) {
-		result = smooth_buffer_float((const float *) inmap.data, inmap.size / element->unit_size, (float *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+		result = smooth_buffer_float((const float *) inmap.data, inmap.size / element->unit_size, (float *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 	} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_F64) {
-		result = smooth_buffer_double((const double *) inmap.data, inmap.size / element->unit_size, (double *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+		result = smooth_buffer_double((const double *) inmap.data, inmap.size / element->unit_size, (double *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->avg_array_re, element->default_kappa_re, &element->current_median_re, element->maximum_offset_re, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 	} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_Z64) {
-		result = smooth_complex_buffer_float((const float complex *) inmap.data, inmap.size / element->unit_size, (float complex *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+		result = smooth_complex_buffer_float((const float complex *) inmap.data, inmap.size / element->unit_size, (float complex *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 	} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_Z128) {
-		result = smooth_complex_buffer_double((const double complex *) inmap.data, inmap.size / element->unit_size, (double complex *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros);
+		result = smooth_complex_buffer_double((const double complex *) inmap.data, inmap.size / element->unit_size, (double complex *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 	} else {
 		g_assert_not_reached();
 	}
@@ -1271,6 +1282,7 @@ static void gstlal_smoothkappas_init(GSTLALSmoothKappas *element) {
 	element->num_bad_in_avg_im = G_MAXINT;
 	element->samples_in_filter = 0;
 	element->total_samples = 0;
+	element->future_unused = 0;
 	element->reset_times = NULL;
 	element->num_reset_times = 0;
 
diff --git a/gst/lal/gstlal_smoothkappas.h b/gst/lal/gstlal_smoothkappas.h
index 434664d24..97b520574 100644
--- a/gst/lal/gstlal_smoothkappas.h
+++ b/gst/lal/gstlal_smoothkappas.h
@@ -94,6 +94,7 @@ struct _GSTLALSmoothKappas {
 	int num_bad_in_avg_re;
 	int num_bad_in_avg_im;
 	int samples_in_filter;
+	int future_unused;
 	guint64 total_samples;
 
 	GMutex reset_mutex;
diff --git a/python/calibration_parts.py b/python/calibration_parts.py
index a237d7f38..938b04b19 100644
--- a/python/calibration_parts.py
+++ b/python/calibration_parts.py
@@ -637,7 +637,8 @@ def remove_lines_with_witnesses(pipeline, signal, witnesses, freqs, freq_vars, f
 					coherence_time = 2 * filter_length // 3
 					secular_dur = (num_median + num_avg) // compute_rate // 2
 					stochastic_dur = int(numpy.sqrt(secular_dur * coherence_time))
-					secular_change = detect_secular_change(pipeline, tf_at_f, secular_dur, stochastic_dur = stochastic_dur, coherence_time = coherence_time, rate = compute_rate)
+					secular_change_filter_latency = 0 if filter_latency == 0 else 0.25 + 0.5 * filter_latency
+					secular_change = detect_secular_change(pipeline, tf_at_f, secular_dur, stochastic_dur = stochastic_dur, coherence_time = coherence_time, rate = compute_rate, filter_latency = secular_change_filter_latency)
 					secular_change = pipeparts.mkgeneric(pipeline, secular_change, "lal_property", update_samples = compute_rate * coherence_time, update_threshold = secular_change_threshold, update_after_gap = True, name = "lal_property_secular_change_%d_%d_%d_%d" % (m, n, i, function_inst_num))
 					tfs_at_f[i] = pipeparts.mkgeneric(pipeline, tf_at_f, "lal_smoothkappas", no_default = True, reject_zeros = False, default_kappa_re = 0.0, min_array_size = min_num_median_avg, array_size = num_median, avg_array_size = num_avg, default_to_median = True, filter_latency = filter_latency, name = "linesub_smoothkappas_%d_%d_%d_%d" % (m, n, i, function_inst_num))
 					secular_change.connect("notify::timestamped-average", reset_secular_change, tfs_at_f[i])
@@ -667,7 +668,8 @@ def remove_lines_with_witnesses(pipeline, signal, witnesses, freqs, freq_vars, f
 							coherence_time = 2 * filter_length // 3
 							secular_dur = (num_median + num_avg) // compute_rate // 2
 							stochastic_dur = int(numpy.sqrt(secular_dur * coherence_time))
-							secular_change = detect_secular_change(pipeline, tf_at_f, secular_dur, stochastic_dur = stochastic_dur, coherence_time = coherence_time, rate = compute_rate)
+							secular_change_filter_latency = 0 if filter_latency == 0 else 0.25 + 0.5 * filter_latency
+							secular_change = detect_secular_change(pipeline, tf_at_f, secular_dur, stochastic_dur = stochastic_dur, coherence_time = coherence_time, rate = compute_rate, filter_latency = secular_change_filter_latency)
 							secular_change = pipeparts.mkgeneric(pipeline, secular_change, "lal_property", update_samples = compute_rate * coherence_time, update_threshold = secular_change_threshold, update_after_gap = True, name = "lal_property_secular_change_%d_%d_%d_%d_%d" % (m, n, i, j, function_inst_num))
 							tfs_at_f[(i + 1) * len(witnesses[m]) + j] = pipeparts.mkgeneric(pipeline, tf_at_f, "lal_smoothkappas", no_default = True, reject_zeros = False, default_kappa_re = 0.0, min_array_size = min_num_median_avg, array_size = num_median, avg_array_size = num_avg, default_to_median = True, filter_latency = filter_latency)
 							secular_change.connect("notify::timestamped-average", reset_secular_change, tfs_at_f[(i + 1) * len(witnesses[m]) + j])
@@ -2600,7 +2602,7 @@ def remove_systematic_error(pipeline, res, res_rate, tst, tst_rate, pum, pum_rat
 
 	return res, tst, pum, uim
 
-def detect_secular_change(pipeline, head, secular_dur, stochastic_dur = 0, coherence_time = 60, rate = 16, secular_dur_min = 0, threshold = 0):
+def detect_secular_change(pipeline, head, secular_dur, stochastic_dur = 0, coherence_time = 60, rate = 16, secular_dur_min = 0, threshold = 0, filter_latency = 0):
 
 	# Set good default values
 	if coherence_time >= secular_dur:
@@ -2614,15 +2616,16 @@ def detect_secular_change(pipeline, head, secular_dur, stochastic_dur = 0, coher
 	head = pipeparts.mktee(pipeline, head)
 	# Make a channel that indicates whether the signal has been gated with a GAP flag
 	nongap = pipeparts.mkbitvectorgen(pipeline, head, nongap_is_control = True, bit_vector = 1)
+	nongap = mkinsertgap(pipeline, nongap, remove_gap = True, insert_gap = False)
 	nongap = pipeparts.mkcapsfilter(pipeline, nongap, "audio/x-raw,format=U32LE,rate=%d,channels=1,channel-mask=(bitmask)0x0" % rate)
 	nongap = pipeparts.mkgeneric(pipeline, nongap, "lal_typecast")
 	nongap = pipeparts.mkcapsfilter(pipeline, nongap, "audio/x-raw,format=F64LE,rate=%d,channels=1,channel-mask=(bitmask)0x0" % rate)
 	head = pipeparts.mktee(pipeline, head)
-	sqrt_num = pipeparts.mkgeneric(pipeline, head, "lal_stdev", mode = 2, array_size = int(secular_dur / coherence_time), coherence_length = int(coherence_time * rate), min_array_size = int(secular_dur_min / coherence_time), percentile = percentile)
+	sqrt_num = pipeparts.mkgeneric(pipeline, head, "lal_stdev", mode = 2, array_size = int(secular_dur / coherence_time), coherence_length = int(coherence_time * rate), min_array_size = int(secular_dur_min / coherence_time), percentile = percentile, filter_latency = filter_latency)
 	num = mkpow(pipeline, sqrt_num, exponent = 2.0)
-	den = pipeparts.mkgeneric(pipeline, head, "lal_stdev", mode = 2, array_size = int(stochastic_dur / coherence_time), coherence_length = int(coherence_time * rate), percentile = percentile)
+	den = pipeparts.mkgeneric(pipeline, head, "lal_stdev", mode = 2, array_size = int(stochastic_dur / coherence_time), coherence_length = int(coherence_time * rate), percentile = percentile, filter_latency = filter_latency)
 	den = mkpow(pipeline, den, exponent = 2.0)
-	den = pipeparts.mkgeneric(pipeline, den, "lal_smoothkappas", array_size = secular_dur * rate, avg_array_size = 1, default_kappa_re = 0, default_to_median = True, no_default = True, min_array_size = secular_dur_min * rate, reject_zeros = False)
+	den = pipeparts.mkgeneric(pipeline, den, "lal_smoothkappas", array_size = secular_dur * rate, avg_array_size = 1, default_kappa_re = 0, default_to_median = True, no_default = True, min_array_size = secular_dur_min * rate, reject_zeros = False, filter_latency = filter_latency)
 	inv_den = complex_inverse(pipeline, den)
 	ratio = mkmultiplier(pipeline, [num, inv_den, nongap])
 	# Get rid of inf's and nan's
-- 
GitLab


From 33caab30881e43e6a88d9485bca256282b136cdb Mon Sep 17 00:00:00 2001
From: Aaron Viets <aaron.viets@ligo.org>
Date: Sat, 15 Feb 2025 14:48:13 -0600
Subject: [PATCH 2/3] lal_smoothkappas:  Fix bookkeeping issues in reset() and
 get_new_median()

---
 gst/lal/gstlal_smoothkappas.c | 70 +++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/gst/lal/gstlal_smoothkappas.c b/gst/lal/gstlal_smoothkappas.c
index 6155fe6a5..fc7d96ec6 100644
--- a/gst/lal/gstlal_smoothkappas.c
+++ b/gst/lal/gstlal_smoothkappas.c
@@ -161,7 +161,7 @@ static void set_metadata(GSTLALSmoothKappas *element, GstBuffer *buf, guint64 ou
 }
 
 
-static void get_new_median(double new_element, double *fifo_array, double *current_median, gint array_size, int *index_re, int *index_im, gboolean array_is_imaginary, int samples_in_filter, gboolean no_default, int *future_unused) {
+static void get_new_median(double new_element, double *fifo_array, double *current_median, gint array_size, int *index_re, int *index_im, gboolean array_is_imaginary, int samples_in_filter, gboolean no_default, int future_unused) {
 	if(array_is_imaginary) {
 		fifo_array[*index_im] = new_element;
 		(*index_im)++;
@@ -180,7 +180,7 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 	greater = Greater = G_MAXDOUBLE;
 	less = Less = -G_MAXDOUBLE;
 	num_samples = (no_default && samples_in_filter < array_size) ? samples_in_filter : array_size;
-	j_start = (array_is_imaginary ? *index_im : *index_re) + array_size - num_samples - *future_unused;
+	j_start = (array_is_imaginary ? *index_im : *index_re) + array_size - num_samples - future_unused;
 	for(j = j_start; j < j_start + num_samples; j++) {
 		jj = j % array_size;
 		if(fifo_array[jj] < *current_median) {
@@ -204,14 +204,15 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 		else
 			g_assert_not_reached();
 	}
-	if(*future_unused > 0)
-		(*future_unused)--;
-
 	g_assert_cmpint(number_less + number_equal + number_greater, ==, num_samples);
 
 	if(num_samples % 2) {
-		if(number_greater > num_samples / 2)
+		if(number_greater > 1 + num_samples / 2)
+			*current_median = Greater;
+		else if(number_greater > num_samples / 2)
 			*current_median = greater;
+		else if(number_less > 1 + num_samples / 2)
+			*current_median = Less;
 		else if(number_less > num_samples / 2)
 			*current_median = less;
 	} else {
@@ -272,8 +273,9 @@ static void reset(GSTLALSmoothKappas *element) {
 	g_assert_cmpint(element->future_unused, >=, 0);
 	/* Drop samples to make truncated array */
 	element->samples_in_filter = element->min_array_size;
-	int i, num_default, ii, i_start, i_stop, num_less, num_greater, num_equal;
+	int i, num_default, ii, i_start, i_stop, num_less, num_greater, num_equal, num_samples;
 	double greater, less, replace_value_re, replace_value_im;
+	num_samples = (element->no_default && element->samples_in_filter < element->array_size) ? element->samples_in_filter : element->array_size;
 
 	/* Update median array and bookkeeping */
 	if(element->array_size > element->samples_in_filter) {
@@ -292,10 +294,12 @@ static void reset(GSTLALSmoothKappas *element) {
 		greater = G_MAXDOUBLE;
 		less = -G_MAXDOUBLE;
 		/* Real part */
-		while(num_less + num_equal + num_greater == 0 || num_greater > element->array_size / 2 || num_less > element->array_size / 2) {
+		while(num_less + num_equal + num_greater == 0 || num_greater > num_samples / 2 || num_less > num_samples / 2) {
 			num_less = 0;
 			num_equal = 0;
 			num_greater = 0;
+			greater = G_MAXDOUBLE;
+			less = -G_MAXDOUBLE;
 			i_start = (element->index_re + 2 * element->array_size - element->samples_in_filter - element->future_unused) % element->array_size;
 			i_stop = i_start + (element->no_default ? element->samples_in_filter : element->array_size);
 			for(i = i_start; i < i_stop; i++) {
@@ -312,15 +316,15 @@ static void reset(GSTLALSmoothKappas *element) {
 						greater = element->fifo_array_re[ii];
 				}
 			}
-			if(num_less == element->array_size / 2 && num_greater == element->array_size / 2 && !(element->array_size % 2))
+			if(num_less == num_samples / 2 && num_greater == num_samples / 2 && !(num_samples % 2))
 				element->current_median_re = (less + greater) / 2;
-			else if(num_less == element->array_size / 2 && !(element->array_size % 2))
+			else if(num_less == num_samples / 2 && !(num_samples % 2))
 				element->current_median_re = (less + element->current_median_re) / 2;
-			else if(num_greater == element->array_size / 2 && !(element->array_size % 2))
+			else if(num_greater == num_samples / 2 && !(num_samples % 2))
 				element->current_median_re = (element->current_median_re + greater) / 2;
-			else if(num_greater > element->array_size / 2)
+			else if(num_greater > num_samples / 2)
 				element->current_median_re = greater;
-			else if(num_less > element->array_size / 2)
+			else if(num_less > num_samples / 2)
 				element->current_median_re = less;
 			/* In all other cases, do nothing */
 		}
@@ -330,10 +334,12 @@ static void reset(GSTLALSmoothKappas *element) {
 		greater = G_MAXDOUBLE;
 		less = -G_MAXDOUBLE;
 		/* Imaginary part */
-		while(num_less + num_equal + num_greater == 0 || num_greater > element->array_size / 2 || num_less > element->array_size / 2) {
+		while(num_less + num_equal + num_greater == 0 || num_greater > num_samples / 2 || num_less > num_samples / 2) {
 			num_less = 0;
 			num_equal = 0;
 			num_greater = 0;
+			greater = G_MAXDOUBLE;
+			less = -G_MAXDOUBLE;
 			i_start = (element->index_im + 2 * element->array_size - element->samples_in_filter - element->future_unused) % element->array_size;
 			i_stop = i_start + (element->no_default ? element->samples_in_filter : element->array_size);
 			for(i = i_start; i < i_stop; i++) {
@@ -350,15 +356,15 @@ static void reset(GSTLALSmoothKappas *element) {
 						greater = element->fifo_array_im[ii];
 				}
 			}
-			if(num_less == element->array_size / 2 && num_greater == element->array_size / 2 && !(element->array_size % 2))
+			if(num_less == num_samples / 2 && num_greater == num_samples / 2 && !(num_samples % 2))
 				element->current_median_im = (less + greater) / 2;
-			else if(num_less == element->array_size / 2 && !(element->array_size % 2))
+			else if(num_less == num_samples / 2 && !(num_samples % 2))
 				element->current_median_im = (less + element->current_median_im) / 2;
-			else if(num_greater == element->array_size / 2 && !(element->array_size % 2))
+			else if(num_greater == num_samples / 2 && !(num_samples % 2))
 				element->current_median_im = (element->current_median_im + greater) / 2;
-			else if(num_greater > element->array_size / 2)
+			else if(num_greater > num_samples / 2)
 				element->current_median_im = greater;
-			else if(num_less > element->array_size / 2)
+			else if(num_less > num_samples / 2)
 				element->current_median_im = less;
 			/* In all other cases, do nothing */
 		}
@@ -370,6 +376,9 @@ static void reset(GSTLALSmoothKappas *element) {
 				element->fifo_array_im[i % element->array_size] = element->current_median_im;
 		}
 	}
+	if(element->future_unused > 0)
+		(element->future_unused)--;
+
 	/* Update average array and bookkeeping */
 	if(element->avg_array_size > element->samples_in_filter) {
 		num_default = element->avg_array_size - element->min_array_size;
@@ -405,7 +414,9 @@ static GstFlowReturn smooth_buffer_ ## DTYPE(const DTYPE *src, guint64 src_size,
 		} \
  \
 		/* Compute new median */ \
-		get_new_median(new_element, fifo_array, current_median, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default, future_unused); \
+		get_new_median(new_element, fifo_array, current_median, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default, *future_unused); \
+		if(*future_unused > 0) \
+			(*future_unused)--; \
 		/* Compute new average */ \
 		new_avg = (DTYPE) get_average(*current_median, avg_array, avg_array_size, avg_index_re, avg_index_im, FALSE, *samples_in_filter + (int) i + 1, no_default); \
 		if (track_bad_kappa) { \
@@ -463,8 +474,10 @@ static GstFlowReturn smooth_complex_buffer_ ## DTYPE(const DTYPE complex *src, g
 			*num_bad_in_avg_im = 0; \
 		} \
 		/* Compute new median */ \
-		get_new_median(new_element_re, fifo_array_re, current_median_re, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default, future_unused); \
-		get_new_median(new_element_im, fifo_array_im, current_median_im, array_size, index_re, index_im, TRUE, *samples_in_filter + (int) i + 1, no_default, future_unused); \
+		get_new_median(new_element_re, fifo_array_re, current_median_re, array_size, index_re, index_im, FALSE, *samples_in_filter + (int) i + 1, no_default, *future_unused); \
+		get_new_median(new_element_im, fifo_array_im, current_median_im, array_size, index_re, index_im, TRUE, *samples_in_filter + (int) i + 1, no_default, *future_unused); \
+		if(*future_unused > 0) \
+			(*future_unused)--; \
 		/* Compute new average */ \
 		new_avg = (DTYPE) get_average(*current_median_re, avg_array_re, avg_array_size, avg_index_re, avg_index_im, FALSE, *samples_in_filter + (int) i + 1, no_default) + I * (DTYPE) get_average(*current_median_im, avg_array_im, avg_array_size, avg_index_re, avg_index_im, TRUE, *samples_in_filter + (int) i + 1, no_default); \
 		if(track_bad_kappa) { \
@@ -791,7 +804,7 @@ static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuf
 	g_mutex_lock(&element->reset_mutex);
 	if(element->num_reset_times > 0) {
 		if(GST_BUFFER_PTS(inbuf) >= *element->reset_times) {
-			if(element->min_array_size < element->samples_in_filter)
+			if(element->min_array_size < element->samples_in_filter && element->min_array_size > 0)
 				reset(element);
 			element->num_reset_times--;
 			for(i = 0; (guint) i < element->num_reset_times; i++)
@@ -817,9 +830,8 @@ static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuf
 		result = smooth_complex_buffer_float((const float complex *) inmap.data, inmap.size / element->unit_size, (float complex *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
 	} else if(element->data_type == GSTLAL_SMOOTHKAPPAS_Z128) {
 		result = smooth_complex_buffer_double((const double complex *) inmap.data, inmap.size / element->unit_size, (double complex *) outmap.data, outmap.size / element->unit_size, element->fifo_array_re, element->fifo_array_im, element->avg_array_re, element->avg_array_im, element->default_kappa_re, element->default_kappa_im, &element->current_median_re, &element->current_median_im, element->maximum_offset_re, element->maximum_offset_im, element->array_size, element->avg_array_size, &element->index_re, &element->index_im, &element->avg_index_re, &element->avg_index_im, &element->num_bad_in_avg_re, &element->num_bad_in_avg_im, gap, element->default_to_median, element->track_bad_kappa, &element->samples_in_filter, element->no_default, &element->total_samples, element->reject_zeros, &element->future_unused);
-	} else {
+	} else
 		g_assert_not_reached();
-	}
 
 	set_metadata(element, outbuf, outmap.size / element->unit_size);
 
@@ -936,6 +948,8 @@ static void set_property(GObject *object, enum property prop_id, const GValue *v
 				old_reset_time = new_reset_time;
 			}
 			g_mutex_unlock(&element->reset_mutex);
+			if(element->min_array_size == 0)
+				GST_WARNING_OBJECT(element, "received a reset time, but min_array_size is not set, so reset will not occur");
 		}
 		break;
 	case ARG_REJECT_ZEROS:
@@ -1079,7 +1093,7 @@ static void gstlal_smoothkappas_class_init(GSTLALSmoothKappasClass *klass)
 			"array-size",
 			"Median array size",
 			"Size of the array of values from which the median is calculated.",
-			G_MININT, G_MAXINT, 2049,
+			0, G_MAXINT, 2049,
 			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT
 		)
 	);
@@ -1090,7 +1104,7 @@ static void gstlal_smoothkappas_class_init(GSTLALSmoothKappasClass *klass)
 			"min-array-size",
 			"Minimum Median Array Size",
 			"Number of samples to be retained in median array when element is reset",
-			G_MININT, G_MAXINT, 0,
+			0, G_MAXINT, 0,
 			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT
 		)
 	);
@@ -1102,7 +1116,7 @@ static void gstlal_smoothkappas_class_init(GSTLALSmoothKappasClass *klass)
 			"Average array size",
 			"Size of the array of values from which the average is calculated\n\t\t\t"
 			"from the median values. By default, no average is taken.",
-			G_MININT, G_MAXINT, 1,
+			0, G_MAXINT, 1,
 			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT
 		)
 	);
-- 
GitLab


From 13c1eb0757055219eb11c2e5d12082810465a00b Mon Sep 17 00:00:00 2001
From: Aaron Viets <aaron.viets@ligo.org>
Date: Sun, 16 Feb 2025 18:06:22 -0800
Subject: [PATCH 3/3] lal_smoothkappas:  fix array indexing

---
 gst/lal/gstlal_smoothkappas.c    |  8 +++-----
 tests/check_calibration/Makefile | 12 ++++++++----
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/gst/lal/gstlal_smoothkappas.c b/gst/lal/gstlal_smoothkappas.c
index fc7d96ec6..d13e525b8 100644
--- a/gst/lal/gstlal_smoothkappas.c
+++ b/gst/lal/gstlal_smoothkappas.c
@@ -182,7 +182,7 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 	num_samples = (no_default && samples_in_filter < array_size) ? samples_in_filter : array_size;
 	j_start = (array_is_imaginary ? *index_im : *index_re) + array_size - num_samples - future_unused;
 	for(j = j_start; j < j_start + num_samples; j++) {
-		jj = j % array_size;
+		jj = (j + array_size) % array_size;
 		if(fifo_array[jj] < *current_median) {
 			number_less++;
 			if(fifo_array[jj] >= less) {
@@ -190,8 +190,7 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 				less = fifo_array[jj];
 			} else if(fifo_array[jj] > Less)
 				Less = fifo_array[jj];
-		}
-		else if(fifo_array[jj] == *current_median)
+		} else if(fifo_array[jj] == *current_median)
 			number_equal++;
 		else if(fifo_array[jj] > *current_median) {
 			number_greater++;
@@ -200,8 +199,7 @@ static void get_new_median(double new_element, double *fifo_array, double *curre
 				greater = fifo_array[jj];
 			} else if(fifo_array[jj] < Greater)
 				Greater = fifo_array[jj];
-		}
-		else
+		} else
 			g_assert_not_reached();
 	}
 	g_assert_cmpint(number_less + number_equal + number_greater, ==, num_samples);
diff --git a/tests/check_calibration/Makefile b/tests/check_calibration/Makefile
index 1a58247c1..c06edb3c2 100644
--- a/tests/check_calibration/Makefile
+++ b/tests/check_calibration/Makefile
@@ -10,7 +10,7 @@ OBSRUN = O3
 # Determines whether to find calibration filters in the old SVN or the git repo.  Starting with PreER15 and O4, we switched to the git repo.  Set to 'svn' or 'git'.
 FILTERSRC = svn
 
-START = $(shell echo 1409576018 | bc)
+START = $(shell echo 1410804916 | bc)
 # 1409576018 or 1410782418 gstlal-calibration-1.5.8 linesub issue
 # 1399057926 line sub not working
 # 1371862818 oversubtraction study
@@ -21,7 +21,7 @@ START = $(shell echo 1409576018 | bc)
 # 1238288418
 # 1269090018
 # 1269114645-21449
-END = $(shell echo 1409604100 | bc)
+END = $(shell echo 1410835618 | bc)
 # 1409604100 or 1410839118 gstlal-calibration-1.5.8 linesub issue
 # 1399086062 line sub not working
 # 1371911734 oversubtraction study
@@ -47,7 +47,8 @@ DCSAPPROXKAPPASCONFIGS = Filters/O3/GDSFilters/H1DCS_test_1256655618_v2_approxKa
 #Filters/O3/GDSFilters/H1DCS_20230407_testing_ApproxKappas.ini
 DCSEXACTKAPPASCONFIGS = Filters/O3/GDSFilters/H1DCS_test_1256655618_v2_exactKappas.ini
 #Filters/O3/GDSFilters/H1DCS_20230407_testing_ExactKappas.ini
-DCSCONFIGS = Filters/O3/GDSFilters/H1DCS_1362848367_PreO4test.ini
+DCSCONFIGS = Filters/O3/GDSFilters/gstlal_compute_strain_C00_unified_offlineTest_H1.ini
+#Filters/O3/GDSFilters/H1DCS_1362848367_PreO4test.ini
 DCSALLCORRCONFIGS = Filters/O3/GDSFilters/H1DCS_lowFreqComb_1260652938_AllCorr.ini
 DCSALLCORREXACTCONFIGS = Filters/O3/GDSFilters/H1DCS_lowFreqComb_1260652938_AllCorrExact.ini
 DCS_TDCF_UNCERTAINTY_CONFIGS = Filters/O3/GDSFilters/H1DCS_1256655618_v2_tdcf_unc.ini
@@ -84,7 +85,7 @@ GDSSHMCONFIGS = Filters/O3/GDSFilters/H1GDS_1258216456_testing.ini
 GDSOLDCONFIGS = Filters/ER14/GDSFilters/L1GDS_1235491416_old.ini
 EASYRAWFILTERS = H1DCS_20230407_testing.npz
 
-all: noise_subtraction_spectrogram_GDS
+all: noise_subtraction_spectrogram_DCS
 # state_vector_plot
 # DARM_over_ASC_callines
 # TDCFs_pcal2darm_plots
@@ -425,6 +426,9 @@ noise_subtraction_ASD_GDS: $(IFO)1_hoft_GDS_frames.cache $(IFO)1_hoft_GDS_frames
 noise_subtraction_spectrogram_GDS: $(IFO)1_hoft_GDS_frames.cache
 	python3 plot_spectrogram.py --gps-start-time $(PLOT_START) --gps-end-time $(PLOT_END) --ifo $(IFO)1 --frame-cache $(IFO)1_hoft_GDS_frames.cache --channel-name GDS-CALIB_STRAIN_NOLINES --sample-rate 16384 --window=3 --frequency-min 10 --frequency-max=1000 --amplitude-min 0.01 --amplitude-max 100
 
+noise_subtraction_spectrogram_DCS: $(IFO)1_hoft_DCS_frames.cache
+	python3 plot_spectrogram.py --gps-start-time $(PLOT_START) --gps-end-time $(PLOT_END) --ifo $(IFO)1 --frame-cache $(IFO)1_hoft_DCS_frames.cache --channel-name DCS-CALIB_STRAIN_NOLINES --sample-rate 16384 --window=3 --frequency-min 10 --frequency-max=1000 --amplitude-min 0.01 --amplitude-max 100
+
 noise_subtraction_ASD_GDS1: $(IFO)1_hoft_GDS_frames.cache $(IFO)1_hoft_GDS_frames_shortTF.cache $(IFO)1_hoft_GDS_frames_longTF.cache
 	python3 plot_ASD.py --gps-start-time $(PLOT_START) --gps-end-time $(PLOT_END) --ifo $(IFO)1 --frame-cache-list $(IFO)1_hoft_GDS_frames.cache,$(IFO)1_hoft_GDS_frames_shortTF.cache,$(IFO)1_hoft_GDS_frames_longTF.cache,$(IFO)1_hoft_GDS_frames.cache --channel-list GDS-CALIB_STRAIN,GDS-CALIB_STRAIN_NOLINES,GDS-CALIB_STRAIN_NOLINES,GDS-CALIB_STRAIN_NOLINES --sample-rate 16384 --fft-time 4096 --fft-spacing 2048 --freq-res 0.001 --frequency-min 410.27 --frequency-max=410.33 --ASD-max=1e-19 --labels 'strain,128s\ estimate,4096s\ estimate,switch'
 
-- 
GitLab