From 05b524e7b85fbea4804923b76200d85251dae442 Mon Sep 17 00:00:00 2001
From: Karl Wette <karl.wette@ligo.org>
Date: Wed, 2 Apr 2025 03:20:10 +0000
Subject: [PATCH] Revert "Merge branch 'lal_remove_ReadFTSeries' into 'master'"

This reverts merge request !2440
---
 lal/lib/support/Makefile.am                  |    5 +
 lal/lib/support/ReadFTSeries.h               |  120 ++
 lal/lib/support/ReadFrequencySeries.c        |   88 ++
 lal/lib/support/ReadFrequencySeries_source.c |  169 +++
 lal/lib/support/ReadTimeSeries.c             |   88 ++
 lal/lib/support/ReadTimeSeries_source.c      |  189 +++
 lal/test/support/Makefile.am                 |    2 +
 lal/test/support/PrintFTSeriesTest.c         |  393 +++++
 lal/test/support/ReadFTSeriesTest.c          | 1429 ++++++++++++++++++
 9 files changed, 2483 insertions(+)
 create mode 100644 lal/lib/support/ReadFTSeries.h
 create mode 100644 lal/lib/support/ReadFrequencySeries.c
 create mode 100644 lal/lib/support/ReadFrequencySeries_source.c
 create mode 100644 lal/lib/support/ReadTimeSeries.c
 create mode 100644 lal/lib/support/ReadTimeSeries_source.c
 create mode 100644 lal/test/support/PrintFTSeriesTest.c
 create mode 100644 lal/test/support/ReadFTSeriesTest.c

diff --git a/lal/lib/support/Makefile.am b/lal/lib/support/Makefile.am
index 6c40d1a2c2..16d852ddd7 100644
--- a/lal/lib/support/Makefile.am
+++ b/lal/lib/support/Makefile.am
@@ -9,6 +9,7 @@ pkginclude_HEADERS = \
 	LogPrintf.h \
 	PrintFTSeries.h \
 	PrintVector.h \
+	ReadFTSeries.h \
 	ReadNoiseSpectrum.h \
 	StreamInput.h \
 	StreamOutput.h \
@@ -36,6 +37,8 @@ liblalsupport_la_SOURCES = \
 	LogPrintf.c \
 	PrintFrequencySeries.c \
 	PrintTimeSeries.c \
+	ReadFrequencySeries.c \
+	ReadTimeSeries.c \
 	ReadNoiseSpectrum.c \
 	StreamSeriesInput.c \
 	StreamSeriesOutput.c \
@@ -160,6 +163,8 @@ noinst_HEADERS = \
 	H5ThreadSafe.c \
 	PrintFrequencySeries_source.c \
 	PrintTimeSeries_source.c \
+	ReadFrequencySeries_source.c \
+	ReadTimeSeries_source.c \
 	StreamSequenceInput_source.c \
 	StreamSequenceInputComplex_source.c \
 	StreamSeriesInput_source.c \
