(file) Return to jtsfiddle.c CVS log (file) (dir) Up to [Development] / JSOC / proj / globalhs / apps

File: [Development] / JSOC / proj / globalhs / apps / jtsfiddle.c (download)
Revision: 1.15, Tue Jul 2 19:33:16 2013 UTC (9 years, 10 months ago) by tplarson
Branch: MAIN
CVS Tags: globalhs_version_9, globalhs_version_8, globalhs_version_7, globalhs_version_6, globalhs_version_5, globalhs_version_4, globalhs_version_3, globalhs_version_24, globalhs_version_23, globalhs_version_22, globalhs_version_21, globalhs_version_20, globalhs_version_2, globalhs_version_19, globalhs_version_18, globalhs_version_17, globalhs_version_16, globalhs_version_15, globalhs_version_14, globalhs_version_13, globalhs_version_12, globalhs_version_11, globalhs_version_10, globalhs_version_1, globalhs_version_0, Ver_LATEST, Ver_9-5, Ver_9-41, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, Ver_8-8, Ver_8-7, Ver_8-6, Ver_8-5, Ver_8-4, Ver_8-3, Ver_8-2, Ver_8-12, Ver_8-11, Ver_8-10, Ver_8-1, HEAD
Changes since 1.14: +13 -4 lines
add VERSION parameter, correct bug to now properly reinitialize array msum

/* this JSOC module is a port of an SOI module written by Rasmus Larsen.
 * ported by Tim Larson.
 * tim doubts this works correctly with nskip or navg
 */

/* 
 *  Detrending/gapfilling/differencing module
 *  ts_fiddle_rml upgrades ts_fiddle
 */

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <math.h>
#include <assert.h>
#include <fftw3.h>

#include "jsoc_main.h"
#include "fitsio.h"

#define ARRLENGTH(ARR)  (sizeof(ARR)/sizeof(ARR[0]))
#define kNOTSPECIFIED "not specified"

char *module_name = "jtsfiddle";
char *cvsinfo_jtsfiddle = "cvsinfo: $Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jtsfiddle.c,v 1.15 2013/07/02 20:33:16 tplarson Exp $";

/* Command line arguments: */
ModuleArgs_t module_args[] =
{
  {ARG_STRING,   "in", "", "input data records"},
  {ARG_STRING,   "tsout", kNOTSPECIFIED, "output dataseries for timeseries"},
  {ARG_STRING,   "powout", kNOTSPECIFIED, "output dataseries for power spectra"},
  {ARG_STRING,   "fftout", kNOTSPECIFIED, "output dataseries for fft's"},
  {ARG_STRING,   "fft1out", kNOTSPECIFIED, "output dataseries for fft's reordered"},
  {ARG_STRING,   "arpowout", kNOTSPECIFIED, "output dataseries for AR power"},
  {ARG_STRING,   "mavgout", kNOTSPECIFIED, "output dataseries for m-averaged power spectra"},
//  {ARG_STRING,   "out", "", "output data series"},
  {ARG_STRING,   "segin" , kNOTSPECIFIED, "name of input segment if not using segment 0"},
  {ARG_STRING,   "segout", kNOTSPECIFIED, "name of output segment if not using segment 0"},
  {ARG_STRING,   "histlink", "HISTORY", "name of link to ancillary dataseries for processing metadata"},
  {ARG_STRING,   "srclink",  "SRCDATA", "name of link to source data"},
  {ARG_INT,      "PERM", "1", "set to 0 for transient records, nonzero for permanent records"},
  {ARG_INT,      "VERB", "1",  "option for level of verbosity: 0=only error and warning messages; >0=print messages outside of loop; >1=print messages inside loop; >2=debugging output", NULL},
  {ARG_STRING,   "TAG", kNOTSPECIFIED, "this parameter sets a keyword of the same name to the same value, usually used as an additional primekey"},
  {ARG_STRING,   "VERSION", kNOTSPECIFIED, "this parameter sets a keyword of the same name to the same value, useful for selecting obsolete records"},

  {ARG_STRING,   "LOGFILE", "stdout", ""},
  {ARG_STRING,   "GAPFILE", "", "record or file containing window function"},
  {ARG_STRING,   "SECTIONFILE", kNOTSPECIFIED, "record or file specifying continuous sections of data"},

  {ARG_INT,      "NDT", "-1", "", ""},
//  {ARG_FLOAT,    "TSAMPLE", "60", "", ""},
  {ARG_INT,      "IFILL", "1", "", ""},
  {ARG_INT,      "IFIRST", "0", "", ""},
//  {ARG_INT,      "FLIPM", "0", "", ""},
  {ARG_INT,      "MAX_AR_ORDER", "360", "", ""},
  {ARG_INT,      "FU_FIT_EDGES", "1", "", ""},
  {ARG_INT,      "FU_ITER", "3", "", ""},
  {ARG_INT,      "FU_MIN_PERCENT", "90", "", ""},
  {ARG_FLOAT,    "CDETREND", "50.0", "", ""},
  {ARG_INT,      "DETREND_LENGTH", "1600", "", ""},
  {ARG_INT,      "DETREND_SKIP", "1440", "", ""},
  {ARG_INT,      "DETREND_FIRST", "0", "", ""},
/*
  {ARG_INT,      "TSOUT", "0", "", ""},
  {ARG_INT,      "FFTOUT", "0", "", ""},
  {ARG_INT,      "FFT1OUT", "0", "", ""},
  {ARG_INT,      "POWOUT", "0", "", ""},
  {ARG_INT,      "ARPOWOUT", "0", "", ""},
  {ARG_INT,      "MAVGOUT", "0", "", ""},
*/
  {ARG_INT,      "NAVG", "0", "", ""},
  {ARG_INT,      "NSKIP", "0", "", ""},
  {ARG_INT,      "NOFF", "0", "", ""},
  {ARG_INT,      "IMIN", "0", "", ""},
  {ARG_INT,      "IMAX", "-1", "", ""},
  {ARG_END},
};

#include "saveparm.c"
#include "timing.c"
#include "set_history.c"

extern void cdetrend_discontig( int n, _Complex float *data, int *isgood, 
				int degree, int length, int skip, 
				int m, int *sect_last, int detrend_first);

int cfahlman_ulrych(int n, _Complex float *data, int *isgood, 
		    int minpercentage, int maxorder, int iterations, 
		    int padends, int *order, _Complex float *ar_coeff);

//char *getdetrendversion(void);
//char *getgapfillversion(void);

/* global variables holding the values of the command line variables. */
static char *logfile, *gapfile, *sectionfile;
static int lmode, n_sampled_out, ifill, flipm;
static int ar_order, max_ar_order, fu_iter, fu_fit_edges;
static int fu_min_percent;
static int detrend_length, detrend_skip, detrend_first;
static float tsample, detrend_const;
static int ifirst, tsout,fftout, fft1out, powout, arpowout, mavgout;
static int navg, nskip, noff, imin, imax;


/* Prototypes for local functions. */
static double splitting(int l, int m);

/* Prototypes for external functions */
extern void cffti_(int *, float *);
extern void cfftb_(int *, float *, float *);
static int extract_gaps(int n_in, int *gaps_in, int *n_out, int *gaps_out, 
		  float tsample_in, float *tsample_out,
		  int *num_sections, int *sections);
static void extract_data(int n_in, int *gaps, float *data_in, float *data_out);
static int read_section_file(char *filename, int *num_section, int **section);

/************ Here begins the main module **************/
int DoIt(void)
{
  int i;
  int m, n_in, n_sampled_in;
  TIME epoch, step, start, stop;
  int gapsize, istart, istop, data_dim, detrend_order;
  int npow, mshift;
  float tsamplex, df1, c;
  int *agaps;
  int *gaps, *gaps2;
  float *msum, *pow;
  float *data, *out_data, *in_data;
  fftwf_plan plan;
  int num_sections, *sections;
  float *ar_coeff=NULL;
  float *datarr, *datptr, *outptr;
  float *datahold;
  char tstartstr[100];
  int lmin, lmax;

  int fstatus = 0;
  fitsfile *fitsptr;
  long fdims[1];
  long fpixel[]={1};
  int *anynul=0;

  int instart[2], inend[2];
  int tslength[2], tsstart[2], tsend[2], tstotal[2];
  int fft1length[2], fft1start[2], fft1end[2], fft1total[2];
  int powlength[2], powstart[2], powend[2], powtotal[2];
  int status=DRMS_SUCCESS;
  int newstat=0;

  DRMS_Segment_t *segin = NULL;
  DRMS_Segment_t *segout = NULL;
  DRMS_Array_t *inarr = NULL;
  DRMS_Array_t *outarr = NULL;
  DRMS_Record_t *inrec = NULL;
  DRMS_Record_t *outrec = NULL;
  DRMS_Type_t usetype = DRMS_TYPE_FLOAT;
  DRMS_RecLifetime_t lifetime;
  long long histrecnum = -1;
  DRMS_Segment_t *gapseg = NULL;
  DRMS_Array_t *gaparr = NULL;

  HIterator_t outKey_list;
  DRMS_Keyword_t *outKey;
  TIME tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */

  int errbufstat=setvbuf(stderr, NULL, _IONBF, BUFSIZ);
  int outbufstat=setvbuf(stdout, NULL, _IONBF, BUFSIZ);

  double tstart, tstartsave, tstop, tstopsave, cadence, tstartout, tstopout;
  double wt0, wt1, wt2, wt3, wt;
  double ut0, ut1, ut2, ut3, ut;
  double st0, st1, st2, st3, st;
  double ct0, ct1, ct2, ct3, ct;

  wt0=getwalltime();
  ct0=getcputime(&ut0, &st0);

  /* Read input parameters. */
  logfile     = (char *)cmdparams_save_str    (&cmdparams, "LOGFILE", &newstat);
  gapfile     = (char *)cmdparams_save_str    (&cmdparams, "GAPFILE", &newstat);
  sectionfile = (char *)cmdparams_save_str    (&cmdparams, "SECTIONFILE", &newstat);
  n_sampled_out = cmdparams_save_int  (&cmdparams, "NDT", &newstat);
//  tsample     = cmdparams_save_float  (&cmdparams, "TSAMPLE", &newstat);
  ifill       = cmdparams_save_int    (&cmdparams, "IFILL", &newstat);
  max_ar_order= cmdparams_save_int    (&cmdparams, "MAX_AR_ORDER", &newstat);
  fu_fit_edges= cmdparams_save_int    (&cmdparams, "FU_FIT_EDGES", &newstat);
  fu_iter     = cmdparams_save_int    (&cmdparams, "FU_ITER", &newstat);
  fu_min_percent = cmdparams_save_int (&cmdparams, "FU_MIN_PERCENT", &newstat);
  ifirst      = cmdparams_save_int    (&cmdparams, "IFIRST", &newstat);
//  flipm       = cmdparams_save_int    (&cmdparams, "FLIPM", &newstat);
  detrend_const = cmdparams_save_float(&cmdparams, "CDETREND", &newstat);
  detrend_length = cmdparams_save_int (&cmdparams, "DETREND_LENGTH", &newstat);
  detrend_skip = cmdparams_save_int   (&cmdparams, "DETREND_SKIP", &newstat);
  detrend_first = cmdparams_save_int  (&cmdparams, "DETREND_FIRST", &newstat);
/*
  tsout       = cmdparams_save_int    (&cmdparams, "TSOUT", &newstat);
  fftout      = cmdparams_save_int    (&cmdparams, "FFTOUT", &newstat);
  fft1out     = cmdparams_save_int    (&cmdparams, "FFT1OUT", &newstat);
  powout      = cmdparams_save_int    (&cmdparams, "POWOUT", &newstat);
  arpowout    = cmdparams_save_int    (&cmdparams, "ARPOWOUT", &newstat);
  mavgout     = cmdparams_save_int    (&cmdparams, "MAVGOUT", &newstat);
*/
  navg        = cmdparams_save_int    (&cmdparams, "NAVG", &newstat);
  nskip       = cmdparams_save_int    (&cmdparams, "NSKIP", &newstat);
  noff        = cmdparams_save_int    (&cmdparams, "NOFF", &newstat);
  imin        = cmdparams_save_int    (&cmdparams, "IMIN", &newstat);
  imax        = cmdparams_save_int    (&cmdparams, "IMAX", &newstat);

  char *inrecquery = (char *)cmdparams_save_str(&cmdparams, "in", &newstat);
//  char *outseries = (char *)cmdparams_save_str(&cmdparams, "out", &newstat);
  char *segnamein = (char *)cmdparams_save_str(&cmdparams, "segin", &newstat);
  char *segnameout = (char *)cmdparams_save_str(&cmdparams, "segout", &newstat);
  int seginflag = strcmp(kNOTSPECIFIED, segnamein);
  int segoutflag = strcmp(kNOTSPECIFIED, segnameout);
  char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat);
  char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat);
  int verbflag = cmdparams_save_int(&cmdparams, "VERB", &newstat);
  int permflag = cmdparams_save_int(&cmdparams, "PERM", &newstat);
  if (permflag)
    lifetime = DRMS_PERMANENT;
  else
    lifetime = DRMS_TRANSIENT;

  char *tag = (char *)cmdparams_save_str(&cmdparams, "TAG", &newstat);
  int tagflag = strcmp(kNOTSPECIFIED, tag);
  char *version = (char *)cmdparams_save_str(&cmdparams, "VERSION", &newstat);
  int verflag = strcmp(kNOTSPECIFIED, version);

  char *tsseries = (char *)cmdparams_save_str(&cmdparams, "tsout", &newstat);
  tsout = strcmp(kNOTSPECIFIED, tsseries);
  char *powseries = (char *)cmdparams_save_str(&cmdparams, "powout", &newstat);
  powout = strcmp(kNOTSPECIFIED, powseries);
  char *fftseries = (char *)cmdparams_save_str(&cmdparams, "fftout", &newstat);
  fftout = strcmp(kNOTSPECIFIED, fftseries);
  char *fft1series = (char *)cmdparams_save_str(&cmdparams, "fft1out", &newstat);
  fft1out = strcmp(kNOTSPECIFIED, fft1series);
  char *arpowseries = (char *)cmdparams_save_str(&cmdparams, "arpowout", &newstat);
  arpowout = strcmp(kNOTSPECIFIED, arpowseries);
  char *mavgseries = (char *)cmdparams_save_str(&cmdparams, "mavgout", &newstat);
  mavgout = strcmp(kNOTSPECIFIED, mavgseries);

  char *serieslist[6];
  enum seriesindex  {TSOUT, FFTOUT, FFT1OUT, POWOUT, ARPOWOUT, MAVGOUT};
  int  flagarr[6] = {tsout, fftout, fft1out, powout, arpowout, mavgout};
  int mfliparr[6] = {0, 0, 0, 0, 0, 0};
  int msignarr[6] = {0, 0, 0, 0, 0, 0};
  serieslist[TSOUT]=tsseries;
  serieslist[FFTOUT]=fftseries;
  serieslist[FFT1OUT]=fft1series;
  serieslist[POWOUT]=powseries;
  serieslist[ARPOWOUT]=arpowseries;
  serieslist[MAVGOUT]=mavgseries;
  long long histrecnumarr[6]={-1, -1, -1, -1, -1, -1};
  DRMS_RecordSet_t *outrecsetarr[6]={NULL, NULL, NULL, NULL, NULL, NULL};
  DRMS_Record_t       *outrecarr[6]={NULL, NULL, NULL, NULL, NULL, NULL};
  DRMS_Segment_t      *segoutarr[6]={NULL, NULL, NULL, NULL, NULL, NULL};

  /**** Sanity check of input parameters. ****/

  if ((tsout == 0) && (fftout == 0) && (fft1out == 0) && (powout == 0) && (mavgout == 0) && (arpowout == 0)) 
  {
    fprintf(stderr, "ERROR: must specify an output dataseries\n");
    return 1;
  }

  if (navg <= 0) 
    navg=1;
  if (nskip <= 0) 
    nskip=1;
  if ((navg != 1) && (nskip != 1))
  {
    fprintf(stderr, "ERROR: one of navg and nskip must equal 1\n");
    return 1;
  }
  if (noff < 0 || noff >= nskip) 
  {
    fprintf(stderr, "ERROR: noff must be >= 0 and < nskip\n");
    return 1;
  }
  if (arpowout && !ifill)
  {
    fprintf(stderr, "ERROR: must have nonzero ifill with arpowout\n");
    return 1;
  }
  if (fu_min_percent <= 0 || fu_min_percent > 100)
  {
    fprintf(stderr, "ERROR: FU_MIN_PERCENT must be > 0 and <= 100\n");
    return 1;
  }

  if (newstat) 
  {
    fprintf(stderr, "ERROR: problem with input arguments, status = %d, diagnosis follows\n", newstat);
    cpsave_decode_error(newstat);
    return 1;
  }  
  else if (savestrlen != strlen(savestr)) 
  {
    fprintf(stderr, "ERROR: problem with savestr, savestrlen = %d, strlen(savestr) = %d\n", savestrlen, (int)strlen(savestr));
    return 1;
  }


 // these must be present in the output dataseries and variable, not links or constants
 // the loop is only necessary if the output series don't all link to the same history series, which they usually will, but just in case...
  char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"};
  int is, ishold, itest, mflip;
  char *holdseries="";