diff --git a/lal/lib/support/ReadFTSeries.h b/lal/lib/support/ReadFTSeries.h
new file mode 100644
index 0000000000..ad70cfd2ba
--- /dev/null
+++ b/lal/lib/support/ReadFTSeries.h
@@ -0,0 +1,120 @@
+/*
+*  Copyright (C) 2007 Jolien Creighton
+*
+*  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 with program; see the file COPYING. If not, write to the
+*  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+*  MA  02110-1301  USA
+*/
+
+#ifndef _READFTSERIES_H
+#define _READFTSERIES_H
+
+#include <lal/LALStdlib.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup ReadFTSeries_h Header ReadFTSeries.h
+ * \ingroup lal_support
+ * \author Torres, C. W.
+ *
+ * \brief This is a simple utility to Read time and frequency series into a file.
+ *
+ * ### Synopsis ###
+ *
+ * \code
+ * #include <lal/ReadFTSeries.h>
+ * \endcode
+ *
+ * Provides prototype information for the routines in \ref ReadTimeSeries_c and \ref ReadFrequencySeries_c.
+ */
+/** @{ */
+
+/**\name Error Codes */ /** @{ */
+#define  READFTSERIESH_EFILENOTFOUND       1    /**< Invalid Filename or File Not Found */
+#define  READFTSERIESH_EPARSE              2    /**< Error Parsing File */
+/** @} */
+/** \cond DONT_DOXYGEN */
+#define  READFTSERIESH_MSGEFILENOTFOUND    "Invalid Filename or File Not Found"
+#define  READFTSERIESH_MSGEPARSE           "Error Parsing File"
+/** \endcond */
+
+
+#ifndef SWIG /* exclude from SWIG interface */
+/** \cond DONT_DOXYGEN */
+enum enumLALSupportUnitTextSize {
+  LALSupportUnitTextSize = sizeof("10^-32768 m^-32768/32767 "
+                                  "kg^-32768/32767 "
+                                  "s^-32768/32767 A^-32768/32767 "
+                                  "K^-32768/32767 strain^-32768/32767 "
+                                  "count^-32768/32767")
+};
+enum enumMaxLineLength {
+  MaxLineLength = LALSupportUnitTextSize + sizeof("Units are ()\n")
+};
+/** \endcond */
+#endif /* SWIG */
+
+/** @} */
+
+
+/**
+ * \defgroup ReadTimeSeries_c Module ReadTimeSeries.c
+ * \ingroup ReadFTSeries_h
+ * \author Torres, C. V.
+ *
+ * \brief Each member of this family of functions reads from a file the output of the corresponding \c PrintTimeSeries routine.
+ *
+ * ### Notes ###
+ *
+ * These functions perform I/O operations, which are not a part of LAL
+ * proper They should only be used for debugging purposes in test
+ * functions, not in any production code.
+ */
+/** @{ */
+void LALReadTimeSeries(LALStatus* status,  REAL4TimeSeries *series , const CHAR *filename );
+void LALSReadTimeSeries(LALStatus* status,  REAL4TimeSeries *series , const CHAR *filename );
+void LALDReadTimeSeries(LALStatus* status,  REAL8TimeSeries *series , const CHAR *filename );
+void LALCReadTimeSeries(LALStatus* status,  COMPLEX8TimeSeries *series , const CHAR *filename );
+void LALZReadTimeSeries(LALStatus* status,  COMPLEX16TimeSeries *series , const CHAR *filename );
+/** @} */
+
+/**
+ * \defgroup ReadFrequencySeries_c Module ReadFrequencySeries.c
+ * \ingroup ReadFTSeries_h
+ * \author Torres, C. V.
+ *
+ * \brief Each member of this family of functions reads from a file the output of the corresponding \c PrintFrequencySeries routine.
+ *
+ * ### Notes ###
+ *
+ * These functions perform I/O operations, which are not a part of LAL
+ * proper. They should only be used for debugging purposes in test
+ * functions, not in any production code.
+ */
+/** @{ */
+void LALReadFrequencySeries(LALStatus* status,  REAL4FrequencySeries *series , const CHAR *filename );
+void LALSReadFrequencySeries(LALStatus* status,  REAL4FrequencySeries *series , const CHAR *filename );
+void LALDReadFrequencySeries(LALStatus* status,  REAL8FrequencySeries *series , const CHAR *filename );
+void LALCReadFrequencySeries(LALStatus* status, COMPLEX8FrequencySeries *series , const CHAR *filename );
+void LALZReadFrequencySeries(LALStatus* status,  COMPLEX16FrequencySeries *series , const CHAR *filename );
+/** @} */
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* _READSERIES_H */
diff --git a/lal/lib/support/ReadFrequencySeries.c b/lal/lib/support/ReadFrequencySeries.c
new file mode 100644
index 0000000000..0af1f698cd
--- /dev/null
+++ b/lal/lib/support/ReadFrequencySeries.c
@@ -0,0 +1,88 @@
+#include <complex.h>
+#include <lal/LALStdlib.h>
+#include <lal/LALStdio.h>
+#include <lal/FileIO.h>
+#include <string.h>
+#include <lal/LALDatatypes.h>
+#include <lal/Units.h>
+#include <lal/AVFactories.h>
+#include <lal/ReadFTSeries.h>
+
+/* Change the first instance of the target to '\0'; returns 0 on success,
+   1 on failure */
+static INT2 changeCharToNull (CHAR *string, CHAR target, CHAR *offEndOfString)
+{
+  CHAR *charPtr;
+
+  for ( charPtr=string; charPtr<offEndOfString; ++charPtr )
+  {
+    if ( *charPtr == target )
+    {
+      *charPtr = '\0';
+      return 0;
+    }
+  }
+  return 1;
+}
+
+#define TYPECODE Z
+#define TYPE COMPLEX16
+#define BASETYPE REAL8
+#define FMT "%lf\t%lf\t%lf\n"
+#define ARG &(data.array[0]),&(data.array[1])
+#define NARGS 2
+#include "ReadFrequencySeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE C
+#define TYPE COMPLEX8
+#define BASETYPE REAL4
+#define FMT "%lf\t%f\t%f\n"
+#define ARG &(data.array[0]),&(data.array[1])
+#define NARGS 2
+#include "ReadFrequencySeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE D
+#define TYPE REAL8
+#define FMT "%lf\t%lf\n"
+#define ARG data.array
+#define NARGS 1
+#include "ReadFrequencySeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE S
+#define TYPE REAL4
+#define FMT "%lf\t%f\n"
+#define ARG data.array
+#define NARGS 1
+#include "ReadFrequencySeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE
+#define TYPE REAL4
+#define FMT "%lf\t%f\n"
+#define ARG data.array
+#define NARGS 1
+#include "ReadFrequencySeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
diff --git a/lal/lib/support/ReadFrequencySeries_source.c b/lal/lib/support/ReadFrequencySeries_source.c
new file mode 100644
index 0000000000..0c1e9a3ef1
--- /dev/null
+++ b/lal/lib/support/ReadFrequencySeries_source.c
@@ -0,0 +1,169 @@
+#define CONCAT2x(a,b) a##b
+#define CONCAT2(a,b) CONCAT2x(a,b)
+#define CONCAT3x(a,b,c) a##b##c
+#define CONCAT3(a,b,c) CONCAT3x(a,b,c)
+#define STRING(a) #a
+
+#define STYPE CONCAT2(TYPE,FrequencySeries)
+#define VTYPE CONCAT2(TYPE,Sequence)
+#define FUNC CONCAT3(LAL,TYPECODE,ReadFrequencySeries)
+
+#ifndef BASETYPE
+#define BASETYPE TYPE
+#endif
+
+/* Maybe for consistent allocation of memory we should include a
+companion function called element counter that will notify the calling
+routine of how large we should allocate the Series to be before
+calling the read frequency series module */
+
+
+void FUNC ( LALStatus* status,
+                              STYPE *series,
+	                      const CHAR *filename )
+
+{
+  REAL8Vector		*f=NULL;
+  REAL8			*fPtr;
+  REAL8			*fStopPtr;
+  union { TYPE value; BASETYPE array[sizeof(TYPE)/sizeof(BASETYPE)]; } data;
+  TYPE			*outputPtr;
+  FILE			*fp;
+  CHAR			line[MaxLineLength];  /*holds data from each line*/
+  LALUnit		tempUnit;
+  CHARVector            *string=NULL;
+
+  /* need to declare error section here */
+  INITSTATUS(status);
+  ATTATCHSTATUSPTR(status);
+
+  ASSERT( filename != NULL, status, READFTSERIESH_EFILENOTFOUND,
+	  READFTSERIESH_MSGEFILENOTFOUND );
+
+  /* if (filename == NULL) return; */
+
+  fp = LALFopen( filename, "r" );
+  if (fp == NULL)
+  {
+    ABORT( status, READFTSERIESH_EFILENOTFOUND,
+	   READFTSERIESH_MSGEFILENOTFOUND );
+  }
+
+  /* limited to line of data not exceeding MaxLineLength chars*/
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (line[0] != '#' || line[1] != ' ')
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (snprintf( series->name, sizeof( series->name ), "%s", line + 2) < 0)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+  /* Change trailing linefeed to '\0' */
+  if ( changeCharToNull(series->name, '\n', series->name + LALNameLength) )
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (line[0] != '#' || line[1] != ' ')
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+  if (line[2] == '\n')
+  {
+    series->epoch.gpsSeconds = 0;
+    series->epoch.gpsNanoSeconds = 0;
+  }
+  else if ( sscanf( line, "# Epoch is %d seconds, %d nanoseconds\n",
+	            &(series->epoch.gpsSeconds),
+                    &(series->epoch.gpsNanoSeconds) )
+	    != 2 )
+  {
+    ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+  }
+
+  TRY( LALCHARCreateVector(status->statusPtr, &string, MaxLineLength), status );
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+    ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+  }
+
+  if (!strcmp(line,"# Units are ()\n"))
+  {
+    series->sampleUnits = lalDimensionlessUnit;
+  }
+  else {
+    if ( sscanf( line, "# Units are (%[^)]", string->data ) != 1 )
+    {
+      TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+      ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+    }
+    if ( XLALParseUnitString(&tempUnit, string->data) == NULL )
+    {
+      TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+      ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+    }
+    series->sampleUnits = tempUnit;
+  }
+
+  TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+
+  TRY( LALDCreateVector(status->statusPtr, &f, series->data->length),
+       status );
+
+  fPtr = &(f->data[0]);
+  fStopPtr = fPtr + f->length;
+  outputPtr = &(series->data->data[0]);
+
+  if(fgets(line,sizeof(line),fp) == NULL)
+  {
+    TRY( LALDDestroyVector( status->statusPtr, &f ), status );
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  while(fgets(line,sizeof(line),fp)!=NULL)
+  {
+    /*change arg so we dereference pointer */
+    if ( sscanf(line, FMT, fPtr, ARG) != 1 + NARGS )
+    {
+      TRY( LALDDestroyVector( status->statusPtr, &f ), status );
+      ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+    }
+    *(outputPtr) = data.value;
+    fPtr++;
+    outputPtr++;
+
+    if (fPtr > fStopPtr) {
+      TRY( LALDDestroyVector( status->statusPtr, &f ), status );
+      ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+    }
+  }
+  if (fPtr != fStopPtr)
+  {
+    TRY( LALDDestroyVector( status->statusPtr, &f ), status );
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  (series->deltaF) = ( f->data[1] - f->data[0] );
+  (series->f0) = f->data[0];
+
+  TRY( LALDDestroyVector( status->statusPtr, &f ), status );
+
+  DETATCHSTATUSPTR(status);
+  RETURN(status);
+}
+
+#undef BASETYPE
diff --git a/lal/lib/support/ReadTimeSeries.c b/lal/lib/support/ReadTimeSeries.c
new file mode 100644
index 0000000000..d35c7bd2a0
--- /dev/null
+++ b/lal/lib/support/ReadTimeSeries.c
@@ -0,0 +1,88 @@
+#include <complex.h>
+#include <lal/LALStdlib.h>
+#include <lal/LALStdio.h>
+#include <lal/FileIO.h>
+#include <string.h>
+#include <lal/LALDatatypes.h>
+#include <lal/Units.h>
+#include <lal/AVFactories.h>
+#include <lal/ReadFTSeries.h>
+
+/* Change the first instance of the target to '\0'; returns 0 on success,
+   1 on failure */
+static INT2 changeCharToNull (CHAR *string, CHAR target, CHAR *offEndOfString)
+{
+  CHAR *charPtr;
+
+  for ( charPtr=string; charPtr<offEndOfString; ++charPtr )
+  {
+    if ( *charPtr == target )
+    {
+      *charPtr = '\0';
+      return 0;
+    }
+  }
+  return 1;
+}
+
+#define TYPECODE Z
+#define TYPE COMPLEX16
+#define BASETYPE REAL8
+#define FMT "%lf\t%lf\t%lf\n"
+#define ARG &(data.array[0]),&(data.array[1])
+#define NARGS 2
+#include "ReadTimeSeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE C
+#define TYPE COMPLEX8
+#define BASETYPE REAL4
+#define FMT "%lf\t%f\t%f\n"
+#define ARG &(data.array[0]),&(data.array[1])
+#define NARGS 2
+#include "ReadTimeSeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE D
+#define TYPE REAL8
+#define FMT "%lf\t%lf\n"
+#define ARG data.array
+#define NARGS 1
+#include "ReadTimeSeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE S
+#define TYPE REAL4
+#define FMT "%lf\t%f\n"
+#define ARG data.array
+#define NARGS 1
+#include "ReadTimeSeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
+
+#define TYPECODE
+#define TYPE REAL4
+#define FMT "%lf\t%f\n"
+#define ARG data.array
+#define NARGS 1
+#include "ReadTimeSeries_source.c"
+#undef TYPECODE
+#undef TYPE
+#undef FMT
+#undef ARG
+#undef NARGS
diff --git a/lal/lib/support/ReadTimeSeries_source.c b/lal/lib/support/ReadTimeSeries_source.c
new file mode 100644
index 0000000000..2070b40725
--- /dev/null
+++ b/lal/lib/support/ReadTimeSeries_source.c
@@ -0,0 +1,189 @@
+#define CONCAT2x(a,b) a##b
+#define CONCAT2(a,b) CONCAT2x(a,b)
+#define CONCAT3x(a,b,c) a##b##c
+#define CONCAT3(a,b,c) CONCAT3x(a,b,c)
+#define STRING(a) #a
+
+#define STYPE CONCAT2(TYPE,TimeSeries)
+#define VTYPE CONCAT2(TYPE,Sequence)
+#define FUNC CONCAT3(LAL,TYPECODE,ReadTimeSeries)
+
+#ifndef BASETYPE
+#define BASETYPE TYPE
+#endif
+
+
+/* Maybe for consistent allocation of memory we should include a
+companion function called element counter that will notify the calling
+routine of how large we should allocate the Series to be before
+calling the read frequency series module */
+
+
+void
+FUNC ( LALStatus* status,
+                  STYPE *series,
+                  const CHAR *filename )
+
+{
+  REAL8Vector	*t=NULL;
+  REAL8         *tPtr;
+  REAL8         *tStopPtr;
+  union { TYPE value; BASETYPE array[sizeof(TYPE)/sizeof(BASETYPE)]; } data;
+  TYPE	        *outputPtr;
+  FILE		*fp;
+  CHAR		 line[MaxLineLength];  /*holds data from each line*/
+  LALUnit        tempUnit;
+  CHARVector    *string=NULL;
+
+  /* need to declare error section here */
+  INITSTATUS(status);
+  ATTATCHSTATUSPTR(status);
+
+  ASSERT( filename != NULL,status,READFTSERIESH_EFILENOTFOUND,
+	  READFTSERIESH_MSGEFILENOTFOUND );
+
+  /* if (filename == NULL) return; */
+
+  fp = LALFopen( filename, "r" );
+  if (fp == NULL)
+  {
+    ABORT( status, READFTSERIESH_EFILENOTFOUND,
+	   READFTSERIESH_MSGEFILENOTFOUND );
+  }
+
+  /* limited to line of data not exceeding MaxLineLength chars*/
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (line[0] != '#' || line[1] != ' ')
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (snprintf( series->name, sizeof( series->name ), "%s", line + 2) < 0)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+  /* Change trailing linefeed to '\0' */
+  if ( changeCharToNull(series->name, '\n', series->name + LALNameLength) )
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+  if (line[0] != '#' || line[1] != ' ')
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+  if (line[2] == '\n')
+  {
+    series->f0 = 0.0;
+  }
+  else if ( sscanf( line, "# Heterodyned at %lf Hz\n", &(series->f0) ) != 1 )
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  if (line[0] != '#' || line[1] != ' ')
+  {
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+  if (line[2] == '\n')
+  {
+    series->epoch.gpsSeconds = 0;
+    series->epoch.gpsNanoSeconds = 0;
+  }
+  else if ( sscanf( line, "# Epoch is %d seconds, %d nanoseconds\n",
+	            &(series->epoch.gpsSeconds),
+                    &(series->epoch.gpsNanoSeconds) )
+	    != 2 )
+  {
+    ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+  }
+
+  TRY( LALCHARCreateVector(status->statusPtr, &string, MaxLineLength), status );
+
+  if (fgets(line,sizeof(line),fp) == NULL)
+  {
+    TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+    ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+  }
+
+  if (!strcmp(line,"# Units are ()\n"))
+  {
+    series->sampleUnits = lalDimensionlessUnit;
+  }
+  else {
+    if ( sscanf( line, "# Units are (%[^)]", string->data ) != 1 )
+    {
+      TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+      ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+    }
+    if ( XLALParseUnitString(&tempUnit, string->data) == NULL )
+    {
+      TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+      ABORT( status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE );
+    }
+    series->sampleUnits = tempUnit;
+  }
+
+  TRY( LALCHARDestroyVector( status->statusPtr, &string ), status );
+
+  TRY( LALDCreateVector(status->statusPtr, &t, series->data->length),
+       status );
+
+
+  tPtr = &(t->data[0]);
+  tStopPtr = tPtr + t->length;
+  outputPtr = &(series->data->data[0]);
+
+  if(fgets(line,sizeof(line),fp) == NULL)
+  {
+    TRY( LALDDestroyVector( status->statusPtr, &t ), status );
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  while(fgets(line,sizeof(line),fp)!=NULL)
+  {
+    /*change arg so we dereference pointer */
+    if ( sscanf(line, FMT, tPtr, ARG) != 1 + NARGS )
+    {
+      TRY( LALDDestroyVector( status->statusPtr, &t ), status );
+      ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+    }
+    *(outputPtr) = data.value;
+    tPtr++;
+    outputPtr++;
+
+    if (tPtr > tStopPtr)
+    {
+      TRY( LALDDestroyVector( status->statusPtr, &t ), status );
+      ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+    }
+  }
+  if (tPtr != tStopPtr)
+  {
+    TRY( LALDDestroyVector( status->statusPtr, &t ), status );
+    ABORT(status, READFTSERIESH_EPARSE, READFTSERIESH_MSGEPARSE);
+  }
+
+  (series->deltaT) = ( t->data[1] - t->data[0] );
+
+  TRY( LALDDestroyVector( status->statusPtr, &t ), status );
+
+  DETATCHSTATUSPTR(status);
+  RETURN(status);
+}
+
+#undef BASETYPE
diff --git a/lal/test/support/Makefile.am b/lal/test/support/Makefile.am
index 1a3444fb8e..ac7f558bde 100644
--- a/lal/test/support/Makefile.am
+++ b/lal/test/support/Makefile.am
@@ -6,7 +6,9 @@ test_programs += ConfigFileTest
 test_programs += H5FileIOTest
 test_programs += LALMath3DPlotTest
 test_programs += LALMathNDPlotTest
+test_programs += PrintFTSeriesTest
 test_programs += PrintVectorTest
+test_programs += ReadFTSeriesTest
 test_programs += StreamInputTest
 test_programs += StreamSeriesInputTest
 test_programs += TranslateAnglesTest
diff --git a/lal/test/support/PrintFTSeriesTest.c b/lal/test/support/PrintFTSeriesTest.c
new file mode 100644
index 0000000000..369adc9522
--- /dev/null
+++ b/lal/test/support/PrintFTSeriesTest.c
@@ -0,0 +1,393 @@
+/*
+*  Copyright (C) 2007 Jolien Creighton, John Whelan
+*
+*  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 with program; see the file COPYING. If not, write to the
+*  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+*  MA  02110-1301  USA
+*/
+
+/**
+ * \file
+ * \ingroup PrintFTSeries_h
+ * \author J. T. Whelan <jtwhelan@loyno.edu>
+ *
+ * \brief Tests the routines in \ref PrintTimeSeries_c and \ref PrintFrequencySeries_c.
+ *
+ * ### Usage ###
+ *
+ * \code
+ * PrintFTSeriesTest
+ * \endcode
+ *
+ * ### Description ###
+ *
+ * This program generates and prints a sequence of frequency and time
+ * series; the program only detects errors coming from other LAL
+ * functions, so more in-depth testing requires  examinaton of
+ * the output files.  (The program \c ReadFTSeriesTest also tests
+ * the routines in \ref PrintFrequencySeries_c and
+ * \ref ReadFrequencySeries_c.)
+ *
+ * ### Notes ###
+ *
+ * The program as written generates and prints single and double
+ * precision real and complex time and frequency series.  The routines
+ * for integers are not tested.
+ */
+
+/**\name Error Codes */ /** @{ */
+#define PRINTFTSERIESTESTC_ENOM 0       /**< Nominal exit */
+#define PRINTFTSERIESTESTC_EFUN 1       /**< Error from LAL function */
+/** @} */
+
+/** \cond DONT_DOXYGEN */
+
+#define PRINTFTSERIESTESTC_MSGENOM "Nominal exit"
+#define PRINTFTSERIESTESTC_MSGEFUN "Error from LAL function"
+
+
+#include <complex.h>
+#include <lal/Units.h>
+#include <lal/PrintFTSeries.h>
+#include <math.h>
+#include <lal/LALStdlib.h>
+#include <lal/AVFactories.h>
+
+
+int main( void )
+{
+  static LALStatus status;
+
+  COMPLEX16Sequence   *zSequence;
+  COMPLEX8Sequence    *cSequence;
+  REAL8Sequence       *dSequence;
+  REAL4Sequence       *sSequence;
+
+  COMPLEX16TimeSeries   zTimeSeries;
+  COMPLEX8TimeSeries    cTimeSeries;
+  REAL8TimeSeries       dTimeSeries;
+  REAL4TimeSeries       sTimeSeries;
+
+  COMPLEX16FrequencySeries   zFrequencySeries;
+  COMPLEX8FrequencySeries    cFrequencySeries;
+  REAL8FrequencySeries       dFrequencySeries;
+  REAL4FrequencySeries       sFrequencySeries;
+
+  COMPLEX16        *z;
+  COMPLEX8         *c;
+  REAL8            *d;
+  REAL4            *s;
+
+  INT2             n;
+  LIGOTimeGPS      t80;
+  LIGOTimeGPS      t00;
+  LIGOTimeGPS      t10;
+  UINT4            i;
+
+  t80.gpsSeconds = 0;
+  t80.gpsNanoSeconds = 0;
+
+  t00.gpsSeconds = 3600 * 24 * (15 * 365 + 5 * 366);
+  t00.gpsNanoSeconds = 0;
+
+  t10.gpsSeconds = 3600 * 24 * (22 * 365 + 8 * 366);
+  t10.gpsNanoSeconds = 0;
+
+  fprintf(stderr,"Printing COMPLEX16TimeSeries to zTS.dat\n");
+
+  zSequence = NULL;
+
+  LALZCreateVector( &status, &zSequence, 8 );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+  for ( n=zSequence->length, z=zSequence->data; n > 0 ; --n, ++z ) {
+    *z = sinh(90.0*(4-n));
+    *z += - I / (1e-300 + creal(*z));
+  }
+  strncpy(zTimeSeries.name,"Complex time series",LALNameLength);
+  zTimeSeries.sampleUnits = lalDimensionlessUnit;
+  zTimeSeries.deltaT = 1e-3;
+  zTimeSeries.f0 = 0;
+  zTimeSeries.epoch = t80;
+  zTimeSeries.data = zSequence;
+
+  LALZPrintTimeSeries(&zTimeSeries, "zTS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing COMPLEX16FrequencySeries to zFS.dat\n");
+
+  strncpy(zFrequencySeries.name,"Complex frequency series",LALNameLength);
+  zFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  zFrequencySeries.deltaF = 1;
+  zFrequencySeries.epoch = t80;
+  zFrequencySeries.f0 = 0;
+  zFrequencySeries.data = zSequence;
+
+  LALZPrintFrequencySeries(&zFrequencySeries, "zFS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  LALZDestroyVector( &status, &zSequence );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  cSequence = NULL;
+
+  fprintf(stderr,"Printing COMPLEX8TimeSeries to cTS.dat\n");
+
+  LALCCreateVector( &status, &cSequence, 8 );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+  for ( n=cSequence->length, c=cSequence->data; n > 0 ; --n, ++c ) {
+    *c = sinh(9.0*(4-n));
+    *c += - I / (1e-30 + creal(*c));
+  }
+  strncpy(cTimeSeries.name,"Complex time series",LALNameLength);
+  cTimeSeries.sampleUnits = lalDimensionlessUnit;
+  cTimeSeries.deltaT = 1.0/1024.0;
+  cTimeSeries.f0 = 0;
+  cTimeSeries.epoch = t00;
+  cTimeSeries.data = cSequence;
+
+  LALCPrintTimeSeries(&cTimeSeries, "cTS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing COMPLEX8FrequencySeries to cFS.dat\n");
+
+  strncpy(cFrequencySeries.name,"Complex frequency series",LALNameLength);
+  cFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  cFrequencySeries.deltaF = 1;
+  cFrequencySeries.epoch = t80;
+  cFrequencySeries.f0 = 0;
+  cFrequencySeries.data = cSequence;
+
+  LALCPrintFrequencySeries(&cFrequencySeries, "cFS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing REAL8TimeSeries to dTS.dat\n");
+
+  dSequence = NULL;
+
+  LALDCreateVector( &status, &dSequence, 8 );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+  for ( n=dSequence->length, d=dSequence->data; n > 0 ; --n, ++d ) {
+    *d = sinh(90.0*(4-n));
+  }
+  strncpy(dTimeSeries.name,"Real time series",LALNameLength);
+  dTimeSeries.sampleUnits = lalDimensionlessUnit;
+  dTimeSeries.f0 = 0;
+  dTimeSeries.deltaT = 1.0/1024.0;
+  dTimeSeries.epoch = t00;
+  dTimeSeries.data = dSequence;
+
+  LALDPrintTimeSeries(&dTimeSeries, "dTS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing REAL8FrequencySeries to dFS.dat\n");
+
+/*    for ( n=dSequence->length, d=dSequence->data; n > 0 ; --n, ++d ) { */
+/*      *d = 1 / (1e-300 + *d); */
+/*    } */
+  for ( n=dSequence->length, d=dSequence->data; n > 0 ; --n, ++d ) {
+    *d = 1 / (1e-300 + *d);
+  }
+  strncpy(dFrequencySeries.name,"Real frequency series",LALNameLength);
+  dFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  dFrequencySeries.f0 = 0     ;
+  dFrequencySeries.deltaF = 128;
+  dFrequencySeries.epoch = t00;
+  dFrequencySeries.data = dSequence;
+  LALDPrintFrequencySeries(&dFrequencySeries, "dFS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  LALDDestroyVector( &status, &dSequence );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing REAL4TimeSeries to sFS.dat\n");
+
+  sSequence = NULL;
+
+  LALSCreateVector( &status, &sSequence, 8 );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+  for ( n=sSequence->length, s=sSequence->data; n > 0 ; --n, ++s ) {
+    *s = sinh(9.0*(4-n));
+  }
+  strncpy(sFrequencySeries.name,"Real time series",LALNameLength);
+  sTimeSeries.sampleUnits = lalDimensionlessUnit;
+  sTimeSeries.deltaT = 1.0/1024.0;
+  sTimeSeries.f0 = 0;
+  sTimeSeries.epoch = t10;
+  sTimeSeries.data = sSequence;
+  LALSPrintTimeSeries(&sTimeSeries, "sTS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing REAL4FrequencySeries to sFS.dat\n");
+
+  for ( n=sSequence->length, s=sSequence->data; n > 0 ; --n, ++s ) {
+    *s = 1 / (1e-30 + *s);
+  }
+  strncpy(sFrequencySeries.name,"Real frequency series",LALNameLength);
+  sFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  sFrequencySeries.f0 = 0;
+  sFrequencySeries.deltaF = 128;
+  sFrequencySeries.epoch = t10;
+  sFrequencySeries.data = sSequence;
+  LALSPrintFrequencySeries(&sFrequencySeries, "sFS.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  LALSDestroyVector( &status, &sSequence );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing heterodyned REAL8FrequencySeries to hFSe.dat\n");
+
+  strncpy(cFrequencySeries.name,"Heterodyned frequency series",LALNameLength);
+  cFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  cFrequencySeries.f0 = 500.0;
+  cFrequencySeries.deltaF = 50.0;
+  cFrequencySeries.epoch = t00;
+  cFrequencySeries.data = cSequence;
+
+  for (i=0; i<cSequence->length; ++i) {
+    cSequence->data[i] = 1.0*i;
+    cSequence->data[i] += I * (cFrequencySeries.f0 + cFrequencySeries.deltaF * i);
+  }
+
+  LALCPrintFrequencySeries(&cFrequencySeries, "hFSe.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  LALCDestroyVector( &status, &cSequence );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"Printing heterodyned REAL8FrequencySeries to hFSo.dat\n");
+
+  LALCCreateVector( &status, &cSequence, 9 );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  cFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  cFrequencySeries.f0 = 500.0;
+  cFrequencySeries.deltaF = 50.0;
+  cFrequencySeries.epoch = t00;
+  cFrequencySeries.data = cSequence;
+
+  for (i=0; i<cSequence->length; ++i) {
+    cSequence->data[i] = 1.0*i;
+    cSequence->data[i] += I * (cFrequencySeries.f0 + cFrequencySeries.deltaF*i);
+  }
+
+  LALCPrintFrequencySeries(&cFrequencySeries, "hFSo.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+  LALCDestroyVector( &status, &cSequence );
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [PrintFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, PRINTFTSERIESTESTC_MSGEFUN);
+    return PRINTFTSERIESTESTC_EFUN;
+  }
+
+  LALCheckMemoryLeaks();
+
+  return 0;
+}
+/** \endcond */
diff --git a/lal/test/support/ReadFTSeriesTest.c b/lal/test/support/ReadFTSeriesTest.c
new file mode 100644
index 0000000000..8a0e9ce78c
--- /dev/null
+++ b/lal/test/support/ReadFTSeriesTest.c
@@ -0,0 +1,1429 @@
+/*
+*  Copyright (C) 2007 Cristina Valeria Torres, Jolien Creighton, John Whelan
+*
+*  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 with program; see the file COPYING. If not, write to the
+*  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+*  MA  02110-1301  USA
+*/
+
+/**
+ * \file
+ * \ingroup ReadFTSeries_h
+ * \author Torres, C. W.
+ *
+ * \brief Tests the routines in \ref ReadTimeSeries_c and \ref ReadFrequencySeries_c.
+ *
+ * ### Usage ###
+ *
+ * \code
+ * ReadFTSeriesTest
+ * \endcode
+ *
+ * ### Description ###
+ *
+ * For each of the real and complex datatypes (single and double
+ * precision), this program fills a Time- and FrequencySeries, prints
+ * them to disk with the appropriate
+ * \c LALPrint<datatype><tt>FrequencySeries()</tt>
+ * and \c LALPrint<datatype><tt>TimeSeries()</tt>
+ * routines, then reads them back in with the appropriate
+ * \c LALRead<datatype><tt>FrequencySeries()</tt>
+ * and \c LALRead<datatype><tt>TimeSeries()</tt>
+ * routines and checks to make sure the resulting series agree, printing the results to standard error.
+ */
+
+/**\name Error Codes */ /** @{ */
+#define READFTSERIESTESTC_ENOM 0        /**< Nominal exit */
+#define READFTSERIESTESTC_ECHK 1        /**< Error checking failed to catch bad data */
+#define READFTSERIESTESTC_EFUN 2        /**< Subroutine returned error for valid data */
+#define READFTSERIESTESTC_EFLS 3        /**< Subroutine returned unexpected results */
+/** @} */
+
+/** \cond DONT_DOXYGEN */
+#define READFTSERIESTESTC_MSGENOM "Nominal exit"
+#define READFTSERIESTESTC_MSGECHK "Error checking failed to catch bad data"
+#define READFTSERIESTESTC_MSGEFUN "Subroutine returned error for valid data"
+#define READFTSERIESTESTC_MSGEFLS "Subroutine returned unexpected results"
+
+
+#include <lal/Units.h>
+#include <lal/ReadFTSeries.h>
+#include <lal/PrintFTSeries.h>
+#include <math.h>
+#include <lal/LALStdlib.h>
+#include <lal/AVFactories.h>
+#define  READFTSERIESTEST_TOL 1e6
+#define  READFTSERIESTEST_LEN 20
+
+
+
+int main( void )
+{
+  static LALStatus status;
+
+  REAL4Sequence       *sSequenceIn;
+  REAL4Sequence       *sSequenceOut;
+  REAL8Sequence       *dSequenceIn;
+  REAL8Sequence       *dSequenceOut;
+
+  COMPLEX8Sequence    *cSequenceIn;
+  COMPLEX8Sequence    *cSequenceOut;
+  COMPLEX16Sequence   *zSequenceIn;
+  COMPLEX16Sequence   *zSequenceOut;
+
+
+  REAL4FrequencySeries      sFrequencySeries;
+  REAL8FrequencySeries      dFrequencySeries;
+  COMPLEX8FrequencySeries   cFrequencySeries;
+  COMPLEX16FrequencySeries  zFrequencySeries;
+
+  REAL4FrequencySeries      sFrequencySeries2;
+  REAL8FrequencySeries      dFrequencySeries2;
+  COMPLEX8FrequencySeries   cFrequencySeries2;
+  COMPLEX16FrequencySeries  zFrequencySeries2;
+
+  REAL4TimeSeries           sTimeSeries;
+  REAL8TimeSeries           dTimeSeries;
+  COMPLEX8TimeSeries        cTimeSeries;
+  COMPLEX16TimeSeries       zTimeSeries;
+
+  REAL4TimeSeries           sTimeSeries2;
+  REAL8TimeSeries           dTimeSeries2;
+  COMPLEX8TimeSeries        cTimeSeries2;
+  COMPLEX16TimeSeries       zTimeSeries2;
+
+  REAL4            *sData;
+  REAL8            *dData;
+  COMPLEX8         *cData;
+  COMPLEX16        *zData;
+
+  /* Boolean Vars */
+  BOOLEAN     unitComp;
+
+  /* variables for units */
+  RAT4        raise;
+  LALUnit     strainToMinus2;
+  LALUnit     adcToMinus2;
+  LALUnit     adcStrain;
+
+
+  /* This routine should generate a file with data */
+  /* to be read by ReadFTSeries.c*/
+  LIGOTimeGPS  t;
+  UINT4         i;
+
+
+  /* Data Test Variable */
+  UINT4   j;
+
+
+  fprintf(stderr,"Testing value of LALUnitTextSize ... ");
+  if ( (int)LALSupportUnitTextSize != (int)LALUnitTextSize )
+  {
+    fprintf(stderr,"UnitTextSize mismatch: [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  fprintf(stderr,"PASS\n");
+
+  t.gpsSeconds = 0;
+  t.gpsNanoSeconds = 0;
+
+  fprintf(stderr,"Testing Print/Read COMPLEX8FrequencySeries ... ");
+
+  cSequenceIn = NULL;
+  LALCCreateVector(&status, &cSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+  for ( i=1, cData=cSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, cData++ )
+  {
+    *(cData) = crectf( i, i+1 );
+    }
+
+  strncpy(cFrequencySeries.name,"Complex frequency series",LALNameLength);
+  cFrequencySeries.sampleUnits = lalHertzUnit;
+  cFrequencySeries.deltaF = 1;
+  cFrequencySeries.epoch = t;
+  cFrequencySeries.f0 = 5;
+
+  cFrequencySeries.data = cSequenceIn;
+
+  LALCPrintFrequencySeries(&cFrequencySeries, "cFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  cSequenceOut = NULL;
+  LALCCreateVector( &status, &cSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  cFrequencySeries2.data = cSequenceOut;
+
+  LALCReadFrequencySeries(&status, &cFrequencySeries2, "./cFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (fabs(cFrequencySeries.deltaF - cFrequencySeries.deltaF)/
+      cFrequencySeries.deltaF > READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"DeltaF MisMatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (strcmp(cFrequencySeries.name,cFrequencySeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((cFrequencySeries.epoch.gpsSeconds) !=
+      (cFrequencySeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Second Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((cFrequencySeries.epoch.gpsNanoSeconds) !=
+      (cFrequencySeries2.epoch.gpsNanoSeconds))
+  {
+    fprintf(stderr,"Epoch NanosecondMismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((cFrequencySeries.f0) ?
+      (fabs(cFrequencySeries.f0 - cFrequencySeries2.f0)/cFrequencySeries.f0) :
+      (fabs(cFrequencySeries.f0 - cFrequencySeries2.f0)  >
+      READFTSERIESTEST_TOL))
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  unitComp = XLALUnitCompare(&cFrequencySeries.sampleUnits,&cFrequencySeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  for (j = 0; j < cSequenceIn->length;j++)
+  {
+    if ((crealf(cSequenceIn->data[j]) ?
+	 fabs((crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))
+	      /crealf(cSequenceIn->data[j]))
+	 :fabs(crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+    if ((cimagf(cSequenceIn->data[j]) ?
+	 fabs((cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))
+	      /cimagf(cSequenceIn->data[j]))
+	 :fabs(cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+  fprintf(stderr,"PASS\n");
+
+  fprintf(stderr,"Testing Print/Read COMPLEX16FrequencySeries ... ");
+
+  /* Test case 2 */
+
+  t.gpsSeconds = 45678;
+  t.gpsNanoSeconds = 89065834;
+
+  zSequenceIn = NULL;
+  LALZCreateVector( &status, &zSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  for ( i=1, zData=zSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, zData++ )
+  {
+    *(zData) = crect( i/4.0, (i+1)/5.0 );
+  }
+  zFrequencySeries.sampleUnits = lalDimensionlessUnit;
+  strncpy(zFrequencySeries.name,"Complex frequency series",LALNameLength);
+  zFrequencySeries.deltaF = 1.3;
+  zFrequencySeries.epoch = t;
+  zFrequencySeries.f0 = 0;
+  zFrequencySeries.data = zSequenceIn;
+
+  LALZPrintFrequencySeries(&zFrequencySeries, "zFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  zSequenceOut = NULL;
+  LALZCreateVector( &status, &zSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  zFrequencySeries2.data = zSequenceOut;
+
+  LALZReadFrequencySeries(&status, &zFrequencySeries2, "./zFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if ((zFrequencySeries.deltaF) != (zFrequencySeries2.deltaF))
+  {
+    fprintf(stderr,"DeltaF Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (strcmp(zFrequencySeries.name,zFrequencySeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((zFrequencySeries.epoch.gpsSeconds) !=
+      (zFrequencySeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((zFrequencySeries.epoch.gpsNanoSeconds) !=
+      (zFrequencySeries2.epoch.gpsNanoSeconds))
+  {
+    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (zFrequencySeries.f0 ?
+       (fabs(zFrequencySeries.f0 - zFrequencySeries2.f0)/zFrequencySeries.f0)
+       : (fabs(zFrequencySeries.f0 - zFrequencySeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  unitComp = XLALUnitCompare(&zFrequencySeries.sampleUnits,&zFrequencySeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  for (j = 0; j < zSequenceIn->length;j++)
+  {
+    if ((creal(zSequenceIn->data[j]) ?
+	fabs((creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))
+	     /creal(zSequenceIn->data[j])) :
+	fabs(creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))) >
+	READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+   if ((cimag(zSequenceIn->data[j]) ?
+	fabs((cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))
+	     /cimag(zSequenceIn->data[j])) :
+	fabs(cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))) >
+	READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+  fprintf(stderr,"PASS\n");
+
+  fprintf(stderr,"Testing Print/Read REAL8FrequencySeries ... ");
+
+  /* Test case 3 */
+  t.gpsSeconds = 45678;
+  t.gpsNanoSeconds = 89065834;
+
+  dSequenceIn = NULL;
+  LALDCreateVector( &status, &dSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  for ( i=1, dData=dSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, dData++ )
+  {
+    *(dData) = 0.005;
+  }
+
+  strncpy(dFrequencySeries.name,"Complex frequency series",LALNameLength);
+  /* set units */
+  raise.numerator = -2;
+  raise.denominatorMinusOne = 0;
+  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&dFrequencySeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  dFrequencySeries.deltaF = 1.3;
+  dFrequencySeries.epoch = t;
+  dFrequencySeries.f0 = 0;
+  dFrequencySeries.data = dSequenceIn;
+  LALDPrintFrequencySeries(&dFrequencySeries, "dFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  dSequenceOut = NULL;
+  LALDCreateVector( &status, &dSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  dFrequencySeries2.data = dSequenceOut;
+
+  LALDReadFrequencySeries(&status, &dFrequencySeries2, "./dFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if ((dFrequencySeries.deltaF) != (dFrequencySeries.deltaF))
+  {
+    fprintf(stderr,"DeltaF Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (strcmp(dFrequencySeries.name,dFrequencySeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((dFrequencySeries.epoch.gpsSeconds)
+      != (dFrequencySeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((dFrequencySeries.epoch.gpsSeconds)
+      != (dFrequencySeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (dFrequencySeries.f0 ?
+       (fabs(dFrequencySeries.f0 - dFrequencySeries2.f0)/dFrequencySeries.f0)
+       : (fabs(dFrequencySeries.f0 - dFrequencySeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  unitComp = XLALUnitCompare(&dFrequencySeries.sampleUnits,&dFrequencySeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+
+  for (j = 0; j < dSequenceIn->length;j++)
+  {
+    if ((dSequenceIn->data[j] ?
+	 fabs((dSequenceIn->data[j] - dSequenceOut->data[j])
+	      /dSequenceIn->data[j])
+	 :fabs(dSequenceIn->data[j] - dSequenceOut->data[j])) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+
+  }
+
+
+  fprintf(stderr,"PASS\n");
+
+  fprintf(stderr,"Testing Print/Read REAL4FrequencySeries ... ");
+
+
+ /* Test case 4 */
+  t.gpsSeconds = 45678;
+  t.gpsNanoSeconds = 89065834;
+
+  sSequenceIn = NULL;
+  LALSCreateVector( &status, &sSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  for ( i=1, sData=sSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, sData++ )
+  {
+    *(sData) = 0.005;
+  }
+
+  strncpy(sFrequencySeries.name,"Complex frequency series",LALNameLength);
+  /* set units */
+  raise.numerator = -2;
+  raise.denominatorMinusOne = 0;
+  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&sFrequencySeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  sFrequencySeries.deltaF = 1.3;
+  sFrequencySeries.epoch = t;
+  sFrequencySeries.f0 = 5;
+  sFrequencySeries.data = sSequenceIn;
+
+  sSequenceOut = NULL;
+  LALSCreateVector( &status, &sSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  sFrequencySeries2.data = sSequenceOut;
+  LALSPrintFrequencySeries(&sFrequencySeries, "sFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALSReadFrequencySeries(&status, &sFrequencySeries2, "./sFSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (fabs(sFrequencySeries.deltaF - sFrequencySeries2.deltaF)
+      /sFrequencySeries.deltaF > READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"Deltaf Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if (strcmp(sFrequencySeries.name,sFrequencySeries2.name)!=0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if ((sFrequencySeries.epoch.gpsSeconds) !=
+      (sFrequencySeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((sFrequencySeries.epoch.gpsNanoSeconds) !=
+      (sFrequencySeries2.epoch.gpsNanoSeconds))
+  {
+    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (sFrequencySeries.f0 ?
+       (fabs(sFrequencySeries.f0 - sFrequencySeries2.f0)/sFrequencySeries.f0)
+       : (fabs(sFrequencySeries.f0 - sFrequencySeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  unitComp = XLALUnitCompare(&sFrequencySeries.sampleUnits,&sFrequencySeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  for (j = 0; j < sSequenceIn->length;j++)
+  {
+    if ((sSequenceIn->data[j] ?
+	 fabs((sSequenceIn->data[j] - sSequenceOut->data[j])
+	      /sSequenceIn->data[j])
+	 :fabs(sSequenceIn->data[j] - sSequenceOut->data[j])) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+
+  LALCDestroyVector(&status, &cSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALCDestroyVector(&status, &cSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALZDestroyVector(&status, &zSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+  LALZDestroyVector(&status, &zSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALDDestroyVector(&status, &dSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALDDestroyVector(&status, &dSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALSDestroyVector(&status, &sSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALSDestroyVector(&status, &sSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  fprintf(stderr,"PASS\n");
+
+
+  fprintf(stderr,"Testing Print/Read REAL4TimeSeries ... ");
+
+  /* Here is where testing for ReadTimeSeries is done */
+  /* S Case ReadTimeSeries */
+
+  raise.numerator = -2;
+  raise.denominatorMinusOne = 0;
+  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&sTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  t.gpsSeconds = 45678;
+  t.gpsNanoSeconds = 89065834;
+
+  sSequenceIn = NULL;
+  LALSCreateVector( &status, &sSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  for ( i=1, sData=sSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, sData++ )
+  {
+    *(sData) = 0.005;
+  }
+  strncpy(sTimeSeries.name,"Real4 Time series",LALNameLength);
+  sTimeSeries.deltaT = 1.3;
+  sTimeSeries.epoch = t;
+  sTimeSeries.data = sSequenceIn;
+  sTimeSeries.f0 = 5;
+  LALSPrintTimeSeries(&sTimeSeries, "sTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  sSequenceOut = NULL;
+  LALSCreateVector( &status, &sSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  sTimeSeries2.data = sSequenceOut;
+
+  LALSReadTimeSeries(&status, &sTimeSeries2, "./sTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (fabs(sTimeSeries.deltaT-sTimeSeries2.deltaT) /
+      sTimeSeries.deltaT > READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"DeltaT Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if (strcmp(sFrequencySeries.name,sFrequencySeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if ((sTimeSeries.epoch.gpsSeconds) != (sTimeSeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((sTimeSeries.epoch.gpsNanoSeconds) != (sTimeSeries2.epoch.gpsNanoSeconds))
+  {
+    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  /*  printf("%f ... %f  f0 value\n",sTimeSeries.f0,sTimeSeries2.f0);*/
+  if (sTimeSeries.f0 ?
+       (fabs(sTimeSeries.f0 - sTimeSeries2.f0)/sTimeSeries.f0)
+       : (fabs(sTimeSeries.f0 - sTimeSeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  unitComp = XLALUnitCompare(&sTimeSeries.sampleUnits,&sTimeSeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  for (j = 0; j < sSequenceIn->length;j++)
+  {
+    if ((sSequenceIn->data[j] ?
+	 fabs((sSequenceIn->data[j] - sSequenceOut->data[j])
+	      /sSequenceIn->data[j])
+	 :fabs(sSequenceIn->data[j] - sSequenceOut->data[j])) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+  fprintf(stderr,"PASS\n");
+
+  fprintf(stderr,"Testing Print/Read COMPLEX16TimeSeries ... ");
+
+  /* Z case ReadTimeSeries*/
+
+  raise.numerator = -2;
+  raise.denominatorMinusOne = 0;
+  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&zTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  t.gpsSeconds = 45678;
+  t.gpsNanoSeconds = 89065834;
+
+  zSequenceIn = NULL;
+  LALZCreateVector( &status, &zSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  for ( i=1, zData=zSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, zData++ )
+  {
+    *(zData) = crect( 0.005, 1 );
+  }
+  strncpy(zTimeSeries.name,"Complex16 Time series",LALNameLength);
+  zTimeSeries.deltaT = 1.3;
+  zTimeSeries.epoch = t;
+  zTimeSeries.data = zSequenceIn;
+  zTimeSeries.f0 = 0;
+  LALZPrintTimeSeries(&zTimeSeries, "zTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  zSequenceOut = NULL;
+  LALZCreateVector( &status, &zSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  zTimeSeries2.data = zSequenceOut;
+
+  LALZReadTimeSeries(&status, &zTimeSeries2, "./zTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (fabs(zTimeSeries.deltaT) - (zTimeSeries2.deltaT)/zTimeSeries.deltaT >
+      READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"Mismatch DeltaT [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+
+  if (strcmp(zTimeSeries.name,zTimeSeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if ((zTimeSeries.epoch.gpsSeconds) != (zTimeSeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Second Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ( (zTimeSeries.epoch.gpsNanoSeconds)
+       != (zTimeSeries2.epoch.gpsNanoSeconds) )
+  {
+    fprintf(stderr,"Epoch Nanosecond Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if (zTimeSeries.f0 ?
+       (fabs(zTimeSeries.f0 - zTimeSeries2.f0)/zTimeSeries.f0)
+       : (fabs(zTimeSeries.f0 - zTimeSeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  unitComp = XLALUnitCompare(&zTimeSeries.sampleUnits,&zTimeSeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  for (j = 0; j < zSequenceIn->length;j++)
+  {
+    if ((creal(zSequenceIn->data[j]) ?
+	 fabs((creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))
+	      /creal(zSequenceIn->data[j]))
+	 :fabs(creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+    if ((cimag(zSequenceIn->data[j]) ?
+	 fabs((cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))
+	      /cimag(zSequenceIn->data[j]))
+	 :fabs(cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+  fprintf(stderr,"PASS\n");
+
+  fprintf(stderr,"Testing Print/Read REAL8TimeSeries ... ");
+
+  /* D case  ReadTimeSeries*/
+
+  raise.numerator = -2;
+  raise.denominatorMinusOne = 0;
+  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&sTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  strncpy(dTimeSeries.name,"REAL8 Time series",LALNameLength);
+  dTimeSeries.sampleUnits = lalHertzUnit;
+  t.gpsSeconds = 4578;
+  t.gpsNanoSeconds = 890634;
+
+  dSequenceIn = NULL;
+  LALDCreateVector( &status, &dSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+
+  for ( i=1, dData=dSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, dData++ )
+  {
+    *(dData) = 0.005;
+  }
+
+  dTimeSeries.deltaT = 1.3;
+  dTimeSeries.epoch = t;
+  dTimeSeries.data = dSequenceIn;
+  dTimeSeries.f0 = 0;
+  LALDPrintTimeSeries(&dTimeSeries, "dTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  dSequenceOut = NULL;
+  LALDCreateVector( &status, &dSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  dTimeSeries2.data = dSequenceOut;
+  LALDReadTimeSeries(&status, &dTimeSeries2, "./dTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (fabs(dTimeSeries.deltaT) - (dTimeSeries2.deltaT)/dTimeSeries.deltaT
+      > READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"DeltaT Mismatch [ReadFTSeriesTest:%d,%s]\n",status.statusCode,
+	    status.statusDescription );
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (strcmp(dTimeSeries.name,dTimeSeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%d,%s]\n",status.statusCode,
+	    status.statusDescription );
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if ((dTimeSeries.epoch.gpsSeconds) != (dTimeSeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if ((dTimeSeries.epoch.gpsNanoSeconds)
+      != (dTimeSeries2.epoch.gpsNanoSeconds))
+  {
+    fprintf(stderr,"Epoch Nanoseconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if (dTimeSeries.f0 ?
+       (fabs(dTimeSeries.f0 - dTimeSeries2.f0)/dTimeSeries.f0)
+       : (fabs(dTimeSeries.f0 - dTimeSeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  unitComp = XLALUnitCompare(&dTimeSeries.sampleUnits,&dTimeSeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  for (j = 0; j < dSequenceIn->length;j++)
+  {
+    if ((dSequenceIn->data[j] ?
+	 fabs((dSequenceIn->data[j] - dSequenceOut->data[j])
+	      /dSequenceIn->data[j])
+	 :fabs(dSequenceIn->data[j] - dSequenceOut->data[j])) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+  fprintf(stderr,"PASS\n");
+
+  fprintf(stderr,"Testing Print/Read COMPLEX8TimeSeries ... ");
+
+  /* C case ReadTimeSeries*/
+
+  raise.numerator = -2;
+  raise.denominatorMinusOne = 0;
+  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (XLALUnitMultiply(&cTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  t.gpsSeconds = 45678;
+  t.gpsNanoSeconds = 89065834;
+
+  cSequenceIn = NULL;
+  LALCCreateVector( &status, &cSequenceIn, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  for ( i=1, cData=cSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, cData++ )
+  {
+    *(cData) = crectf( 0.005, 1 );
+  }
+  strncpy(cTimeSeries.name,"Complex8 Time series",LALNameLength);
+  cTimeSeries.deltaT = 1.3;
+  cTimeSeries.epoch = t;
+  cTimeSeries.data = cSequenceIn;
+  cTimeSeries.f0 = 0;
+  cSequenceOut = NULL;
+  LALCPrintTimeSeries(&cTimeSeries, "cTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+  LALCCreateVector( &status, &cSequenceOut, READFTSERIESTEST_LEN);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  cTimeSeries2.data = cSequenceOut;
+
+  LALCReadTimeSeries(&status, &cTimeSeries2, "./cTSInput.dat");
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  if (fabs(cTimeSeries.deltaT - cTimeSeries2.deltaT)/cTimeSeries.deltaT
+      > READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"DeltaT Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  if (strcmp(cTimeSeries.name,cTimeSeries2.name) != 0)
+  {
+    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((cTimeSeries.epoch.gpsSeconds) != (cTimeSeries2.epoch.gpsSeconds))
+  {
+    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if ((cTimeSeries.epoch.gpsNanoSeconds)!=(cTimeSeries2.epoch.gpsNanoSeconds))
+  {
+    fprintf(stderr,"Epoch Nanoseconds Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+  if (cTimeSeries.f0 ?
+       (fabs(cTimeSeries.f0 - cTimeSeries2.f0)/cTimeSeries.f0)
+       : (fabs(cTimeSeries.f0 - cTimeSeries2.f0)) >
+       READFTSERIESTEST_TOL)
+  {
+    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  unitComp = XLALUnitCompare(&cTimeSeries.sampleUnits,&cTimeSeries2.sampleUnits);
+
+  if (unitComp != 0)
+  {
+    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
+	    READFTSERIESTESTC_MSGEFLS);
+    return READFTSERIESTESTC_EFLS;
+  }
+
+  for (j = 0; j < cSequenceIn->length;j++)
+  {
+    if ((crealf(cSequenceIn->data[j]) ?
+	 fabs((crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))
+	      /crealf(cSequenceIn->data[j]))
+	 :fabs(crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+    if ((cimagf(cSequenceIn->data[j]) ?
+	 fabs((cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))
+	      /cimagf(cSequenceIn->data[j]))
+	 :fabs(cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))) >
+	 READFTSERIESTEST_TOL)
+    {
+      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
+	      READFTSERIESTESTC_MSGEFLS);
+      return READFTSERIESTESTC_EFLS;
+    }
+  }
+
+  fprintf(stderr,"PASS\n");
+
+  /* *******************Deallocate all memory****************** */
+  LALCDestroyVector(&status, &cSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALCDestroyVector(&status, &cSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALZDestroyVector(&status, &zSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALZDestroyVector(&status, &zSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALDDestroyVector(&status, &dSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALDDestroyVector(&status, &dSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALSDestroyVector(&status, &sSequenceIn);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALSDestroyVector(&status, &sSequenceOut);
+  if (status.statusCode != 0)
+  {
+    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
+	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
+    return READFTSERIESTESTC_EFUN;
+  }
+
+  LALCheckMemoryLeaks();
+
+  fprintf(stderr,"ReadFTSeries passed all tests.\n");
+
+  return READFTSERIESTESTC_ENOM;
+
+}
+/** \endcond */
-- 
GitLab