/*
  char *cvsinfo;
  cvsinfo = (char *)malloc(1024);
  strcpy(cvsinfo,"$Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jtsfiddle.c,v 1.15 2013/07/02 20:33:16 tplarson Exp $");
  strcat(cvsinfo,"\n");
  strcat(cvsinfo,getdetrendversion());
  strcat(cvsinfo,"\n");
  strcat(cvsinfo,getgapfillversion());
*/
  for (is=0;is<6;is++)
  {

    if (!flagarr[is])
      continue;

    DRMS_Record_t *tempoutrec = drms_create_record(drms_env, 
                                                   serieslist[is],
                                                   DRMS_TRANSIENT, 
                                                   &status);

    if (status != DRMS_SUCCESS) 
    {
     fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", serieslist[is], status);
     return 1;
    }

    DRMS_Link_t *histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);


    // set up ancillary dataseries for processing metadata
    if (histlink != NULL) 
    {
      if (strcmp(holdseries, histlink->info->target_series))
      {
        ishold=is;
        holdseries=strdup(histlink->info->target_series);
        histrecnumarr[is]=set_history(histlink);
        if (histrecnumarr[is] < 0)
        {
          fprintf(stderr, "ERROR: problem creating record in history dataseries for output dataseries %s\n", serieslist[is]);
          drms_close_record(tempoutrec, DRMS_FREE_RECORD);
          return 1;
        }
      }
      else
      {
        histrecnumarr[is]=histrecnumarr[ishold];
      }
    }
    else
    {
      fprintf(stderr,"WARNING: could not find history link in output dataseries %s\n", serieslist[is]);
    }

    for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
    {
      DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]);
      if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
      {
        fprintf(stderr, "ERROR: output keyword %s in series %s is either missing, constant, or a link\n", outchecklist[itest], serieslist[is]);
        drms_close_record(tempoutrec, DRMS_FREE_RECORD);
        return 1;
      }
    }

    mflip = drms_getkey_int(tempoutrec, "MFLIPPED", &status);
    if (status == DRMS_SUCCESS)
      mfliparr[is]=mflip;    

    drms_close_record(tempoutrec, DRMS_FREE_RECORD);
  }

// for efficiency require that tsseries and fftseries have the same value of MFLIPPED.  this restriction may be lifted as noted below.
  if ((tsout && fftout) && (mfliparr[TSOUT] != mfliparr[FFTOUT]))
  {
    fprintf(stderr, "ERROR: series %s and %s must have the same value of MFLIPPED\n", tsseries, fftseries);
    return 1;
  }

  if (fits_open_file(&fitsptr, gapfile, READONLY, &fstatus))
  {
    DRMS_RecordSet_t *gaprecset = drms_open_records(drms_env, gapfile, &status);
    if (status != DRMS_SUCCESS || gaprecset == NULL) 
    {
      fprintf(stderr,"ERROR: problem reading gaps: file status = %d, DRMS status = %d\n",fstatus,status);
      return 1;
    }
    if (gaprecset->n == 0)
    {
      fprintf(stderr,"ERROR: gapfile recordset contains no records\n");
      return 1;
    }
    if (gaprecset->n > 1)
    {
      fprintf(stderr,"ERROR: gapfile recordset with more than 1 record not yet supported.\n");
      return 1;
    } 
    gapseg = drms_segment_lookupnum(gaprecset->records[0], 0);
    if (gapseg != NULL)
      gaparr = drms_segment_read(gapseg, DRMS_TYPE_INT, &status);
    if (status != DRMS_SUCCESS || gaparr == NULL || gapseg == NULL)
    {
      fprintf(stderr, "problem reading gaps segment: status = %d\n", status);
      return 1;
    }
    agaps=(int *)(gaparr->data);
    gapsize=gaparr->axis[0];
  }
  else
  {
    fits_get_img_size(fitsptr, 1, fdims, &fstatus);
    gapsize=fdims[0];
    agaps=(int *)(malloc(gapsize*sizeof(int)));
    fits_read_pix(fitsptr, TINT, fpixel, gapsize, NULL, agaps, anynul, &fstatus); 
    fits_close_file(fitsptr, &fstatus);
    if (fstatus) 
    {
      fits_report_error(stderr, fstatus);
      return 1;
    }
  }

  if (verbflag)
    printf("gapfile read, gapsize = %d\n",gapsize);

  data_dim=gapsize;
  if (n_sampled_out>gapsize) 
    data_dim=n_sampled_out;

  /* allocate temporary storage */
  gaps=(int *)(malloc(gapsize*sizeof(int)));
  gaps2=(int *)(malloc(gapsize*sizeof(int)));
  data=(float *)(fftwf_malloc(2*data_dim*sizeof(float)));
  ar_coeff = (float *)malloc((max_ar_order+1)*2*sizeof(float));
// now done below
//  if (fft1out || powout || mavgout || arpowout)
//    pow=(float *)(malloc(n_sampled_out*sizeof(float)));

  /* Read location of jumps. */
  if (!strcmp(sectionfile,kNOTSPECIFIED))
  {
    /* No sections file specified. Assume that the whole 
       time series in one section. */
    num_sections=1;
    sections = malloc(2*sizeof(int));
    sections[0] = 0;
    sections[1] = data_dim-1;
  }
  else
  {
    int secstat;
    if (secstat=read_section_file(sectionfile, &num_sections, &sections))
    {
      DRMS_RecordSet_t *secrecset = drms_open_records(drms_env, sectionfile, &status);
      if (status != DRMS_SUCCESS || secrecset == NULL) 
      {
        fprintf(stderr,"ERROR: problem reading sections: file status = %d, DRMS status = %d\n",secstat,status);
        return 1;
      }
      if (secrecset->n == 0)
      {
        fprintf(stderr,"ERROR: sectionfile recordset contains no records\n");
        return 1;
      }
      if (secrecset->n > 1)
      {
        fprintf(stderr,"ERROR: sectionfile recordset with more than 1 record not yet supported.\n");
        return 1;
      }
      num_sections=drms_getkey_int(secrecset->records[0], "NSECS", NULL);
      if (num_sections < 1)
      {
        fprintf(stderr,"ERROR: Invalid NSECS keywords\n");
        return 1;
      }
      sections = (int *)malloc(2*(num_sections)*sizeof(int));
      char *sectkey=drms_getkey_string(secrecset->records[0], "SECS", NULL);
      sscanf(strtok(sectkey," \n"),"%d",&(sections[0]));
      sscanf(strtok(NULL," \n"),"%d",&(sections[1]));
      int i;
      for (i=2 ;i<2*(num_sections); i+=2)
      {
        sscanf(strtok(NULL," \n"), "%d", &(sections)[i]);
        sscanf(strtok(NULL," \n"), "%d", &(sections)[i+1]);

        if (sections[i]>sections[i+1] || (i>0 && sections[i]<=sections[i-1]))
        {
          fprintf(stderr,"ERROR: Invalid SECS keyword, sections overlap.\n");
          return 1;
        }
      }
      free(sectkey);
    }
  }

  if (verbflag)
    printf("num_sections = %d\n",num_sections);

  DRMS_RecordSet_t *inrecset = drms_open_records(drms_env, inrecquery, &status);

  if (status != DRMS_SUCCESS || inrecset == NULL) 
  {
    fprintf(stderr,"ERROR: problem opening input recordset: status = %d\n",status);
    return 1;
  }
  if (inrecset->n == 0)
  {
    fprintf(stderr, "ERROR: input recordset contains no records\n");
    return 1;
  }

  inrec=inrecset->records[0];
  char *inchecklist[] = {"T_START", "T_STOP", "QUALITY", "LMIN", "LMAX", "T_STEP"};
  for (itest=0; itest < ARRLENGTH(inchecklist); itest++)
  {
    DRMS_Keyword_t *inkeytest = hcon_lookup_lower(&inrec->keywords, inchecklist[itest]);
    if (inkeytest == NULL)
    {
      fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]);
      drms_close_records(inrecset, DRMS_FREE_RECORD);
      return 1;
    }
  }

  cadence=drms_getkey_float(inrec, "T_STEP", NULL); //assume constant across all input records
  tsample=cadence;
  tstartsave=drms_getkey_time(inrec, "T_START", NULL); //must be constant across all input records unless GAPFILE is implemented differently

  int mflipin=drms_getkey_int(inrec, "MFLIPPED", &status);
  if (status != DRMS_SUCCESS) mflipin=0;

// already required mfliparr[TSOUT] == mfliparr[FFTOUT] above
  if (tsout && mfliparr[TSOUT] != mflipin)
    flipm=1;
  else if (fftout && mfliparr[FFTOUT] != mflipin)
    flipm=1;
  else
    flipm=0;

  for (is=2;is<5;is++)
  {
    if (!flagarr[is])
      continue;
    if (mfliparr[is] != (mflipin || flipm))
      msignarr[is]=-1;
    else
      msignarr[is]=1;
  }

  if (mflipin)
    msignarr[MAVGOUT]=1;
  else
    msignarr[MAVGOUT]=-1;

  // changed n_in to gapsize in following call
  if (extract_gaps(gapsize, agaps, &n_sampled_in, gaps, tsample, &tsamplex, &num_sections, sections))
  {
    fprintf(stderr, "ERROR: problem in extract_gaps\n");
    return 1;
  }

  /* Adjust detrend parameters according to the number of
     available points. */
  if (n_sampled_in<detrend_length)
  {
    detrend_length = n_sampled_in;
    detrend_skip = detrend_length;
  }

  int idtf;
  if (detrend_first > 0)
  {
    for (idtf=0;idtf<detrend_first;idtf++)
      gaps[idtf]=0;
  }


  if (n_sampled_out == -1) 
    n_sampled_out = n_sampled_in;
  df1 = tsamplex*n_sampled_out;

  if (fftout || fft1out || powout || arpowout || mavgout)     
    plan = fftwf_plan_dft_1d(n_sampled_out, (fftwf_complex *)data, 
			    (fftwf_complex *)data, FFTW_BACKWARD, FFTW_MEASURE);

  /* Set sum to zero before starting */
  if (mavgout) 
    msum = (float *)malloc((n_sampled_out/2)*sizeof(float));

  if (fft1out || powout || mavgout || arpowout)
  {
    /* Set first and last output index if not set as a parameter. */
    if (imax < imin) 
    {
      imin=0;
      imax=n_sampled_out/2-1;
    }
    npow=imax-imin+1;
    pow=(float *)(malloc(n_sampled_out*sizeof(float)));
    datahold=(float *)malloc(2*npow*sizeof(float));
  }

// needed to implement mfliparr[TSOUT] != mfliparr[FFTOUT] 
//  float *datatemp=(float *)malloc(2*n_sampled_out*sizeof(float));
  float *tmpptr=data;

  if (tsout || fftout) 
  {
    tslength[0]=tstotal[0]=2*n_sampled_out;
    tslength[1]=1;
    tsstart[0]=0;
    tsend[0]=2*n_sampled_out-1;
  }
  if (fft1out)
  {
    fft1length[0]=fft1total[0]=2*npow;
    fft1length[1]=1;
    fft1start[0]=0;
    fft1end[0]=2*npow-1;
  }
  if (powout || arpowout || mavgout)
  {
    powlength[0]=powtotal[0]=npow;
    powlength[1]=1;
    powstart[0]=0;
    powend[0]=npow-1;
  }
  instart[0]=0;
  inend[0]=2*gapsize - 1;

  status=drms_stage_records(inrecset, 1, 0);
  if (status != DRMS_SUCCESS)
  {
    fprintf(stderr, "ERROR: drms_stage_records returned status = %d\n", status);
    return 1;
  }

  for (is=0; is<6; is++)
  {
    if (!flagarr[is])
      continue;

    outrecsetarr[is] = drms_create_records(drms_env, inrecset->n, serieslist[is], DRMS_PERMANENT, &status);

    if (status != DRMS_SUCCESS || outrecsetarr[is] == NULL) 
    {
     fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", serieslist[is], status);
     return 1;
    }
  }

  int irec;
  for (irec=0;irec<inrecset->n;irec++)
  {

    inrec = inrecset->records[irec];

    lmin=drms_getkey_int(inrec, "LMIN", NULL);
    lmax=drms_getkey_int(inrec, "LMAX", NULL);
    if (lmin != lmax)
    {
      fprintf(stderr, "ERROR: lmin != lmax not yet supported.\n");
      return 0;
    }
    lmode=lmin;

    if (verbflag > 1) 
    {
      printf("starting l=%d\n", lmode);
    }

    tstart=drms_getkey_time(inrec, "T_START", NULL);
    tstop =drms_getkey_time(inrec, "T_STOP", NULL);
    cadence=drms_getkey_float(inrec, "T_STEP", NULL);
    if (tstart != tstartsave)
    {
// to lift this restriction must be able to specify multiple gap files/records as input
      sprint_time(tstartstr, tstart, "TAI", 0);
      fprintf(stderr, "ERROR: all input records must have same T_START, record %d has %s\n", irec, tstartstr);
      return 0;
    }

    n_in=(tstop-tstart)/cadence;
    if (n_in != gapsize)
    {
      fprintf(stderr, "ERROR: gaps seem incompatible with timeseries, gapsize=%d, n_in=%d\n", gapsize, n_in);
      return 0;
    }

    tstartout=tstart+ifirst*tsample;
    tstopout=tstartout+df1;
    sprint_time(tstartstr, tstartout, "TAI", 0);

    if (seginflag)
      segin = drms_segment_lookup(inrec, segnamein);
    else
      segin = drms_segment_lookupnum(inrec, 0);
    if (segin == NULL)
    {
      fprintf(stderr, "ERROR: problem looking up input segment: recnum = %lld\n", inrec->recnum);
      return 0;
    }

    for (is=0; is<6; is++)
    {
      if (!flagarr[is])
        continue;
/*
      outrecarr[is] = drms_create_record(drms_env, serieslist[is], DRMS_PERMANENT, &status);
      if (status != DRMS_SUCCESS) 
      {
       fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", serieslist[is], status);
       return 0;
      }
*/
      outrec=outrecsetarr[is]->records[irec];
      if (histrecnumarr[is] > 0)
        drms_setlink_static(outrec, histlinkname,  histrecnumarr[is]);
      drms_setlink_static(outrec, srclinkname,  inrec->recnum);

      if (segoutflag)
        segoutarr[is] = drms_segment_lookup(outrec, segnameout);
      else
        segoutarr[is] = drms_segment_lookupnum(outrec, 0);
      if (segoutarr[is] == NULL)
      {
        fprintf(stderr, "ERROR: problem looking up outputput segment in series %s\n", serieslist[is]);
        return 0;
      }

// the following is not needed if at least one of the first N-1 dimensions are 0 in the jsd, 
// or if the first N-1 dimensions in the jsd are always the dimensions desired.
// it *is* needed any time one must override the jsd defaults
/*
      switch(is)
      {
        case TSOUT:
        case FFTOUT:
          segoutarr[is]->axis[0]=2*n_sampled_out;
          segoutarr[is]->axis[1]=lmode+1;
          break;
        case FFT1OUT:
          segoutarr[is]->axis[0]=2*npow;
          segoutarr[is]->axis[1]=2*lmode+1;
          break;
        case POWOUT:
        case ARPOWOUT:
          segoutarr[is]->axis[0]=npow;
          segoutarr[is]->axis[1]=2*lmode+1;
          break;
        case MAVGOUT:
          segoutarr[is]->axis[0]=npow;
          segoutarr[is]->axis[1]=1;
          break;
        default:
          ;
      }
*/
      switch(is)
      {
        case TSOUT:
        case FFTOUT:
          tstotal[1]=lmode+1;
          break;
        case FFT1OUT:
          fft1total[1]=2*lmode+1;
          break;
        case POWOUT:
        case ARPOWOUT:
          powtotal[1]=2*lmode+1;
          break;
        case MAVGOUT:
        default:
          ;
      }

    }

    if (mavgout)
      for (i=0;i<n_sampled_out/2;i++) 
        msum[i] = 0.0;

  /***** Main Loop over m: Detrend, gapfill and/or compute FFT/power spectrum *******/
    for (m=0; m<=lmode; m++) 
    {

      if (verbflag > 2) 
      {
        printf("starting m=%d\n", m);
      }

      instart[1]=m;
      inend[1]=m;
      inarr = drms_segment_readslice(segin, usetype, instart, inend, &status);
      if (status != DRMS_SUCCESS || inarr == NULL )
      {
        fprintf(stderr, "ERROR: problem reading input segment: status = %d, recnum = %lld\n", status, inrec->recnum);
        return 0;
      }
      in_data=(float *)(inarr->data);

    /* Extracts data copy */
      extract_data(n_sampled_in, gaps, in_data, data);

    /* Detrend entire time series if required */
      if (detrend_const != 0) 
      {
        detrend_order = floor(detrend_length/detrend_const)+2;
        cdetrend_discontig(n_sampled_in, (_Complex float *)data, gaps, 
			 detrend_order, detrend_length, detrend_skip, 
			 num_sections, sections, detrend_first);
      }

    /* Fill gaps in entire time series if required */
      memcpy(gaps2, gaps, n_sampled_in*sizeof(int));
      if (ifill != 0 && max_ar_order > 0) 
      {
        cfahlman_ulrych(n_sampled_in, (_Complex float *)data, gaps2,
		      fu_min_percent, max_ar_order, fu_iter, fu_fit_edges, 
		      &ar_order, (_Complex float *)ar_coeff);
      }

      drms_free_array(inarr);

      memmove(data, &data[2*ifirst], 2*(n_sampled_in-ifirst)*sizeof(float));
      if ((ifirst+n_sampled_out) >= n_sampled_in) 
        memset(&data[2*(n_sampled_in-ifirst)], 0, 2*(n_sampled_out+ifirst-n_sampled_in)*sizeof(float));      

      if (tsout)
      {
// code to flip m on this output separately.  in the present code this has already been accomplished by setting flipm.
/*
        if (mfliparr[TSOUT] != mflipin)
        {
          for (i = 0; i < n_sampled_out; i++)
          {
            datatemp[2*i]=data[2*i];
            datatemp[2*i+1]=-data[2*i+1];
          }
          tmpptr=datatemp;
        }
        else
          tmpptr=data;
*/
        tsstart[1]=m;
        tsend[1]=m;
        outarr = drms_array_create(usetype, 2, tslength, tmpptr, &status);
        outarr->bzero=segoutarr[TSOUT]->bzero;
        outarr->bscale=segoutarr[TSOUT]->bscale;
        status=drms_segment_writeslice_ext(segoutarr[TSOUT], outarr, tsstart, tsend, tstotal, 0);
        free(outarr);
        if (status != DRMS_SUCCESS)
        {
          fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[TSOUT], status, m, tstartstr, lmode, histrecnumarr[TSOUT]);
          return 0;
        }
      }

      if (fftout || fft1out || powout || mavgout)
        fftwf_execute(plan);

      if (fftout)
      {
// code to flip m on this output separately.  in the present code this has already been accomplished by setting flipm.
/*
        if (mfliparr[FFTOUT] != mflipin)
        {
          datatemp[0]=data[0];
          datatemp[1]=-data[1];
          for (i = 1; i < n_sampled_out; i++)
          {
            datatemp[2*i]=data[2*(n_sampled_out-i)];
            datatemp[2*i+1]=-data[2*(n_sampled_out-i)+1];
          }
          tmpptr=datatemp;
        }
        else
          tmpptr=data;
*/
        tsstart[1]=m;
        tsend[1]=m;
        outarr = drms_array_create(usetype, 2, tslength, tmpptr, &status);
        outarr->bzero=segoutarr[FFTOUT]->bzero;
        outarr->bscale=segoutarr[FFTOUT]->bscale;
        status=drms_segment_writeslice_ext(segoutarr[FFTOUT], outarr, tsstart, tsend, tstotal, 0);
        free(outarr);
        if (status != DRMS_SUCCESS)
        {
          fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[FFTOUT], status, m, tstartstr, lmode, histrecnumarr[FFTOUT]);
          return 0;
        }
      }

      if (fft1out)
      {

        fft1start[1]=lmode+m*msignarr[FFT1OUT];
        fft1end[1]=lmode+m*msignarr[FFT1OUT];
        outarr = drms_array_create(usetype, 2, fft1length, data+2*imin, &status);
        outarr->bzero=segoutarr[FFT1OUT]->bzero;
        outarr->bscale=segoutarr[FFT1OUT]->bscale;
        status=drms_segment_writeslice_ext(segoutarr[FFT1OUT], outarr, fft1start, fft1end, fft1total, 0);
        free(outarr);
        if (status != DRMS_SUCCESS)
        {
          fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[FFT1OUT], status, m, tstartstr, lmode, histrecnumarr[FFT1OUT]);
          return 0;
        }

        if (m > 0) 
        {
          /* Do negative m */
          for (i=0; i<npow; i++) 
          {
            /* Conjugate for negative m */
            datahold[2*i] = data[2*(n_sampled_out-imin-i)];
            datahold[2*i+1] = -data[2*(n_sampled_out-imin-i)+1];
          }
          fft1start[1]=lmode-m*msignarr[FFT1OUT];
          fft1end[1]=lmode-m*msignarr[FFT1OUT];
          outarr = drms_array_create(usetype, 2, fft1length, datahold, &status);
          outarr->bzero=segoutarr[FFT1OUT]->bzero;
          outarr->bscale=segoutarr[FFT1OUT]->bscale;
          status=drms_segment_writeslice_ext(segoutarr[FFT1OUT], outarr, fft1start, fft1end, fft1total, 0);
          free(outarr);
          if (status != DRMS_SUCCESS)
          {
            fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[FFT1OUT], status, m, tstartstr, lmode, histrecnumarr[FFT1OUT]);
            return 0;
          }
        }
      }

      if (powout || mavgout)
        for (i = 0; i < n_sampled_out; i++) 
          pow[i] = data[2*i]*data[2*i] + data[2*i+1]*data[2*i+1];

      if (powout)
      {
        powstart[1]=lmode+m*msignarr[POWOUT];
        powend[1]=lmode+m*msignarr[POWOUT];
        outarr = drms_array_create(usetype, 2, powlength, pow+imin, &status);
        outarr->bzero=segoutarr[POWOUT]->bzero;
        outarr->bscale=segoutarr[POWOUT]->bscale;
        status=drms_segment_writeslice_ext(segoutarr[POWOUT], outarr, powstart, powend, powtotal, 0);
        free(outarr);
        if (status != DRMS_SUCCESS)
        {
          fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[POWOUT], status, m, tstartstr, lmode, histrecnumarr[POWOUT]);
          return 0;
        }

        if (m > 0) 
        {
          /* Do negative m */
          if (imin)
            datahold[0] = pow[n_sampled_out-imin];
          else
            datahold[0] = pow[0];
          for (i=1; i<npow;i++) 
            datahold[i] = pow[n_sampled_out-imin-i];

          powstart[1]=lmode-m*msignarr[POWOUT];
          powend[1]=lmode-m*msignarr[POWOUT];
          outarr = drms_array_create(usetype, 2, powlength, datahold, &status);
          outarr->bzero=segoutarr[POWOUT]->bzero;
          outarr->bscale=segoutarr[POWOUT]->bscale;
          status=drms_segment_writeslice_ext(segoutarr[POWOUT], outarr, powstart, powend, powtotal, 0);
          free(outarr);
          if (status != DRMS_SUCCESS)
          {
            fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[POWOUT], status, m, tstartstr, lmode, histrecnumarr[POWOUT]);
            return 0;
          }
        }
      }

      if (mavgout)
      {
        mshift = floor(df1*splitting(lmode,m*msignarr[MAVGOUT])+0.5f);
        if (mshift >= 0) 
          for (i=0; i<n_sampled_out/2-mshift; i++)
            msum[i] += pow[mshift+i];
        else
          for (i=0; i<n_sampled_out/2+mshift; i++)
            msum[i-mshift] += pow[i];
        if (m > 0) 
        {
          /* Do negative m */
          mshift = floor(df1*splitting(lmode,-m*msignarr[MAVGOUT])+0.5f);
          if (mshift >=0)
            for (i=1; i<n_sampled_out/2-mshift;i++)
              msum[i] += pow[n_sampled_out-mshift-i];
          else
            for (i=1; i<n_sampled_out/2+mshift; i++)
              msum[i-mshift] += pow[n_sampled_out-i];
        }
      }

      if (arpowout)
      {
        memmove(data, ar_coeff, 2*(ar_order+1)*sizeof(float));
        memset(&data[2*(ar_order+1)],0,2*(n_sampled_out-ar_order-1)*sizeof(float));
        fftwf_execute(plan);
        for (i = 0; i < n_sampled_out; i++) 
          pow[i] = 1.0/(data[2*i]*data[2*i] + data[2*i+1]*data[2*i+1]);

        powstart[1]=lmode+m*msignarr[ARPOWOUT];
        powend[1]=lmode+m*msignarr[ARPOWOUT];
        outarr = drms_array_create(usetype, 2, powlength, pow+imin, &status);
        outarr->bzero=segoutarr[ARPOWOUT]->bzero;
        outarr->bscale=segoutarr[ARPOWOUT]->bscale;
        status=drms_segment_writeslice_ext(segoutarr[ARPOWOUT], outarr, powstart, powend, powtotal, 0);
        free(outarr);
        if (status != DRMS_SUCCESS)
        {
          fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[ARPOWOUT], status, m, tstartstr, lmode, histrecnumarr[ARPOWOUT]);
          return 0;
        }

        if (m > 0) 
        {
          /* Do negative m */
          if (imin)
            datahold[0] = pow[n_sampled_out-imin];
          else
            datahold[0] = pow[0];
          for (i=1; i<npow;i++) 
            datahold[i] = pow[n_sampled_out-imin-i];

          powstart[1]=lmode-m*msignarr[ARPOWOUT];
          powend[1]=lmode-m*msignarr[ARPOWOUT];
          outarr = drms_array_create(usetype, 2, powlength, datahold, &status);
          outarr->bzero=segoutarr[ARPOWOUT]->bzero;
          outarr->bscale=segoutarr[ARPOWOUT]->bscale;
          status=drms_segment_writeslice_ext(segoutarr[ARPOWOUT], outarr, powstart, powend, powtotal, 0);
          free(outarr);
          if (status != DRMS_SUCCESS)
          {
            fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[ARPOWOUT], status, m, tstartstr, lmode, histrecnumarr[ARPOWOUT]);
             return 0;
          }
        }
      }

    } //end of loop over m

    if (mavgout)
    {
      c=1.0f/(2*lmode+1);
      for (i=0; i<npow; i++) 
        datahold[i] = msum[imin+i] * c;
      outarr = drms_array_create(usetype, 2, powlength, datahold, &status);
      outarr->bzero=segoutarr[MAVGOUT]->bzero;
      outarr->bscale=segoutarr[MAVGOUT]->bscale;
      status=drms_segment_write(segoutarr[MAVGOUT], outarr, 0);
      free(outarr);
      if (status != DRMS_SUCCESS)
      {
        fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[MAVGOUT], status, tstartstr, lmode, histrecnum);
        return 0;
      }
    }

    for (is=0;is<6;is++)
    {
      if (!flagarr[is])
        continue;

      outrec=outrecsetarr[is]->records[irec];
      drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
      drms_setkey_int(outrec, "QUALITY", 0);
      drms_setkey_time(outrec, "T_START", tstartout);
      drms_setkey_time(outrec, "T_STOP", tstopout);
      drms_setkey_time(outrec, "T_OBS", (tstartout + tstopout)/2);
      drms_setkey_float(outrec, "T_STEP", tsamplex);
      drms_setkey_int(outrec, "NDT", n_sampled_out);
      if (tagflag)
        drms_setkey_string(outrec, "TAG", tag);
      if (verflag)
         drms_setkey_string(outrec, "VERSION", version);

      tnow = (double)time(NULL);
      tnow += UNIX_epoch;
      drms_setkey_time(outrec, "DATE", tnow);

//      drms_close_record(outrec, DRMS_INSERT_RECORD);

    }

  }

  drms_close_records(inrecset, DRMS_FREE_RECORD);
  for (is=0;is<6;is++)
  {
    if (!flagarr[is])
      continue;
    drms_close_records(outrecsetarr[is], DRMS_INSERT_RECORD);
  }

  if(ar_coeff != NULL)
    free(ar_coeff);

  if (fftout || fft1out || powout || arpowout || mavgout)   
    fftwf_destroy_plan(plan); 

  wt=getwalltime();
  ct=getcputime(&ut, &st);
  if (verbflag) 
  {
    printf("total time spent: %.2f ms wall time, %.2f ms cpu time\n", 
            wt-wt0, ct-ct0);
  }

  printf("module %s successful completion\n", cmdparams.argv[0]);
  return 0;
}


static double splitting(int l, int m)
{
  double a1x[] = {406.0,407.0,408.0,410.5,412.0,411.5,409.0,406.0,406.0};
  double a3x[] = {10.0,10.0,15.0,19.5,21.0,21.3,21.3,21.3,21.8};
  double a5x[] = {0.0,0.0,0.0,-1.5,-2.5,-3.5,-4.0,-4.0,-4.5};
  /* f0 is the frequency used for generating the above a-coeff */
  double f0 = 1500.0;
  /* fcol is the frequency for which to optimize the collaps */
  double fcol = 800.0;

  double ll,x,x3,x5,a1,a2,a3,a5,frac,lx;
  int ix;

  if (l == 0) 
    ll = 1; 
  else 
    ll = sqrt(l*(l+1.));
  x = m/ll;
  x3 = x*x*x;
  x5 = x3*x*x;
  lx = 5*log10(l*f0/fcol)-4;
  ix = floor(lx);
  frac = lx-ix;
  if (lx <= 0) {
    ix = 0;
    frac = 0.0;
  }
  if (lx >=8) {
    ix = 7;
    frac = 1.0;
  }
  a1 = (1.0-frac)*a1x[ix]+frac*a1x[ix+1];
  a2 = 0.0;
  a3 = (1.0-frac)*a3x[ix]+frac*a3x[ix+1];
  a5 = (1.0-frac)*a5x[ix]+frac*a5x[ix+1];

  return ll*(a1*x+a2*(1.5*x*x-0.5)+a3*(2.5*x3-1.5*x)+a5*(63./8.*x5-70./8.*x3+15./8.*x))/1e9;
}



/* Extract the data samples actually used by skipping or averaging
   data. Replace missing data that are not marked as gaps with zero. */
void extract_data(int n_in, int *gaps, float *data_in, float *data_out)
{
  int i,j, nmiss = 0;
// the following check will be skipped in production executables since they will be built with NDEBUG defined.
// it doesn't matter because the check is already done in DoIt().
  assert(nskip==1 || navg==1);
  if ((navg == 1) && (nskip == 1)) 
  {
    for (i=0; i<n_in; i++) 
    {
      if (gaps[i]==0 )
      {
	data_out[2*i] = 0.0f;
	data_out[2*i+1] = 0.0f;
      }
      else
      {
	if (isnan(data_in[2*i]) || isnan(data_in[2*i+1]))
	{
	  data_out[2*i] = 0.0f;
	  data_out[2*i+1] = 0.0f;
	  gaps[i] = 0;
	  nmiss++;
	}
	else
	{
	  data_out[2*i] = data_in[2*i];
	  data_out[2*i+1] = flipm ? -data_in[2*i+1] : data_in[2*i+1];
	}
      }
    }
  }
  else if (nskip != 1) 
  {
    for (i = 0; i<n_in; i++) 
    {
      if (gaps[i]==0 )
      {
	data_out[2*i] = 0.0f;
	data_out[2*i+1] = 0.0f;
      }
      else
      {
	int ix = nskip*i+noff;
	if (isnan(data_in[2*ix]) || isnan(data_in[2*ix+1]))
	{
	  data_out[2*i] = 0.0f;
	  data_out[2*i+1] = 0.0f;
	  gaps[i] = 0;
	  nmiss++;
	}
	else
	{
	  data_out[2*i] = data_in[2*ix];
	  data_out[2*i+1] =  flipm ? -data_in[2*ix+1] : data_in[2*ix+1];
	}
      }
    }
  }
  else if (navg != 1) 
  {
    for (i = 0; i<n_in; i++) 
    {
      if (gaps[i]==0 )
      {
	data_out[2*i] = 0.0f;
	data_out[2*i+1] = 0.0f;
      }
      else
      {
	float avgr = 0.0f;
	float avgi = 0.0f;
	for (j=0; j<navg; j++) 
	{
	  int ix = navg*i+j;
	  if (isnan(data_in[2*ix]) || isnan(data_in[2*ix+1]))
	  {
	    data_out[2*i] = 0.0f;
	    data_out[2*i+1] = 0.0f;
	    gaps[i] = 0;
	    nmiss++;
	    break;
	  }
	  else 
	  {
	    avgr += data_in[2*ix];
	    avgi += data_in[2*ix+1];
	  }
	}
	if (j == navg) 
	{
	  data_out[2*i] = avgr/navg;
	  data_out[2*i+1] = avgi/navg;
	}
      }
    }  
  }
}

/* Extract the windows function for the samples actually used after
   subsampling or averaging. Modify the list of continous sections
   accordingly, and make sure we do not average across section boundaries. */
static int extract_gaps(int n_in, int *gaps_in, int *n_out, int *gaps_out, 
		  float tsample_in, float *tsample_out, 
		  int *num_sections, int *sections)
{
// the following check will be skipped in production executables since they will be built with NDEBUG defined.
// it doesn't matter because the check is already done in DoIt().
  assert(nskip==1 || navg==1);
  int i,j,sect, start,stop;


  if (*num_sections<1)
  {
    fprintf(stderr,"Apparantly no sections of data available.");
    return 1;
  }
  /* Mask out data that in between sections if this hasn't already been
     done in gapfile. */
  for (i=0; i<sections[0] && i<n_in; i++)
    gaps_in[i] = 0;
  for (sect=1; sect<(*num_sections); sect++)
  {
    for (i=sections[2*sect-1]+1; i<sections[2*sect] && i<n_in; i++)
      gaps_in[i] = 0;
  }
  for (i=sections[2*(*num_sections-1)+1]+1; i<n_in; i++)
    gaps_in[i] = 0;
    

  if ((navg == 1) && (nskip == 1)) 
  {
    *n_out = n_in;
    *tsample_out = tsample_in;
    for (i=0; i<*n_out; i++) 
      gaps_out[i] = gaps_in[i];
  }
  else if (nskip != 1) 
  {
    *n_out = n_in/nskip;
    *tsample_out = nskip*tsample_in;
    for (i=0; i<*n_out; i++) 
    {
      gaps_out[i] = gaps_in[nskip*i+noff];
    }
    for (i=0; i<2*(*num_sections); i+=2)
    {
      start = (int)ceilf(((float)(sections[i]-noff))/nskip);
      stop = (int)floorf(((float)(sections[i+1]-noff))/nskip);
      if (start <= stop)
      {
	sections[i] = start;
	sections[i+1] = stop;
      }
      else 
      {
	/* This section was skipped entirely. */
	for (j=i; j< 2*(*num_sections-1); j+=2) 
	{
	  sections[j] = sections[j+2];
	  sections[j+1] = sections[j+3];
	}
	*num_sections -= 1;
      }
    }
  }
  else  if (navg != 1) 
  {
    sect = 0;
    *n_out = n_in/navg;
    *tsample_out = tsample*navg;
    for (i=0; i<*n_out; i++) 
    {      
      int igx = 1;
      while (sect < *num_sections && 
	     !(navg*i >= sections[2*sect] && navg*i >= sections[2*sect+1]))
	sect++;

      /* Don't allow averaging of data from different sections. */
      if (navg*i >= sections[2*sect] && (navg*i+navg-1)<=sections[2*sect+1])
      {
	for (j=0; j<navg; j++) 
	  igx *= gaps_in[navg*i+j];
	gaps_out[i] = igx;
      }
      else
	gaps_out[i] = 0;
    }
    for (i=0; i<2*(*num_sections); i+=2)
    {
      start = (int)ceilf(((float)sections[i])/navg);
      stop = (int)floorf(((float)sections[i+1])/navg);
      if (start <= stop)
      {
	sections[i] = start;
	sections[i+1] = stop;
      }
      else 
      {
	/* This section was skipped entirely. */
	for (j=i; j< 2*(*num_sections-1); j+=2) 
	{
	  sections[j] = sections[j+2];
	  sections[j+1] = sections[j+3];
	}
	*num_sections -= 1;
      }
    }
  }  
  return 0;
}


/*
   Read a list of sections [start_sample:end_sample] that should
   contain continuous data. When detrending, jumps are allow to
   occur between sections. The sections file should be a text file 
   of the form:

   num
   start_1  end_1
   start_2  end_2
   ...
   start_num  end_num
*/
static int read_section_file(char *filename, int *num_sections, int **sections)
{
  FILE *fh;
  int i;

  fh = fopen(filename,"r");
  if (fh!=NULL)
  {
    fscanf(fh,"%d",num_sections);
    *sections = (int *)malloc(2*(*num_sections)*sizeof(int));
    
    for (i=0 ;i<2*(*num_sections); i+=2)
    {
      fscanf(fh,"%d",&(*sections)[i]);
      fscanf(fh,"%d",&(*sections)[i+1]);
    
      if ((*sections)[i]>(*sections)[i+1] ||
	  (i>0 && (*sections)[i]<=(*sections)[i-1]))
      {
	fprintf(stderr,"Invalid sections file, sections overlap.\n");
	return 2;
      }
    }
    fclose(fh);
    return 0;
  }
  else 
    return 1;
}  


Karen Tian
Powered by
ViewCVS 0.9.4