/***************************************************************************
 * rtdet
 * SeedLink client using libslink (Chad Trabant).
 *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <math.h>		                 // For math routines (such as sqrt & trig).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "gd.h"
#include <sh_mem_rt.h>
#include <libslink.h>
#include <signal.h>
#include <pthread.h>
#include <sys/shm.h>
#include <sys/timeb.h>
#include <sys/stat.h>
#include <dirent.h>

#include "sachdr.h"
#include "ew_bridge.h"
#include "PickData.h"
#include "FilterPicker5_Memory.h"
#include "FilterPicker5.h"


#include <libmseed.h>
#include "cm6.h"

enum ResultType resultType = PICKS;

#define QUEUE 5                     // MAX NUMBER OF EVENTS IN QUEUE

/* prototype for thread routine */
void READ_PACKETS ( void *ptr );
void CHECK_MAILS ( void *ptr);
void WRITE_RTPHASE ( void *ptr);



static void design();
static void appl(int fnd,float fseismo[MAXCHA][2000],int ns[]);
static void STA_LTA();
static void ZERO_START(float scr[]);
static void MaxAmp(int no_of_smp,float scr[],float *MxAmp);
static void Scale_to_1(int no_of_smp,float scr[],float MxAmp);
static void STALTAPHFL(int ne, float kanal[],int ws,int wl,float rat[]);
static void TRIGGER_TIME_P(int ws,int pindex,int kanal,float sr,int sekunder,int lno_str,int ch);
//static int TRIGGER_TIME_FPICK(char P_PHASE[],int lno_str,int ch,int ns[],float values[MAXCHA][RTBUFSIZ]);
static int TRIGGER_TIME_FPICK(char P_PHASE[],int lno_str,int ch,int ns[]);
static void TRIGGER_DUR(int sekunder,int kanal,int nn,int lno_str);
static void C_TIME();
static int Create_Sfile_P(char tid[],char filename[],int nchannels,int subnetno,char SFILNAM[]);
static void CAT_MUL(void *ptr);
static int parameter_proc (int argcount, char **argvec);
static int packet_handler (char *msrecord, int packet_type,
			    int seqnum, int packet_size,SLCD * slconn,int lno_str,int sseismo[MAXCHA][3000],int ns[],int sr[]);


//------------------------pdata-----------------------------------
static void packtraces (flag flush,int nextport,MSTraceGroup*);
static int slg2group (char *slgfile, MSTraceGroup *mstg, int ls,int blokker,int irate,int nextport,int quality,char header[500][150]);
//static int slg2group (char *slgfile, MSTraceGroup *mstg, int ls,int blokker,int irate,int nextport,int quality,char header[500][150],float values[MAXCHA][RTBUFSIZ]);
static int readlistfile (char *listfile);
static void addfile (char *filename);




struct filelink {
  char *filename;
  struct filelink *next;
};

/* A list of input files */
struct filelink *filelist = 0;

static MSTraceGroup *mstg = 0;

static int packedtraces  = 0;
static int packedsamples = 0;
static int packedrecords = 0;

int tq=0;                              // time-quality

static int   verbose2    = 0;
static char  bufferall   = 0;
static char *outputfile  = 0;
static FILE *ofp         = 0;

char out[200];
  float  values[MAXCHA][RTBUFSIZ];    // values per block per channel
//------------------------pdata-----------------------------------


// 2000 i sseismo[MAXCHA][2000]
/* struct to hold data to be passed to a thread
   this shows how multiple data items can be passed to a thread */
typedef struct str_thdata
{
    int thread_no;
    char ipaddr[100];
    char streams[100];
    char stations[100];
    int no_comp;
    int no_str;

} thdata;

typedef struct str_trgmul
{
    int   thread_no;
    int   no_comp;
    int   antkan;
    int   fra;
    int   til;
    int   minimum_no_triggers;
} trgmul;

typedef struct str_catmul
{
    int   thread_no;
    int   maxdur;
    int   no_comp;
    int   antkan;
    int   fra;
    int   til;
} catmul;

typedef struct str_rtphase
{
    int   thread_no;
    int   maxdur;
    int   no_comp;
    int   antkan;
    int   fra;
    int   til;
    char  sname[200];
    char  wname[200];
//    float verdier[MAXCHA][RTBUFSIZ];    
} rtphase;


  int   start_rec[500];                 // start index of record
  int   stopp_rec[500];                 // stop index of record   

  char tabell[MAXCHA][MAXCHA];

rtmod *spt;                            // pointer shared memory

int    klon         = 0;
static short int verbose  = 0;
static short int ppackets = 0;
static char *dumpfile     = 0;	                 /* output file for data dump */
static char *location     = "1";                 // switch to read data for plotting
static FILE *outfile      = 0;                   /* the descriptor for the dumpfile */


int     LOCK=0;
/***************************************************************/
/* Mutex & Condition synchronizing start of threads from main  */
/***************************************************************/
int main_cnd=0;                    // condition variable for main
pthread_mutex_t cnd_mtx_main = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  cnd_cnd_main  = PTHREAD_COND_INITIALIZER;
/***************************************************************/
/* Mutex & Condition synchronizing MEM_RNG and WRT_RNG         */
/***************************************************************/
int mem_wrt_rng_cnd[MAXCHA];
pthread_mutex_t cnd_mtx_MEM_WRT_RNG[MAXCHA];
pthread_cond_t  cnd_cnd_MEM_WRT_RNG[MAXCHA];
//------------------------------------------------------------------
// Mutex & Condition synchronizing of READ_PACKETS and BUFFER_SHUFLE
//------------------------------------------------------------------
pthread_mutex_t shufle_mutex;
pthread_cond_t signal_shufle; 
//------------------------------------------------------------------
// Mutex & Condition synchronizing of READ_PACKETS and BUFFER_SHUFLE
//------------------------------------------------------------------
pthread_mutex_t shift_mutex;
pthread_cond_t signal_shift; 


float LOW_PASS = 2.0;
float HIGH_PASS= 8.0;
float STAW     = 2.0;
float LTAW     = 100.0;
float TRGLEV   = 4.5;
float DTRGLEV  = 2.0;

int    automag        =     0;       // 1 = automag, 0 = no automag
int    wavedbactive   =     0;       // 0 = no wave dbase, 1 = wave dbase
int  keep = 0;
int  sound= 0;


int  printarg = 0;

char *topdir_rt = 0;                   // top directory RTQUAKE
char  *topdir;                         // top directory SEISAN
char  cfgfile[80]   = "";              // configuration file 
char  streamfile[80]= "";              // stream list file to read from seedlink-server
char  detfile[80]   = "";              // components list file for detection 
char  streampath[80]= "";              // complete path for streamfile
char  recpath[80]   = "";              // complete path for recording file
char  detpath[80]   = "";              // complete path for detection file
char  recordfile[80]= "";              // station list for recording
char  trgdir[80]    = "";              // directory for triggers
int   autolocate   = 0;
int   rtsphases    = 0;                // switch phases: 0 = p phases only, 1 = p+s phases
int    mail1          =     0;       // 0-no mail, 1-mail
int    mail2          =     0;       // 0-no mail, 1-mail
int    mail3          =     0;       // 0-no mail, 1-mail1
int    mail4          =     0;       // 0-no mail, 1-mail
int    mail5          =     0;       // 0-no mail, 1-mail
char   mailaddress1[256];            // mailaddress 
char   mailaddress2[256];            // mailaddress 
char   mailaddress3[256];            // mailaddress 
char   mailaddress4[256];            // mailaddress 
char   mailaddress5[256];            // mailaddress 
int    sendmail=0;

  int antsamp[500];
int    kanaler_hver_stream[200];
int    kanaler_hver_record[200];

char   toplot[MAXCHA][50];
char   tmpfiles[MAXCHA][200];
char   staname[MAXCHA][200];


float  filt;

char   fullna[MAXCHA][200];
float  flow;
float  fhigh;
float  tflow[MAXCHA];
float  tfhigh[MAXCHA];

char   allstreams[MAXCHA][200];

//*************************************************************************************
// FOR THE RT PHASE PICKING
//*************************************************************************************
int    mail_switch=0;
char   mail_storage1[1000];
char   mail_storage2[1000];
char   mail_storage3[1000];
char   mail_storage4[1000];
char   mail_storage5[1000];
char   ttdly_rtp[MAXPAR][20][MAXCHA][20];        // P-Phase STATION
double tt_rtp[MAXPAR][20][MAXCHA];               // P-Phase MSECS for klon n and channel m
char   ttstring_rtp[MAXPAR][20][MAXCHA][30];       // P-Phase timestring
int    phasepicks_rtp[20];
int    lokalisering = 0;
int    realtimepick;
float  maxrespph;
int    minstalopph;
int    timewindowback;
//*************************************************************************************
int    stream_count = 0;
int    rec_count = 0;

int    antall_stasjoner;
char   rtdly[MAXCHA][20];
char   current_station[50];

  int new[MAXCHA];

static void DTE();
static void TIMSEC();

static int  unpack_samples();

char   tid[MAXCHA][100];

long   ryrn[MAXCHA];
long   rmon[MAXCHA];
long   rday[MAXCHA];
long   rhrn[MAXCHA];
long   rmin[MAXCHA];
int    time_quality[MAXCHA];
int    risec[MAXCHA];
float  rsek[MAXCHA];
int    rsecs[MAXCHA];
int    ryrn_int;
int    rmon_int;
int    rday_int;
int    rhrn_int;
int    rmin_int;
int    rsr[MAXCHA];
int    rns[MAXCHA];
char   rtid[MAXCHA][200];


int    sum[MAXCHA];
int    teller[MAXCHA];
int    avg[MAXCHA];



double CCC_TIME;
#ifndef abs
#define ABS(x) ((x)<0?-(x):(x))
#endif
#define TRUE 1
float   fl;
float   fh;
int     orden;
float  fl_par[MAXCHA];
float  fh_par[MAXCHA];
static  int nsects;

static  float sn[5*3+1],sd[5*3+1];
float   snc[MAXCHA][16];                            // filter coefficients
float   sdc[MAXCHA][16];                            // filter coefficients
int     cset[MAXCHA];
static  float save_y2[MAXCHA][16];                  // overlap between 2 filter buffers
static  float save_y1[MAXCHA][16];
static  float save_x2[MAXCHA][16];
static  float save_x1[MAXCHA][16];
static  float save_y2_pick[MAXCHA][16];                  // overlap between 2 filter buffers
static  float save_y1_pick[MAXCHA][16];
static  float save_x2_pick[MAXCHA][16];
static  float save_x1_pick[MAXCHA][16];
typedef struct {float r, i;} complex;

/* Table of constant values */
static  float c_b12 = 2.;
static  complex c_b43 = {1.,0.};




/* Local function prototypes */
static  double warp();
static  int chebparm(), lptbp(), lptbr(), lpthp(), bilin2(), lp();
static  int c1roots(), c2roots();
static  int cutoffs(), beroots();
static  complex cmul(), cpowi(), csqrt1(), conjg(), cdiv();



double latency[MAXCHA];
float  ftemp[MAXCHA][RTBUFSIZ];   // 5000
float  sta_par[MAXCHA];
float  lta_par[MAXCHA];
char   params[MAXCHA][200];


char   trig_stations[MAXCHA][200];
char   trig_components[MAXCHA][200];
float  trg_par[MAXCHA];
float  dtrg_par[MAXCHA];

int    trig_flag[MAXCHA];
int    trig_dur[MAXCHA];
int    det_flg;
char   TRIGGER_TIMES[MAXCHA][200];
int    arrwnd= 100;
double TIME_NOW=0.0;
double TID_NOW = 0.0;
double trgdly[MAXCHA][MAXDLY];      // trigger delay buffer
int   SKIPPED[MAXCHA];
  int pk=0; 
int    mintrg=0;
int    DURTRG[MAXCHA];
double MINSTETID;
char MINTRGTID[200];

int    preevent=60;
int    postevent=60;

char  dbname[200]    = "";              // SEISAN database name
int  dbase_switch = 0;
char  trgpath[200]   = "";              // complete path for triggers
int    no_to_record;
char   record[MAXCHA][200];
char  sfilepath[200] = "";              // SEISAN S-file path
//char SFILETOPICK[256];

char   EVENTS_S[200];




  int first[MAXCHA]; 
  int    ON_OFF[MAXCHA];
  int duration[MAXCHA];  

char streams[MAXCHA][100];
char stations[MAXCHA][100];
char slserv[MAXCHA][100];

//------------------------pdata-----------------------------------
//***************************************************************************
// * record_handler:
// * Saves passed records to the output file.
// ***************************************************************************/
static void record_handler (char *record, int reclen ,void *srcname)
{
  if(tq==1)
  {
    record[38]=128;
  }else{
    record[38]=0;
  }
  if ( fwrite(record, reclen, 1, ofp) != 1 )
    {
      fprintf (stderr, "Error writing to output file\n");
    }
}  /* End of record_handler() */

/***************************************************************************
 * packtraces:
 *
 * Pack all traces in a group.
 *
 * Returns 0 on success, and -1 on failure
 ***************************************************************************/
static void
packtraces (flag flush,int nextport,MSTraceGroup *mstg)
{
  MSTrace *mst;
  int trpackedsamples = 0;
  int trpackedrecords = 0;
  char srcname[50];
  mst = mstg->traces;
  while ( mst )
    {
      if ( mst->numsamples <= 0 )
        {
          mst = mst->next;
          continue;
        }
      
      trpackedrecords = mst_pack (mst, &record_handler, srcname, 4096,DE_STEIM1,1,
                                  &trpackedsamples, 1, verbose-2, NULL);
      if ( trpackedrecords < 0 )
        {
          fprintf (stderr, "Error packing data\n");
        }
      else
        {
          packedrecords += trpackedrecords;
          packedsamples += trpackedsamples;
        }
      
      mst = mst->next;
    }
}  /* End of packtraces() */

/***************************************************************************
 * slg2group:
 * Read a SEISLOG QNX file and add data samples to a TraceGroup.  As the 
 * SEISLOG QNX is read in a MSrecord struct is used as a holder for the input
 * information.
 *
 * Returns 0 on success, and -1 on failure
 ***************************************************************************/
//static int
//slg2group (char *slgfile, MSTraceGroup *mstg,int ls,int channels,int irate,int nextport,int quality,char header[20][150],float values[MAXCHA][RTBUFSIZ])
static int
slg2group (char *slgfile, MSTraceGroup *mstg,int ls,int channels,int irate,int nextport,int quality,char header[20][150])
{
  FILE *ifp;
  MSRecord *msr = 0;
//struct fsdh_s *fsdh;
  char line[1328];
  int buf[2000];
  int linesize;

  char timestr[25];
  char tid[25];
  char sampstr[10];
  char ratestr[15];
  char chkstr[10];
  char stasjon[10];
  char kompon[10];
  char nett[10];
  char loca[10];
  char sr[20];
  
  float srfl;
  int ch;
  int i;
  int ix;
  int sec;

  int rate;
  int tel;
  
  int retval = 0;

  int32_t *intbuf = 0;
  int32_t intbufsize = 0;
  


  
  /* Open .mseed output file if needed, replacing .gse if present */
  if ( ! ofp )
  {
    char mseedoutputfile[1024];
    int filelen;
    printf("slg2group: OFP\n");
    strncpy (mseedoutputfile, slgfile, sizeof(mseedoutputfile)-6 );
    filelen = strlen (mseedoutputfile);
    strcat (mseedoutputfile, ".mseed");
      
    if ( (ofp = fopen (mseedoutputfile, "wb")) == NULL )
    {
      printf ("Cannot open output file: %s \n",mseedoutputfile);
      return -1;
    }
  }

  if ( ! (msr = msr_init(msr)) )
  {
    fprintf (stderr, "Cannot initialize MSrecord strcture\n");
    return -1;
  }


  for(ch=0;ch<channels;ch++)
  {  
//    printf("%s\n",header[ch]); 
    	  /* Extract values from HEADER and populate the msr holder */
    if(header[ch][0] != 'X')
    {  
//    if(ch==0)
//    {
      strncpy (tid, header[ch] + 41, 24); tid[24] = '\0';
//      printf("time: %s\n",tid);

      timestr[0]=tid[6]; // year
      timestr[1]=tid[7];
      timestr[2]=tid[8];
      timestr[3]=tid[9];
      timestr[4]='/';
      timestr[5]=tid[3]; // month
      timestr[6]=tid[4];
      timestr[7]='/';
      timestr[8]=tid[0];  // day
      timestr[9]=tid[1];
      timestr[10]=' ';
      timestr[11]=tid[11];  // hour
      timestr[12]=tid[12];
      timestr[13]=':';
      timestr[14]=tid[14];  // minute
      timestr[15]=tid[15];
      timestr[16]=':';
      timestr[17]=tid[17];
      timestr[18]=tid[18];
      timestr[19]=tid[19];
      timestr[20]=tid[20];
      timestr[21]=tid[21];
      timestr[22]=tid[22];

            if(tid[23] == '-')
            {

              tq=1;
            }else{

              tq=0;
            }

      timestr[23]='\0';
//      printf("time: %s\n",timestr);

      msr->starttime = ms_timestr2hptime (timestr);
      strncpy(stasjon,header[ch] + 3,5);stasjon[5]='\0';

    strncpy(kompon,header[ch] + 9,3);kompon[3]='\0';
    strncpy(nett,header[ch] + 16,2);nett[2]='\0';
    strncpy(loca,header[ch] + 13,2);loca[2]='\0';

    ms_strncpclean (msr->channel, kompon , 3);     // temporary	
    ms_strncpclean (msr->network, nett, 2);
    ms_strncpclean (msr->station, header[ch] + 3, 5);
    ms_strncpclean (msr->location,loca, 2);
    	      

      strncpy(sampstr,header[ch] + 20, 10);sampstr[10]='\0';
 //      printf("sampstr: %s\n",sampstr);

      msr->samplecnt = strtol (sampstr, NULL, 10);
  /* Allocate intbuf if needed */
      if(ch==0)
        intbuf = realloc (intbuf, sizeof(int32_t) * msr->samplecnt * channels);
//      printf("samplecnt: %d\n",msr->samplecnt);


      ms_strncpclean (sr, header[ch] + 30, 10);
//      printf("sr: %s\n",sr);
      sscanf(sr,"%f",&srfl);
//      printf("srfl: %f\n",srfl);
      sprintf(ratestr,"%10.3f\n",srfl);
//      printf("ratestr: %s\n",ratestr);

      msr->samprate = strtod (ratestr, NULL);

    /* Read in data */
    tel= msr->samplecnt;  
    for(;;)
    {
      rate=(int)srfl;

      for(i=0;i<msr->samplecnt;i++)
      {
//        printf("%3d %6d %4x\n",i,buf[i],buf[i]);
        *(intbuf + intbufsize) = (int32_t)values[ch][tel-1];
        intbufsize++;
	tel--;
      }

      if(intbufsize == msr->samplecnt)
        break;
    }
//    printf("%d samples read\n",msr->samplecnt);
	  /* Add data to TraceGroup */
    msr->datasamples = intbuf;
    msr->numsamples = intbufsize;
    msr->sampletype = 'i';

    if ( ! mst_addmsrtogroup (mstg, msr, -1.0, -1.0,-1.0) )
    {
      fprintf (stderr, "[%s] Error adding samples to TraceGroup\n", slgfile);
    }
	  
	  /* Unless buffering all files in memory pack any Traces now */
    if ( ! bufferall )
    {
      packtraces (1,nextport,mstg);
      packedtraces += mstg->numtraces;
      mst_initgroup (mstg);
    }
    intbufsize = 0;
    
  }
    
  }
	  


	  /* Cleanup and reset state */
    msr->datasamples = 0;
    msr = msr_init (msr);

    intbufsize = 0;

//    fclose (ifp);
  
  if ( ofp  && ! outputfile )
    {
      fclose (ofp);
      ofp = 0;
    }

  if ( intbuf )
    free (intbuf);
  
  if ( msr )
    msr_free (&msr);
      
  return retval;
}  /* End of slg2group() */




/***************************************************************************
 * addfile:
 *
 * Add file to end of the global file list (filelist).
 ***************************************************************************/
static void
addfile (char *filename)
{
  struct filelink *lastlp, *newlp;

  if ( filename == NULL )
    {
      fprintf (stderr, "addfile(): No file name specified\n");
      return;
    }
  
  lastlp = filelist;
  while ( lastlp != 0 )
    {
      if ( lastlp->next == 0 )
        break;
      
      lastlp = lastlp->next;
    }
  
  newlp = (struct filelink *) malloc (sizeof (struct filelink));
  newlp->filename = strdup(filename);
  newlp->next = 0;
  
  if ( lastlp == 0 )
    filelist = newlp;
  else
    lastlp->next = newlp;
 
}  /* End of addfile() */


//------------------------pdata-----------------------------------

Check_S(int *ne,float *resid,int *nst,float res_lim,int lp)
{
  FILE *sf;
  FILE *out;
  int no,i,br,l,n;
  int totlines;
  char linjer[200];

  char toplot1[MAXCHA][80];
  int index[200];
  char navn[25];
  char seq[2];
  int goon;
  int cr;
  int readings_left;
  float residual;
  int ant=0;
  int idx;
  int bytes_read;
  char dummy[50];
  float res[200];
  float res_save[200];
  float max_res;

  sf=fopen("hyp.out","r");
  if(sf == NULL)
  {
    printf("RTPPH :CHECK_S:Can't open S-file: hyp.out\n");
    exit(0);
  }else{
    if(lp==0)                                              // write only once
      printf("RTPPH: Found............................: hyp.out\n");

    br=0;
    cr=0;
    no = 200;
    totlines=0;

    for(i=0;i<10;i++)
    {
      for(l=0;l<90;l++)
      {
        linjer[l]=fgetc(sf);
        if(linjer[l] == 0xa)
          cr++;
        linjer[l]='\0';

        if(cr>=5)
        {
          br=1;
          break;
        }
      }
      if(br==1)
        break;
    }

    br=0;
    cr=0;
    seq[0]=' ';
    seq[1]=' ';
    for(i=0;i<no;i++)
    {
      br=0;
      for(l=0;l<90;l++)
      {
        linjer[l]=fgetc(sf);
        if(linjer[l] == EOF)
        {
          totlines = i-1;
          ant = i-1;
          fclose(sf);
          cr=1;
          break;
        }else{
          if(linjer[l] == 0xa )
          {
            br=1;
            linjer[l]='\0';

            for(n=0;n<20;n++)
              navn[n]='\0';
            for(n=0;n<6;n++)
              navn[n]=linjer[n];
            sprintf(toplot1[i], "%s",navn);


            sscanf(linjer,"%63c %f",dummy,&res[i]);

            res_save[i]=res[i];
            ant++;
          }        // 0xa
        }
        if(br == 1)
          break;
      }    // l=0-90
      if(cr == 1)
        break;
    }  // i=0-no
  }
    fclose(sf);


  residual=0;
  
  for(l=0;l<ant;l++)
    residual=residual+fabs(res_save[l]);
  residual=residual/ant;
  printf("RTPPH: readings left....................: %2d Avg.res: %8.2f  ",ant,residual);
  *resid = residual;
  *nst   = ant;
  for(l=0;l<200;l++)
    index[l]=0;

  for(l=0;l<1;l++)
  {
    max_res = fabs(res[0]);
    idx=0;
    for(i=1;i<ant;i++)
    {
      if(fabs(res[i]) > max_res)
      {
        max_res = fabs(res[i]);
        idx = i;
      }
    }
    res[idx]=0.0;
    index[idx]=1;
    
  }

  residual=0;
  sf=fopen("hyp.out","r");
  if(sf == NULL)
  {
    printf("RTPPH: CHECK_S: Can't open hyp.out\n");
    exit(0);
  }
  out=fopen("hyp_new.out","w");
  if(out == NULL)
  {
    printf("RTPPH: CHECK_S: Can't open hyp_new.out\n");
    exit(0);
  }else{

    br=0;
    cr=0;
    readings_left = 0;
    for(i=0;i<(ant+5);i++)
    {
      for(l=0;l<90;l++)
      {
        linjer[l]=fgetc(sf);
        if(linjer[l] == 0xa)
        {
          cr=1;
          br++;
        }
        if(cr == 1)
        {
          if(br <= 5)
          {
            fprintf(out,"%s",linjer);
            cr=0;
            break;
          }else{
            if(index[i-5] == 0)
            {
              fprintf(out,"%s",linjer);
              readings_left++;
              residual=residual+fabs(res_save[i-5]);
            }
            cr=0;
            break;
          }
        }
      }
    }
    fclose(out);
    fclose(sf);

    ant=ant-1;

    printf("phases left: %2d Avg.residual in HYP_NEW: %6.2f\n",readings_left,residual/ant);
    *ne=ant;

    if( (residual/ant) > res_lim)
    {
      goon=1;  // Continue
    }else{
      printf("RTPPH: STOP iterations. Residual below..: %4.2f\n",res_lim);
      goon=0;  // Stop

    }
    return(goon);

  }
}


Create_New_Sfile(char sfilepath[],int klon,int locate,char yr_trg[],char mo_trg[],char da_trg[],char hr_trg[],char mi_trg[],char se_trg[])
{
  FILE *sf;
  FILE *so1;
  FILE *so2;
  int retur;
  int i;

  char syscmd[200];
  char comm0[200];
  char comm1[200];
  char comm1b[200];
  char comm2[200];
  char comm3[200];
  char comm5[200];
  char comm6[200];
  char comm8[200];
  char comm9[200];
  char com10[200];
  char com11[200];


  int ret;
  int lp;
  int kart;
  int ne;
  int rettur;
  int br;

  float resid;
  float res_lim;
  int nst;
  
float  maxres         =   maxrespph;       // stop iterations when this value is reached, input
int    iterations     =   200;       // number of iterations removing phases giving bad residuals, input
int    no_stations_trg=   minstalopph;       // min number of stations with phase reading needed to locate
int    sendmail=0;  
  

  printf("RTPPH: Path+s-filename..................: %s\n",sfilepath);

//---------------------------------------------
// check for auto locate
//---------------------------------------------
  if(locate == 1)
  {
    printf("RTPPH: Create_Sfile.....................: Locate + new s-file.\n");

    sprintf(comm0,"rm hyptemp.txt");                    // active
    sprintf(comm1,"hyp %s >> hyptemp.txt",sfilepath);   // active
    sprintf(comm1b,"cp hyp.out hyp2.out");
    sprintf(comm2,"cp hyp.out %s", sfilepath);          // active
    sprintf(comm3,"cp hyp_new.out %s", sfilepath);
    sprintf(comm5,"cp hyp_save.out %s",sfilepath);
    sprintf(comm6,"cp hyp.out hyp.tmp");                // active
    sprintf(comm8,"cp hyp.out hyp_all.out");            // active
    sprintf(comm9,"cp hyp_save.out %s",sfilepath);
    sprintf(com10,"cp %s s_org.out",sfilepath);         // active
    sprintf(com11,"cp hyp.out %s/map",topdir_rt);
    
//    printf("RTPPH: comm0............................: %s\n",comm0);
    ret=system(comm0);                                     // remove old hyptemp.txt
 
//    printf("RTPPH: com10............................: %s\n",com10);
    ret=system(com10);                                     // copy original s-file to s_org.out

//    printf("RTPPH: comm1............................: %s\n",comm1);
    ret=system(comm1);                                     // run hyp, input s-file, this produces "hyp.out"
    
//    ret=system(comm1b);

//    printf("RTPPH: comm2............................: %s\n",comm2);
    ret=system(comm2);                                     // copy hyp.out new s-file

//    printf("RTPPH: comm8............................: %s\n",comm8);
    ret=system(comm8);                                     // copy hyp.out to hyp_all.out

    res_lim = maxres;

    kart=0;
    rettur=0;
    for(lp=0;lp<iterations;lp++)
    {
      ret=Check_S(&ne,&resid,&nst,res_lim,lp);       // read 'hyp.out', create 'hyp_new.out'
      
//printf("ret: %d ne: %d resid: %f6.2 nst: %d\n",ret,ne,resid,nst);      
      
      if(ret==1)
      {
        ret=system(comm3);                                 // copy hyp_new to new s-file 
        ret=system(comm0);                                 // remove old hyptemp.txt
        ret=system(comm1);                                 // run hyp, input s-file
//    ret=system(comm1b);	
        ret=system(comm2);                                 // copy hyp.out new s-file
      }else{
        printf("RTPPH: Average residual.................: %f\n",resid);
        printf("RTPPH: No more iterations...............: Number of stations: %d Avg: res.: %8.3f\n",nst,resid);
        if(  nst < no_stations_trg)
        {
          printf("RTPPH: Too few stations (<%d)............: No location\n",no_stations_trg);
	  sendmail=-1;
          ret=system(comm5);
          kart=1;
          rettur = -1;
        }
        break;
      }
    }
    if(rettur==0)
    {
      ret=system(comm6);                                   // copy last hyp.out to hyp.tmp

      ret=system(comm2);
    }else{
      ret=system(comm9);
//      printf("RTPPH: comm9............................: %s\n",comm9);
      return(-1);
    }

    int rss=resid*1000;
//    printf("RTPPH: RSS..............................: %d\n",rss);
    
    if(rss != 0)
    {
//      printf("RTPPH:..................................: Update map\n");
//        Update_map_file(sfilename,ne,resid,nst,klon);
//    sprintf(com20,"respng");
//    ret= system(com20); 
//    allpng=1;

    }
  }
  return(0);
}
les_linje(FILE *streamfp,char linje[])
{
  int l;
  int br;
  br=0;
  for(l=0;l<85;l++)
  {
    linje[l]=fgetc(streamfp);
    if(linje[l] == 0xa && l == 0)
    {
      br=2;
      break;
    }
    if(linje[l] == 0xa && l > 0)
    {
      linje[l]='\0';
      break;        
    }
    if(linje[l] == EOF)
    {
      br=1;
      return(br);
    }
  }
  return(br);
}
les_linje2(FILE *streamfp,char linje[])
{
  int l;
  int br;
  br=0;
  for(l=0;l<600;l++)
  {
    linje[l]=fgetc(streamfp);
    if(linje[l] == 0xa && l == 0)
    {
      br=2;
      break;
    }
    if(linje[l] == 0xa && l > 0)
    {
      linje[l]='\0';
      break;        
    }
    if(linje[l] == EOF)
    {
      br=1;
      return(br);
    }
  }
  return(br);
}

createHTML(float mw,float latt,float lonn,char tid[],char where[],char trg_tid[],char s_file_name[])
{
  FILE *out;
  FILE *sfile;
  FILE *in;
  char filn[200];
  char filn2[200];
  char syscmd[200];
  int i,br,k,l,ret;
  char record[100];
  char slines[100][100];
  char sli[100][100];  
  int ant=0;
  int yval=15;
  
  printf("RTPPH: %s\n",s_file_name);
  if ((sfile = fopen (s_file_name, "rb")) == NULL)
  {
    printf("RTPPH: Can't open sfile file: %s\n",s_file_name);
    return(-1);
  }
  for(i=0;i<50;i++)
  {
    br = les_linje(sfile,record);    
    sprintf(slines[i],"%s",record);
    if(br==1)
    {
      ant=i;
      break;
    }
  }  
  fclose(sfile);
  
  
  sprintf(filn,"%s/map/phase.html",topdir_rt);
  out = fopen(filn,"w");
  if(out == NULL)
  {
    return(-1);
  }
  fprintf(out,"<!DOCTYPE html PUBLIC %c-//W3C//DTD HTML 4.01//EN%c %chttp://www.w3.org/TR/html4/strict.dtd%c>\n",0x22,0x22,0x22,0x22);  
  fprintf(out,"<html>\n");
  fprintf(out,"  <head>\n");
  fprintf(out,"  <meta content=%ctext/html; charset=UTF-8%c\n",0x22,0x22);
  fprintf(out," http-equiv=%ccontent-type%c>\n",0x22,0x22);
  fprintf(out,"  <style>\n");
  fprintf(out,"    body {\n");
  fprintf(out,"    margin: 0px;\n");
  fprintf(out,"    padding: 0px;\n");
  fprintf(out,"  }\n");
  fprintf(out,"  </style>\n");
  fprintf(out,"  </head>\n");
  fprintf(out,"  <body>\n");
  fprintf(out,"    <canvas id=%cmyCanvas%c width=%c1380%c height=%c740%c ></canvas>\n",0x22,0x22,0x22,0x22,0x22,0x22);
  fprintf(out,"    <script>\n");
  fprintf(out,"      var line1=%c%s%c\n",0x22,where,0x22);
  fprintf(out,"      var line2=%cUTC %s%c;\n",0x22,tid,0x22);
  if(automag == 1)
  {
    if(mw > 0.0)
    {
      fprintf(out,"      var line3=%cLat: %6.2f Lon: %6.2f MW: %3.1f%c;\n",0x22,latt,lonn,mw,0x22);
    }else{
      fprintf(out,"      var line3=%cLat: %6.2f Lon: %6.2f MW: -%c;\n",0x22,latt,lonn,0x22);    
    }
  }else{
    fprintf(out,"      var line3=%cLat: %6.2f Lon: %6.2f%c;\n",0x22,latt,lonn,0x22);     
  }
  fprintf(out,"      var line4=%cPreliminary locations. Solutions are automatic and may have large errors.%c\n",0x22,0x22);
  fprintf(out,"      var canvas = document.getElementById('myCanvas');\n");
  fprintf(out,"      var context = canvas.getContext('2d');\n");
  fprintf(out,"      var imageObj = new Image();\n");
  fprintf(out,"      context.fillStyle = %c#000000%c;\n",0x22,0x22);
  fprintf(out,"      context.fillRect(0,0,1380,740);\n");  
  fprintf(out,"      context.fillStyle = %c#dddddd%c;\n",0x22,0x22);
  fprintf(out,"      context.fillRect(0,0,640,740);\n");
  fprintf(out,"      imageObj.onload = function() {\n");
  fprintf(out,"      context.drawImage(imageObj, 0, 65);\n");
  fprintf(out,"      context.font = %c15px Arial%c;\n",0x22,0x22);
  fprintf(out,"      context.fillStyle = 'blue';\n");
  fprintf(out,"      context.fillText(line1,10,20);\n");
  fprintf(out,"      context.fillText(line2,10,40);\n");
  fprintf(out,"      context.fillText(line3,10,60);\n");
  fprintf(out,"      context.fillText(line4,10,730);\n");
  fprintf(out,"      context.font = %c14px Dejavu sans mono%c;\n",0x22,0x22);  
  fprintf(out,"      context.fillStyle = 'white';\n");  
  for(i=0;i<ant;i++)    
  {
    fprintf(out,"      context.fillText(%c%s%c,650,%d);\n",0x22,slines[i],0x22,yval); 
    yval=yval+20;
  }
  fprintf(out,"      };\n");
  fprintf(out,"      imageObj.src = 'map.png';\n");  
  fprintf(out,"    </script>\n");
  fprintf(out,"  </body>\n");
  fprintf(out,"</html> \n");

  fclose(out); 

  yval=15;
  
  sprintf(filn,"%s/rt/pph/%s.html",topdir_rt,trg_tid);
  out = fopen(filn,"w");
  if(out == NULL)
  {
    return(-1);
  }
  fprintf(out,"<!DOCTYPE html PUBLIC %c-//W3C//DTD HTML 4.01//EN%c %chttp://www.w3.org/TR/html4/strict.dtd%c>\n",0x22,0x22,0x22,0x22);  
  fprintf(out,"<html>\n");
  fprintf(out,"  <head>\n");
  fprintf(out,"  <meta content=%ctext/html; charset=UTF-8%c\n",0x22,0x22);
  fprintf(out," http-equiv=%ccontent-type%c>\n",0x22,0x22);
  fprintf(out,"  <style>\n");
  fprintf(out,"    body {\n");
  fprintf(out,"    margin: 0px;\n");
  fprintf(out,"    padding: 0px;\n");
  fprintf(out,"  }\n");
  fprintf(out,"  </style>\n");
  fprintf(out,"  </head>\n");
  fprintf(out,"  <body>\n");
  fprintf(out,"    <canvas id=%cmyCanvas%c width=%c1300%c height=%c740%c ></canvas>\n",0x22,0x22,0x22,0x22,0x22,0x22);
  fprintf(out,"    <script>\n");
  fprintf(out,"      var line1=%c%s%c\n",0x22,where,0x22);
  fprintf(out,"      var line2=%cUTC %s%c;\n",0x22,tid,0x22);
  if(automag == 1)
  {
    if(mw > 0.0)
    {
      fprintf(out,"      var line3=%cLat: %6.2f Lon: %6.2f MW: %3.1f%c;\n",0x22,latt,lonn,mw,0x22);
    }else{
      fprintf(out,"      var line3=%cLat: %6.2f Lon: %6.2f MW: -%c;\n",0x22,latt,lonn,0x22);    
    }
  }else{
    fprintf(out,"      var line3=%cLat: %6.2f Lon: %6.2f%c;\n",0x22,latt,lonn,0x22);    
  }
  fprintf(out,"      var line4=%cPreliminary locations. Solutions are automatic and may have large errors.%c\n",0x22,0x22);
  fprintf(out,"      var canvas = document.getElementById('myCanvas');\n");
  fprintf(out,"      var context = canvas.getContext('2d');\n");
  fprintf(out,"      var imageObj = new Image();\n");
  fprintf(out,"      context.fillStyle = %c#000000%c;\n",0x22,0x22);
  fprintf(out,"      context.fillRect(0,0,1300,740);\n");  
  fprintf(out,"      context.fillStyle = %c#dddddd%c;\n",0x22,0x22);
  fprintf(out,"      context.fillRect(0,0,640,740);\n");
  fprintf(out,"      imageObj.onload = function() {\n");
  fprintf(out,"      context.drawImage(imageObj, 0, 65);\n");
  fprintf(out,"      context.font = %c15px Arial%c;\n",0x22,0x22);
  fprintf(out,"      context.fillStyle = 'blue';\n");
  fprintf(out,"      context.fillText(line1,10,20);\n");
  fprintf(out,"      context.fillText(line2,10,40);\n");
  fprintf(out,"      context.fillText(line3,10,60);\n");
  fprintf(out,"      context.fillText(line4,10,730);\n");
  fprintf(out,"      context.font = %c14px Dejavu sans mono%c;\n",0x22,0x22);  
  fprintf(out,"      context.fillStyle = 'white';\n");  
  for(i=0;i<ant;i++)
  {
    fprintf(out,"      context.fillText(%c%s%c,650,%d);\n",0x22,slines[i],0x22,yval); 
    yval=yval+20;
  }
  fprintf(out,"      };\n");
  fprintf(out,"      imageObj.src = '%s.png';\n",trg_tid);
  fprintf(out,"    </script>\n");
  fprintf(out,"  </body>\n");
  fprintf(out,"</html> \n");
  fclose(out);    
  
  sprintf(syscmd,"ls %s/rt/pph/*.html > unsorted",topdir_rt);
  ret = system(syscmd);
  sprintf(syscmd,"sort -r unsorted > sorted");
  ret = system(syscmd);  

  sprintf(filn,"%s/map/AUTOLOC_RT.html",topdir_rt);
  out = fopen(filn,"w");
  if(out == NULL)
  {
    return(-1);
  }
  fprintf(out,"<!DOCTYPE html PUBLIC %c-//W3C//DTD HTML 4.01//EN%c %chttp://www.w3.org/TR/html4/strict.dtd%c>\n",0x22,0x22,0x22,0x22);  
  fprintf(out,"<html>\n");
  fprintf(out,"  <head>\n");
  fprintf(out,"  <meta content=%ctext/html; charset=UTF-8%c\n",0x22,0x22);
  fprintf(out," http-equiv=%ccontent-type%c>\n",0x22,0x22);
  fprintf(out,"<meta http-equiv='refresh' content='60'>\n");  
  fprintf(out,"<title>Auto-location RT</title>\n");
  fprintf(out,"<SCRIPT LANGUAGE=%cJavaScript%c>",0x22,0x22);
  fprintf(out,"function formHandler(form){");
  fprintf(out,"var URL = document.form1.site.options[document.form1.site.selectedIndex].value;");
  fprintf(out,"parent.main.location = URL;");
  fprintf(out,"}\n");
  fprintf(out,"</SCRIPT>\n");
  fprintf(out,"</head>\n");

  fprintf(out,"<body bgcolor=%c#FFFFFF%c text=%c#000000%c>\n",0x22,0x22,0x22,0x22);
  fprintf(out,"<form name=%cform1%c>\n",0x22,0x22);

  fprintf(out,"<select name=%csite%c size=1 onChange=%cformHandler(this)%c >\n",0x22,0x22,0x22,0x22);
  
  sprintf(filn2,"sorted");
  in = fopen(filn2,"r");
  if(in == NULL)
  {
    return(-1);
  }
  ant=20;
  br = les_linje(in,record);
  for(l=0;l<200;l++)
  {
    if(record[l] == '2')
    {
      k=l;
      break;
    }
  }
  rewind(in);  
  for(i=0;i<20;i++)
  {
    br = les_linje(in,record);
//    printf("%s\n",record);
    sprintf(slines[i],"%s",record);    
    for(l=0;l<21;l++)
      record[l]=record[k+l];
    record[l]='\0';
    sprintf(sli[i],"%s",record);
    if(br==1)
    {
      ant=i;
      break;
    }
  }
  fclose(in);
  for(i=0;i<ant;i++)
  {
    fprintf(out,"<option value=%c%s%c>%s\n",0x22,slines[i],0x22,sli[i]);
  }
  fprintf(out,"</select>\n");
  fprintf(out,"<font face=%cDejavu sans mono%c color=%cblack%c</font>\n",0x22,0x22,0x22,0x22);
  fprintf(out,"<label for=%cmenu%c>Auto-location, early real-time phases.</label>\n",0x22,0x22); 
  fprintf(out,"</form>\n");
 
  fprintf(out,"<IFRAME SRC=%c%s%c name=%cmain%c WIDTH=1305 HEIGHT=745 frameborder=1 border=1></IFRAME>\n",0x22,slines[0],0x22,0x22,0x22);
  fprintf(out,"</body>\n");
  fprintf(out,"</html>\n");
  fclose(out);



  
  return(0);
}
/************************************************************************************/
/*                                                                                  */
/************************************************************************************/
RTPPH(char s_file_name[])
{
  FILE *sfile;
  FILE *out;  
  char yr_trg[200];
  char mo_trg[200];
  char da_trg[200];
  char hr_trg[200];
  char mi_trg[200];
  char se_trg[200];
  int  br;
  int  i,l,ix;
  int  prt;
  int  cnt=0;
  char dm[200]; 
  char key[10];
  char text[10];  
  char record[600];
  char MINTRGTID[80];
  char MINTRGTIDMAIL[80];
  char TRG_TID[80];
  int  klon;
  int  locate;
  float lat,lon;
  float mw;
  char melding0[500];
  char melding[500];
  char melding2[1000];
  char melding3[1000];  
  char mail_message[500];
  char png_request[500]; 
  char png_request2[500];
  char png_request3[500];  
  char where[600];
  char fnavn[200];
  char mmww[10];
  int zoom;  
  int ret;
  double AFT;
//-------------------------------------------------------------------
// open s-file and read the '1' line to get the time for trigger
//-------------------------------------------------------------------
  if ((sfile = fopen (s_file_name, "rb")) == NULL)
  {
    printf("RTPPH: Can't open sfile file: %s\n",s_file_name);
    return(-1);
  }

  br = les_linje(sfile,record);  // read first line in s-file and extract time

  if(record[79]=='1')
  {
    sscanf(record,"%s",yr_trg);
    dm[0]=record[6];
    if(dm[0]==' ') dm[0]='0';
    dm[1]=record[7];
    dm[2]='\0';
    sscanf(dm,"%s",mo_trg);
    dm[0]=record[8];
    if(dm[0]==' ') dm[0]='0';
    dm[1]=record[9];
    dm[2]='\0';
    sscanf(dm,"%s",da_trg);
    dm[0]=record[11];
    if(dm[0]==' ') dm[0]='0';
    dm[1]=record[12];
    dm[2]='\0';
    sscanf(dm,"%s",hr_trg);
    dm[0]=record[13];
    if(dm[0]==' ') dm[0]='0';
    dm[1]=record[14];
    dm[2]='\0';
    sscanf(dm,"%s",mi_trg);
    dm[0]=record[16];
    if(dm[0]==' ') dm[0]='0';
    dm[1]=record[17];
    dm[2]=record[18];
    dm[3]=record[19];
    dm[4]='\0';
    sscanf(dm,"%s",se_trg);

    sprintf(MINTRGTID,"%s/%s/%s0%s:%s:%s",da_trg,mo_trg,yr_trg,hr_trg,mi_trg,se_trg);
//    sprintf(TRG_TID,"%s-%s-%s-%s:%s:%s",da_trg,mo_trg,yr_trg,hr_trg,mi_trg,se_trg);
    sprintf(TRG_TID,"%s-%s-%s-%s:%s:%s",yr_trg,mo_trg,da_trg,hr_trg,mi_trg,se_trg);    
    printf("RTPPH:..................................: MINTRGTID: %s\n",MINTRGTID);
    printf("RTTPH:..................................: TRG_TID:   %s\n",TRG_TID);
    sprintf(MINTRGTIDMAIL,"%s/%s/%s %s:%s:%s",da_trg,mo_trg,yr_trg,hr_trg,mi_trg,se_trg);      
  }

  fclose(sfile);
  klon=0;  
  locate = 1;
  ret = Create_New_Sfile(s_file_name,klon,locate,yr_trg,mo_trg,da_trg,hr_trg,mi_trg,se_trg);  

  if(ret == 0)
  {
    C_TIME();
    AFT = CCC_TIME;  
  
    if ((sfile = fopen (s_file_name, "rb")) == NULL)
    {
      printf("RTPPH: Can't open sfile file: %s\n",s_file_name);
      return(-1);
    } 
    br = les_linje(sfile,record);             // read first line in s-file
    printf("%s\n",record);
    sscanf(record,"%23c%f%f",dm,&lat,&lon);   // read latitude + longitude
    sscanf(record,"%56c%3c",dm,mmww);
    sscanf(mmww,"%f",&mw);
    fclose(sfile);  
    if(lat != 0.0 && lon != 0.0)
    {  
      lokalisering = 1;
      sprintf(where,"wget -T 1 -O geo.xml %cnominatim.openstreetmap.org/reverse?format=xml&lat=%f&lon=%f&zoom=8&addressdetails=0%c 2>xml.log",0x22,lat,lon,0x22); 
//      sprintf(where,"wget -T 1 -O geo.xml %cnominatim.openstreetmap.org/reverse?format=xml&lat=%f&lon=%f&zoom=8&addressdetails=1&accept-language=en%c 2>xml.log",0x22,lat,lon,0x22);     
      ret = system(where);
    
      if ((sfile = fopen ("geo.xml", "rb")) == NULL)
      {
        printf("RTPPH: Can't open geo.xml file");
        return(-1);
      }

      br = les_linje2(sfile,record);  // read first line geo.xml
      if(record[0]=='<')
        cnt++;
      br = les_linje2(sfile,record);  // read second line geo.xml
      if(record[0]=='<')
        cnt++;    
      br = les_linje2(sfile,record);  // read third line geo.xml
      if(record[0]=='<')
        cnt++;
      fclose(sfile);
      if(cnt == 3)
      {
        ix = 0;
        br = 0;
        for(l=0;l<1000;l++)
        {
          if(record[l] == '>')
          {
	    for(i=(l+1);i<500;i++)
	    {
	      if(record[i] == '<')
	      {
	        melding2[ix] = '\0';
	        br = 1;
	        break;
	      }else{
	        melding2[ix] = record[i];
	        ix++;
	      }
	     }
	     if(br == 1)
	       break;
          }
        }
      }else{
        sprintf(melding2,"Geocoding not active"); 
      }
    
      zoom = 8;

      sprintf(melding,"UTC: %s Lat: %5.2f Lon: %5.2f %s",MINTRGTIDMAIL,lat,lon,melding2);    
      printf("RTPPH: %s\n",melding); 
      sprintf(melding3,"UTC: %s | Lat: | %5.2f | Lon: | %5.2f | %s\n",MINTRGTIDMAIL,lat,lon,melding2);
      printf("RTPPH: %s",melding3);

      if(automag == 1)
      {
        if(mw > 0.0)
        {
          sprintf(melding0,"Real-time\n%s\nUTC: %s\nLat: %5.2f Lon: %5.2f MW:%3.1f",melding2,MINTRGTIDMAIL,lat,lon,mw);      
        }else{
          sprintf(melding0,"Real-time\n%s\nUTC: %s\nLat: %5.2f Lon: %5.2f MW: -",melding2,MINTRGTIDMAIL,lat,lon);
        }
      }else{
          sprintf(melding0,"Real-time\n%s\nUTC: %s\nLat: %5.2f Lon: %5.2f",melding2,MINTRGTIDMAIL,lat,lon);
      }
      sprintf(mail_storage1,"echo %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c | mutt -s %cPPH %s%c -- %s &",0x22,lat,lon,zoom,lat,lon,0x22,0x22,melding,0x22,mailaddress1);
      sprintf(mail_storage2,"echo %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c | mutt -s %cPPH %s%c -- %s &",0x22,lat,lon,zoom,lat,lon,0x22,0x22,melding,0x22,mailaddress2);
      sprintf(mail_storage3,"echo %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c | mutt -s %cPPH %s%c -- %s &",0x22,lat,lon,zoom,lat,lon,0x22,0x22,melding,0x22,mailaddress3);
      sprintf(mail_storage4,"echo %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c | mutt -s %cPPH %s%c -- %s &",0x22,lat,lon,zoom,lat,lon,0x22,0x22,melding,0x22,mailaddress4);
      sprintf(mail_storage5,"echo %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c | mutt -s %cPPH %s%c -- %s &",0x22,lat,lon,zoom,lat,lon,0x22,0x22,melding,0x22,mailaddress5);
        
    
      for(l=0;l<800;l++)
      {
        if(mail_storage1[l]=='_')
          mail_storage1[l]='%';
        if(mail_storage2[l]=='_')
          mail_storage2[l]='%';
        if(mail_storage3[l]=='_')
          mail_storage3[l]='%';
        if(mail_storage4[l]=='_')
          mail_storage4[l]='%';
        if(mail_storage5[l]=='_')
          mail_storage5[l]='%';      
      } 
      sprintf(png_request,"wget -O %s/map/map.png %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c 2>request.log ",topdir_rt,0x22,lat,lon,zoom,lat,lon,0x22);
//    printf("%s\n",png_request); 
      sprintf(png_request2,"wget -O %s/rt/pph/%s.png %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=640x640&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c 2>request.log ",topdir_rt,TRG_TID,0x22,lat,lon,zoom,lat,lon,0x22);
//    printf("%s\n",png_request2); 
      sprintf(png_request3,"wget -O %s/map/smallmap.png %chttp://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=320x320&maptype=hybrid&markers=icon:http://maps.google.com/mapfiles/kml/pal3/icon33.png_7C%f,%f&sensor=false%c 2>request.log ",topdir_rt,0x22,lat,lon,zoom,lat,lon,0x22);
//    printf("%s\n",png_request);     
    
      for(l=0;l<500;l++)
      {
        if(png_request[l]=='_')
          png_request[l]='%';
        if(png_request2[l]=='_')
          png_request2[l]='%';  
        if(png_request3[l]=='_')
          png_request3[l]='%';      
      } 
    
    
      sprintf(fnavn,"%s/map/smallmap.txt",topdir_rt);   
      if((out = fopen(fnavn,"w")) == NULL)
      {
        printf("RTPPH: Can't open file smallmap.txt\n"); 
      }
      fprintf(out,"%s",melding0);
      fclose(out);    
    

      sprintf(fnavn,"%s/map/map.txt",topdir_rt);   
      if((out = fopen(fnavn,"w")) == NULL)
      {
        printf("RTPPH: Can't open file map.txt\n"); 
      }
      fprintf(out,"%s",melding3);
      fclose(out);
    
      ret=system(png_request);
      ret=system(png_request2);
      ret=system(png_request3);  
  
      ret = createHTML(mw,lat,lon,MINTRGTIDMAIL,melding2,TRG_TID,s_file_name);
      if(ret==-1)
        return(-1);
    }
  }   
  return(0);
}
/*----------------------------------------------------------------*/
/* Read recording file                                            */
/*----------------------------------------------------------------*/
read_memrec(char memsrv[100][100],int no_of_servers,char memrec[500][256],int no_of_rec,int no_of_nets,int start_rec[],int stopp_rec[])
{
  int i,j,k;
  char keyword[10];
  char serv[10];
  char ipaddr[50];
  char nw[10];
  char st[10];
  char lo[10];
  char co[10];
  char sr[10];
  
  for(i=0;i<no_of_rec;i++)
  {
    sscanf(memrec[i],"%s %s %s %s %s",nw,st,lo,co,sr);
    sprintf(keyword,"%s",sr);    
    for(j=0;j<no_of_servers;j++)
    {
      sscanf(memsrv[j],"%s %s",serv,ipaddr);
      if(strstr(sr,serv))
      {
	if(lo[0] != '.' && lo[1] != '.')
	{
	  sprintf(record[i],"%s_%s:%s%s %s",nw,st,lo,co,ipaddr);
	}else{
	  sprintf(record[i],"%s_%s:%s %s",nw,st,co,ipaddr); 
	}
      }
      
    }
    
  }


} 

/*----------------------------------------------------------------*/
/* Read streams file                                              */
/*----------------------------------------------------------------*/
read_inputstreams( const char * streamfile,int p)
{
  FILE *streamfp;
  char linje[100];
  int count = 0;
  int s;

/* Open the streams file */
  if ((streamfp = fopen (streamfile, "rb")) == NULL)
  {
    printf("RTDET: read_inputstreams Can't open input stream file: %s\n",streamfile);
    printf("RTDET: read_inputstreams Check if file exists, or is wrong.\n");
    exit(0);
  }
  while ( (fgets (linje, sizeof(linje), streamfp)) !=  NULL)
  {
    for(s=0;s<20;s++)
    {
      if(linje[s] == 0xa)
        linje[s] = '\0';
    }
    sprintf(allstreams[stream_count],"%s %s",linje,slserv[p]);

    

//    printf("allstreams: %3d %s\n",stream_count,allstreams[stream_count]);
    stream_count++;
    count++;
  }
  kanaler_hver_stream[p]=count;
  if ( fclose (streamfp) )
  {
    return -1;
  }
}
//-----------------------------------------------------------------------------------------------
// S_REC_P called by Create_Sfile_P.
// Create s-file content with header lines and
// all phase readings
//
// MINPHASE        minimum time pick in time window
// idsfile         ID number s-file
// nchannels       number of channnels
// s_fullpath      fullpath+s-file name
// subnetno        subnet number
// wave_file_name  name of waveform file
//-----------------------------------------------------------------------------------------------
S_REC_P(char MINPPHASE[],char idsfile[],int nchannels,char s_fullpath[],int subnetno,char wave_file_name[])

{
FILE    *sf;
char buf[256];
char comp[200];
char dm1[200];
char dm2[200];
char stname[20];
int  p_or_s[MAXCHA];
int hr1;
int mn1;
int sc1;
int ms1;
char sta[20];
int i;
int ch; 
int ret;
int cnt;
int YR,MTH,DAY,HR,MIN;
float SEC;
int AR;

for(i=0;i<MAXCHA;i++)
  p_or_s[i] = 0;

for(i=0;i<(nchannels-1);i++)
{
  strncpy(stname,ttdly_rtp[klon][subnetno-1][i],10);
  for(ch=(i+1);ch<nchannels;ch++)
  {
    ret=strncmp(stname,ttdly_rtp[klon][subnetno-1][ch],10);
    if(ret == 0)
    {
      if(tt_rtp[klon][subnetno-1][i] < tt_rtp[klon][subnetno-1][ch])
      {
        p_or_s[ch] = 1;
      }else{
	p_or_s[i] = 1;
      }
    }
  }
}
//-------------------------------------------------------------
// Read minimum time picks into strings
//-------------------------------------------------------------
sscanf(MINPPHASE,"%2d%1c%2d%1c%2d%1c%2d%1c%2d%1c%f",&DAY,dm1,&MTH,dm1,&YR,dm1,&HR,dm1,&MIN,dm1,&SEC);
YR=YR+2000;
//----------------------------------------------------
// open s-file
//----------------------------------------------------
sf=fopen(s_fullpath,"w");
if(sf == NULL)
{
  printf("RTDET: S_REC_P Can't open S-file: %st\n",s_fullpath);
  return(-1);
}else{
//-----------------------------------------------------
// create and write line '1' in s-file
//-----------------------------------------------------
  for(i=0;i<100;i++)
  buf[i]=' ';
  printf("RTDET: S_REC_P......................: %4d %2d%2d %2d%2d %4.1f\n",YR,MTH,DAY,HR,MIN,SEC);
  sprintf(buf," %4d %2d%2d %2d%2d %4.1f",YR,MTH,DAY,HR,MIN,SEC);
  for(i=0;i<100;i++)
    if(buf[i]=='\0')buf[i]=' ';
  buf[21]='L';
  buf[22]='M';
  buf[45]='T';   // extract Agency from short network name
  buf[46]='S';
  buf[47]='T';
  buf[79]='1';
  buf[80]='\0';
  fprintf(sf,"%s\n",buf);
//-----------------------------------------------------
// create and write line '6' in s-file
//-----------------------------------------------------
  for(i=0;i<100;i++)
    buf[i]=' ';
  printf("In S_REC_P: FILENAME: %s\n",wave_file_name);
  sprintf(buf," %s",wave_file_name);
  for(i=0;i<100;i++)
    if(buf[i]=='\0')buf[i]=' ';
  buf[79]='6';
  buf[80]='\0';
  fprintf(sf,"%s\n",buf);
//-----------------------------------------------------
// create and write line 'I' in s-file
//-----------------------------------------------------  
  sprintf(dm1,"%4d",YR);
  sscanf(dm1,"%2c%d",dm2,&AR);

  for(i=0;i<100;i++)
    buf[i]=' ';

  sprintf(buf," ACTION:NEW %2d-%2d-%2d %2d:%2d OP:SEIS STATUS:               %s",AR,MTH,DAY,HR,MIN,idsfile);  

  if(buf[12]==' ')buf[12]='0';
  if(buf[15]==' ')buf[15]='0';
  if(buf[18]==' ')buf[18]='0';
  if(buf[21]==' ')buf[21]='0';
  if(buf[24]==' ')buf[24]='0';
    
  for(i=0;i<100;i++)
    if(buf[i]=='\0')buf[i]=' ';
  for(i=59;i<73;i++)
    if(buf[i]==' ')buf[i]='0';
  buf[79]='I';
  buf[80]='\0';
  fprintf(sf,"%s\n",buf);
//-----------------------------------------------------
// create and write line '7' in s-file
//-----------------------------------------------------  
  sprintf(buf," STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W  DIS CAZ7");
  fprintf(sf,"%s\n",buf);
//-----------------------------------------------------
// create and write phase reading lines
//-----------------------------------------------------
  for(ch=0;ch<nchannels;ch++)
  {
    printf("%s   %12.1f  %s  %d\n",ttdly_rtp[klon][subnetno-1][ch],tt_rtp[klon][subnetno-1][ch],ttstring_rtp[klon][subnetno-1][ch],p_or_s[ch]);
    comp[0]=ttdly_rtp[klon][subnetno-1][ch][7];
    comp[1]=ttdly_rtp[klon][subnetno-1][ch][9];
    comp[2]='\0';

    cnt=0;
    for(i=0;i<6;i++)
    {
      if(ttdly_rtp[klon][subnetno-1][ch][i] != ' ')
      {
        cnt++;
      }else{
        break;
      }
    }

    sscanf(ttstring_rtp[klon][subnetno-1][ch],"%9c%2d",dm1,&hr1);
    sscanf(ttstring_rtp[klon][subnetno-1][ch],"%12c%2d",dm1,&mn1);
    sscanf(ttstring_rtp[klon][subnetno-1][ch],"%15c%2d",dm1,&sc1);
    sscanf(ttstring_rtp[klon][subnetno-1][ch],"%18c%2d",dm1,&ms1);
      
    sscanf(ttdly_rtp[klon][subnetno-1][ch],"%s",sta);
    if(p_or_s[ch] == 0)          // check if p or s picks
    {
      switch(cnt)                // always p picks
      {
        case 2:
        fprintf(sf," %s   %s IP    A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
        break;
        case 3:
        fprintf(sf," %s  %s IP    A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
        break;
        case 4:
        fprintf(sf," %s %s IP    A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
        break;
        case 5:
        fprintf(sf," %s%s IP    A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
        break;
      }
    }else{
      if(rtsphases == 1)        // check if s picks to be used
      {
        switch(cnt)
        {
          case 2:
          fprintf(sf," %s   %s IS   3A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
          break;
          case 3:
          fprintf(sf," %s  %s IS   3A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
          break;
          case 4:
          fprintf(sf," %s %s IS   3A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
          break;
          case 5:
          fprintf(sf," %s%s IS   3A  %2d%2d %2d.%2d\n",sta,comp,hr1,mn1,sc1,ms1);
          break;
        }
      }
    }
  }
  fclose(sf);
  return(0);
}
}
S_REC(year,month,day,hour,minute,seconds,dummy,fullpath,filename,nchannels,trgdur,idsfile)
char year[];
char month[];
char day[];
char hour[];
char minute[];
char seconds[];
char dummy[];
char fullpath[];
char filename[];
int nchannels;
int trgdur[];
char idsfile[];
//int thr[];
//int tmn[];
//int tsc[];
//int tms[];
//int start_trg[];
{
FILE    *sf;
char buf[256];
char comp[200];
char dm1[200];
char dm2[200];
int hr1;
int mn1;
int sc1;
int ms1;

int i;
int ch; 
int cnt;
int YR,MTH,DAY,HR,MIN;
float SEC;
int AR;

//printf("SECONDS: %s\n",seconds);
sscanf(year,"%d",&YR);
//printf("%s %d\n",year,YR);
sscanf(month,"%d",&MTH);
//printf("%s %d\n",month,MTH);
sscanf(day,"%d",&DAY);
//printf("%s %d\n",day,DAY);
sscanf(hour,"%d",&HR);
//printf("%s %d\n",hour,HR);
sscanf(minute,"%d",&MIN);
//printf("%s %d\n",minute,MIN);
sscanf(seconds,"%f",&SEC);
//printf("%s %f\n",seconds,SEC);




sf=fopen(fullpath,"w");
if(sf == NULL)
{
  printf("RTDET: S_REC Can't open S-file: %s\n",fullpath);
  for(i=0;i<52;i++)
    printf("%2d %2x %c\n",i,fullpath[i],fullpath[i]);

  exit(0);
}else{
  for(i=0;i<100;i++)
  buf[i]=' ';
  printf("RTDET: S_REC.............................: %4d %2d%2d %2d%2d %4.1f\n",YR,MTH,DAY,HR,MIN,SEC);
  sprintf(buf," %4d %2d%2d %2d%2d %4.1f",YR,MTH,DAY,HR,MIN,SEC);
  for(i=0;i<100;i++)
    if(buf[i]=='\0')buf[i]=' ';
  buf[21]='L';
  buf[22]='M';
  buf[45]='T';   // extract Agency from short network name
  buf[46]='S';
  buf[47]='T';
  buf[79]='1';
  buf[80]='\0';
  fprintf(sf,"%s\n",buf);

  for(i=0;i<100;i++)
    buf[i]=' ';
//printf("In S_REC: FILENAME: %s\n",filename);
  sprintf(buf," %s",filename);
  for(i=0;i<100;i++)
    if(buf[i]=='\0')buf[i]=' ';
  buf[79]='6';
  buf[80]='\0';
  fprintf(sf,"%s\n",buf);

  sprintf(dm1,"%4d",YR);
  sscanf(dm1,"%2c%d",dm2,&AR);

  for(i=0;i<100;i++)
    buf[i]=' ';
//  sprintf(buf," ACTION:NEW %2d-%2d-%2d %2d:%2d OP:SEIS STATUS:               ID:%4d%2d%2d%2d%2d%2d",AR,MTH,DAY,HR,MIN,YR,MTH,DAY,HR,MIN,(int)SEC);
  sprintf(buf," ACTION:NEW %2d-%2d-%2d %2d:%2d OP:SEIS STATUS:               %s",AR,MTH,DAY,HR,MIN,idsfile);  

  if(buf[12]==' ')buf[12]='0';
  if(buf[15]==' ')buf[15]='0';
  if(buf[18]==' ')buf[18]='0';
  if(buf[21]==' ')buf[21]='0';
  if(buf[24]==' ')buf[24]='0';
  
  

  for(i=0;i<100;i++)
    if(buf[i]=='\0')buf[i]=' ';
  for(i=59;i<73;i++)
    if(buf[i]==' ')buf[i]='0';
  buf[79]='I';
  buf[80]='\0';
  fprintf(sf,"%s\n",buf);                 
  sprintf(buf," STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W  DIS CAZ7");
  fprintf(sf,"%s\n",buf);

// STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W
// BER  BZ IP       2223  6.00    4
  printf("nchannels: %d\n",nchannels);
  for(ch=0;ch<nchannels;ch++)
  {
    if(printarg > 0)
      printf("RTDET: S_REC %2d dur: %3d time: %s\n",ch,trgdur[ch],TRIGGER_TIMES[ch]);
  }
  for(ch=0;ch<nchannels;ch++)
  {
    if(printarg > 0)
      printf("RTDET: S_REC %2d dur: %3d time: %s\n",ch,trgdur[ch],TRIGGER_TIMES[ch]);
  }
  for(ch=0;ch<nchannels;ch++)
  {

    if(trgdur[ch] != 0)     
    {
//      printf("%s   %s\n",trig_stations[ch],trig_components[ch]);
      comp[0]=trig_components[ch][0];
      comp[1]=trig_components[ch][2];
      comp[2]='\0';

      cnt=0;
      for(i=0;i<6;i++)
      {
        if(trig_stations[ch][i] != '\0')
        {
          cnt++;
        }else{
          break;
        }
      }
      sscanf(TRIGGER_TIMES[ch],"%9c%2d",dm1,&hr1);
      sscanf(TRIGGER_TIMES[ch],"%12c%2d",dm1,&mn1);
      sscanf(TRIGGER_TIMES[ch],"%15c%2d",dm1,&sc1);
      sscanf(TRIGGER_TIMES[ch],"%18c%2d",dm1,&ms1);
      
if(keep==0)      
{      
      switch(cnt)
      {
        case 2:
        fprintf(sf," %s   %s IP    A  %2d%2d %2d.%2d %4d\n",trig_stations[ch],comp,hr1,mn1,sc1,ms1,trgdur[ch]);
        break;
        case 3:
        fprintf(sf," %s  %s IP    A  %2d%2d %2d.%2d %4d\n",trig_stations[ch],comp,hr1,mn1,sc1,ms1,trgdur[ch]);
        break;
        case 4:
        fprintf(sf," %s %s IP    A  %2d%2d %2d.%2d %4d\n",trig_stations[ch],comp,hr1,mn1,sc1,ms1,trgdur[ch]);
        break;
        case 5:
        fprintf(sf," %s%s IP    A  %2d%2d %2d.%2d %4d\n",trig_stations[ch],comp,hr1,mn1,sc1,ms1,trgdur[ch]);
        break;

        break;
      }
}
  
}
  }

  fclose(sf);
  for(ch=0;ch < nchannels;ch++)
  {
    for(i=0;i<80;i++)
      TRIGGER_TIMES[ch][i]='\0';
  }

}
}
//-----------------------------------------------------------------------------------------------
// Called by TRIGGER_TIME_FPICK.
// Create s-file name based on minimum time from phase picks inside timewindow
// Write new s-file in PPP__ data base
// tid            minimum time from TRIGGER_TIME_FPICK
// wave_file_name name of waveform file to be written to new s-file
// nchannels      number of channels
// subnetno       subnet number
// s_file_name    s-file name (also to be returned)
//-----------------------------------------------------------------------------------------------
Create_Sfile_P(char tid[],char wave_file_name[],int nchannels,int subnetno,char s_file_name[])
{
  int i;
  int ret;
  char s_fullpath[200];
  char comm1[200];
  char snam[200];
  char dummy[200];

  char year[5];
  char month[5];
  char day[5];
  char hour[5];
  char minute[5];
  char sec[5];
  
  char idsfile[20];
  char events_p[200];
  char database[20];
  char spath[200];
    
  int yr;
  int mn;
  int dy;
  int ho;
  int mi;
  int sc;

  char seconds[10];
  char tempo[80];

  for(i=0;i<200;i++)
  {
    snam[i]='\0';
    s_fullpath[i]='\0';
  }
//--------------------------------------------
// make sfile name based on minimum phase time
//----------------------------------------

  printf("CREATE_Sfile_P: Time to make Sfile..: %s\n",tid);
  for(i=0;i<23;i++)
    if(tid[i]==' ')tid[i]='0';
  sscanf(tid,"%6s%2d",dummy,&yr);
  yr=yr+2000;
  sprintf(year,"%4d",yr);
  sscanf(tid,"%3s%2s",dummy,month);
  sscanf(tid,"%2s",day);
  sscanf(tid,"%9s%2s",dummy,hour);
  sscanf(tid,"%12s%2s",dummy,minute);
  sscanf(tid,"%15s%2s",dummy,sec);
  sscanf(tid,"%15s%6s",dummy,seconds);

  sscanf(year,"%d",&yr);
  sscanf(month,"%d",&mn);
  sscanf(day,"%d",&dy);
  sscanf(hour,"%d",&ho);
  sscanf(minute,"%d",&mi);
  sscanf(sec,"%d",&sc);


  sprintf(snam,"%2s-%2s%2s-%2sL.S%4s%2s",day,hour,minute,sec,year,month);  // s-file name
  for(i=0;i<19;i++)                                                        // replace ' ' with '0'
    if(snam[i]==' ')snam[i]='0';
    
  printf("Create_Sfile_P: S-filename..........: %s\n",snam);
  sprintf(database,"PPP__");
  sprintf(spath,"%s/REA",topdir);
  sprintf(events_p,"%s/%s",spath,database);
  sprintf(dummy,"%s/%s/%s",events_p,year,month);
  printf("Create_Sfile_P DUMMY................: %s\n",dummy);
  CreateDirectory(dummy);
//--------------------------------------------
// make full path for S-file
//--------------------------------------------
  sprintf(s_fullpath,"%s/%s",dummy,snam);

  printf("Create_Sfile_P FULLPATH.............: %s\n",s_fullpath);
  sprintf(idsfile,"ID:%4s%2s%2s%2s%2s%2s",year,month,day,hour,minute,sec);    
  sprintf(s_file_name,"%s",s_fullpath);
//-----------------------------------------------------------------------
// write new s-file
//-----------------------------------------------------------------------
  ret = S_REC_P(tid,idsfile,nchannels,s_fullpath,subnetno,wave_file_name);
  if(ret == 0)
  {
    sprintf(comm1,"cp %s hyp_save.out",s_fullpath);
    ret=system(comm1);                                     // copy sfile (no location) to "hyp_save.out" OK
    printf("Create_Sfile_P..........................: %s\n",comm1);
    return(0);
  }else{
    return(-1);
  }


  
}
Create_Sfile(char tid[],char filename[],int nchannels,int trgdur[],char sfil_coda_pick[])
{
  int retur;
  int i;
  int ret;
  char fullpath[200];
  char syscmd[200];
  char comm1[200];
  char comm2[200];
  char comm4[200];
  char snam[200];
  char dummy[200];

  char year[5];
  char month[5];
  char day[5];
  char hour[5];
  char minute[5];
  char sec[5];
  
  char idsfile[20];
  
  int yr;
  int mn;
  int dy;
  int ho;
  int mi;
  int sc;

  char seconds[10];
  char tempo[80];

  for(i=0;i<200;i++)
  {
    snam[i]='\0';
    fullpath[i]='\0';
  }
//----------------------------------------
// make sfile name
//----------------------------------------
  if(printarg >= 1)
    printf("RTDET:......................Create_Sfile Time to make Sfile: %s\n",tid);
  for(i=0;i<23;i++)
    if(tid[i]==' ')tid[i]='0';

  sscanf(tid,"%6s%4s",dummy,year);
//printf("Year: %s\n",year);
  sscanf(tid,"%3s%2s",dummy,month);
//printf("Month:%s\n",month);
  sscanf(tid,"%2s",day);
//printf("Day:  %s\n",day);
  sscanf(tid,"%11s%2s",dummy,hour);
//printf("Hour; %s\n",hour);
  sscanf(tid,"%14s%2s",dummy,minute);
//printf("Minu: %s\n",minute);
  sscanf(tid,"%17s%2s",dummy,sec);
//printf("Sec:  %s\n",sec);
  sscanf(tid,"%17s%6s",dummy,seconds);

  sscanf(year,"%d",&yr);
  sscanf(month,"%d",&mn);
  sscanf(day,"%d",&dy);
  sscanf(hour,"%d",&ho);
  sscanf(minute,"%d",&mi);
  sscanf(sec,"%d",&sc);


  sprintf(snam,"%2s-%2s%2s-%2sL.S%4s%2s",
day,hour,minute,sec,year,month);
  for(i=0;i<19;i++)
    if(snam[i]==' ')snam[i]='0';
  printf("RTDET: Create_Sfile S-filename...........: %s\n",snam);

  sprintf(EVENTS_S,"%s/%s",sfilepath,dbname);
  sprintf(dummy,"%s/%s/%s",EVENTS_S,year,month);
  printf("RTDET: Create_Sfile DUMMY................: %s\n",dummy);
  CreateDirectory(dummy);
//--------------------------------------------
// make full path for S-file
//--------------------------------------------
  sprintf(fullpath,"%s/%s",dummy,snam);
  retur=exists(fullpath);
  if(printarg > 0)
    printf("RTDET: RETUR: %d\n",retur);
  printf("RTDET: Create_Sfile FULLPATH.............: %s\n",fullpath);
  if(retur == 1)
  {
    printf("RTDET: Create_Sfile......................: File exist, add 1 second and create new name.\n");
    sc = sc +1;
    if(sc > 59)
    {
      sc = 0;
      mi = mi +1;
      if(mi > 59)
      {
	mi = 0;
	ho = ho+1;
      }
    }
    sprintf(hour,"%2d",ho);
    sprintf(minute,"%2d",mi);
    sprintf(sec,"%2d",sc);

    sprintf(idsfile,"ID:%4s%2s%2s%2s%2s%2sd",year,month,day,hour,minute,sec);
    
    
    sprintf(snam,"%2s-%2s%2s-%2sL.S%4s%2s",day,hour,minute,sec,year,month);
    for(i=0;i<19;i++)
      if(snam[i]==' ')snam[i]='0';
    printf("RTDET:.Create_Sfile......................: S-filename: %s\n",snam);
    sprintf(fullpath,"%s/%s",dummy,snam);
    printf("RTDET:.Create_Sfile......................: FULLPATH: %s\n",fullpath);  
  }else{
    sprintf(idsfile,"ID:%4s%2s%2s%2s%2s%2s",year,month,day,hour,minute,sec);    
  }
//  sprintf(SFILETOPICK,"%s",fullpath);
  sprintf(sfil_coda_pick,"%s",fullpath);

  S_REC(year,month,day,hour,minute, seconds, dummy,fullpath,filename,nchannels,trgdur,idsfile);

  sprintf(comm4,"cp %s hyp_save.out",fullpath);
  ret=system(comm4);                                     // copy sfile (no location) to "hyp2_save.out" OK
  
//  sprintf(comm4,"cp %s %s/tmp/hyp2_save.out",fullpath,topdir_rt);
//  ret=system(comm4);
  
  printf("RTDET: Create_Sfile......................: %s\n",comm4);

}
int exists(const char *fname)
{
    FILE *file;
    if (file = fopen(fname, "r"))
    {
        fclose(file);
        return 1;
    }
    return 0;
}
//----------------------------------------------------------------------
// create directory given in 'buffer' if not present
//----------------------------------------------------------------------
CreateDirectory(char* buffer) 
{ 
  int ret;
  int i;
  int siz;
  char path2[80];
  char message[100];
  DIR  *dirp; 
  struct dirent *direntp; 

  siz=strlen(buffer);
  buffer[siz]='/';
  buffer[siz+1]='\0';
  for(i=0;i<siz+1;i++)
  {
    if(buffer[i]=='/' && i > 0)
    {
      strncpy(path2,buffer,i);
      path2[i]='\0';
      dirp = opendir(path2);              // check if dir exists 
      if(dirp == NULL) 
      { 
//--------------------log message-------------------------------
        sprintf(message,"%d %s does not exist. Create it !",klon,path2);
//        ErrMsg();
        ret=mkdir(path2,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
//        if(processor == 0)
//          changemod(path2);
//      }else{
//--------------------log message-------------------------------
//        sprintf(message,"CreateDirectory: '%s' exist.",buffer);
//        ErrMsg();
      } 
      closedir(dirp);
    }
  }
} 




/*----------------------------------------------------------------*/
/* Create detection tables                                        */
/*----------------------------------------------------------------*/
create_detectiontable()
{
  int k,n;
  char navn[50];
  char dum1[20];
  char dum2[20];
  
  for(k=0;k < stream_count; k++)
  {
    for(n=0;n<25;n++)
      navn[n]='\0';
    for(n=0;n<10;n++)
      navn[n]=allstreams[k][n+3];
    sprintf(toplot[k], "%s",navn);      
//    sprintf(spt->trig_stations[klon][k],"%s",navn); 

    for(n=0;n<20;n++)
    {
      dum1[n]='\0';
      dum2[n]='\0';
    }
    for(n=0;n<5;n++)
      dum1[n]=allstreams[k][n+3];
    for(n=0;n<3;n++)    
      dum2[n]=allstreams[k][n+10];
    
//    sscanf(dum1,"%s",sta);
//    sscanf(dum2,"%s",com);
    sscanf(dum1,"%s",trig_stations[k]);
    sscanf(dum2,"%s",trig_components[k]);
//printf("%s      %s\n",trig_stations[k],trig_components[k]);    
  }
}
/*----------------------------------------------------------------*/
/* Read memsrv                                                    */
/*----------------------------------------------------------------*/
read_servers(int no_of_servers, char memsrv[100][100])
{
  int i;
  
  for(i=0;i<no_of_servers;i++)
    sscanf(memsrv[i],"%s %s",streams[i],slserv[i]);       
}
/*--------------------------------------------------------------------------*/
/* Compute STA and LTA and store max STA                                    */
/*--------------------------------------------------------------------------*/
void STA_LTA(float* sta1,float* lta1,float* lev1,float* stamax,int chan,int ns,int nsta,int nlta,int levn,int* ixmax,float fseismo[MAXCHA][2000])
{
  register    int ix;
  float       idx;                    /* Average difference in data value     */
                                      /* between 2 samples.                   */
  int no_sta = nsta;
  int no_lta = nlta;
  int no_lev = levn;
  float value;
  int i;
/*----initialise max sta----*/

  *stamax=0.0;
  *ixmax=0;

  for(ix=0; ix<ns; ix++)
  {
//    for(i=0;i<MAXCHA;i++)
//    {
//      if(tabell[chan][i] == 'X')
//      {    
    
        idx=(float)(fabs((double)(fseismo[chan][ix])));
//        idx=idx * idx;
/*--calculate sta and lta, and assign max if necessary--*/
        *sta1 += (idx - *sta1)/no_sta;
        *lta1 += (*sta1 - *lta1)/no_lta;

        *lev1 += (*sta1 - *lev1)/no_lta;

        if(*sta1 > *stamax)
        {
          *stamax = *sta1;
          *ixmax=ix;
        }
        if(*lta1 == 0.0)
          *lta1 = *sta1;
        if(*lev1 == 0.0)
          *lev1 = *sta1;
//      }
//    }
  }
} /* end of sta_lta procedure */
void C_TIME()
{
  char dummy[256];
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;
  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;
  int   isec;
  int   i,j;
  int   BUFSECS;
  float  sek;
  char dum[50];

  time_t now = time(NULL);
  struct tm *now_s = localtime(&now);
  sprintf(dummy,"%d-%02d-%02d_%02d:%02d:%02d", 1900+now_s->tm_year, ++now_s ->tm_mon,now_s->tm_mday, now_s->tm_hour, now_s->tm_min,now_s->tm_sec);
//printf("dummy: %s\n",dummy);
  sscanf(dummy,"%4d%1c%2d%1c%2d%1c%2d%1c%2d%1c%2d",&iyrn,dum,&imon,dum,&iday,dum,&ihrn,dum,&imin,dum,&isec);
//  printf("iyrn: %d imon: %d iday: %d ihrn: %d imin: %d isec: %d\n",iyrn,imon,iday,ihrn,imin,isec);
  yrn=iyrn;
  mon=imon;
  day=iday;
  hrn=ihrn;
  min=imin;
  mon=imon;
  sek=isec;
//  printf("yrn: %d\n",yrn);
//  printf("mon: %d\n",mon);
//  printf("day: %d\n",day);
//  printf("hrn: %d\n",hrn);
//  printf("min: %d\n",min);
//  printf("sek: %f\n",sek);
  TIMSEC(iyrn,imon,iday,ihrn,imin,sek,&CCC_TIME);
//  printf("CCC_TIME: %12.1f\n",CCC_TIME);
}
void CURRENT_TIME()
{
  char dummy[256];
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;
  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;
  int   isec;
  int   i,j;
  int   BUFSECS;
  float  sek;
  char dum[50];

  time_t now = time(NULL);
  struct tm *now_s = localtime(&now);
  sprintf(dummy,"%d-%02d-%02d_%02d:%02d:%02d", 1900+now_s->tm_year, ++now_s ->tm_mon,now_s->tm_mday, now_s->tm_hour, now_s->tm_min,now_s->tm_sec);
  sscanf(dummy,"%4d%1c%2d%1c%2d%1c%2d%1c%2d%1c%2d",&iyrn,dum,&imon,dum,&iday,dum,&ihrn,dum,&imin,dum,&isec);
  yrn=iyrn;
  yrn=yrn-2000;
  mon=imon;
  day=iday;
  hrn=ihrn;
  min=imin;
  mon=imon;
  sek=isec;

  TIMSEC(yrn,mon,day,hrn,min,sek,&TIME_NOW); 
}
void NOW()
{
  char dummy[256];
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;
  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;
  int   isec;
  int   i,j;
  int   BUFSECS;
  float  sek;
  char dum[50];

  time_t now = time(NULL);
  struct tm *now_s = localtime(&now);
  sprintf(dummy,"%d-%02d-%02d_%02d:%02d:%02d", 1900+now_s->tm_year, ++now_s ->tm_mon,now_s->tm_mday, now_s->tm_hour, now_s->tm_min,now_s->tm_sec);
  sscanf(dummy,"%4d%1c%2d%1c%2d%1c%2d%1c%2d%1c%2d",&iyrn,dum,&imon,dum,&iday,dum,&ihrn,dum,&imin,dum,&isec);
  yrn=iyrn;
  yrn=yrn-2000;
  mon=imon;
  day=iday;
  hrn=ihrn;
  min=imin;
  mon=imon;
  sek=isec;

  TIMSEC(yrn,mon,day,hrn,min,sek,&TID_NOW); 
}
void TRIGGER_TIME_P(int ws,int pindex,int kanal,float sr,int sekunder,int lno_str,int ch)
{
  int DDAY,MMTH;
  int DY;
  int YR;
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;

  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;

  float  sek;
  double MSECS;
  int   br=0;

  int   SECONDS_NOW;
  int   DELAY_INDX;

  int seconds_cpu;
  char tiden_cpu[80];
  char millis_cpu[4];
  long day_cpu;
  long mon_cpu;
  long yrn_cpu;
  long hrn_cpu;
  long min_cpu;
  float sek_cpu;
  char dm[10];
  double MSECS_CPU;
  double BUFFER_TIME_TRG;

  char   timestamp[80];
  char dum[50];
  int i,j,nn,nc;

  sscanf(rtid[kanal],"%4d%1c%3d%1c%2d%1c%2d%1c%f6.3",&YR,dum,&DY,dum,&ihrn,dum,&imin,dum,&sek);
  hrn=ihrn;
  min=imin;

  DTE (DY,&DDAY,&MMTH,YR);     //-- convert from doy to date  
  yrn=YR;
  yrn=yrn-2000;
  mon=MMTH;
  day=DDAY;

  iday=day;
  imon=mon;
  iyrn=yrn;
  ihrn=hrn;
  imin=min;

  TIMSEC(yrn,mon,day,hrn,min,sek,&MSECS);
  BUFFER_TIME_TRG = MSECS;
  MSECS=MSECS+(sr * pindex)-(sr * ws);
  SECTIM(MSECS,&yrn,&doy,&mon,&day,&hrn,&min,&sek);

  iday=day;
  imon=mon;
  iyrn=yrn;
  ihrn=hrn;
  imin=min;
  iyrn=iyrn-2000;

  sprintf(timestamp,"%2d/%2d/%2d %2d:%2d:%6.3f",iday,imon,iyrn,ihrn,imin,sek);
  if(timestamp[0] == ' ') timestamp[0] = '0';
  if(timestamp[3] == ' ') timestamp[3] = '0';
  if(timestamp[6] == ' ') timestamp[6] = '0';
  if(timestamp[9] == ' ') timestamp[9] = '0';
  if(timestamp[12] == ' ') timestamp[12] = '0';
  if(timestamp[15] == ' ') timestamp[15] = '0';
  if(timestamp[18] == ' ') timestamp[18] = '0';
  if(timestamp[19] == ' ') timestamp[19] = '0';
  if(timestamp[20] == ' ') timestamp[20] = '0';

  sprintf(TRIGGER_TIMES[kanal],"%s",timestamp);
  spt->tt[klon][kanal]=MSECS;                      // save trigger time
//      printf("TRIGGER_TIME_P: kanal %2d time: %12.1f\n",i,spt->tt[klon][i]);
  spt->age[klon][kanal][0] = arrwnd;
  spt->dur[klon][kanal] = 0;      
      
  SECONDS_NOW = MINUT_NOW * 60;

  DELAY_INDX = SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG);
//  printf("DELAY_INDX: %d\n",DELAY_INDX);
  
  if(DELAY_INDX >= 0 && DELAY_INDX <= (SECONDS_NOW + 60))
  {
    spt->ttdly[klon][kanal][SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG)] = 122;  
    trgdly[kanal][SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG)] = BUFFER_TIME_TRG;
    SKIPPED[kanal]=kanal;
  }else{
    printf("DELAY_INDX outside buffer, trigger skipped. Channel: %d %s\n",kanal,toplot[ch]);
    SKIPPED[kanal]=-1;
  }
}
//int TRIGGER_TIME_FPICK(char P_PHASE[],int lno_str,int ch,int ns[],float values[MAXCHA][RTBUFSIZ])
//------------------------------------------------------------------------------------------------
// TRIGGER_TIME_FPICK is called only when picks are detected by filterpicker
// P_PHASE     pickline from filterpicker
// lno_str
// ch          current channel
// ns          number of samples in buffer
//------------------------------------------------------------------------------------------------
int TRIGGER_TIME_FPICK(char P_PHASE[],int lno_str,int ch,int ns[])
{
  
    pthread_t write_rtphase_thread;       // definition for WRITE_RTPHASE thread
  
  
  char pyear[5];
  char pmonth[5];
  char pday[5];
  char phour[5];
  char pminute[5];
  char psec[5];
  
  char idsfile[20];
  char MINPPHASE[200];    
  char wave_file_name[1024]; 
  char s_file_name[1024];               // return from Create_Sfile_P
  int DDAY,MMTH;
  int DY;
  int YR;
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;

  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;

  float  sek;
  double MSECS;
  double TNOW;
  double TBEF;
  int ret;
  int ret1;
  int   br=0;
  int    kk,p;
  int   phasepicks = 0;
  int   SECONDS_NOW;
  int   DELAY_INDX;
  int kanal;
  char stas[10];
  int    varighet[MAXCHA];
//  char dm[10];
  double mintid;
  double MSECS_CPU;
  double BUFFER_TIME_TRG;
  double BTIME;
  double LAT;

  char   timestamp[80];
  char   timeutc[80];
  char   timeapw[80];
  char dum[50];
  int i,j,nn,nc,pidx;
  int sw=0;
  int subnetno;
  char   cur_chan[20];
  char   search[20];
  
  
  rtphase phases;
  

  for(j=0;j<20;j++)
    phasepicks_rtp[j]=0;
  for(j=0;j<20;j++)
    cur_chan[j]='\0';
//-----------------------------------------------------------------------------------------------------
// Check for picks on current channel
//-----------------------------------------------------------------------------------------------------
  strncpy(cur_chan,allstreams[ch],13);
  for(kk=0;kk<stream_count;kk++)
  {
    for(j=0;j<13;j++)
      search[j]=spt->trig_stations[klon][kk][j+3];
    search[13] = '\0';
    ret=strncmp(cur_chan,search,13);
    if(ret==0)
    {
      sscanf(spt->trig_stations[klon][kk],"%d",&subnetno);
      sscanf(P_PHASE,"%3d%28c%4d%2d%2d%1c%2d%2d%3c%f7.4",&kanal,dum,&iyrn,&imon,&iday,dum,&ihrn,&imin,dum,&sek);      
      printf("*************************************************************************************************************************\n");
      printf("* FPICK:  Detection SUBNET:%2d ch:%2d %s BUFFER_TIME: %s TRG_TIME: %4d/%2d/%2d %2d:%2d:%5.2f  *\n",subnetno,ch,cur_chan,rtid[ch],iyrn,imon,iday,ihrn,imin,sek);
      printf("*************************************************************************************************************************\n");
      break;
    }
  }

//----------------------------------------------------------------------------------------------
// Use the current buffer time and compute the number of seconds, store in BTIME
//----------------------------------------------------------------------------------------------
  sscanf(rtid[ch],"%4d%1c%3d%1c%2d%1c%2d%1c%f6.3",&YR,dum,&DY,dum,&ihrn,dum,&imin,dum,&sek);
  hrn=ihrn;
  min=imin;
  DTE (DY,&DDAY,&MMTH,YR);     //-- convert from doy to date  
  yrn=YR;
  yrn=yrn-2000;
  mon=MMTH;
  day=DDAY;

  iday=day;
  imon=mon;
  iyrn=yrn;
  ihrn=hrn;
  imin=min;

  TIMSEC(yrn,mon,day,hrn,min,sek,&BTIME);  
//
//---------------------------------------------------------------------------------------------
// Based on the picklines from filterpicker, compute the number of seconds for the phase-pick
// Stored in BUFFER_TIME_TRG
// (Here one can also extract first movement (if any) to be used in s-file
//---------------------------------------------------------------------------------------------  
  printf("FPICKS: P_PHASE: %s\n",P_PHASE); 
//    printf("%s\n",P_PHASE);
  sscanf(P_PHASE,"%3d%28c%4d%2d%2d%1c%2d%2d%3c%f7.4",&kanal,dum,&iyrn,&imon,&iday,dum,&ihrn,&imin,dum,&sek);
//  printf("kanal: %2d iyrn: %2d imon: %2d iday: %2d ihrn: %2d min: %2d sek: %f7.4\n",kanal,iyrn,imon,iday,ihrn,imin,sek);
  yrn = iyrn;
  mon = imon;
  day = iday;
  hrn = ihrn;
  min = imon;  
  TIMSEC(iyrn,imon,iday,ihrn,imin,sek,&MSECS);
  BUFFER_TIME_TRG = MSECS;  
  iyrn=iyrn-2000;

  sprintf(timestamp,"%2d/%2d/%2d %2d:%2d:%6.3f",iday,imon,iyrn,ihrn,imin,sek);
  if(timestamp[0] == ' ') timestamp[0] = '0';
  if(timestamp[3] == ' ') timestamp[3] = '0';
  if(timestamp[6] == ' ') timestamp[6] = '0';
  if(timestamp[9] == ' ') timestamp[9] = '0';
  if(timestamp[12] == ' ') timestamp[12] = '0';
  if(timestamp[15] == ' ') timestamp[15] = '0';
  if(timestamp[18] == ' ') timestamp[18] = '0';
  if(timestamp[19] == ' ') timestamp[19] = '0';
  if(timestamp[20] == ' ') timestamp[20] = '0';

//-------------------------------------------------------------------------------------------
// Compute current time based on CPU and store in TNOW.
//-------------------------------------------------------------------------------------------
  C_TIME();
  TNOW = CCC_TIME;
  SECTIM(TNOW,&yrn,&doy,&mon,&day,&hrn,&min,&sek);
  iyrn = yrn;
  imon = mon;
  iday = day;
  ihrn = hrn;
  imin = min;
  iyrn = iyrn - 2000;
  
  sprintf(timeutc,"%2d/%2d/%2d %2d:%2d:%6.3f",iday,imon,iyrn,ihrn,imin,sek);
  if(timeutc[0] == ' ') timeutc[0] = '0';
  if(timeutc[3] == ' ') timeutc[3] = '0';
  if(timeutc[6] == ' ') timeutc[6] = '0';
  if(timeutc[9] == ' ') timeutc[9] = '0';
  if(timeutc[12] == ' ') timeutc[12] = '0';
  if(timeutc[15] == ' ') timeutc[15] = '0';
  if(timeutc[18] == ' ') timeutc[18] = '0';
  if(timeutc[19] == ' ') timeutc[19] = '0';
  if(timeutc[20] == ' ') timeutc[20] = '0';  

//----------------------------------------------------------------------------------------
// We want to compute a timewindow in seconds, from current time to an earlier time
// to accept picks within this time frame. How far back is determined by a parameter in
// the parameterfile TIMEWINDOW. The seconds back in time is stored in TBEF
//----------------------------------------------------------------------------------------
  TBEF = CCC_TIME - timewindowback;  

  SECTIM(TBEF,&yrn,&doy,&mon,&day,&hrn,&min,&sek);
  iyrn = yrn;
  imon = mon;
  iday = day;
  ihrn = hrn;
  imin = min;
  iyrn = iyrn - 2000;
  
  sprintf(timeapw,"%2d/%2d/%2d %2d:%2d:%6.3f",iday,imon,iyrn,ihrn,imin,sek);
  if(timeapw[0] == ' ') timeapw[0] = '0';
  if(timeapw[3] == ' ') timeapw[3] = '0';
  if(timeapw[6] == ' ') timeapw[6] = '0';
  if(timeapw[9] == ' ') timeapw[9] = '0';
  if(timeapw[12] == ' ') timeapw[12] = '0';
  if(timeapw[15] == ' ') timeapw[15] = '0';
  if(timeapw[18] == ' ') timeapw[18] = '0';
  if(timeapw[19] == ' ') timeapw[19] = '0';
  if(timeapw[20] == ' ') timeapw[20] = '0';  
  

//--------------------------------------------------------------------------------------
// print latency receiving data buffer
//--------------------------------------------------------------------------------------
  printf("FPICKS: LATENCY: TNOW-BTIME: %12.1f - %12.1f = %12.1f\n",TNOW,BTIME,TNOW - BTIME);
//--------------------------------------------------------
// zero indexes that is outside APW
//--------------------------------------------------------

  for(kk=0; kk < MAXCHA; kk++)
  {
    if(tt_rtp[klon][subnetno-1][kk] > TNOW &&  tt_rtp[klon][subnetno-1][kk] < TBEF) // inside APW ?
    {
      tt_rtp[klon][subnetno-1][kk] = -1.0;
      sprintf(ttdly_rtp[klon][subnetno-1][kk],"                  ");
      sprintf(ttstring_rtp[klon][subnetno-1][kk],"                             ");
    }
  }  
  
//----------------------------------------------------------
// insert time, station and timestring in first index < 1.0
//----------------------------------------------------------

  sw = 0;
  for(kk=0;kk < MAXCHA; kk++)
  {
    if(tt_rtp[klon][subnetno-1][kk] < 1.0)
    {
      br = kk;
      printf("FPICKS: First free is index subnetno %2d: %3d\n",subnetno,br);
      tt_rtp[klon][subnetno-1][kk] = BUFFER_TIME_TRG;
      sprintf(ttdly_rtp[klon][subnetno-1][kk],"%s",toplot[kanal]);
      sprintf(ttstring_rtp[klon][subnetno-1][kk],"%s",timestamp);
      sw = 1;
    }
    if(sw == 1)
      break;
  }  
//--------------------------------------------------------------
// find number of picks within APW 
//--------------------------------------------------------------

  for(kk=0; kk < MAXCHA; kk++)
  {
//    printf("%s %12.1f %12.1f %12.1f\n",spt->ttdly_p[klon][kk],TBEF,spt->tt_p[klon][kk],TNOW);
    if(tt_rtp[klon][subnetno-1][kk] < TNOW &&  tt_rtp[klon][subnetno-1][kk] > TBEF) // inside APW ?
    {
      printf("FPICKS: subnet: %2d index: %2d %s TBEF:%12.1f TRG: %12.1f TNOW: %12.1f %s\n",subnetno,kk,ttdly_rtp[klon][subnetno-1][kk],TBEF,tt_rtp[klon][subnetno-1][kk],TNOW,ttstring_rtp[klon][subnetno-1][kk]);
      phasepicks_rtp[subnetno-1]++; 
    }else{
      tt_rtp[klon][subnetno-1][kk] = -1.0;
    }
  }
  printf("FPICKS: Phasepics subnet %2d: %d\n",subnetno,phasepicks_rtp[subnetno-1]);


//--------------------------------------------------------------------------------------------
// check if number of phase picks within time window is higher than the the criteria
// specified in the parameter file
//--------------------------------------------------------------------------------------------

  if(phasepicks_rtp[subnetno-1] >= minstalopph)
  {
    printf("FPICK: AN EVENT IS DETECTED !!\n");
    mintid = 9333333333.0;

    for(p = 0; p < MAXCHA; p++)                                   // find the minimum time among the phase picks
    {
      if(tt_rtp[klon][subnetno-1][p] > 0.0)
      {
//        printf("FPICKS: %2d %12.1f\n",p,tt_rtp[klon][subnetno-1][p]);
        if(tt_rtp[klon][subnetno-1][p] < mintid)
        {
          mintid=tt_rtp[klon][subnetno-1][p];
          pidx = p;
        }
      }
    }
    
    for(p = 0; p < MAXCHA; p++)                                  // print out the phase picks
    {
      if(tt_rtp[klon][subnetno-1][p] > 0.0)
      {
        printf("FPICKS: %2d %12.1f  %6.1f\n",p,tt_rtp[klon][subnetno-1][p],tt_rtp[klon][subnetno-1][p]-mintid);
      }
    }    
//--------------------------------------------------------------------------------
// use the minimum time (seconds) to compute the date and time for the event.
// The date and time are used to create the name of the waveform.
// Also create the ID for the s-file based on the same date and time
//--------------------------------------------------------------------------------
    printf("FPICK: pidx: %d\n",pidx);
    sprintf(MINPPHASE,"%s",ttstring_rtp[klon][subnetno-1][pidx]);
    printf("FPICK: MINPPHASE: %s  mintid: %12.1f\n",MINPPHASE,mintid);
    sscanf(MINPPHASE,"%2d%1c%2d%1c%2d%1c%2d%1c%2d%1c%f",&iday,dum,&imon,dum,&iyrn,dum,&ihrn,dum,&imin,dum,&sek);     
    sprintf(pyear,"%4d",iyrn);
    sprintf(pmonth,"%2d",imon);
    sprintf(pday,"%2d",iday);
    sprintf(phour,"%2d",ihrn);
    sprintf(pminute,"%2d",imin);
    sprintf(psec,"%2d",(int)sek);
  
    sprintf(idsfile,"ID:%4s%2s%2s%2s%2s%2sd",pyear,pmonth,pday,phour,pminute,psec);
    
    
    sprintf(wave_file_name, "%4d-%2d-%2d-%2d%2d-%2d.NNSN__%3d_%2d_%2d",iyrn+2000,imon,iday,ihrn,imin,(int)sek,lno_str,klon,subnetno);

    for(p=0;p<35;p++)
      if(wave_file_name[p] == ' ') wave_file_name[p]='0';

    wave_file_name[34]='\0';
    wave_file_name[19] = dbname[0];
    wave_file_name[20] = dbname[1];
    wave_file_name[21] = dbname[2];
    wave_file_name[22] = dbname[3];
    wave_file_name[23] = dbname[4];
    wave_file_name[19] = 'P';
    wave_file_name[20] = 'P';
    wave_file_name[21] = 'P';
    wave_file_name[22] = '_';
    wave_file_name[23] = '_';  
    printf("TRIGGER_TIME_FPICK: ......wave_file_name: %s\n",wave_file_name);    
    
//---------------------------------------------------------------------------------------    
// Create s-file with corresponding phase picks
//---------------------------------------------------------------------------------------
    ret = Create_Sfile_P(MINPPHASE,wave_file_name,phasepicks_rtp[subnetno-1],subnetno,s_file_name);   
    if(ret == 0)
    {
//      ret1 = RTPPH(s_file_name);    
//      mail_switch++;
      
//------------------Prepare parameter structure for WRITE_RTPHASE thread ------------------------- 
      strcpy(phases.wname,wave_file_name);   // wave file name as parameter to WRITE_RTPHASE
      strcpy(phases.sname,s_file_name);      // s_file_name as parameter to WRITE_RTPHASE 
      
//      pthread_create(&write_rtphase_thread, NULL, (void *) &WRITE_RTPHASE,(void *) &phases);  
      WRITE_RTPHASE_F(s_file_name,wave_file_name);
      printf("WRITE_RTPHASE started!\n");
//      ret1 = RTPPH(s_file_name);    
//      mail_switch++;         
      

    }else{
      return(-1);
    }
  
  return(0);
 }  
  
  
}
 
void TRIGGER_DUR(int sekunder,int kanal,int nn,int lno_str)
{
  int DDAY,MMTH;
  int DY;
  int YR;
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;

  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;

  float  sek;
  double MSECS;
  double BUFFER_TIME_TRG;
  int   br=0;

  int   SECONDS_NOW;
  int   index;

  int seconds_cpu;
  char tiden_cpu[80];
  char millis_cpu[4];
  long day_cpu;
  long mon_cpu;
  long yrn_cpu;
  long hrn_cpu;
  long min_cpu;
  float sek_cpu;
  char dm[10];
  double MSECS_CPU;

  char   timestamp[80];
  char dum[50];
  int i,j,ii,nc;

  sscanf(rtid[kanal],"%4d%1c%3d%1c%2d%1c%2d%1c%f6.3",&YR,dum,&DY,dum,&ihrn,dum,&imin,dum,&sek);
  hrn=ihrn;
  min=imin;

  DTE (DY,&DDAY,&MMTH,YR);     //-- convert from doy to date  
  yrn=YR;
  yrn=yrn-2000;
  mon=MMTH;
  day=DDAY;

  TIMSEC(yrn,mon,day,hrn,min,sek,&MSECS);
  BUFFER_TIME_TRG = MSECS;

  SECONDS_NOW = MINUT_NOW * 60;
  
 
//  for(ii=0;ii<MAXCHA;ii++)
//  {
//    if(tabell[kanal][ii] == 'X')
//    {   
      if(SKIPPED[kanal] >= 0)
      {
        spt->ttdly[klon][kanal][SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG)] = 111;  
        trgdly[kanal][SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG)] = 111;  
//  printf("duration index: %6d\n",SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG));
        for(i=1;i<600;i++)
        {
          index = SECONDS_NOW - (int)(TIME_NOW - BUFFER_TIME_TRG) - i;
          if(spt->ttdly[klon][kanal][index] < 122 && trgdly[kanal][index] < 10000)
          {
            spt->ttdly[klon][kanal][index] = 111;
            trgdly[kanal][index] = 111;
          }else{
            break;
          }
        }
      }else{
        printf("channel %2d skipped\n",kanal); 
      }
//    }
//  }


}
//-----------------------------------------------------
// find maximum amplitude channel ->MxAMP
//-----------------------------------------------------
void MaxAmp(int no_of_smp,float scr[],float *MxAmp)                 // Find max amplitude channel
{
  float max;
  int k;

  max=(float)0.0;
  for(k=0;k<no_of_smp;k++)
  {
    if(fabsf(scr[k])>max)
      max=fabsf(scr[k]);
  }
  *MxAmp=max;
//  printf("MxAmp: %8.3f\n",MxAmp);

  }
//-----------------------------------------------------
// scale seis->1.0
//-----------------------------------------------------
void Scale_to_1(int no_of_smp,float scr[],float MxAmp)             // Scale channel to max 1
{
  int k;

  for(k=0;k<no_of_smp;k++)
  {
    scr[k]=scr[k]/MxAmp;
  }

}



Read_Parameters()
{
  FILE *par;
  char  dummy[256];
  char  linjer[256];
  char  keyword[256];
  char  text[256];
  float val;
  int   k;
  int   br = 0;

  par = fopen("rtquake.par","r");
  if(par == NULL)
  {
    printf("RTDET: Default parameters	rtquake.par does not exist in current directory.\n");

    sprintf(dummy,"%s/com/rtquake.par",topdir_rt);
   
    printf("RTDET: Default parameters	Look in %s\n",dummy);    
    par = fopen(dummy,"r");
    if(par == NULL)
    {
      printf("RTDET: Default parameters		rtquake.par does not exist in %s/com. Use program defaults.\n",topdir_rt);
      br=1;      
    }
  }
  if(br == 0)
  {
    if(printarg > 0)
      printf("RTDET:...................................: read rtquake.par\n");
    sprintf(keyword,"DELAY_BUFFER");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//	printf("val: %5.1f\n",val);
	DELAY_BUFFER = (int)val;
        break;
      }
    }
    rewind(par);    
    sprintf(keyword,"SECONDS2SHUFLE");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	SECONDS2SHUFLE = (int)val;
        break;
      }
    }   
    rewind(par);
    sprintf(keyword,"KEEP");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	keep = (int)val;
        break;
      }
    }   
    rewind(par);
    
    sprintf(keyword,"PRE_EVENT");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	preevent = (int)val;
        break;
      }
    }   
    rewind(par); 
    
    sprintf(keyword,"POST_EVENT");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	postevent = (int)val;
        break;
      }
    }   
    rewind(par);    
    
    
    
    sprintf(keyword,"ALLSUBNETS");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
//        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	mintrg = (int)val;
        break;
      }
    }   
    rewind(par);  
    sprintf(keyword,"REALTIME_PICK");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
//        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	realtimepick = (int)val;
        break;
      }
    }   
    rewind(par);      
    
    
    sprintf(keyword,"MAX_RES_PPH");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
//        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	maxrespph = val;
        break;
      }
    }   
    rewind(par); 
    
    sprintf(keyword,"MINSTALOCPPH");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
//        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	minstalopph = (int)val;
        break;
      }
    }   
    rewind(par);     
    
    sprintf(keyword,"TIMEWINDOW");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
//        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	timewindowback = (int)val;
        break;
      }
    }   
    rewind(par);    
    sprintf(keyword,"RTPHASES");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
//        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	rtsphases = (int)val;
        break;
      }
    }   
    rewind(par);       
    sprintf(keyword,"SOUND");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	sound = (int)val;
        break;
      }
    }   
    rewind(par); 

    sprintf(keyword,"AUTOMAG");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
	if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
	if(printarg > 0)
          printf("val: %5.1f\n",val);
	automag = (int)val;

        break;
      }
    }   
    rewind(par);  
    
    sprintf(keyword,"DBASENAME");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%s",dummy,text);
//        printf("val: %5.1f\n",val);
	sprintf(dbname,"%s",text);
        break;
      }
    }   
    rewind(par); 
    
    sprintf(keyword,"WAVE_DB_ACTIVE");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	wavedbactive = (int)val;
        break;
      }
    }   
    rewind(par);     
    
    
    sprintf(keyword,"WAVEDIR");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%s",dummy,text);
//        printf("val: %5.1f\n",val);
	sprintf(trgdir,"%s",text);

          sprintf(trgpath,"%s/%s",topdir,trgdir);
          printf("RTDET: Specified events path:   %s\n",trgpath);
	
        break;
      }
    }   
    rewind(par);       
    
    
    
    sprintf(keyword,"MINUT_NOW");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	MINUT_NOW = (int)val;
        break;
      }
    }
    
    rewind(par);    
    sprintf(keyword,"PRINTING");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
//	prt = (int)val;	
        break;
      }
    }   
    rewind(par);
/*
    sprintf(keyword,"LOW_PASS");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
	printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	LOW_PASS = (int)val;	
        break;
      }
    }   
    rewind(par);
    
    sprintf(keyword,"HIGH_PASS");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
	printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	HIGH_PASS = (int)val;	
        break;
      }
    }   
    rewind(par);
    
    sprintf(keyword,"STAW");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
	printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	STAW = (int)val;	
        break;
      }
    }   
    rewind(par);
    
    sprintf(keyword,"LTAW");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
	printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	LTAW = (int)val;	
        break;
      }
    }   
    rewind(par);
    
     sprintf(keyword,"TRGLEV");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
	printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	TRGLEV = (int)val;	
        break;
      }
    }   
    rewind(par);

     sprintf(keyword,"DTRGLEV");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
	printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	DTRGLEV = (int)val;	
        break;
      }
    }   
    rewind(par);    
*/    
    sprintf(keyword,"DET_DELAY");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	DET_DELAY = val;
        break;
      }
    }
    rewind(par);    
    sprintf(keyword,"APW");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
        if(printarg > 0)
	  printf("%s", linjer);
	sscanf(linjer,"%40c%f",dummy,&val);
//        printf("val: %5.1f\n",val);
	APW = val;
        break;
      }
    }
    
    rewind(par);    
    sprintf(keyword,"MAIL1");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
//	printf("%s", linjer);
	sscanf(linjer,"%50c%s",dummy,mailaddress1);
	sscanf(linjer,"%40c%f",dummy,&val);	
        printf("val: %5.1f  %s\n",val,mailaddress1);
	mail1 = (int)val;	
	break;
      }
    }
    
    rewind(par);    
    sprintf(keyword,"MAIL2");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
//	printf("%s", linjer);
	sscanf(linjer,"%50c%s",dummy,mailaddress2);
	sscanf(linjer,"%40c%f",dummy,&val);	
//        printf("val: %5.1f  %s\n",val,mailaddress1);
	mail2 = (int)val;	
        break;
      }
    }      
    rewind(par);    
    sprintf(keyword,"MAIL3");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
//	printf("%s", linjer);
	sscanf(linjer,"%50c%s",dummy,mailaddress3);
	sscanf(linjer,"%40c%f",dummy,&val);	
//        printf("val: %5.1f  %s\n",val,mailaddress1);
	mail3 = (int)val;	
        break;
      }
    }      
    
    rewind(par);    
    sprintf(keyword,"MAIL4");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
//	printf("%s", linjer);
	sscanf(linjer,"%50c%s",dummy,mailaddress4);
	sscanf(linjer,"%40c%f",dummy,&val);	
//        printf("val: %5.1f  %s\n",val,mailaddress1);
	mail4 = (int)val;	
        break;
      }
    }        
    
    rewind(par);    
    sprintf(keyword,"MAIL5");
    while ( fgets ( linjer, sizeof linjer, par ) != NULL ) // read a line from file 
    {
  
      if (strstr(linjer, keyword) )
      {
//	printf("%s", linjer);
	sscanf(linjer,"%50c%s",dummy,mailaddress5);
	sscanf(linjer,"%40c%f",dummy,&val);	
//        printf("val: %5.1f  %s\n",val,mailaddress1);
	mail5 = (int)val;	
        break;
      }
    }      
    
    
    
    
    
     fclose(par);    
    
  }
}  
LATENCY(int kanal)
{
  int DDAY,MMTH;
  int DY;
  int YR;
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;

  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;

  float  sek;
  double MSECS;

  int seconds_cpu;
  char tiden_cpu[80];
  char millis_cpu[4];
  long day_cpu;
  long mon_cpu;
  long yrn_cpu;
  long hrn_cpu;
  long min_cpu;

  int iday_cpu;
  int imon_cpu;
  int iyrn_cpu;
  int ihrn_cpu;
  int imin_cpu;

  float sek_cpu;
  char dm[10];
  double MSECS_CPU;



  char dum[50];
  int i,j;
  char   timestamp[80];
  struct timeb  tp;               // structure CPU time
  for(i=0;i<MAXCHA;i++)
  {
    if(tabell[kanal][i] == 'X')
    {
      ftime(&tp);               // CPU time
      seconds_cpu=tp.time;
      sprintf(tiden_cpu,"%s",ctime(&tp.time));
      sprintf(millis_cpu,"%3d",tp.millitm);
      Cnv_CPUtime(tiden_cpu,millis_cpu);

      sscanf(tiden_cpu,"%2d%1s%2d%1s%4d %2d%1s%2d%1s%f6.3",
&iday_cpu,dm,&imon_cpu,dm,&iyrn_cpu,&ihrn_cpu,dm,&imin_cpu,dm,&sek_cpu);
      day_cpu=iday_cpu;
      mon_cpu=imon_cpu;
      yrn_cpu=iyrn_cpu;
      hrn_cpu=ihrn_cpu;
      min_cpu=imin_cpu;

      TIMSEC(yrn_cpu,mon_cpu,day_cpu,hrn_cpu,min_cpu,sek_cpu,&MSECS_CPU);

      sscanf(rtid[i],"%4d%1c%3d%1c%2d%1c%2d%1c%f6.3",&YR,dum,&DY,dum,&ihrn,dum,&imin,dum,&sek);
      hrn=ihrn;
      min=imin;

//  printf("%4d %3d %2d %2d %4.1f\n",YR,DY,hrn,min,sek);

      DTE (DY,&DDAY,&MMTH,YR);     //-- convert from doy to date  
      yrn=YR;
      yrn=yrn-2000;
      mon=MMTH;
      day=DDAY;

      iday=day;
      imon=mon;
      iyrn=yrn;
      ihrn=hrn;
      imin=min;

      sprintf(timestamp,"%2d/%2d/%2d %2d:%2d:%6.3f",iday,imon,iyrn,ihrn,imin,sek);
      if(timestamp[0] == ' ') timestamp[0] = '0';
      if(timestamp[3] == ' ') timestamp[3] = '0';
      if(timestamp[6] == ' ') timestamp[6] = '0';
      if(timestamp[9] == ' ') timestamp[9] = '0';
      if(timestamp[12] == ' ') timestamp[12] = '0';
      if(timestamp[15] == ' ') timestamp[15] = '0';
      if(timestamp[18] == ' ') timestamp[18] = '0';
      if(timestamp[19] == ' ') timestamp[19] = '0';
      if(timestamp[20] == ' ') timestamp[20] = '0';
      TIMSEC(yrn,mon,day,hrn,min,sek,&MSECS);
      latency[i] = MSECS_CPU - MSECS;
      spt->latency[klon][i] = latency[i];
    }
  }
}
Cnv_CPUtime(char tiden[],char millis[])
{
  int ret;
  char word[4];
      word[0]=tiden[4];
      word[1]=tiden[5];
      word[2]=tiden[6];
      word[3]='\0';


      tiden[0]=tiden[8];
      tiden[1]=tiden[9];
      tiden[2]='/';
      ret=strcmp(word,"Jan");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='1';
      }
      ret=strcmp(word,"Feb");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='2';
      }
      ret=strcmp(word,"Mar");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='3';
      }
      ret=strcmp(word,"Apr");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='4';
      }
      ret=strcmp(word,"May");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='5';
      }
      ret=strcmp(word,"Jun");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='6';
      }
      ret=strcmp(word,"Jul");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='7';
      }
      ret=strcmp(word,"Aug");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='8';
      }
      ret=strcmp(word,"Sep");
      if(ret==0)
      {
        tiden[3]='0';
        tiden[4]='9';
      }
      ret=strcmp(word,"Oct");
      if(ret==0)
      {
        tiden[3]='1';
        tiden[4]='0';
      }
      ret=strcmp(word,"Nov");
      if(ret==0)
      {
        tiden[3]='1';
        tiden[4]='1';
      }
      ret=strcmp(word,"Dec");
      if(ret==0)
      {
        tiden[3]='1';
        tiden[4]='2';
      }
      tiden[5]='/';
      tiden[6]=tiden[20];
      tiden[7]=tiden[21];
      tiden[8]=tiden[22];
      tiden[9]=tiden[23];
      tiden[19]='.';


      tiden[20]=millis[0];
      tiden[21]=millis[1];
      tiden[22]=millis[2];
      tiden[23]='\n';



}

/*  Subroutine to apply an iir filter to a data sequence.                   */
/*    The filter is assumed to be stored as second order sections.          */
/*    Filtering is in-place.                                                */
/*    Zero-phase (forward and reverse) is an option.                        */
//appl(sw,chan,nsamp,peker)
void appl_pick(int fnd,float seis[])
//int      sw;
//int      chan;
//int      nsamp;
//float    *peker;
{
//float    *tpek;
    /* System generated locals */
int      i1;
int      i2;

    /* Local variables */
int      jptr;
int      i;
int      j;
float    b0;
float    b1;
float    b2;
float    a1;
float    a2;
float    x1;
float    x2;
float    y1;
float    y2;
float    output;
//tpek=peker;

/* Parameter adjustments                                                    */
/*    --data;*/

/* Function Body                                                            */
jptr = 1;
i1 = cset[fnd];

for (j = 1; j <= i1; ++j)
{
    x1 = save_x1_pick[fnd][j];
    x2 = save_x2_pick[fnd][j];
    y1 = save_y1_pick[fnd][j];
    y2 = save_y2_pick[fnd][j];
    b0 = snc[fnd][jptr];
    b1 = snc[fnd][jptr + 1];
    b2 = snc[fnd][jptr + 2];
    a1 = sdc[fnd][jptr + 1];
    a2 = sdc[fnd][jptr + 2];
if(fnd==1000)
  printf("%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n",x1,x2,y1,y2,b0,b1,b2,a1,a2);

    i2 = RTBUFSIZ;        // 5000

    for (i = 0; i < i2; ++i)
    {
      output = b0 * seis[i] + b1 * x1 + b2 * x2;
      output -= a1 * y1 + a2 * y2;
      y2 = y1;
      y1 = output;
      x2 = x1;
      x1 = seis[i];
      seis[i] = output;

    }

    jptr += 3;

    save_y2_pick[fnd][j]=y2;
    save_y1_pick[fnd][j]=y1;
    save_x2_pick[fnd][j]=x2;
    save_x1_pick[fnd][j]=x1;

}

}
void WRITE_RTPHASE(void *ptr)
{
  int ret;
  char com1[200];
  char com2[200];
  char com3[200];
  
  char lsname[200];
  char lwname[200];
  
  rtphase *data;
  data = (rtphase *) ptr;
  sprintf(lsname,"%s",data->sname);
  sprintf(lwname,"%s",data->wname);
  
  
  sprintf(com1,"automag %s s 10 p >> autotmp.txt",lsname);
  sprintf(com2,"hyp automag.out >> hyptemp.txt");
  sprintf(com3,"cp hyp.out %s",lsname);  
  
  
  
//  sleep(10); 
  printf("********************************************************************\n");
  printf("                       WRITE DATA BUFFER                            \n");
  printf("      S_FILE:   %s\n",lsname);
  printf("      W_FILE:   %s\n",lwname);
  printf("********************************************************************\n");



     char header[500][150];                // componnents to be written to p-phase wave file    
     int ls;
     int blokker;
     int irate;
     int nextport;
     int quality;
     int ii;

     struct filelink *flp;
  
     addfile ("input");  

     // Init TraceGroup 
     mstg = mst_initgroup (mstg);

    
     flp = filelist;  
     sprintf(out,"%s",lwname); 
 
     // Open the output file if specified otherwise stdout 
     if ( (ofp = fopen (out, "w")) == NULL )
        {
          printf ("Cannot open output file: %s\n",out);
//          return -1;
        } 
        
     char nwrk[10];
     char stas[10];
     char loka[10];
     char cmpo[10];
    
     int DY;
     int YR;
     int DDAY,MMTH;  
     int   iyrn;
     int   imon;
     int   iday;
     int   ihrn;
     int   imin;
     float  sek;
     float fsr;
     float fsmp;
     double MSECS;
     double RTMSECS;
     char  dum[20];

     long   yrn;
     long   mon;
     long   day;
     long   hrn;
     long   min;
     long   doy;  
 printf("here 1\n");    
     NOW();
        
     for(ii=0;ii<stream_count;ii++)
     {
       strncpy(stas,allstreams[ii] + 3,5);stas[5]='\0';
       strncpy(cmpo,allstreams[ii] + 10,3);cmpo[3]='\0';
       strncpy(nwrk,allstreams[ii] + 0,2);nwrk[2]='\0';
       strncpy(loka,allstreams[ii] + 8,2);loka[2]='\0';
//       printf("01  %s  %s  %s  %s  rns: %4d rsr: %3d rtid: %s\n",stas,cmpo,loka,nwrk,rns[ii],rsr[ii],rtid[ii]);
      
       sscanf(rtid[ii],"%4d%1c%3d%1c%2d%1c%2d%1c%f6.3",&YR,dum,&DY,dum,&ihrn,dum,&imin,dum,&sek);
//      printf("YR: %4d DY: %3d IHRN: %2d IMIN: %2d SEK: %6.2f\n",YR,DY,ihrn,imin,sek);
       if(rns[ii] != 0 || rsr[ii] != 0)
       {
         hrn=ihrn;
         min=imin;

         DTE (DY,&DDAY,&MMTH,YR);     //-- convert from doy to date  
         yrn=YR;
         yrn=yrn-2000;
         mon=MMTH;
         day=DDAY;

         iday=day;
         imon=mon;
         iyrn=yrn;
         ihrn=hrn;
         imin=min;

         TIMSEC(yrn,mon,day,hrn,min,sek,&MSECS);
	 RTMSECS=MSECS;
	 fsr=rsr[ii];
	 fsmp=2000-rns[ii];
         MSECS=MSECS - fsmp/fsr;
         SECTIM(MSECS,&yrn,&doy,&mon,&day,&hrn,&min,&sek);

         iday=day;
         imon=mon;
         iyrn=yrn;
         ihrn=hrn;
         imin=min;
         iyrn=iyrn;
	 
	 if((TID_NOW-RTMSECS) > 120)
	 {
	   sprintf(header[ii],"XXXX");
	 }else{
           sprintf(header[ii],"   %s %s %s %s        2000       %3d %2d %2d %4d %2d %2d %6.3f",stas,cmpo,loka,nwrk,rsr[ii],iday,imon,iyrn,ihrn,imin,sek);
	 }
//      printf("%s %s %d\n",stas,rtid[ii],ns[ii]);

//	printf("02  %s\n",header[ii]);
       }else{
	 sprintf(header[ii],"XXXX");
       }
     }  
     
 printf("here 2\n");      
//     slg2group (flp->filename, mstg,ls,stream_count,irate,nextport,quality,header,values);
     slg2group (flp->filename, mstg,ls,stream_count,irate,nextport,quality,header);
 printf("here 3\n"); 
     // Pack any remaining, possibly all data 
     packtraces (1,nextport,mstg);
     packedtraces += mstg->numtraces;
  
     fprintf (stderr, "Packed %d trace(s) of %d samples into %d records\n",
           packedtraces, packedsamples, packedrecords);
     packedtraces=0;
     packedsamples=0;
     packedrecords=0;
     // Make sure everything is cleaned up 
     mst_freegroup (&mstg);
  
     if ( ofp )
       fclose (ofp);
  
     if(automag == 1)
     {
       ret = system(com1);
       ret = system(com2);
       ret = system(com3);
     }
 printf("here 4\n");      
      ret = RTPPH(lsname); 
      printf("RTPPH ret: %d\n",ret);
      mail_switch++;              
     
     
  
}





WRITE_RTPHASE_F(char lsname[],char lwname[])
{
  int ret;
  char com1[200];
  char com2[200];
  char com3[200];
  
//  char lsname[200];
//  char lwname[200];
  
//  rtphase *data;
//  data = (rtphase *) ptr;
//  sprintf(lsname,"%s",data->sname);
//  sprintf(lwname,"%s",data->wname);
  
  
  sprintf(com1,"automag %s s 10 p >> autotmp.txt",lsname);
  sprintf(com2,"hyp automag.out >> hyptemp.txt");
  sprintf(com3,"cp hyp.out %s",lsname);  
  
  
  
//  sleep(10); 
  printf("********************************************************************\n");
  printf("                       WRITE DATA BUFFER                            \n");
  printf("      S_FILE:   %s\n",lsname);
  printf("      W_FILE:   %s\n",lwname);
  printf("********************************************************************\n");



     char header[500][150];                // componnents to be written to p-phase wave file    
     int ls;
     int blokker;
     int irate;
     int nextport;
     int quality;
     int ii;

     struct filelink *flp;
  
     addfile ("input");  

     // Init TraceGroup 
     mstg = mst_initgroup (mstg);

    
     flp = filelist;  
     sprintf(out,"%s",lwname); 
 
     // Open the output file if specified otherwise stdout 
     if ( (ofp = fopen (out, "w")) == NULL )
        {
          printf ("Cannot open output file: %s\n",out);
//          return -1;
        } 
        
     char nwrk[10];
     char stas[10];
     char loka[10];
     char cmpo[10];
    
     int DY;
     int YR;
     int DDAY,MMTH;  
     int   iyrn;
     int   imon;
     int   iday;
     int   ihrn;
     int   imin;
     float  sek;
     float fsr;
     float fsmp;
     double MSECS;
     double RTMSECS;
     char  dum[20];

     long   yrn;
     long   mon;
     long   day;
     long   hrn;
     long   min;
     long   doy;  
 printf("here 1\n");    
     NOW();
        
     for(ii=0;ii<stream_count;ii++)
     {
       strncpy(stas,allstreams[ii] + 3,5);stas[5]='\0';
       strncpy(cmpo,allstreams[ii] + 10,3);cmpo[3]='\0';
       strncpy(nwrk,allstreams[ii] + 0,2);nwrk[2]='\0';
       strncpy(loka,allstreams[ii] + 8,2);loka[2]='\0';
//       printf("01  %s  %s  %s  %s  rns: %4d rsr: %3d rtid: %s\n",stas,cmpo,loka,nwrk,rns[ii],rsr[ii],rtid[ii]);
      
       sscanf(rtid[ii],"%4d%1c%3d%1c%2d%1c%2d%1c%f6.3",&YR,dum,&DY,dum,&ihrn,dum,&imin,dum,&sek);
//      printf("YR: %4d DY: %3d IHRN: %2d IMIN: %2d SEK: %6.2f\n",YR,DY,ihrn,imin,sek);
       if(rns[ii] != 0 || rsr[ii] != 0)
       {
         hrn=ihrn;
         min=imin;

         DTE (DY,&DDAY,&MMTH,YR);     //-- convert from doy to date  
         yrn=YR;
         yrn=yrn-2000;
         mon=MMTH;
         day=DDAY;

         iday=day;
         imon=mon;
         iyrn=yrn;
         ihrn=hrn;
         imin=min;

         TIMSEC(yrn,mon,day,hrn,min,sek,&MSECS);
	 RTMSECS=MSECS;
	 fsr=rsr[ii];
	 fsmp=2000-rns[ii];
         MSECS=MSECS - fsmp/fsr;
         SECTIM(MSECS,&yrn,&doy,&mon,&day,&hrn,&min,&sek);

         iday=day;
         imon=mon;
         iyrn=yrn;
         ihrn=hrn;
         imin=min;
         iyrn=iyrn;
	 
	 if((TID_NOW-RTMSECS) > 120)
	 {
	   sprintf(header[ii],"XXXX");
	 }else{
           sprintf(header[ii],"   %s %s %s %s        2000       %3d %2d %2d %4d %2d %2d %6.3f",stas,cmpo,loka,nwrk,rsr[ii],iday,imon,iyrn,ihrn,imin,sek);
	 }
//      printf("%s %s %d\n",stas,rtid[ii],ns[ii]);

//	printf("02  %s\n",header[ii]);
       }else{
	 sprintf(header[ii],"XXXX");
       }
     }  
     
 printf("here 2\n");      
//     slg2group (flp->filename, mstg,ls,stream_count,irate,nextport,quality,header,values);
     ret=slg2group (flp->filename, mstg,ls,stream_count,irate,nextport,quality,header);
 printf("here 3 ret: %d\n",ret); 
     // Pack any remaining, possibly all data 
     packtraces (1,nextport,mstg);
     packedtraces += mstg->numtraces;
  
     fprintf (stderr, "Packed %d trace(s) of %d samples into %d records\n",
           packedtraces, packedsamples, packedrecords);
     packedtraces=0;
     packedsamples=0;
     packedrecords=0;
     // Make sure everything is cleaned up 
     mst_freegroup (&mstg);
  
     if ( ofp )
       fclose (ofp);
  
     if(automag == 1)
     {
       ret = system(com1);
       ret = system(com2);
       ret = system(com3);
     }
 printf("here 4\n");      
      ret = RTPPH(lsname); 
      printf("RTPPH ret: %d\n",ret);
      mail_switch++;              
     
     
  
}











/*---------------------------------------------------------*/
/*     Network Delay Trigger  TRG_MUL Thread               */
/*---------------------------------------------------------*/
void TRG_MUL(void *ptr)
{

      int lthread_no;
      int lantkan;
      int lfra;
      int ltil;
      int lminimum_no_triggers;

  
  
  trgmul *data;            
  data = (trgmul *) ptr;  /* type cast to a pointer to thdata */

  lthread_no = data->thread_no;
  lantkan = data->antkan;
  lfra = data->fra;
  ltil = data->til;
  lminimum_no_triggers = data-> minimum_no_triggers;

  
  
  pthread_t cat_mul_thread;             // definition for CAT_MUL thread  
  catmul catinfo1, catinfo2, catinfo3;

  
  long   yrn;
  long   doy;
  long   mon;
  long   day;
  long   hrn;
  long   min;

  int   iyrn;
  int   idoy;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;

  float  sek;
  
  int from;
  int to;
  int t1;
  int t2;

  int ch1;
  int kan1;
  int thread;
  int kk;
  int df1;
  int p;
  int pk;
  int t;
  int jj;
  int rt1;
  int br1;
  int teller;
  int min_trg;
  int min_trg_cnt=0;
  int retur;
//  int triggers;
  int maxdur;
  double diff;
  double d1;
  double dd1[200];
  int avpa;
  char lyd[200];
  double mintid;
  double start_time;
  int    triggers[MAXCHA];
  double trigtime[MAXCHA];
  int    trigindx[MAXCHA];
  int    durk[MAXCHA];
  pthread_t cat_del_thread;            // definition for CAT_DELAY thread
  sprintf(lyd,"aplay %s/map/glasses.wav",topdir_rt);
/******** SIGNAL to main thread to go on **************/
  main_cnd=0;                    // change condition variable and let main goon
  if( main_cnd == 0 )
  {
    pthread_cond_signal( &cnd_cnd_main );
  }
  t1   = (MINUT_NOW - DET_DELAY) * 60;
  t2   = t1 + APW/2;  
  from = (MINUT_NOW - DET_DELAY) * 60;
  to   = from + APW;

  for(;;)
  {
    sleep(1);
//----------------------------------------------------------------------------------------
// check for trigger on-sets in Array-Propagation-Window that is delayed DET_DELAY minutes
//----------------------------------------------------------------------------------------    
    min_trg_cnt = 0;
    br1=0;
    for(t = t1; t < t2; t++)
    {
      for(kan1 = lfra; kan1 < ltil; kan1++)
      {
	if(spt->ttdly[klon][kan1][t] == 122 &&  trgdly[kan1][t] > 10000.0)
        {
          br1=1;
          break;
        }
      }
    }
    
    if(br1 ==1)
    {   
      for(jj = from; jj < to; jj++)
      {
        for(kan1 = lfra;kan1 < ltil; kan1++)
        {
	  if(spt->ttdly[klon][kan1][jj] == 122 && trgdly[kan1][jj] > 10000.0)
	  {  
	    for(pk = lfra; pk < ltil; pk++)
	    {
	      if(triggers[kan1] == 0)        // not triggered before
	      {
		triggers[kan1] = 1;
	        min_trg_cnt++;
//                printf("Thread %2d new trigger on chan: %2d min_trg_cnt: %d\n",lthread_no,kan1,min_trg_cnt);
	        trigtime[kan1] = trgdly[kan1][jj];
	        trigindx[kan1] = jj;
//		printf("trigindx: kan1: %2d jj: %4d\n",kan1,jj);
	        for(p=jj+1;p<(DELAY_BUFFER*60);p++)
	        {
	          if(spt->ttdly[klon][kan1][p] == 111 && trgdly[kan1][p] == 111)	    
	          {
	            durk[kan1] = durk[kan1] + 1;
//		    printf("increment durk: %2d %3d\n",kan1,durk[kan1]);
	          }else{
	            break;
	          }  // spt
	        }    // p
	      }      // if triggers
	    }        // pk 
//	  printf("min_trg: %2d ch: %2d dur: %3d index: %5d\n",min_trg_cnt,kan1,dur[kan1],jj);
	  }          // spt
        }            // kan1
      }              // jj
    }                // if br


    if(min_trg_cnt >= lminimum_no_triggers)
    {
      
      printf("********************************************\n");    
      printf("*          TRIGGER on thread %2d !          *\n",lthread_no);
      printf("********************************************\n");
      if(sound == 1)
        rt1=system(lyd);
      for(p = lfra;p < ltil;p++)
      {
        DURTRG[p]=durk[p];
//	printf("dur: %6d\n",durk[p]);
      }
      for(p = lfra;p < ltil;p++)
      {
	if(trigindx[p] != 0)
	  printf("kan: %3d %s time: %12.2f index: %5d dur: %3d\n",p,spt->trig_stations[klon][p],trigtime[p],trigindx[p],durk[p]);
      }
      mintid = 9333333333.0;
      for(p = lfra; p < ltil; p++)
      {
        if(trigtime[p] > 10000.0)
	{
	  if(trigtime[p] < mintid)
	    mintid=trigtime[p];
	}
      }
      
      maxdur = 0;
      for(p = lfra; p < ltil; p++)
      {
        if(trigtime[p] > 10000.0)
	{
	  if(durk[p] > maxdur)
	    maxdur=durk[p];
	}
      }
      printf("RTDET: TRG_MUL.......................: mintid   :   %12.2f  maxdur: %d\n",mintid,maxdur);
      SECTIM(mintid,&yrn,&doy,&mon,&day,&hrn,&min,&sek);
      iyrn=yrn;
      imon=mon;
      iday=day;
      ihrn=hrn;
      imin=min;
      MINSTETID=mintid;
      printf("RTDET: TRG_MUL.......................: MINTRGTID: %4d/%2d/%2d %2d:%2d:%4.1f\n",iyrn,imon,iday,ihrn,imin,sek);
      sprintf(MINTRGTID,"%02d/%02d/%4d %02d:%02d:%4.1f",iday,imon,iyrn,ihrn,imin,sek);
      printf("RTDET: TRG_MUL.......................: MINTRGTID: %s\n",MINTRGTID);
      

      main_cnd=1;                              // set conditon to WAIT
/*------------------------------------------------------------------------------*/
/* Start thread CAT_DET to retreive data from SEEDLINK buffer and store the data*/
/*------------------------------------------------------------------------------*/

     if(mintrg == 0)
     {
       thread = lthread_no-1;
       catinfo1.maxdur = maxdur;
       catinfo1.thread_no           = thread+1;
       catinfo1.antkan              = kanaler_hver_record[thread];	  
       catinfo1.fra                 = start_rec[thread];
       catinfo1.til                 = stopp_rec[thread];
     }else{
       thread = lthread_no-1;
       catinfo1.maxdur = maxdur;
       catinfo1.thread_no           = thread+1;
       catinfo1.antkan              = rec_count;	  
       catinfo1.fra                 = 0;
       catinfo1.til                 = lantkan;       
     }
      printf("RTDET: CAT_MUL thread: %2d started. channels: %2d from: %2d to: %2d\n",catinfo1.thread_no,catinfo1.antkan,catinfo1.fra,catinfo1.til);     
      pthread_create(&cat_mul_thread, NULL, (void *) &CAT_MUL,(void *) &catinfo1);




      for(p =lfra;p < ltil;p++)
      {
	if(trigindx[p] != 0)
	{
	  for(t=trigindx[p];t<(trigindx[p]+durk[p]+1);t++)
	  {
            spt->ttdly[klon][p][t] = 0;
            trgdly[p][t] = 0.0;	    
	  }
	}
      }
      for(p = lfra;p < ltil;p++)
      {
	trigtime[p] = 0.0;
	trigindx[p] = 0;
	durk[p] = 0;
	triggers[p] = 0;
      }
      min_trg_cnt = 0;

      
    }else{
      for(p=0;p<MAXCHA;p++)
      {
	trigtime[p] = 0.0;
	trigindx[p] = 0;
	durk[p] = 0;
        triggers[p] = 0;
      }     
    }    
    
  }  // for ;;
  
 
 
  


//  return NULL;
}



/*---------------------------------------------------------*/
/*     CAT_MUL Thread                                    */
/*---------------------------------------------------------*/
void CAT_MUL(void *ptr)
{
  
  catmul *data;
  data = (catmul *) ptr;

      int lthread_no;
      int lmaxdur;
      int lantkan;	  
      int lfra;
      int ltil;

      lthread_no = data->thread_no;
      lmaxdur = data->maxdur;
      lantkan = data->antkan;
      lfra = data->fra;
      ltil = data->til;
  
  
  FILE   *req;
  char   reqnam[200];
  char   comm[200];
  char   stasjon[20];
  char   ipserv[50];
  int    cr;
  double stop_time;
  double start_time;
  char   FILNAVN[1024];
  char   CRTDIR[256];
  char   PATHANDFIL[256];
  char   startpick[256];
  char   syscmd[512];
  char   sfil_coda_pick[512];
  int    varighet[MAXCHA];
  long   fyrn;
  long   fdoy;
  long   fmon;
  long   fday;
  long   fhrn;
  long   fmin;

  int   ifyrn;
  int   ifdoy;
  int   ifmon;
  int   ifday;
  int   ifhrn;
  int   ifmin;
  
  int   ityrn;
  int   itdoy;
  int   itmon;
  int   itday;
  int   ithrn;
  int   itmin;
  
  long   tyrn;
  long   tdoy;
  long   tmon;
  long   tday;
  long   thrn;
  long   tmin;
    

  float  tsek;
  int   writesw=0; 
  int   kk;
  int   rt1;
  int   pp;
  float  fsek;
  int   no_cmp_to_record=ltil-lfra;
  
  printf("********************************************************************************\n");
  printf("RTDET:                       CAT_MUL started\n");
  printf("********************************************************************************\n"); 



  main_cnd=0;                    // change condition variable and let main goon
  if( main_cnd == 0 )
  {
    pthread_cond_signal( &cnd_cnd_main );
  }
  printf("RTDET: CAT_MUL.......................: maxdur: %d\n",lmaxdur);
  start_time = MINSTETID - preevent;
  stop_time = MINSTETID + lmaxdur + postevent;

  SECTIM(start_time,&fyrn,&fdoy,&fmon,&fday,&fhrn,&fmin,&fsek);

  ifyrn=fyrn;
  ifmon=fmon;
  ifday=fday;
  ifhrn=fhrn;
  ifmin=fmin;

  sprintf(FILNAVN, "%4d-%2d-%2d-%2d%2d-%2d.NNSN__%3d_%2d_%2d",ifyrn,ifmon,ifday,ifhrn,ifmin,(int)fsek,no_cmp_to_record,klon,lthread_no);

  for(kk=0;kk<35;kk++)
    if(FILNAVN[kk] == ' ') FILNAVN[kk]='0';

  FILNAVN[34]='\0';
  FILNAVN[19] = dbname[0];
  FILNAVN[20] = dbname[1];
  FILNAVN[21] = dbname[2];
  FILNAVN[22] = dbname[3];
  FILNAVN[23] = dbname[4];
  printf("RTDET: CAT_MUL.......................: FILNAVN: %s\n",FILNAVN);
  
//--------------------------------------------------------------
// check if waveform is to be stored in WOR (no database structure,
// or in WAV seisan database structure.
//-----------------------------------------------------------------
  if(automag == 0 && wavedbactive == 1)
  {
    sprintf(PATHANDFIL,"%s/%s/%2d/%2d/%s",trgpath,dbname,ifyrn,ifmon,FILNAVN);

    for(kk=0;kk<256;kk++)
      if(PATHANDFIL[kk] == ' ') PATHANDFIL[kk] = '0';
    printf("RTDET: CAT_MUL.......................: PATHANDFIL: %s\n",PATHANDFIL);  
    sprintf(CRTDIR,"%s/%s/%2d/%2d",trgpath,dbname,ifyrn,ifmon);

    for(kk=0;kk<256;kk++)
      if(CRTDIR[kk] == ' ') CRTDIR[kk] = '0';
    printf("RTDET: CAT_MUL.......................: CRTDIR: %s\n",CRTDIR);   
    CreateDirectory(CRTDIR);
  }
  if(automag == 0 && wavedbactive == 0)
  {
    sprintf(PATHANDFIL,"%s/%s",trgpath,FILNAVN);
    printf("RTDET: CAT_MUL.......................: PATHANDFIL: %s\n",PATHANDFIL);     
  }
  if(automag == 1 && wavedbactive == 1)
  {
    sprintf(PATHANDFIL,"%s/%s/%2d/%2d/%s",trgpath,dbname,ifyrn,ifmon,FILNAVN);

    for(kk=0;kk<256;kk++)
      if(PATHANDFIL[kk] == ' ') PATHANDFIL[kk] = '0';
    printf("RTDET: CAT_MUL.......................: PATHANDFIL: %s\n",PATHANDFIL);  
    sprintf(CRTDIR,"%s/%s/%2d/%2d",trgpath,dbname,ifyrn,ifmon);

    for(kk=0;kk<256;kk++)
      if(CRTDIR[kk] == ' ') CRTDIR[kk] = '0';
    printf("RTDET: CAT_MUL.......................: CRTDIR: %s\n",CRTDIR);   
    CreateDirectory(CRTDIR);
  }
  if(automag == 1 && wavedbactive == 0)  // works for WAV
  {
    sprintf(PATHANDFIL,"%s/%s",trgpath,FILNAVN);
    printf("RTDET: CAT_MUL.......................: PATHANDFIL: %s\n",PATHANDFIL);     
  }
  
  
  SECTIM(stop_time,&tyrn,&tdoy,&tmon,&tday,&thrn,&tmin,&tsek);

  ityrn=tyrn;
  itmon=tmon;
  itday=tday;
  ithrn=thrn;
  itmin=tmin;

  printf("RTDET: CAT_MUL.......................: %4d/%2d/%2d %2d:%2d:%4.1f\n",ityrn,itmon,itday,ithrn,itmin,tsek);
  sprintf(reqnam,"%s/req/%s",topdir_rt,FILNAVN);
  if ((req = fopen (reqnam, "w")) == NULL)
  {
    printf("RTDET: CAT_MUL Can't open: %s\n",reqnam);
    writesw=1;
  }
  printf("********************************************************************************\n");
  printf("RTDET: CAT_MUL Extracting data from SeedLink server...........\n");
  printf("********************************************************************************\n");
  for(kk = lfra; kk < ltil; kk++)
  {
    sscanf(record[kk],"%s %s",stasjon,ipserv);
    if(printarg > 0)    
      printf("thread_no: %d %2d -%2d %s %s\n",lthread_no,lfra,ltil,stasjon,ipserv);
  }
  for(kk = lfra; kk < ltil; kk++)    
  {
    ifyrn=fyrn;
    ifmon=fmon;
    ifday=fday;
    ifhrn=fhrn;
    ifmin=fmin;

    ityrn=tyrn;
    itmon=tmon;
    itday=tday;
    ithrn=thrn;
    itmin=tmin;


    sscanf(record[kk],"%s %s",stasjon,ipserv);
    
    sprintf(syscmd,"%s/bin/getwindow -S %c%s%c -tw %d,%d,%d,%d,%d,%d:%d,%d,%d,%d,%d,%d -nt 5 -nd 5 -o %s %s",topdir_rt,0x22,stasjon,0x22,ifyrn,ifmon,ifday,ifhrn,ifmin,(int)fsek,ityrn,itmon,itday,ithrn,itmin,(int)tsek,PATHANDFIL,ipserv);
    printf(" -S %c%s%c -tw %d,%d,%d,%d,%d,%d:%d,%d,%d,%d,%d,%d -nt 5 -nd 5 -o %s %s\n",0x22,stasjon,0x22,ifyrn,ifmon,ifday,ifhrn,ifmin,(int)fsek,ityrn,itmon,itday,ithrn,itmin,(int)tsek,PATHANDFIL,ipserv);

    if(printarg > 0)
      printf("%s\n",syscmd); 
    if(writesw == 0)
      fprintf(req,"%s\n",syscmd);
    rt1=system(syscmd);
  }
  if(writesw==0)
    fclose(req);
  sprintf(comm,"chmod +x %s",reqnam);
  rt1=system(comm);
  for(kk=0;kk<MAXCHA;kk++)
  {
    varighet[kk] = DURTRG[kk];
    DURTRG[kk] = 0;
  }
  printf("RTDET: CAT_MUL...........................: call Create_Sfile\n");

  Create_Sfile(MINTRGTID,FILNAVN,no_cmp_to_record,varighet,sfil_coda_pick);  
  
  printf("RTDET: CAT_MUL..................SFILEPATH: %s\n",sfilepath);
  printf("RTDET: CAT_MUL..................DBNAME   : %s\n",dbname);
//  printf("RTDET: CAT_MUL detection_file: %s\n",detection_file);
//  sprintf(startpick,"rtpick -prt %d -sfile %s -wavefile %s -iter 200 -maxres 3.0",printarg,SFILETOPICK,PATHANDFIL);   
//  sprintf(syscmd,"%s/bin/rtpick -prt %d -sfile %s -wavefile %s -iter 200 -maxres 3.0",topdir_rt,printarg,SFILETOPICK,PATHANDFIL);
  
  sprintf(startpick,"(cd %s/rt/tmp%d && exec %s/bin/rtpick -prt %d -sfile %s -wavefile %s)",topdir_rt,lthread_no,topdir_rt,printarg,sfil_coda_pick,PATHANDFIL);   
  sprintf(syscmd,"%s/bin/rtpick -prt %d -sfile %s -wavefile %s",topdir_rt,printarg,sfil_coda_pick,PATHANDFIL);   

  sprintf(syscmd,"(cd %s/rt/tmp%d && exec %s/bin/rtpick -prt %d -sfile %s -wavefile %s)",topdir_rt,lthread_no,topdir_rt,printarg,sfil_coda_pick,PATHANDFIL);   
   

  if(keep == 1 )
  {
    for(;;)
    {
      if(0==system("pidof rtpick > /dev/null")) {
	{
          printf("RTPICK is running.\n");
	  sleep(60);
	}
      }
      else{
        printf("RTPICK is NOT running.\n");
        printf("RTDET: CAT_MUL %s\n",startpick);    
        rt1=system(syscmd);
	break;
      }    
    }
  }
    

    
}



/*---------------------------------------------------------*/
/*     Delay buffer shufle  BUFFER_SHUFLE Thread           */
/*---------------------------------------------------------*/
void *BUFFER_SHUFLE(int *parno)
{
  char dummy[256];
  long   yrn;
  long   mon;
  long   day;
  long   hrn;
  long   min;
  long   doy;
  int   iyrn;
  int   imon;
  int   iday;
  int   ihrn;
  int   imin;
  int   isec;
  int   i,j;
  int   BUFSECS;
  float  sek;
  char dum[50];
  double MSECS_OLD=0;
  double MSECS_NEW=0;
  double DIFF=0;

/******** SIGNAL to main thread to go on **************/
  main_cnd=0;                    // change condition variable and let main goon
  if( main_cnd == 0 )
  {
    pthread_cond_signal( &cnd_cnd_main );
  }  
  BUFSECS = DELAY_BUFFER * 60;
  MSECS_OLD = TIME_NOW;
  for(;;)
  {
//    printf("BUFFER_SHUFLE lock\n");    
    pthread_mutex_lock(&shift_mutex);

    
    time_t now = time(NULL);
    struct tm *now_s = localtime(&now);
    sprintf(dummy,"%d-%02d-%02d_%02d:%02d:%02d", 1900+now_s->tm_year, ++now_s ->tm_mon,now_s->tm_mday, now_s->tm_hour, now_s->tm_min,now_s->tm_sec);
    sscanf(dummy,"%4d%1c%2d%1c%2d%1c%2d%1c%2d%1c%2d",&iyrn,dum,&imon,dum,&iday,dum,&ihrn,dum,&imin,dum,&isec);
    yrn=iyrn;
    yrn=yrn-2000;
    mon=imon;
    day=iday;
    hrn=ihrn;
    min=imin;
    mon=imon;
    sek=isec;
    
    TIMSEC(yrn,mon,day,hrn,min,sek,&MSECS_NEW); 
    DIFF = MSECS_NEW - MSECS_OLD;
    if(DIFF >= SECONDS2SHUFLE)
    {
      MSECS_OLD = MSECS_NEW;
      TIME_NOW = MSECS_NEW;
//      printf("DIFF: %6.3f SHIFFT\n",DIFF);

      for(i=0;i<MAXCHA;i++)
      {
        for(j=0;j<(BUFSECS-SECONDS2SHUFLE);j++)
	{
          spt->ttdly[klon][i][j] = spt->ttdly[klon][i][j+SECONDS2SHUFLE];
          trgdly[i][j] = trgdly[i][j+SECONDS2SHUFLE];	 
	}
      }
    }
//    printf("signal_shift\n");
//    pthread_cond_signal(&signal_shift); 
    pthread_mutex_unlock(&shift_mutex);

    sleep(1);

  }

}

/**************************************************************************/
/*   Thread to check for sending mail with              */
/**************************************************************************/
void CHECK_MAILS(void *ptr)
{
  int prev=0;
  int save=0;
  int tick=0;
  int ret =0;
  for(;;)
  {
//    printf("here1\n");
    if(mail1 == 1 || mail2 == 1 || mail3 == 1 || mail4 == 1 || mail5 == 1)
    {
      if(mail_switch != 0)
      {
        save = mail_switch;
        if(save > prev)
        {
	  prev = save;
        }else{
	  tick++;
	  if(tick > 60)
	  {
            if(lokalisering == 1)
            {
              lokalisering = 0;

	      printf("**********************SEND MAIL*******************\n");
	      if(mail1 == 1)
	      {
	        printf("%s\n",mail_storage1);
	        ret=system(mail_storage1);
	      }
	      if(mail2 == 1)
	      {
	        printf("%s\n",mail_storage2);
	        ret=system(mail_storage2);
	      }
	      if(mail3 == 1)
	      {
	        printf("%s\n",mail_storage3);
	        ret=system(mail_storage3);
	      }
	      if(mail4 == 1)
	      {
	        printf("%s\n",mail_storage4);
	        ret=system(mail_storage4);
	      }
	      if(mail5 == 1)
	      {
	        printf("%s\n",mail_storage5);
	        ret=system(mail_storage5);
	      }	      
	      tick = 0;
	      mail_switch = 0;
	      save = 0;
	      prev = 0;
	      sprintf(mail_storage1,"-----------------------------------------------------------------");
	      sprintf(mail_storage2,"-----------------------------------------------------------------");
	      sprintf(mail_storage3,"-----------------------------------------------------------------");
	      sprintf(mail_storage4,"-----------------------------------------------------------------");
	      sprintf(mail_storage5,"-----------------------------------------------------------------");	      
	    
            }
	  }
        }
      }
      sleep(1);
    }
    sleep(1);
  }
}
/**************************************************************************/
/*         Read MINISEED packets from SEEDLINK server Thread              */
/**************************************************************************/
void READ_PACKETS(void *ptr)
{
  
  int     sseismo[MAXCHA][3000];
  int     ns[MAXCHA];
  int     sr[MAXCHA];  
  int     ch;
  int     seqnum;
  int     ptype;
  int     fnd=0;
  int     tr;
  int     i,j;
  int     ret1;
  int     now;
  int     forskjell;
  
  int     lthread_no;
  char    lipaddr[100];
  char    lstreams[100];
  char    lstations[100];
  int     lno_comp;
  int     lno_str;
  
  char totalstreams[255];
  char *streamfile   = 0;	    /* stream list file for configuring streams */  
  char addr[256];
  char *selectors   = 0;  
  
  thdata *data;            
  data = (thdata *) ptr;                         // type cast to a pointer to thdata
  
  SLCD * slconn;	                         // connection parameters each SL server 

  SLpacket * slpack;

  lthread_no = data->thread_no;
  sprintf(lipaddr,"%s",data->ipaddr);
  sprintf(lstreams,"%s",data->streams);
  sprintf(lstations,"%s",data->stations);
  lno_comp = data->no_comp;
  lno_str = data->no_str;

// Allocate and initialize a new connection description SEEDLINK
  
  slconn = sl_newslcd();
   
// connect to seedlink server this address
   
  sprintf(addr,"%s",lipaddr);

  slconn->sladdr = addr;
   
// full path to stream file   
    
  sprintf(totalstreams,"%s/par/%s/%s",topdir_rt,cfgfile,lstreams);
  
  streamfile = totalstreams;
  
  for(i=0;i<MAXCHA;i++)
    new[i]=(int)time(NULL);

  printf("LNO_STR: %d\n",lno_str);
  printf("****************************************************************************\n");  
  printf("Thread: %2d seedlink server: %s streamfile: %s\n",lthread_no,lipaddr,streamfile);
// connect input streams to specified seedlink server 
  sl_read_streamlist (slconn, streamfile, selectors); 
  printf("****************************************************************************\n");
// Never-ending loop reading defined inputstreams for detection 
  for(;;)
  {
    tr=lthread_no;
    if( sl_collect (slconn, &slpack))              // Connect to seedlink server
    {
      pthread_mutex_lock(&shufle_mutex);           // ******LOCK******
      ptype  = sl_packettype (slpack);             // get packet type
      seqnum = sl_sequence (slpack);               // get sequence number
      fnd=packet_handler ((char *) &slpack->msrecord, ptype, seqnum, SLRECSIZE,slconn,stream_count,sseismo,ns,sr);
      if(fnd != -1)                                // PACKET FOUND ?
      {

//          printf("  stream_count: %d chan:  %2d  \n",stream_count,fnd);
/*	  
          for(i=0;i<MAXCHA;i++)
          {
            if(tabell[fnd][i] == 'X')
              printf("%2d ",i);
          }
          printf("\n");  
*/
        ch=fnd;                                    // YES, SAVE STATION NUMBER

        for(i=0;i<antall_stasjoner;i++)
	{
	  ret1=strcmp(current_station,rtdly[i]);
	  if(ret1 == 0)
            new[i] = (int)time(NULL);
	}
//	printf("SR: %d\n",sr[ch]);
        PROCESS_BLOCK(ch,tr,stream_count,lno_str,sseismo,ns,sr);
        fnd=-1;                                    // RESET 'fnd'
      }
      pthread_mutex_unlock(&shufle_mutex);         // *****UNLOCK******
    }
//    printf("current_station: %s  len: %d\n",current_station,strlen(current_station));
///    printf("thread %2d  ",tr);
    for(i=0;i<antall_stasjoner;i++)
    {
      now = (int)time(NULL);
      forskjell = now - new[i];
      if(forskjell >=90)                         // after X seconds not receiving
      {
//	printf("Station not receiving: %s\n",spt->trig_stations[klon][i] );
        spt->receiving[klon][i] = -111;          // mark not receiving
      }else{
        spt->receiving[klon][i] = 0;             // mark receiving 
      }
    }
///  printf("\n");	

  }

}
//FPicker(double dtfp,float values[MAXCHA][RTBUFSIZ],int kan,int ns[],int lno_str,int ch)
FPicker(double dtfp,int kan,int ns[],int lno_str,int ch)
{
  int k1,n;
  float sample[RTBUFSIZ]; // FP 
  char   PICKLINES[MAXCHA][1024];      // result lines from filterpicker  
//  char   PICKTIMES[MAXCHA][500];       // contains number of picks + picktimes extracted from PICKLINES  
  double filterWindow = 4.0; // NOTE: auto set below
  double tUpEvent = 0.5; // NOTE: auto set below
  double longTermWindow = 10.0; // NOTE: auto set below
  int nsamp = RTBUFSIZ;
  double threshold1 = 10.0;
  double threshold2 = 10.0;
  BOOLEAN_INT useMemory = TRUE_INT;
  int indeks0;
  int indeks1;
  float addtime;  
  char tmptid[40];
  int YEAR;
  char dummy[200];
  int DDAY,MMTH,DY,YR;
  int HOUR;
  int MINU;
  int SEC;
  int MSEC;
  int mmonth, dday;
  char P_PHASE[200];
  int space;  
  int EVT;
  
  filterWindow = 300.0 * dtfp;
  long iFilterWindow = (long) (0.5 + filterWindow * 1000.0);
  if (iFilterWindow > 1)
    filterWindow = (double) iFilterWindow / 1000.0;
    
  longTermWindow = 500.0 * dtfp; // seconds
  long ilongTermWindow = (long) (0.5 + longTermWindow * 1000.0);
  if (ilongTermWindow > 1)
    longTermWindow = (double) ilongTermWindow / 1000.0;

  tUpEvent = 20.0 * dtfp; // AJL20090522
  long itUpEvent = (long) (0.5 + tUpEvent * 1000.0);
  if (itUpEvent > 1)
    tUpEvent = (double) itUpEvent / 1000.0;
  
  for(k1=0;k1<RTBUFSIZ;k1++)
    sample[k1]=values[kan][RTBUFSIZ-1-k1];
  
// do picker function test
// definitive pick data
  PickData** pick_list_definative = NULL;
  int num_picks_definative = 0;
// persistent memory
  FilterPicker5_Memory* mem = NULL;

  int proc_samples = 0;
  int read_samples = nsamp;

// temporary data
  PickData** pick_list = NULL; // array of num_picks ptrs to PickData structures/objects containing returned picks
  int num_picks = 0;

  Pick(
    dtfp,
    sample,
    read_samples,
    filterWindow,
    longTermWindow,
    threshold1,
    threshold2,
    tUpEvent,
    &mem,
    useMemory,
    &pick_list,
    &num_picks,
    "TEST"
    );
	    
// save pick data
  for (n = 0; n < num_picks; n++) 
  {
    PickData* pick = *(pick_list + n);
    pick->indices[0] += proc_samples; // pick indices returned are relative to start of packet
    pick->indices[1] += proc_samples;
//    printf("%2d %5d %5d\n",n,(int)(pick->indices[0]),(int)(pick->indices[1]));
    if((int)(pick->indices[0]) >= (RTBUFSIZ - ns[kan]) && (int)(pick->indices[0]) < RTBUFSIZ)
    {
//      printf("%2d %5d %5d\n",n,(int)(pick->indices[0]),(int)(pick->indices[1]));
      pick->indices[0] = ns[kan] - (RTBUFSIZ - pick->indices[0]);
      pick->indices[1] = ns[kan] - (RTBUFSIZ - pick->indices[1]);
      indeks0 = (int)(pick->indices[0]);
      indeks1 = (int)(pick->indices[1]);	      
      addPickToPickList(pick, &pick_list_definative, &num_picks_definative);
    }
  }
// clean up temporary data
  free(pick_list); // do not use free_PickList() since we want to keep PickData objects

  proc_samples += read_samples;
  


  sprintf(tmptid,"%s",rtid[kan]);
  sscanf(tmptid,"%4d%1c%3d%1c%2d%1c%2d%1c%2d%1c%3d",&YEAR,dummy,&DY,dummy,&HOUR,dummy,&MINU,dummy,&SEC,dummy,&MSEC);
  DTE(DY,&DDAY,&MMTH,YEAR);
  dday = DDAY;
  mmonth = MMTH;

  double sec = (double) SEC + (double) MSEC / 1000.0;
// id fields
  char onset[] = "?";
  char* kstnm;
  kstnm = calloc(1, 16 * sizeof (char));
  sprintf(kstnm, "STAT");
  char* kinst;
  kinst = calloc(1, 16 * sizeof (char));
  sprintf(kinst, "DIG");
  if (strstr(kinst, "(count") != NULL)
    strcpy(kinst, "(counts)");
  char* kcmpnm;
  kcmpnm = calloc(1, 16 * sizeof (char));
  sprintf(kcmpnm, "CMP");
  char phase[16];
// create NLL picks
  char* pick_str;
  pick_str = calloc(1, 1024 * sizeof (char));
  for (n = 0; n < num_picks_definative; n++) 
  {
    sprintf(phase, "P%d_", n);
    pick_str = printNlloc(pick_str,
      *(pick_list_definative + n), dtfp, kstnm, kinst, kcmpnm, onset, phase,
      YEAR, mmonth, dday, HOUR, MINU, sec);

    sprintf(PICKLINES[n],"%s",pick_str);
  }
  
  if(num_picks_definative > 1)
    num_picks_definative = 1;
  for(n=0;n<num_picks_definative; n++)
  {
    addtime = indeks0 * dtfp;

    sprintf(P_PHASE,"%3d %s",kan,PICKLINES[n]);
//    EVT=TRIGGER_TIME_FPICK(P_PHASE,lno_str,ch,ns,values);    
    EVT=TRIGGER_TIME_FPICK(P_PHASE,lno_str,ch,ns);         // called only when there are picks
    if(EVT == 1)
    {
      printf("EVT: %d\n",EVT);
    }
  }

// clean up
  free(pick_str);
  free(kcmpnm);
  free(kinst);
  free(kstnm);
  free_PickList(pick_list_definative, num_picks_definative); // PickData objects freed here
  free_FilterPicker5_Memory(&mem);
  
}
PROCESS_BLOCK(int ch,int tr,int stream_count,int lno_str,int sseismo[MAXCHA][3000],int ns[], int sr[])
{
//  float  values[MAXCHA][RTBUFSIZ];    // values per block per channel
  float  fseismo[MAXCHA][2000];
  float  seis[RTBUFSIZ]; 
  float  dc[MAXCHA]; 
  float  rat[MAXCHA]; 
  float  ratios[RTBUFSIZ]; 
  int    hold[MAXCHA];  
 
  int    nsta;
  int    nlta;
  int    nnoi;
  float  sta1;                     // STA at current sample
  float  lta1;                     // LTA at current sample
  float  noi1;                     // noise level
  float  stamax;                   // Maximum STA within buffer
  int    ixmax;
  int    sw_hold=0;
  int sw_trg=0;  
  int ixx,k1,i,j;
  int kan;
  int dif;
  int prt=0;
  
  int pindex;
  int nn;  
  int sekunder;  
  int ant;
  float MxAmp;
  int ws=5;                  // sta in samples
  int wl=100;                // lta in samples  
  float dt;
  
  float srate;
  int npts;
  int antsamples[MAXCHA];
    double dtfp;   

//printf("PB1 1\n");

  for(kan=0;kan<MAXCHA;kan++)
  {
    if(tabell[ch][kan] == 'X')
    {
//      printf("CH: %2d  Current chan: %s BUFFERTIME: %s\n",ch,allstreams[ch],rtid[ch]);
    
      dc[kan] = 0.0;                             // Initialize dc to zero  
      ixx = RTBUFSIZ-1;  

      antsamp[kan] = antsamp[kan] + ns[kan];
   
      for(k1=0;k1<(RTBUFSIZ-ns[kan]);k1++)           // shift out bottom ns samples
      {
        values[kan][ixx] = values[kan][ixx-ns[kan]];
        ixx = ixx -1;
      }
      for(k1=0;k1<ns[kan];k1++)                      // put ns new samples in on top
        values[kan][ns[kan]-k1-1] = (float)sseismo[kan][k1];	
 
      for(k1=0;k1<RTBUFSIZ;k1++)                     // add all samples in buffer
        dc[kan] = dc[kan] + values[kan][k1];
     
      dc[kan] = dc[kan]/(float)RTBUFSIZ;             // dc of tot samples
      spt->cdcavg[klon][kan] = dc[kan];              // Update dc

      for(k1=0;k1<ns[kan];k1++)                      // REMOVE DC
        fseismo[kan][k1]=((float)(sseismo[kan][k1])-spt->cdcavg[klon][kan]);	
    
      LATENCY(ch);

      if(pk < 20)
      {
        printf(".");
        fflush(stdout);
      }
      if(pk==20)
        printf("  receiving data\n");
      if(pk > 20)                                   // let dc stabelize for 20 blocks before starting
      {
        for(k1=0;k1<RTBUFSIZ;k1++)                  // remove DC this channel, for PICKING
          ftemp[kan][k1]=values[kan][RTBUFSIZ-1-k1]-spt->cdcavg[klon][kan];

        dt=srate;
        npts=RTBUFSIZ;
        dt = 1.0/(float)(sr[kan]);
        srate = dt;
        ixx=npts-1;
/*************************************************************************************/
/* Check if realtime picker is set to active                                         */
/*************************************************************************************/

        if(realtimepick == 1)
        {
	  antsamples[kan] = antsamples[kan] + ns[kan]; // accumulate samples
	
	  if(antsamples[kan] > RTBUFSIZ)               // do not start picker until RTBUFSIZ
	  {
	    antsamples[kan] = RTBUFSIZ+10;
            dtfp = dt;
//	    FPicker(dtfp,values,kan,ns,lno_str,ch);
	    FPicker(dtfp,kan,ns,lno_str,ch);
          }
        }

        for(k1=0;k1<npts;k1++)                      // get seismogram for PICKING processing
          seis[k1] = ftemp[kan][k1];
    
        appl_pick(kan,seis);                        // bandpass filter
    
        nsta=(int)(sta_par[kan]*(float)(sr[kan]));  // number of samples in sta window
        nlta=(int)(lta_par[kan]*(float)(sr[kan]));  // number of samples in lta window
        nnoi=(int)(lta_par[kan]*(float)(sr[kan]));  // number of samples to measure noise-level

        if(fl_par[kan] != 0.0 && fh_par[kan] != 0.0) // FILTER DATA ?
        {
          appl(kan,fseismo,ns);                                // FILTER ONE BUFFER
          sta1=spt->csta[klon][kan];                // get previous sta
          lta1=spt->clta[klon][kan];                // get previous lta
          noi1=spt->cnoi[klon][kan];                // get previous noise-level

          STA_LTA(&sta1,&lta1,&noi1,&stamax,kan,ns[kan],nsta,nlta,nnoi,&ixmax,fseismo);

          if(hold[kan] < VENT)                      // wait for sta-lta to be stable each component
          {
//	    printf("%3d %3d %3d\n",kan,hold[kan],VENT);
	    if(sw_hold == 0)
	    {
	      sw_hold = 1;
	    }
            spt->csta[klon][kan]=sta1;              // update sta
            spt->clta[klon][kan]=sta1;              // set lta = sta until stable
            spt->cnoi[klon][kan]=sta1;
            hold[kan] = hold[kan] + ns[kan]/sr[kan]; // count blocks holding processing in wait
            spt->age[klon][kan][4] = hold[kan];
            if(spt->age[klon][kan][4] >= VENT)
              spt->age[klon][kan][4] = 0;
          }else{   // hold
              //--------------------------------------------------------
              // start single-kanannel trigger after initializing sta lta
              //--------------------------------------------------------
            if(sw_trg == 0)
	    {
              sw_trg = 1;
	    }
            spt->csta[klon][kan]=sta1;                               // store new STA in shared
            rat[kan]=spt->csta[klon][kan]/spt->clta[klon][kan];      // compute current ratio
//printf("%s ch: %2d kan: %2d nsta: %3d nlta: %6d fl:%4.1f fh:%4.1f %4.1f %4.1f %4.1f\n",toplot[ch],ch,kan,nsta,nlta,fl_par[kan],fh_par[kan],spt->csta[klon][kan],spt->clta[klon][kan],rat[kan]);
            if(rat[kan] >= trg_par[kan])                             // check for trigger this channel
            {
              if(trig_flag[kan] == 0 && det_flg == 0)                // compute trigger time, look for P
              {
	        first[kan]=0;
                spt->coda[klon][kan]=spt->cnoi[klon][kan];           // save noise-level at trigger point
                ant=ns[kan];                                         // number of samples last buffer this channel
                ZERO_START(seis);                                    // zero start of signal after filtering
                MaxAmp(RTBUFSIZ,seis,&MxAmp);                        // Find maximum amplitude
                Scale_to_1(RTBUFSIZ,seis,MxAmp);                     // Scale to max 1
                STALTAPHFL(RTBUFSIZ,seis, ws, wl, ratios);           // compute STA/LTA ratios, store in rat
                pindex=FIND_P(ant,RTBUFSIZ,ratios);                  // find P in detection buffer (last buffer)
                sekunder = ns[kan]/sr[kan];                  
                TRIGGER_TIME_P(ws,pindex,kan,srate,sekunder,stream_count,ch);  // detection buffer-time + time to P
   
                printf("READ_PACKETS...:Trigger CH: %2d->%2d ant: %4d MxAmp: %8.1f nlev: %8.1f sta:%6.1f lta:%6.1f rat:%6.1f %12.1f %s\n",ch,kan,ant,MxAmp,spt->coda[klon][kan],spt->csta[klon][kan],spt->clta[klon][kan],rat[kan],spt->tt[klon][kan],toplot[ch]);

	        ON_OFF[kan] = 1;
              }  // trig_flag
              trig_flag[kan] = 1;                                    // set trigger flag
              spt->age[klon][kan][3] = 1;                            // set flag in shared
              spt->dur[klon][kan]=spt->dur[klon][kan]+ns[kan]/sr[kan];  // increment duration
              if(spt->dur[klon][kan] > 300)
              {
                printf("Channel %2d more than 300 secs. duration.\n",kan);
                trig_flag[kan] = 0;
              }
              sekunder = ns[kan]/sr[kan];
              nn=first[kan];
              first[kan]++;
            }else{   // if ratio.....ratio < trg_par
              if(rat[kan] < dtrg_par[kan])                           // check for de-trigger this channel
              {
                if(trig_flag[kan] == 1)                              // if less than de-trig lev., but still trigger mode
                {
                  printf("READ_PACKETS...:klon: %d %s turned off. Dur: %3d\n",klon,toplot[ch],spt->dur[klon][kan]); // turn off trigger flag
                  trig_dur[kan] = spt->dur[klon][kan]; 
                  trig_flag[kan] = 0;                                // turn off trigger flag
                  spt->age[klon][kan][3] = 0;
                  duration[kan] = trig_dur[kan];
                  nn=duration[kan];
                  if(ON_OFF[kan] == 1)
                  {
                    ON_OFF[kan] = 0;
                    TRIGGER_DUR(sekunder,kan,nn,stream_count);
                  }
                }                                                    // if trig_flag == 1
              }                                                      // if rat < dtrg_par
              if(trig_flag[kan] == 1)
              {
                spt->dur[klon][kan]=spt->dur[klon][kan]+ns[kan]/sr[kan];
              }
            }                                                        // if rat < trg_pr
            spt->cnoi[klon][kan] = noi1;
            if(trig_flag[kan] == 0)
            {
              spt->clta[klon][kan]=lta1;                             // update lta
              if(rat[kan] < 0.6)
              {
                spt->clta[klon][kan]=spt->clta[klon][kan]-(spt->clta[klon][kan] * 20.0)/100.0;
              }
            }
          }     // hold 
        }       // if filter ?
      }else{
        pk++;        // check pk > 20
      }
    }
  }
}
void ZERO_START(float scr[])
{
  int s;

  for (s=0;s<300;s++)
    scr[s]=0.0;
}

void STALTAPHFL(int ne, float kanal[],int ws,int wl,float rat[])
  {
    float extra=(float)0.0;
    float sta1=(float)0.0;
    float lta1=(float)0.0;
    float k1=(float)0.0;
    float k2=(float)0.0;
    float R=(float)0.0;
    int s,ss;
    sta1=(float)0.0;
    lta1=(float)0.0;
    
//      System.out.println("STALTAPHFL: ne:"+ne);

    for(s=1;s<800;s++)
    {
      extra=(float)kanal[s]-(float)kanal[s-1];
      extra=extra * extra;
      k1=fabsf((float)kanal[s-1]);
      k2=k1 * k1;
      sta1=sta1+(k2+ (float)3.0*extra-sta1)/(float)ws;
      k1=fabsf((float)kanal[s]);
      k2=k1 * k1;
      lta1=lta1+(k2-lta1)/(float)wl;
    }

    for(ss=1;ss<(ne-1);ss++)
    {
      extra=(float)kanal[ss]-(float)kanal[ss-1];
      extra=extra * extra;
      k1=fabsf((float)kanal[ss-1]);
      k2=k1 * k1;
      sta1=sta1+(k2+ (float)3.0*extra-sta1)/(float)ws;
      k1=fabsf((float)kanal[ss]);
      k2=k1 * k1;
      lta1=lta1+(k2-lta1)/(float)wl;
      R=sta1/lta1;
      rat[ss]=R;
    }

  }
int FIND_P(int ant,int tot,float rati[])
{
  int indx=0;
  int tel=0;
  int k;
  float max;
  max=0.0;
  for(k=(RTBUFSIZ-ant);k<tot;k++)   // 5000
  {
//    printf("%4d  %8.2f max: %8.2f indx: %d\n",k,rati[k],max,indx);
    if(rati[k]>max)
    {
      max=rati[k];
      indx=tel;
    }
    tel++;
  }
  return(indx);
}  




/*  Subroutine to apply an iir filter to a data sequence.                   */
/*    The filter is assumed to be stored as second order sections.          */
/*    Filtering is in-place.                                                */
/*    Zero-phase (forward and reverse) is an option.                        */

void appl(int fnd,float fseismo[MAXCHA][2000],int ns[])
{
    /* System generated locals */
  int      i1;
  int      i2;

    /* Local variables */
  int      jptr;
  int      i;
  int      j;
  float    b0;
  float    b1;
  float    b2;
  float    a1;
  float    a2;
  float    x1;
  float    x2;
  float    y1;
  float    y2;
  float    output;

/* Parameter adjustments                                                    */

/* Function Body                                                            */
  jptr = 1;
  i1 = cset[fnd];

  for (j = 1; j <= i1; ++j)
  {
    x1 = save_x1[fnd][j];
    x2 = save_x2[fnd][j];
    y1 = save_y1[fnd][j];
    y2 = save_y2[fnd][j];
    b0 = snc[fnd][jptr];
    b1 = snc[fnd][jptr + 1];
    b2 = snc[fnd][jptr + 2];
    a1 = sdc[fnd][jptr + 1];
    a2 = sdc[fnd][jptr + 2];
    i2 = ns[fnd];

    for (i = 0; i < i2; ++i)
    {
      output = b0 * fseismo[fnd][i] + b1 * x1 + b2 * x2;
      output -= a1 * y1 + a2 * y2;
      y2 = y1;
      y1 = output;
      x2 = x1;
      x1 = fseismo[fnd][i];
      fseismo[fnd][i] = output;
    }
    jptr += 3;

    save_y2[fnd][j]=y2;
    save_y1[fnd][j]=y1;
    save_x2[fnd][j]=x2;
    save_x1[fnd][j]=x1;
  }
}
//------------------------------------------------------------------------------------------
// Read configuration file into memory
//------------------------------------------------------------------------------------------
Read_Config_to_MEM(char config[],char mempar[500][256])
{
  FILE *par;
  char  filepath[256];
  char  linjer[500];
  int   tel,i;
  
  sprintf(filepath,"%s/par/%s/rt_config",topdir_rt,config);
  par = fopen(filepath,"r");
  if(par == NULL)
  {
    printf("************RTDET-Read_Config_to_MEM**********************\n");
    printf("* %s does not exist.\n",filepath);
    printf("* Check your configuration file.                         *\n");
    printf("**********************************************************\n");
    exit(0);
  }
  tel=0;
  while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
  {
    if(linjer[0] == ' ' || linjer[0] == 0xa )
      break;
    if(linjer[0] != '#')
    {
      sprintf(mempar[tel],"%s",linjer);
      tel++;
    }      
  }
  fclose(par);
  return(tel);
}
//-------------------------------------------------------------------------------------
// Find all seedlink servers to use specified under label SERVERS in configuration file
//-------------------------------------------------------------------------------------
Find_SL_Servers(int no_of_lines_cfg,char mempar[500][256],char memsrv[100][100])
{
  char keyword[20];
  int k,l;
  int re;
  int found;
  int tel;
  found = -1;
  sprintf(keyword,"SERVERS");             // Search for label SERVERS
  for(k=0;k<no_of_lines_cfg;k++)
  {
    if(strstr(mempar[k],keyword))
    {
      found = k; 
    }
  }
  if(found == -1)
  {
    printf("**************************RTDET-Find_SL_Servers*************\n");
    printf("* Label SERVERS does not exist in configuration file.      *\n");
    printf("************************************************************\n");
    exit(0);
  }
  tel = 0;
  for(l=0;l<100;l++)
  {
    sprintf(keyword,"S%2d",l);
    if(keyword[1] == ' ') keyword[1] = '0';
    for(k=0;k<no_of_lines_cfg;k++)
    {
      re = strncmp(keyword,mempar[k],3);
      if(re == 0)
      {
	sprintf(memsrv[tel],"%s",mempar[k]);
	tel++;
      }
    }      
  }
  return(tel);
}
//------------------------------------------------------------------------------------------
// Find all networks specified by label TRIGGER in configuration file
//-----------------------------------------------------------------------------------------
Find_Networks(int no_of_lines_cfg,char mempar[500][256],char memnet[500][256],int start_net[],int stopp_net[],int min_trg_net[])
{
  char keyword[20];
  char dummy[200];
//  char rtdly[50];
  char d1[10];
  char d2[10];
  char d3[10];
  char d4[10];
  int k,l,p,q;
  int re;
  int found;
  int tel;
  int br;
  int fra;
  int til;
  int cnt;
  int antall_netverk;
  int mt;
  int length;
  found = -1;
  antall_netverk = 0;
  sprintf(keyword,"NETWORK");             // Search for label SERVERS
  for(k=0;k<no_of_lines_cfg;k++)
  {
    if(strstr(mempar[k],keyword))
    {
      found = k;
      antall_netverk++;
    }
  }
  if(found == -1)
  {
    printf("**************************RTDET-Find_Networks************\n");
    printf("* Label NETWORK does not exist in configuration file.   *\n");
    printf("*********************************************************\n");
    exit(0);
  } 
  tel=0;                                  // nework index
  cnt=0;
  br =0;
  q=0;
//  printf("**********************************************************************************\n");
//  printf("antall_netverk: %d\n",antall_netverk);
  for(k=0;k<no_of_lines_cfg;k++)
  {
    
    for(p=0;p<antall_netverk;p++)
    {
      br=0;

      if(strstr(mempar[k],keyword))       // Label TRIGGER found ?
      {
        if(printarg > 0)
          printf("FOUND:   %s",mempar[k]);           // TRIGGER found print header
        sscanf(mempar[k],"%s %s %d",dummy,dummy,&mt);
        if(printarg > 0)
	  printf("mt: %d tel: %d\n",mt,tel);
	min_trg_net[tel] = mt;
	if(mintrg == 0)
	{
	  tel++;
	}else{
	  tel=1;
	}
        start_net[q] = cnt;
        k=k+2;
	for(;;)
        {
          if(mempar[k][0] != '-' && mempar[k][1] != '-')  // end of network ?
          {
            if(printarg > 0)
              printf("%2d %s",cnt,mempar[k]);
	    sscanf(mempar[k],"%s %s %s %s %f %f %f %f %f %f",d1,d2,d3,d4,&fl_par[cnt],&fh_par[cnt],&sta_par[cnt],&lta_par[cnt],&trg_par[cnt],&dtrg_par[cnt]);
	    if(d3[0]=='.' && d3[1]=='.')
	    {
	      d3[0]=' ';
	      d3[1]=' ';
	    }
            length=strlen(d2);
            switch(length)
	    {
	      case 2:
	      sprintf(spt->trig_stations[klon][cnt],"%2d %s %s    %s%s",tel,d1,d2,d3,d4);
	      break;	      
	      case 3:
	      sprintf(spt->trig_stations[klon][cnt],"%2d %s %s  %s%s",tel,d1,d2,d3,d4);
	      break;
	      case 4:
	      sprintf(spt->trig_stations[klon][cnt],"%2d %s %s %s%s",tel,d1,d2,d3,d4);
	      break;
	      case 5:
	      sprintf(spt->trig_stations[klon][cnt],"%2d %s %s%s%s",tel,d1,d2,d3,d4);
	      break;	      
	    }
printf("NET: %s\n",spt->trig_stations[klon][cnt]);	    
	    sprintf(memnet[cnt],"%s",mempar[k]);
	    k++;
            cnt++;
          }else{                         // end of this network
            stopp_net[q] = cnt;
	    q++;
	    br=1;
          }
          if(br==1)
	    break;
	}
	if(br==1)
	  break;
      }
      if(br==1)
	break;
    }
  }

  return(antall_netverk);  
}
Check_Config(char config[])
{
  FILE *par;
  char  filepath[256];
  char  linjer[500];
  char  du[10];
  char  ord[100];
  char  keyword[100];
  char  chkpar[500][256];
  int   tel,i,found;
  
  sprintf(filepath,"%s/par/%s/rt_config",topdir_rt,config);
  par = fopen(filepath,"r");
  if(par == NULL)
  {
    printf("************RTDET-Read_Config_to_MEM**********************\n");
    printf("* %s does not exist.\n",filepath);
    printf("* Check your configuration file.                         *\n");
    printf("**********************************************************\n");
    exit(0);
  }
  tel=0;
  while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
  {
//    printf("%3d %s",tel,linjer);
    if(linjer[0] == ' ' || linjer[0] == 0xa)
    {
        printf("******************RTDET Check_Config*****************************\n");
        printf("* Blank line or line beginning with space in configuration file.*\n");
        printf("*****************************************************************\n");
        exit(0);
    }    
    tel++;      
  }
  rewind(par);
  tel=0;
  while ( fgets ( linjer, sizeof linjer, par ) != NULL ) /* read a line from file */
  {
    if(linjer[0] == ' ' || linjer[0] == 0xa)
      break;
    sprintf(chkpar[tel],"%s",linjer);
    tel++;      
  }
  if(printarg > 0)  
    printf("\nRTDET: number of lines in rt_config: %d\n",tel);  
  fclose(par);
  
  sprintf(keyword,"SERVERS");
  found=0;
  for(i=0;i<tel;i++)
  {
    sscanf(chkpar[i],"%s",ord);
    if(strstr(keyword,ord))
    {
      found=1; 
    }
  }
  if(found == 0)
  {
    printf("******************RTDET Check_Config*****************************\n");
    printf("* Keyword SERVERS missing in configuration file.                *\n");
    printf("*****************************************************************\n");
    exit(0);    
  }

  sprintf(keyword,"NETWORK");
  found=0;
  for(i=0;i<tel;i++)
  {
    sscanf(chkpar[i],"%s",ord);
    if(strstr(keyword,ord))
    {
      found=1; 
    }
  }
  if(found == 0)
  {
    printf("******************RTDET Check_Config*****************************\n");
    printf("* Keyword NETWORK missing in configuration file.                *\n");
    printf("*****************************************************************\n");
    exit(0);    
  }  
  
  sprintf(keyword,"RECORD");
  found=0;
  for(i=0;i<tel;i++)
  {
    sscanf(chkpar[i],"%s",ord);
    if(strstr(keyword,ord))
    {
      found=1; 
    }
  }
  if(found == 0)
  {
    printf("******************RTDET Check_Config*****************************\n");
    printf("* Keyword RECORD missing in configuration file.                 *\n");
    printf("*****************************************************************\n");
    exit(0);    
  }  



  found=0;
  for(i=0;i<tel;i++)
  {
    sprintf(keyword,"NETWORK");    
    sscanf(chkpar[i],"%s",ord);
    if(strstr(keyword,ord))
    {
      found=1;
      i=i+1;
      sprintf(keyword,"NW");
      sscanf(chkpar[i],"%s",ord);
        if(strstr(keyword,ord))
      {
        found=0;
      }else{
        printf("******************RTDET Check_Config******************************\n");
        printf("* Header line after keyword NETWORK missing in configuration file.*\n");
        printf("******************************************************************\n");
        exit(0); 
      }
    }
  }
  

  found=0;
  for(i=0;i<tel;i++)
  {
    sprintf(keyword,"RECORD");    
    sscanf(chkpar[i],"%s",ord);
    if(strstr(keyword,ord))
    {
      found=1;
      i=i+1;
      sprintf(keyword,"NW");
      sscanf(chkpar[i],"%s",ord);
        if(strstr(keyword,ord))
      {
        found=0;
      }else{
        printf("******************RTDET Check_Config******************************\n");
        printf("* Header line after keyword RECORD missing in configuration file.*\n");
        printf("******************************************************************\n");
        exit(0); 
      }
    }
  }  
  
  fclose(par);
  
}
//------------------------------------------------------------------------------------------
// Find all recording specified by label RECORD in configuration file
//-----------------------------------------------------------------------------------------
RecStreams(int no_of_lines_cfg,char mempar[500][256],char memrec[500][256],int start_rec[],int stopp_rec[])
{
  char keyword[20];
  char dummy[200];
  char name[200];
  int k,l,p,q,n;
  int re;
  int found;
  int tel;
  int br;
  int fra;
  int til;
  int cnt;
  int antall_record;
  int mt;
  found = -1;
  antall_record = 0;
  sprintf(keyword,"RECORD");             // Search for label RECORD
  for(k=0;k<no_of_lines_cfg;k++)
  {
    if(strstr(mempar[k],keyword))
    {
      found = k;
      antall_record++;
    }
  }
  if(found == -1)
  {
    printf("**************************RTDET-RecStreams******************\n");
    printf("* Label RECORD does not exist in configuration file.       *\n");
    printf("************************************************************\n");
    exit(0);
  } 
  tel=0;                                  // nework index
  cnt=0;
  br =0;
  q=0;

  for(k=0;k<no_of_lines_cfg;k++)
  {
    
    for(p=0;p<antall_record;p++)
    {
      br=0;

      if(strstr(mempar[k],keyword))       // Label RECORD found ?
      {
        if(printarg > 0)
          printf("FOUND:   %s",mempar[k]);           // RECORD found print header
        sscanf(mempar[k],"%s %s",dummy,name);
        tel++;
        start_rec[q] = cnt;
        k=k+2;
	for(n=0;n<no_of_lines_cfg;n++)
        {
          if(mempar[k][0] != '-' || mempar[k][1] != '-')  // end of network ?
          {
            if(printarg > 0)
              printf("%2d %s",cnt,mempar[k]);
	    sprintf(memrec[cnt],"%s",mempar[k]);
	    k++;
            cnt++;
          }else{                         // end of this network
            stopp_rec[q] = cnt;
	    q++;
	    br=1;
          }
          if(br==1)
	    break;
	}
	if(br==1)
	  break;
      }
      if(br==1)
	break;
    }
  }
  
  return(cnt);  
}
Create_Streamfiles(int total_streams_net,int min_trg_net[],int number_of_networks,int number_of_servers, int start_net[],int stopp_net[],char memsrv[100][100],char memnet[500][256],char stream_names[500][10],int *str_cnt)
{
  FILE *str;
  FILE *asc;
  int i,j,k,l,p,q,lik,n,re,tel,ii,jj,kk,ret1,ret2,ret3,ret4,found,tt,ant_memnet;
  int no_of_stream_files;
  char dum[10];
  char keyword[30];
  char linje[256];
  char nettverk[50];
  char cha[500][256];
  char newstr[500][256];
  char srtmem[500][256];
  char memmem[500][256];
  char finmem[500][256];
  char kanmem[500][256];
  char srvdef[10];
  char srv[10];
  char filepath[256];
  char cfgpath[256];
  char netname[10];
  char staname[10];
  char loc[10];
  char com[10];
  char stname[20];
  char nystring[20];
  char slipaddr[100];
  char txt1[15];
  char reco[10];

  int  kolonne[500];
  int  ix;
  int  len;
  char akey1[10];
  char akey2[10];
  char akey3[10];
  char akey4[10];
  char bkey1[10];
  char bkey2[10];
  char bkey3[10];
  char bkey4[10];
  int  ixant[500];
  int  ixpos[500];
  int  str_cint;
  if(printarg > 0)  
    printf("total_streams: %d\n",total_streams_net);

  q=0;
  lik=0;
  
//printarg=1;  
  
  
  if(printarg > 0)  
    printf("\nMEMNET\n");
  str_cint = 0;
  for(k=0;k<number_of_servers;k++)
  {
    sscanf(memsrv[k],"%s",keyword);
    for(i=0;i<total_streams_net;i++)
    {
      sscanf(memnet[i],"%s %s %s %s %s %s %s %s %s %s %s",dum,dum,dum,dum,dum,dum,dum,dum,dum,dum,srv);
      if(strstr(keyword,srv))
      {
        if(printarg > 0)
	  printf("%2d %s",i,memnet[i]);
	sprintf(srtmem[str_cint],"%s",memnet[i]);
	ixpos[str_cint] = i;
	str_cint++;
      }
    }  // streams net
  }  // servers
  ant_memnet=str_cint;
  if(printarg > 0)
    printf("\nSRTMEM\n"); 
  spt->val20[klon]=total_streams_net;   
  for(i=0;i<total_streams_net;i++)
  {
    if(printarg > 0)    
      printf("%2d %s",i,srtmem[i]);
    sscanf(srtmem[i],"%s %s",dum,staname);
    sprintf(spt->stasjon[klon][i],"%s",staname);
  }
  tt=0;
  no_of_stream_files = 0;
  for(i=0;i<number_of_servers;i++)
  {
    str_cint = 0;
    if(printarg > 0)    
      printf("server: %d\n",i);
    sscanf(memsrv[i],"%s",keyword);    
    for(k=0;k<total_streams_net;k++)
    {
      sscanf(srtmem[k],"%s %s %s %s %s %s %s %s %s %s %s",dum,dum,dum,dum,dum,dum,dum,dum,dum,dum,srv);
      if(strstr(keyword,srv))
      {
	sprintf(memmem[str_cint],"%s",srtmem[k]);
	str_cint++;
      }      
    }

    q=0;
    found=-1;
    if(printarg > 0)  
      printf("str_cint: %d\n",str_cint);
    
    for(kk=0;kk<str_cint;kk++)
      sprintf(finmem[kk],"a b c d");
    for(kk=0;kk<str_cint;kk++)
    {
      sscanf(memmem[kk],"%s %s %s %s",akey1,akey2,akey3,akey4);
      for(jj=0;jj<str_cint;jj++)
      {
        sscanf(finmem[jj],"%s %s %s %s",bkey1,bkey2,bkey3,bkey4);
        ret1=strcmp(akey1,bkey1);
        ret2=strcmp(akey2,bkey2);
        ret3=strcmp(akey3,bkey3);
        ret4=strcmp(akey4,bkey4);
        if(ret1 == 0 && ret2 == 0 && ret3 == 0 && ret4 == 0)
        {
          found=jj;
        }
      }
      if(found >= 0)
      {
        found=-1;
      }else{
        sprintf(finmem[q],"%s",memmem[kk]);	  
        q++;
        found=-1;
      }      
    }
    if(printarg > 0)    
      printf("\n");
    for(p=0;p<q;p++)
    {
      if(printarg > 0)      
        printf("%2d %s",p,finmem[p]);
      sprintf(kanmem[tt],"%s",finmem[p]);
      tt++;
    }
    
    sscanf(memsrv[i],"%s",srvdef);
    if(printarg > 0)    
      printf("SERVER:  %s\n",srvdef);
    sprintf(filepath,"%s/par/%s/%s",topdir_rt,cfgfile,srvdef);
    if(printarg > 0)    
      printf("%s\n",filepath);    
    str = fopen(filepath,"w"); 
    for(k=0;k<q;k++)      
    {
      sscanf(finmem[k],"%s %s %s %s",netname,staname,loc,com);
      MakeStrFile(netname,staname,loc,com,nystring);
      sprintf(cha[k],"%s",nystring);
    } 
    for(k=0;k<q;k++)
      fprintf(str,"%s\n",cha[k]);
    fclose(str);
    sprintf(stream_names[no_of_stream_files],"%s",srvdef);
    no_of_stream_files++;
  }
  if(printarg > 0)
  {
    for(i=0;i<tt;i++)
      printf("%2d %s",i,kanmem[i]);
    printf("str_cnt: %2d\n",ant_memnet);
  }
  antall_stasjoner = ant_memnet;  
  for(i=0;i<tt;i++)
  {
    sscanf(kanmem[i],"%s %s %s %s",akey1,akey2,akey3,akey4);   
    for(j=0;j<ant_memnet;j++)
    {
      sscanf(memnet[j],"%s %s %s %s",bkey1,bkey2,bkey3,bkey4);
      switch(strlen(bkey2))
      {
	case 2:
        sprintf(rtdly[j],"%s   ",bkey2);
//        printf("%2d %s len: %2d\n",j,rtdly[j],strlen(rtdly[j]));
        break;
	case 3:
        sprintf(rtdly[j],"%s  ",bkey2);
//        printf("%2d %s len: %2d\n",j,rtdly[j],strlen(rtdly[j]));	  
	break;
	case 4:
        sprintf(rtdly[j],"%s ",bkey2);
//        printf("%2d %s len: %2d\n",j,rtdly[j],strlen(rtdly[j]));	  
	break;
	case 5:
        sprintf(rtdly[j],"%s",bkey2);
//        printf("%2d %s len: %2d\n",j,rtdly[j],strlen(rtdly[j]));	  
	break;
      }
      ret1=strcmp(akey1,bkey1);
      ret2=strcmp(akey2,bkey2);
      ret3=strcmp(akey3,bkey3);
      ret4=strcmp(akey4,bkey4);

      if(ret1 == 0 && ret2 == 0 && ret3 == 0 && ret4 == 0)
      {
        if(printarg > 0)
          printf("kanal %2d til %2d\n",i,j);
        tabell[i][j] = 'X';
      }else{
        tabell[i][j] = ' ';	
      }
    }    
  }
//--------------------------------------------------------------------------
// print out association tables
//--------------------------------------------------------------------------
  sprintf(filepath,"%s/par/%s/asc.tab",topdir_rt,cfgfile);
  printf("RTDET: stream-table:		%s\n",filepath);    
  asc = fopen(filepath,"w"); 
  for(q=3;q<8;q++)
  {
    printf("        ");
    fprintf(asc,"        ");    
    for(i=0;i<tt;i++)
    {
      printf(" %c",kanmem[i][q]);
      fprintf(asc," %c",kanmem[i][q]);       
    }
    printf("\n");
    fprintf(asc,"\n");    
  }
  printf("        ");
  fprintf(asc,"        ");  
  for(i=0;i<tt;i++)
  {
    printf("%2d",i/10);
    fprintf(asc,"%2d",i/10);     
  }
  printf("\n");
  fprintf(asc,"\n");  
  printf("        "); 
  fprintf(asc,"        ");  
  for(i=0;i<tt;i++)
  {
    printf("%2d",(i % 10));
    fprintf(asc,"%2d",(i % 10));   
  }
  printf("\n");
  fprintf(asc,"\n");  
//printf("ant_memnet: %d\n",ant_memnet);  
  for(i=0;i<ant_memnet;i++)
  {
    sscanf(memnet[i],"%s %s %s %s",bkey1,bkey2,bkey3,bkey4);
    len = strlen(bkey2);
    printf("%s",bkey2);
    fprintf(asc,"%s",bkey2);    
    switch(len)
    {
      case 2:
      printf("   %3d",i);
      fprintf(asc,"   %3d",i);      
      break;
      case 3:
      printf("  %3d",i);
      fprintf(asc,"  %3d",i);      
      break;
      case 4:
      printf(" %3d",i);
      fprintf(asc," %3d",i);      
      break;
      case 5:
      printf("%3d",i);
      fprintf(asc,"%3d",i);      
      break;
    }
    for(j=0;j<tt;j++)
    {
      printf(" %c",tabell[j][i]);
      fprintf(asc," %c",tabell[j][i]);      
    }
    printf("\n");
    fprintf(asc,"\n");    
  }  
  fclose(asc);  
  
  
  
/*  
  printf("   ");
  for(i=0;i<tt;i++)
    printf("%3d",i);
  printf("\n");
  
  for(i=0;i<ant_memnet;i++)
  {
    printf("%3d",i);
    for(j=0;j<tt;j++)
      printf("%3c",tabell[j][i]);
    printf("\n");
  }
*/  
  *str_cnt=str_cint;
    
  return(no_of_stream_files);  
}
MakeStrFile(char netname[],char staname[],char loc[],char com[],char nystring[])
{
  int i;
  int len;
  for(i=0;i<20;i++)
    nystring[i] = ' ';
  len=strlen(netname);
  if(len > 2)
  {
     printf("Network name: %s more than 2 characters long. Revise your config file.\n",netname);
     exit(0);
  }
  if(len == 1)
    nystring[0] = netname[0];
  if(len == 2)
  {
    nystring[0] = netname[0];
    nystring[1] = netname[1];
  }
  len = strlen(staname);
  if(len > 5)
  {
     printf("Station name: %s more than 5 characters long. Revise your config file.\n",staname);
     exit(0);
  }
  switch(len)
  {
    case 1:
    nystring[3] = staname[0];
    break;
    case 2:
    nystring[3] = staname[0];
    nystring[4] = staname[1];    
    break;
    case 3:
    nystring[3] = staname[0];
    nystring[4] = staname[1];
    nystring[5] = staname[2];     
    break;
    case 4:
    nystring[3] = staname[0];
    nystring[4] = staname[1];
    nystring[5] = staname[2];
    nystring[6] = staname[3];    
    break;
    case 5:
    nystring[3] = staname[0];
    nystring[4] = staname[1];
    nystring[5] = staname[2];
    nystring[6] = staname[3];
    nystring[7] = staname[4];    
    break;    
  }
  len = strlen(loc);
  if(len != 2)
  {
     printf("Location code: %s is not 2 characters long. Revise your config file.\n",loc);
     exit(0);    
  }
  nystring[8] = loc[0];
  nystring[9] = loc[1];
  if(nystring[8] == '.')
    nystring[8] = ' ';
  if(nystring[9] == '.')
    nystring[9] = ' ';
  len = strlen(com);

  if(len != 3)
  {
     printf("Component code: %s is not 3 characters long. Revise your config file.\n",com);
     exit(0);    
  }
  nystring[10] = com[0];
  nystring[11] = com[1];
  nystring[12] = com[2];
  nystring[13] = '\0';  
 }

int main(int argc, char **argv)
{
  int  idum;
  void      *shared_memory_rt = (void *)0;
  int       shmid_rt; 
  int i;
  int q;
  int p;
  int nc;
  int ix;
  

  
  char syscmd[100];
  int  ret5;
  
  char *environment;                    // TRANSFER_BASE
  
  char  mempar[500][256];               // copy of configuration file  
  int   no_of_lines_cfg;                // number of lines in configuration file

  char  memsrv[100][100];               // servers specified in configuration file
  int   no_of_servers;                  // number of servers specified in configuration file   
 
  char  memnet[500][256];               //all network streams specified as NETWORK in conf. file
  int   no_of_nets;                     // number of networks specified in configuration file  

  char  memrec[500][256];               //all network streams specified as RECORD in conf. file
  int   no_of_rec;                      // number of networks specified in configuration file   
  
  char  stream_names[500][10];          // name of stream files
  int   no_of_stream_files;             // number of stream files
  
  int   start_net[500];                 // start index of nework
  int   stopp_net[500];                 // stop index of network 

 
  
  int   min_trg_net[500];               // minimum number of triggers per network
  int   total_streams_net;              // total number of streams networks   
  
  char streamsfull[255]; 
  char strpath[255];

  int  str_cnt;

  
  pthread_t trg_mul_thread;             // definition for TRG_MUL thread
  pthread_t buffer_shufle_thread;       // definition for BUFFER_SHUFLE thread
  pthread_t read_packets_thread1;       // definition for READ_PACKETS thread
  pthread_t check_mails_thread1;        // definition for CHECK_MAILS thread

  thdata data1;
  trgmul trginfo1;


    
  fl = FL_PRESET;                       // set default filter
  fh = FH_PRESET;                       // set default filter 
    
//------------------------------------------------------------------------
// set path to SEISAN_TOP as default
//------------------------------------------------------------------------
  topdir = (char*)getenv("SEISAN_TOP");
  if(topdir)
  {
    printf("RTDET: SEISAN_TOP:		%s\n", topdir);    
  }else{
    printf("RTDET: SEISAN_TOP not defined.\n");
    printf("Install SEISAN !\n");
    exit(0);    
  }    
//------------------------------------------------------------------------
// set path to RTQUAKE_TOP as default
//------------------------------------------------------------------------
  topdir_rt = (char*)getenv("RTQUAKE_TOP");
  if (topdir_rt)
  {
    printf("RTDET: RTQUAKE_TOP:		%s\n", topdir_rt);
  }else{
    printf("RTDET: RTQUAKE_TOP not defined\n");
    printf("Include setup_rt.bash or setup_rt.csh in your .bashrc or .csh\n");
    exit(0);      
  }
  
 
//-------------------------------------------------------------------------
// open shared memory region                                                
//--------------------------------------------------------------------------
//  if(printarg > 0)
    printf("Size shared module %d\n",(int)sizeof(rtmod));
  shmid_rt = shmget((key_t)5678, sizeof(rtmod), 0666 | IPC_CREAT);
  if(shmid_rt == -1)
  {
    printf("*****************************************************************************\n");
    printf("* RTDET: Can't allocate shared memory !                                     *\n");
    printf("* RTDET: If a new version of RTQUAKE has been installed,                    *\n");
    printf("* RTDET: follow the instructions below and restart.                         *\n");
    printf("* RTDET: Use command ipcs -m to see a list of Shared Memory Segments.       *\n");
    printf("* RTDET: Use command ipcrm -M key to remove old shared memory, where key    *\n");
    printf("* RTDET: is the number in first column in the list where status is blank.   *\n");
    printf("*****************************************************************************\n");
    sprintf(syscmd,"rtdly");
    ret5=system(syscmd);
    sprintf(syscmd,"rtnet");
    ret5=system(syscmd);    
    exit(0);
  }
  shared_memory_rt = shmat(shmid_rt, (void *)0, 0);
  if(shared_memory_rt == (void *)-1)
  {
    printf("RTDET: Can't attach shared memory\n");
    exit(0);
  }
//-------------------------------------------------------------------------
// Compute pointer to shared memory region                                 
//-------------------------------------------------------------------------
  spt=(rtmod *)shared_memory_rt;
//------------------------------------------------------------------------
// read rtquake.par if exist, otherwise use defaults
//------------------------------------------------------------------------
  Read_Parameters();  
//-------------------------------------------------------------------------
// Process command line parameters
//-------------------------------------------------------------------------
  if (parameter_proc (argc, argv) < 0)
  {
    printf("RTDET: Parameter processing failed\n\n");
    printf("       Try '-h' for detailed help\n");
    exit(0);
  }
//--------------------------------------------------------------------------
// Initialize tables and variables
//--------------------------------------------------------------------------
  for(i=0;i<MAXCHA;i++)
  {
    for(p=0;p<MAXCHA;p++)
      tabell[i][p]=' ';
  }
  for(i=0;i<MAXCHA;i++)
  {
    for(p=0;p<MAXDLY;p++)
    {
      spt->ttdly[klon][i][p] = -1;
      trgdly[i][p] = -1.0;      
    }
  }
  for(p=0;p<MAXCHA;p++)
  {
    spt->csta[klon][p]=1.0;
    spt->clta[klon][p]=1.0;
    spt->dur[klon][p]=0;
    spt->cdcavg[klon][p]=0;
    latency[p]=0;
    spt->latency[klon][p]=0;
    spt->tt_p[klon][p] = -1.0;
  }
  for(p=0;p<MAXCHA;p++)
  {
    spt->tt[klon][p]=-1;
    for(q=0;q<5;q++)
    {
      spt->age[klon][p][q] = 0;
    }
  }
  for(p=0;p<QUEUE;p++)
  {
    for(q=0;q<MAXCHA;q++)
    {
      trig_flag[q] = 0;
      trig_dur[q]=0;
    }
  }

//---------------------------------------------------------
// Set TIME_NOW initial value to current CPU time
//---------------------------------------------------------
  CURRENT_TIME();  
  
//  main_cnd=1;                          // set conditon to WAIT
//----------------------------------------------------------------
// Start trigger thread BUFFER_SHUFLE
//----------------------------------------------------------------
//  if(pthread_create(&buffer_shufle_thread,NULL,(void *)BUFFER_SHUFLE,(void *)&i))    
//  {
//    printf("RTDET: main Start BUFFER_SHUFLE thread failed: EXIT\n");
//    abort();
//  }
  
//  sleep(3);
  
//  while( main_cnd != 0 )               // wait for signal to go on
//  {
//    if(LOCK==1)
//      pthread_mutex_lock(&cnd_mtx_main);
//    pthread_cond_wait( &cnd_cnd_main, &cnd_mtx_main );
//  }
  if(printarg > 0)  
    printf("RTDET: main Ready from BUFFER_SHUFLE to go on\n");
//------------------------------------------------------------------
// check configuration file
//------------------------------------------------------------------
  if(printarg > 0)
    printf("*************Check_Config*****************************\n");
  Check_Config(cfgfile);
 //------------------------------------------------------------------
// read configuration file into memory
//------------------------------------------------------------------
  if(printarg > 0)  
    printf("*************Read_Config_to_MEM*****************************\n");  
  no_of_lines_cfg = Read_Config_to_MEM(cfgfile,mempar);
  if(printarg > 0)
    printf("number of lines in parameter file: no_of_lines_cfg %d   MEMPAR\n",no_of_lines_cfg);
  if(printarg > 0)
  {
    for(i=0;i<no_of_lines_cfg;i++)
      printf("%3d %s",i,mempar[i]);
    printf("\n");
  }
//-------------------------------------------------------------------------------
// Find all seedlink servers specified under label SERVERS in configuration file
//-------------------------------------------------------------------------------
  if(printarg > 0)
    printf("*************Find_SL_Servers*****************************\n");  
  no_of_servers = Find_SL_Servers(no_of_lines_cfg,mempar,memsrv);
  if(printarg > 0)  
    printf("number of servers specified: no_of_servers %d   MEMSRV\n",no_of_servers);
  if(printarg > 0)
  {
    for(i=0;i<no_of_servers;i++)
      printf("%3d %s",i,memsrv[i]);
  }
//------------------------------------------------------------------------------
// Find all networks specified under label NETWORK in configuration file
//------------------------------------------------------------------------------
  if(printarg > 0)
    printf("*************Find_Networks*****************************\n");
  no_of_nets = Find_Networks(no_of_lines_cfg,mempar,memnet,start_net,stopp_net,min_trg_net);
  if(printarg > 0)  
    printf("number of networks found: no_of_nets %d   MEMNET\n",no_of_nets);
  if(printarg > 0)
  {
    for(i=0;i<no_of_nets;i++)
      printf("network start_net/stopp_net %2d: %2d - %2d\n",i,start_net[i],stopp_net[i]);
  }
  total_streams_net = stopp_net[no_of_nets-1];
  if(printarg > 0)  
    printf("total_streams_net: %d\n",total_streams_net);
  if(printarg > 0)  
    printf("****************** RecStreams****************************\n");
  no_of_rec=RecStreams(no_of_lines_cfg,mempar,memrec,start_rec,stopp_rec);
  if(printarg > 0)
    printf("no_of_rec: %d\n",no_of_rec);
  if(printarg > 0)
  {
    for(i=0;i<no_of_nets;i++)
      printf("record %2d: %2d - %2d\n",i,start_rec[i],stopp_rec[i]);
  }
  read_memrec(memsrv,no_of_servers,memrec,no_of_rec,no_of_nets,start_rec,stopp_rec);
//  if(printarg > 0)  
    printf("*********************Create_Streamfiles*******************\n");
  no_of_stream_files=Create_Streamfiles(total_streams_net,min_trg_net,no_of_nets,no_of_servers,start_net,stopp_net,memsrv,memnet,stream_names,&str_cnt);
  printf("STR_CNT: %d\n",str_cnt);
//  if(printarg > 0)
//  {
  for(i=0;i<no_of_stream_files;i++)
    printf("%2d %s\n",i,stream_names[i]);
//  }
//----------------------------------------------------------------
// Read memsrv 
//----------------------------------------------------------------
  read_servers(no_of_servers,memsrv);
  if(printarg > 0)
  {
    for(p=0;p<no_of_stream_files;p++)
      printf("%s %s\n",streams[p],slserv[p]);
  }
//----------------------------------------------------------------
// Read streams files specified in configfile
//----------------------------------------------------------------
  if(printarg > 0)
  {
    printf("**************************************************************************\n");
    printf("Read input streams specified in configfile:\n");
  }
  for(p=0;p<no_of_stream_files;p++)
  {
    sprintf(strpath,"%s/par/%s/%s",topdir_rt,cfgfile,streams[p]);
    if(printarg > 0)    
      printf("Read streams-file: %s\n",strpath);
    read_inputstreams(strpath,p);
  }
  if(printarg > 0)  
    printf("total number of input-streams  stream_count: %d\n",stream_count);
//  if(printarg > 0)
//  {
    printf("allstreams:\n");
    for(p=0;p<stream_count;p++)
      printf("%3d %s\n",p,allstreams[p]);
//  }
//------------------------------------------------------------------------------------
// Create detection tables
//------------------------------------------------------------------------------------
  if(printarg > 0)
    printf("**********************create_detectiontable*****************************************************\n");
  create_detectiontable();
//----------------------------------------------------------------
// Start threads
//----------------------------------------------------------------
  if(printarg > 0)  
    printf("NO_OF_STREAM_FILES: %d\n",no_of_stream_files);

  
  
  main_cnd=1;                          // set conditon to WAIT
//----------------------------------------------------------------
// Start trigger thread BUFFER_SHUFLE
//----------------------------------------------------------------
  if(pthread_create(&buffer_shufle_thread,NULL,(void *)BUFFER_SHUFLE,(void *)&i))    
  {
    printf("RTDET: main Start BUFFER_SHUFLE thread failed: EXIT\n");
    abort();
  }
  

  
  while( main_cnd != 0 )               // wait for signal to go on
  {
    if(LOCK==1)
      pthread_mutex_lock(&cnd_mtx_main);
    pthread_cond_wait( &cnd_cnd_main, &cnd_mtx_main );
  }  
  
//   sleep(3); 
  
  
  
  
  for(p=0;p<no_of_stream_files;p++)
  {
//----------------------------------------------------------------
// Prepare structure for threads
//----------------------------------------------------------------
    data1.thread_no = p+1;    
    strcpy(data1.ipaddr, slserv[p]);    
    strcpy(data1.streams,streams[p]);    
    strcpy(data1.stations,stations[p]);    
    data1.no_comp = 0;
    data1.no_str = str_cnt;

    pthread_create (&read_packets_thread1, NULL, (void *) &READ_PACKETS, (void *) &data1);
    sleep(2);
  }
  
  main_cnd=1;                          // set conditon to WAIT
//----------------------------------------------------------------
// Start trigger thread TRG_MUL
//----------------------------------------------------------------

  if(mintrg == 0)                    // Start all subnet trigger threads
  {  
    for(p=0;p<no_of_nets;p++)
    {
      trginfo1.thread_no           = p+1;
      trginfo1.antkan              = kanaler_hver_stream[p];
      trginfo1.fra                 = start_net[p];
      trginfo1.til                 = stopp_net[p];
      trginfo1.minimum_no_triggers = min_trg_net[p];
      pthread_create(&trg_mul_thread, NULL, (void *) &TRG_MUL,(void *) &trginfo1);
      printf("\nRTDET: TRG_MUL thread: %2d started. streams: from: %2d to: %2d mintrg: %2d\n",trginfo1.thread_no,trginfo1.fra,trginfo1.til,trginfo1.minimum_no_triggers);
      sleep(1);    
    }
  }else{                            // Start trigger thread to do network trigger
      trginfo1.thread_no           = 1;
      trginfo1.antkan              = no_of_rec;
      trginfo1.fra                 = 0;
      trginfo1.til                 = stopp_net[no_of_nets-1];
      trginfo1.minimum_no_triggers = mintrg;
      pthread_create(&trg_mul_thread, NULL, (void *) &TRG_MUL,(void *) &trginfo1);
      printf("\nRTDET: TRG_MUL thread: %2d started. streams: from: %2d to: %2d\n",trginfo1.thread_no,trginfo1.fra,trginfo1.til);       
//      sleep(1);
  }
    pthread_create (&read_packets_thread1, NULL, (void *) &CHECK_MAILS, (void *) &data1);
  
  for(;;)                              // let main take siesta
  {
    sleep(1);
  }  
  return 0;
}				/* End of main() */



/***************************************************************************
 * packet_handler():
 * Process a received packet based on packet type.
 ***************************************************************************/
static int
packet_handler (char *msrecord, int packet_type, int seqnum, int packet_size,SLCD * slconn,int stream_count,int sseismo[MAXCHA][3000],int ns[],int sr[])
{
  static SLMSrecord * msr = NULL;
  int trace;
  int i;
  double dtime;			/* Epoch time */
  double secfrac;		/* Fractional part of epoch time */
  time_t itime;			/* Integer part of epoch time */
  char timestamp[20];
  struct tm *timep;

  /* The following is dependent on the packet type values in libslink.h */
  char *type[]  = { "Data", "Detection", "Calibration", "Timing",
		    "Message", "General", "Request", "Info",
                    "Info (terminated)", "KeepAlive" };

  /* Build a current local time string */

  dtime   = sl_dtime ();
  secfrac = (double) ((double)dtime - (int)dtime);
  itime   = (time_t) dtime;
  timep   = localtime (&itime);
  sprintf (timestamp,  "%04d.%03d.%02d:%02d:%02d.%01.0f",
	    timep->tm_year + 1900, timep->tm_yday + 1, timep->tm_hour,
	    timep->tm_min, timep->tm_sec, secfrac);

  /* Process waveform data */
  if ( packet_type == SLDATA )
    {
      sl_log (0, 1, "%s, seq %d, Received %s blockette:\n",
	      timestamp, seqnum, type[packet_type]);

      sl_msr_parse (slconn->log, msrecord, &msr, 1, 0);

      if ( verbose || ppackets )
	sl_msr_print (slconn->log, msr, ppackets);
    }
  else if ( packet_type == SLKEEP )
    {
      sl_log (0, 2, "Keep alive packet received\n");
    }
  else
    {
      sl_log (0, 1, "%s, seq %d, Received %s blockette\n",
	      timestamp, seqnum, type[packet_type]);
    }

  /* Write packet to dumpfile if defined */
  if ( dumpfile )
    {
      if (fwrite (msrecord, packet_size, 1, outfile) <= 0)
	sl_log (2, 0, "fwrite(): error writing data to %s\n", dumpfile);
//      memcpy(buf,msrecord,seed_size);
	sl_msr_parse (slconn->log, msrecord, &msr, 1, 1);
//        trace=unpack_samples (msr);
        return(1);
    }
/* Plot selected data */
if( location )
{
//  printf("%s, seq %d, Received %s blockette:\n",timestamp, seqnum, type[packet_type]);
//  printf("smp:%s\n",timestamp);

  sl_msr_parse (slconn->log, msrecord, &msr, 1, 1);
  if(msr->unpackerr != MSD_UNKNOWNFORMAT)
  {
    trace=unpack_samples (msr,seqnum,stream_count,sseismo,ns,sr);
    
    for(i=0;i<MAXCHA;i++)
    {
      if(tabell[trace][i] == 'X')
        sprintf(tid[i],"%s",timestamp);
    }    
    

    return(trace);
  }else{
	printf("Trouble unpacking buffer\n");
	return(0);
  }
}
return(0);

}				/* End of packet_handler() */

/***************************************************************************
 * print_samples:
 * Print samples in the supplied MSrecord with a simple format.
 ***************************************************************************/
int
unpack_samples (SLMSrecord *msr, int seqnum,int lno_str,int sseismo[MAXCHA][3000],int ns[],int sr[])
{
  char tempo[20];
  char search[20];
  char tmp[80];
  char dd[80];

  int iryrn;
  int irday;
  int irhrn;
  int irmin;

  int j,pp,kan;
  int retur=-1;
  int cnt,p,l,ret;
  float   eqavst;  
  for(j=0;j<20;j++)
  {
    search[j]='\0';
    current_station[j]='\0';
  }
  sprintf(tempo,"%s",msr->fsdh.station);
  strncpy(search,tempo,10);
  for(j=0;j<5;j++)
    current_station[j]=search[j];

//printf("search: %s\n",search);
//  if(search[5] == ' ')search[5]='0';
//  if(search[6] == ' ')search[6]='0';
//  printf("unpack: %3d\n",stream_count);
//  printf("%2d %s\n",stream_count,msr->fsdh.station);   
  for(l=0;l<stream_count;l++)
  {
//    printf("%s  %s\n",search,allstreams[l]);
    for(pp=0;pp<10;pp++)
      dd[pp]=allstreams[l][pp+3];
    dd[pp]='\0';
    ret=strcmp(search,dd);
    if(ret == 0)                   // component found
    {
//printf("FOUND\n");
      retur=l;
      if ( msr->datasamples != NULL )            //EXTRACT DATA FROM MINISEED BUFFER
      {
        for(kan=0;kan<MAXCHA;kan++)
        {
	  

	  
	  
	  
	  
	  
          if(tabell[retur][kan] == 'X')
	  {
	    
//	  printf("1                %d     %d      %d\n",msr->numsamples,msr->fsdh.samprate_fact,msr->fsdh.samprate_mult);	    
	    
        if(msr->fsdh.samprate_fact > 0 && msr->fsdh.samprate_mult < 0)
		  msr->fsdh.samprate_fact = (-1 * msr->fsdh.samprate_fact)/msr->fsdh.samprate_mult;	    
	    
//	    printf("kanal %2d->%2d  fl: %5.1f  fh: %5.1f\n",retur,kan,fl_par[kan],fh_par[kan]);
            ns[kan]   = msr->numsamples;
	    rns[kan]  = ns[kan];

            ryrn[kan] = msr->fsdh.start_time.year;
            rday[kan] = msr->fsdh.start_time.day;
            rhrn[kan] = msr->fsdh.start_time.hour;
            rmin[kan] = msr->fsdh.start_time.min;
            risec[kan]= msr->fsdh.start_time.sec;
            rsecs[kan]= msr->fsdh.start_time.fract; 
            sr[kan]   = msr->fsdh.samprate_fact;
	    rsr[kan]=sr[kan];
	    
//	  printf("2                %d     %d      %d\n",msr->numsamples,msr->fsdh.samprate_fact,msr->fsdh.samprate_mult);	    
	    

            iryrn=ryrn[kan];
            irday=rday[kan];
            irhrn=rhrn[kan];
            irmin=rmin[kan];

            sprintf(tmp,"%4d %3d %2d:%2d:%2d.%4d",iryrn,irday,irhrn,irmin,risec[kan],rsecs[kan]);
            if(tmp[21]==' ')tmp[21]='0';
            if(tmp[20]==' ')tmp[20]='0';
            if(tmp[19]==' ')tmp[19]='0';
            if(tmp[18]==' ')tmp[18]='0';
            if(tmp[15]==' ')tmp[15]='0';

            sprintf(rtid[kan],"%s",tmp);
            sprintf(spt->rtid[klon][kan],"%s",tmp);
	    if(msr->fsdh.dq_flags == 0)
	    {
	      time_quality[kan]=0;
	    }else{
	      time_quality[kan]=1;
	    }
   
            for(pp=0;pp<22;pp++)
              if(tmp[pp]==' ')tmp[pp]='0';   


/* COMPUTE NEW FILTER COEF. EACH BUFFER. THEY MAY HAVE DIFFERENT SAMPLERATE */
            eqavst=1.0/(float)msr->fsdh.samprate_fact;
            orden=4;
            if(fl_par[kan] != 0.0 && fh_par[kan] != 0.0)
            {
              design(orden,"BP","BU",30.0,0.3,fl_par[kan],fh_par[kan],eqavst);
              for(j=0;j<(nsects*3+1);j++)
              {
                snc[kan][j]=sn[j];
                sdc[kan][j]=sd[j];
              }
              cset[kan]=nsects;
            }
            for ( cnt = 0; cnt < ns[kan]; cnt++ )      // EXTRACT DATA SAMPLES
              sseismo[kan][cnt]=*(msr->datasamples + cnt);	      
	  }
	}
        return(retur);
      }    // if(msr->data.........
    }      // if(ret......
  }        // for(no_to_plot........ 
//  		if(l==14)
//			printf("unpack2 FAC:\n");
  return(retur);
}  /* End of print_samples() */

/***************************************************************************
 * parameter_proc:
 *
 * Process the command line parameters.
 *
 * Returns 0 on success, and -1 on failure
 ***************************************************************************/
int
parameter_proc (int argcount, char **argvec)
{
  int optind;
  int error = 0;
  char tm[80];  
  char streamsfull[80]; 
  char *multiselect = 0;
  char *selectors   = 0;

  if (argcount <= 1)
    error++;
  if(printarg > 0)
    printf("argcount: %d\n",argcount);

  /* Process all command line arguments */
  for (optind = 1; optind < argcount; optind++)
  {
//    printf("OPTIND: %d\n",optind);
    if (strcmp (argvec[optind], "-V") == 0)
    {
//      fprintf(stderr, "%s version: %s\n", PACKAGE, VERSION);
      exit (0);
    }
//    else if (strcmp (argvec[optind], "-h") == 0)
//    {
//      usage();
//      exit (0);
//    }
    else if (strcmp (argvec[optind], "-prt") == 0)
    {
      printarg = atoi (argvec[++optind]);
      if(printarg > 0)
        printf("printarg: %d\n",printarg);
    }
/*    
    else if (strcmp (argvec[optind], "-dbn") == 0)         // database name
    {
      strcpy(dbname, argvec[++optind]);
      if(printarg > 0)      
        printf("database name: %s\n",dbname);
    }
*/
    else if (strcmp (argvec[optind], "-sfl") == 0)         // s-file path
    {
      strcpy(sfilepath, argvec[++optind]);
      if(printarg > 0)      
        printf("s-file path: %s\n",sfilepath);
    }
    else if (strcmp (argvec[optind], "-cfg") == 0)         // input config file
    {
      strcpy(cfgfile, argvec[++optind]);
      if(printarg > 0)      
        printf("Config: %s\n",cfgfile);
    }    
/*
    else if (strcmp (argvec[optind], "-trg") == 0)         // minimum number of triggers
    {
      mintrg=atoi (argvec[++optind]);
      if(printarg > 0)      
        printf("mintrg= %d\n",mintrg);
    }
*/
    else if (strcmp (argvec[optind], "-pre") == 0)         // pre-event memory in seconds
    {
      preevent = atoi (argvec[++optind]);
      if(printarg > 0)      
        printf("preevent= %d\n",preevent);
    }
    else if (strcmp (argvec[optind], "-pst") == 0)         // post-event memory in seconds
    {
      postevent = atoi (argvec[++optind]);
      if(printarg > 0)      
        printf("postevent= %d\n",postevent);
    }

    else if (strcmp (argvec[optind], "-par") == 0)         // parameter-set
    {
      klon = atoi(argvec[++optind]);
      if(printarg > 0)      
        printf("klon: %d\n",klon);
    }
/*
    else if (strcmp (argvec[optind], "-tgg") == 0)         // events directory
    {
      dbase_switch = 1;
      strcpy(trgdir, argvec[++optind]);
      if(printarg > 0)      
        printf("events directory: %s\n",trgdir);
    }
*/
      else if (strcmp (argvec[optind], "-aut") == 0)
	{
	  autolocate = atoi (argvec[++optind]);
          if(printarg > 0)
            printf("autolocate: %d\n",autolocate);
	}

    }


/*
  if ( strlen(trgdir) )
  {
    sprintf(trgpath,"%s/%s",topdir,trgdir);
    printf("RTDET: Specified events path:   %s\n",trgpath);
  }else{
    sprintf(trgpath,"%s/WAV",topdir);
    printf("RTDET: Default events path:     %s\n",trgpath);
  }
*/  
/*******************************************************/
/*                SEISAN DATABASE NAME                 */
/*******************************************************/ 
/*
if ( strlen(dbname) )
  {
    printf("RTDET: Specified database name: %s\n",dbname);
  }else{
    sprintf(streamsfull,"TST__");
    strcpy(dbname, streamsfull);
    printf("RTDET: Default database name:   %s\n",dbname);
  }
*/
/*******************************************************/
/*                SEISAN S-FILE PATH                   */
/*******************************************************/ 
  if ( strlen(sfilepath) )
  {
    sprintf(streamsfull,"%s",sfilepath);
    strcpy(sfilepath, streamsfull);
    printf("RTDET: Specified s-file path:%s\n",sfilepath);
  }else{
    sprintf(streamsfull,"%s/REA",topdir);
    strcpy(sfilepath, streamsfull);
    printf("RTDET: Default s-file path:	%s\n",sfilepath);
  }
  

  
  return 0;
}				/* End of parameter_proc() */

//*=========================================================================      
//*                                                                               
//* Routine to convert from day-of-year to date                                   
//*                                                         Leif Kvamme 12-1-85   
void DTE (DOY,DAY,MON,YR)                                          
int DOY;
int *DAY;
int *MON;
int YR;
{
int MTH[14],J,M,N;
for(J=1;J<8;J=J+2)
    MTH[J] = 31;
for(J=8;J<13;J=J+2)
    MTH[J] = 31;
MTH[2] = 28;
MTH[4] = 30;
MTH[6] = 30;
MTH[9] = 30;
MTH[11]= 30;
if ((YR%4) == 0) MTH[2] = 29;
M = 0;                                                                    
for(J=1;J<13;J++)
{
    M = M + MTH[J];
    N = DOY - M;                                                              
    if (N <= 0)
    {                                                       
        *MON = J;
        *DAY = N + MTH[J];                                                     
        goto four;                                                               
    }
}
four:                                                                   
J=0;
}
void TIMSEC (YR,MTH,DAY,HR,MIN,SECS,MSECS)                         
int YR;
int MTH;
int DAY;
int HR;
int MIN;
float SECS;
double *MSECS;                         /* total seconds to be returned      */
{
int DYR;                               /* flag for leap year                */
int IYR;                               /* number of leap-years since 1900   */
int YDY;                               /* number of days in current year    */

if(YR <= 50) YR=YR+100;                /* check for 2000 or more in 2 digits*/

if(YR >= 1900) YR=YR - 1900;
DYR = 0;
if((YR % 4) == 0) DYR = 1;
IYR = YR/4 - DYR;
//                -- Seconds to beginning of     
*MSECS = (float)(IYR*366) + (float)((YR-IYR)*365);
//                -- current year                
*MSECS = *MSECS*86400.0;
//                -- January                     
if (MTH == 1) YDY = DAY;
//                -- February                    
if (MTH == 2) YDY = DAY + 31;
//                -- ....                        
if (MTH == 3) YDY = DAY + DYR + 59;       
if (MTH == 4) YDY = DAY + DYR + 90;                                     
if (MTH == 5) YDY = DAY + DYR + 120;                                    
if (MTH == 6) YDY = DAY + DYR + 151;                                    
if (MTH == 7) YDY = DAY + DYR + 181;                                    
if (MTH == 8) YDY = DAY + DYR + 212;                                    
if (MTH == 9) YDY = DAY + DYR + 243;                                    
if (MTH ==10) YDY = DAY + DYR + 273;                                    
if (MTH ==11) YDY = DAY + DYR + 304;                                    
if (MTH ==12) YDY = DAY + DYR + 334;                                    
*MSECS = *MSECS + (float)(YDY*86400 + HR*3600 + MIN*60) + SECS;
}
/*  Subroutine to design IIR digital filters from analog prototypes. */
/*  Input Arguments: */
/*  ---------------- */
/*    IORD                Filter order (10 MAXIMUM) */
/*    TYPE                Character*2 variable containing filter type */
/*                          LOWPASS (LP) */
/*                          HIGHPASS (HP) */
/*                          BANDPASS (BP) */
/*                          BANDREJECT (BR) */
/*   APROTO              Character*2 variable designating analog prototype*/
/*                          Butterworth (BU) */
/*                          Bessel (BE) */
/*                          Chebyshev Type I (C1) */
/*                          Chebyshev Type II (C2) */
/*    A                   Chebyshev stopband attenuation factor */
/*    TRBNDW              Chebyshev transition bandwidth (fraction of */
/*                          lowpass prototype passband width) */
/*    FL                  Low-frequency cutoff */
/*    FH                  High-frequency cutoff */
/*    TS                  Sampling interval (in seconds) */
/*  Output Arguments: */
/*  ----------------- */
/*    SN                  Array containing numerator coefficients of */
/*                        second-order sections packed head-to-tail. */
/*    SD                  Array containing denominator coefficients */
/*                        of second-order sections packed head-to-tail. */

void design( iord, type,aproto,  a,trbndw,  fl,  fh,  ts)
int iord;
char *type;
char *aproto;
float a;
float trbndw;
float fl;
float fh;
float ts;
{
    /* System generated locals */
    float r__1;

    /* Local variables */
    complex p[10], z[10];
    char stype[3*10];
    float omegar, ripple;
    float fhw, eps, flw, dcvalue;

    /*  Analog prototype selection */

    if (strncmp(aproto, "BU", 2) == 0) {
    buroots(p, stype, &dcvalue, iord);
    } else if (strncmp(aproto, "BE", 2) == 0) {
    beroots(p, stype, &dcvalue, iord);
    } else if (strncmp(aproto, "C1", 2) == 0) {
    chebparm(a, trbndw, iord, &eps, &ripple);
    c1roots(p, stype, &dcvalue, iord, &eps);
    } else if (strncmp(aproto, "C2", 2) == 0) {
    omegar = trbndw + (float)1.;
    c2roots(p, z, stype, &dcvalue, iord, a, omegar);
    }

    /*  Analog mapping selection */

    if (strncmp(type, "BP", 2) == 0) {
    r__1 = fl * ts / (float)2.;
    flw = warp(&r__1, &c_b12);
    r__1 = fh * ts / (float)2.;
    fhw = warp(&r__1, &c_b12);
    lptbp(p, z, stype, &dcvalue, &flw, &fhw);
    } else if (strncmp(type, "BR", 2) == 0) {
    r__1 = fl * ts / (float)2.;
    flw = warp(&r__1, &c_b12);
    r__1 = fh * ts / (float)2.;
    fhw = warp(&r__1, &c_b12);
    lptbr(p, z, stype, &dcvalue, &flw, &fhw, &sn[1], &sd[1]);
    } else if (strncmp(type, "LP", 2) == 0) {
    r__1 = fh * ts / (float)2.;
    fhw = warp(&r__1, &c_b12);
    lp(p, z, stype, &dcvalue, &sn[1], &sd[1]);
    cutoffs(&sn[1], &sd[1], &fhw);
    } else if (strncmp(type, "HP", 2) == 0) {
    r__1 = fl * ts / (float)2.;
    flw = warp(&r__1, &c_b12);
    lpthp(p, z, stype, &dcvalue, &sn[1], &sd[1]);
    cutoffs(&sn[1], &sd[1], &flw);
    }

    /*  Bilinear analog to digital transformation */
    bilin2(&sn[1], &sd[1]);

    return;
}

/* BUROOTS -- SUBROUTINE TO COMPUTE BUTTERWORTH POLES FOR */
/*   NORMALIZED LOWPASS FILTER */
/* LAST MODIFIED:  SEPTEMBER 7, 1990 */
/*  OUTPUT ARGUMENTS: */
/*  ----------------- */
/*      P              COMPLEX ARRAY CONTAINING POLES */
/*                       CONTAINS ONLY ONE FROM EACH */
/*                       COMPLEX CONJUGATE PAIR, AND */
/*                       ALL REAL POLES */
/*      RTYPE          CHARACTER ARRAY INDICATING 2ND ORDER SECTION */
/*                       TYPE: */
/*                         (SP)  SINGLE REAL POLE */
/*                         (CP)  COMPLEX CONJUGATE POLE PAIR */
/*                         (CPZ) COMPLEX CONJUGATE POLE-ZERO PAIRS */
/*      DCVALUE        MAGNITUDE OF FILTER AT ZERO FREQUENCY */
/*  INPUT ARGUMENTS: */
/*  ---------------- */
/*      IORD           DESIRED FILTER ORDER */
int buroots(p,rtype, dcvalue, iord)
complex *p;
char *rtype;
float *dcvalue;
int iord;
{
    /* System generated locals */
    int i__1, i__2;
    double d__1, d__2;
    complex q__1;

    /* Local variables */
    int half, k;
    float angle, pi;

    /* Parameter adjustments */
    rtype -= 3;
    --p;

    /* Function Body */
    pi = (float)3.14159265;

    half = iord / 2;

    /* TEST FOR ODD ORDER, AND ADD POLE AT -1 */

    nsects = 0;
    if (half << 1 < iord) {
    p[1].r = (float)-1., p[1].i = (float)0.;
    strncpy(rtype + 3, "SP", 2);
    nsects = 1;
    }
    i__1 = half;
    for (k = 1; k <= i__1; ++k) {
    angle = pi * ((float) ((k << 1) - 1)/(float) (iord << 1)+(float).5);
    ++(nsects);
    i__2 = nsects;
    d__1 = cos(angle);
    d__2 = sin(angle);
    q__1.r = d__1, q__1.i = d__2;
    p[i__2].r = q__1.r, p[i__2].i = q__1.i;
        strncpy(rtype + nsects * 3, "CP", 2);
    }
    *dcvalue = (float)1.;
    return TRUE;
}

/*  CHEBPARM - Calculates Chebyshev type I and II design parameters */
/*  INPUT ARGUMENTS */
/*  --------------- */
/*       A                Desired stopband attenuation */
/*                          i.e. max stopband amplitude is 1/ATTEN */
/*       TRBNDW           Transition bandwidth between stop and passbands */
/*                          as a fraction of the passband width */
/*       IORD             Filter order (number of poles) */
/*  OUTPUT ARGUMENTS */
/*  ---------------- */
/*       EPS              Chebyshev passband parameter */
/*       RIPPLE           Passband ripple */

static int chebparm(a, trbndw, iord, eps, ripple)
float a, trbndw;
int iord;
float *eps, *ripple;
{
    /* System generated locals */
    float r__1, r__2;

    /* Local variables */
    float g, alpha, omegar;

    omegar = trbndw + 1.;
    /* Computing 2nd power */
    r__2 = omegar;
    r__1 = omegar + sqrt(r__2 * r__2 - 1.);
    alpha = pow((double)r__1, (double)iord);
    /* Computing 2nd power */
    r__1 = alpha;
    g = (r__1 * r__1 + (float)1.) / (alpha * (float)2.);
    /* Computing 2nd power */
    r__1 = a;
    *eps = sqrt(r__1 * r__1 - (float)1.) / g;
    /* Computing 2nd power */
    r__1 = *eps;
    *ripple = (float)1. / sqrt(r__1 * r__1 + (float)1.);

    return TRUE;
}

/* C1ROOTS -- SUBROUTINE TO COMPUTE CHEBYSHEV TYPE I POLES FOR */
/*   NORMALIZED LOWPASS FILTER */
/* LAST MODIFIED:  SEPTEMBER 7, 1990 */
/*  OUTPUT ARGUMENTS: */
/*  ----------------- */
/*      P              COMPLEX ARRAY CONTAINING POLES */
/*                       CONTAINS ONLY ONE FROM EACH */
/*                       COMPLEX CONJUGATE PAIR, AND */
/*                       ALL REAL POLES */
/*      RTYPE          CHARACTER ARRAY INDICATING 2ND ORDER SECTION */
/*                       TYPE: */
/*                         (SP)  SINGLE REAL POLE */
/*                         (CP)  COMPLEX CONJUGATE POLE PAIR */
/*                         (CPZ) COMPLEX CONJUGATE POLE-ZERO PAIRS */
/*      DCVALUE        RESPONSE OF FILTER AT ZERO FREQUENCY */
/*  INPUT ARGUMENTS: */
/*  ---------------- */
/*      IORD           DESIRED FILTER ORDER */
/*      EPS            CHEBYSHEV PAR RELATED TO PASSBAND RIPPLE */

static int c1roots(p, rtype, dcvalue, iord, eps)
complex *p;
char *rtype;
float *dcvalue;
int iord;
float *eps;
{
    /* System generated locals */
    int i__1, i__2;
    float r__1;
    double d__1;
    complex q__1;

    /* Local variables */
    int half;
    float c;
    int i;
    float gamma, s, angle, omega, sigma, pi;

    /* Parameter adjustments */
    rtype -= 3;
    --p;

    /* Function Body */
    pi = (float)3.14159265;
    half = iord / 2;

    /*  INTERMEDIATE DESIGN PARS */

    gamma = (sqrt(*eps * *eps + (float)1.) + (float)1.) / *eps;
    gamma = log(gamma) / (float) (iord);
    gamma = exp(gamma);
    s = (gamma - (float)1. / gamma) * (float).5;
    c = (gamma + (float)1. / gamma) * (float).5;

    /*  CALCULATE POLES */

    nsects = 0;
    i__1 = half;
    for (i = 1; i <= i__1; ++i) {
    strncpy(rtype + i * 3, "CP", 2);
    angle = (float) ((i << 1) - 1) * pi / (float) (iord << 1);
    sigma = -(double)s * sin(angle);
    omega = c * cos(angle);
    i__2 = i;
    q__1.r = sigma, q__1.i = omega;
    p[i__2].r = q__1.r, p[i__2].i = q__1.i;
    ++(nsects);
    }
    if (half << 1 < iord) {
    strncpy(rtype + (half + 1) * 3, "SP", 2);
    i__1 = half + 1;
    d__1 = -(double)s;
    q__1.r = d__1, q__1.i = (float)0.;
    p[i__1].r = q__1.r, p[i__1].i = q__1.i;
    ++(nsects);
    *dcvalue = (float)1.;
    } else {
    /* Computing 2nd power */
    r__1 = *eps;
    *dcvalue = (float)1. / sqrt(r__1 * r__1 + 1);
    }
    return TRUE;
}

/* C2ROOTS -- SUBROUTINE TO COMPUTE ROOTS FOR NORMALIZED LOWPASS */
/*   CHEBYSHEV TYPE 2 FILTER */
/* LAST MODIFIED:  SEPTEMBER 7, 1990 */
/*  OUTPUT ARGUMENTS: */
/*  ----------------- */
/*      P              COMPLEX ARRAY CONTAINING POLES */
/*                       CONTAINS ONLY ONE FROM EACH */
/*                       COMPLEX CONJUGATE PAIR, AND */
/*                       ALL REAL POLES */
/*      Z              COMPLEX ARRAY CONTAINING ZEROS */
/*                       CONTAINS ONLY ONE FROM EACH */
/*                       COMPLEX CONJUGATE PAIR, AND */
/*                       ALL REAL ZEROS */
/*      RTYPE          CHARACTER ARRAY INDICATING 2ND ORDER SECTION */
/*                       TYPE: */
/*                         (SP)  SINGLE REAL POLE */
/*                         (CP)  COMPLEX CONJUGATE POLE PAIR */
/*                         (CPZ) COMPLEX CONJUGATE POLE-ZERO PAIRS */
/*      DCVALUE        MAGNITUDE OF FILTER AT ZERO FREQUENCY */
/*  INPUT ARGUMENTS: */
/*  ---------------- */
/*      IORD           DESIRED FILTER ORDER */
/*      A              STOPBAND ATTENUATION FACTOR */
/*      OMEGAR         CUTOFF FREQUENCY OF STOPBAND */
/*                     PASSBAND CUTOFF IS AT 1.0 HERTZ */

static int c2roots(p, z, rtype, dcvalue, iord, a, omegar)
complex *p, *z;
char *rtype;
float *dcvalue;
int iord;
float a, omegar;
{
    /* System generated locals */
    int i__1, i__2;
    double d__1;
    complex q__1;

    /* Local variables */
    int half;
    float beta, c;
    int i;
    float gamma, s, alpha, angle, omega, sigma, denom, pi;

    /* Parameter adjustments */
    rtype -= 3;
    --z;
    --p;

    /* Function Body */
    pi = (float)3.14159265;
    half = iord / 2;

/*  INTERMEDIATE DESIGN PARS */

    gamma = a + sqrt(a * a - (float)1.);
    gamma = log(gamma) / (float) (iord);
    gamma = exp(gamma);
    s = (gamma - (float)1. / gamma) * (float).5;
    c = (gamma + (float)1. / gamma) * (float).5;
    nsects = 0;
    i__1 = half;
    for (i = 1; i <= i__1; ++i) {

/*  CALCULATE POLES */

    strncpy(rtype + i * 3, "CPZ", 3);
    angle = (float) ((i << 1) - 1) * pi / (float) (iord << 1);
    alpha = -(double)s * sin(angle);
    beta = c * cos(angle);
    denom = alpha * alpha + beta * beta;
    sigma = omegar * alpha / denom;
    omega = -(double)(omegar) * beta / denom;
    i__2 = i;
    q__1.r = sigma, q__1.i = omega;
    p[i__2].r = q__1.r, p[i__2].i = q__1.i;

/*  CALCULATE ZEROS */

    omega = omegar / cos(angle);
    i__2 = i;
    q__1.r = (float)0., q__1.i = omega;
    z[i__2].r = q__1.r, z[i__2].i = q__1.i;
    ++(nsects);
    }

/*  ODD-ORDER FILTERS */

    if (half << 1 < iord) {
    strncpy(rtype + (half + 1) * 3, "SP", 2);
    i__1 = half + 1;
    d__1 = -(double)(omegar) / s;
    q__1.r = d__1, q__1.i = (float)0.;
    p[i__1].r = q__1.r, p[i__1].i = q__1.i;
    ++(nsects);
    }

/*  DC VALUE */

    *dcvalue = 1.;
    return TRUE;
}

/* Subroutine to convert an prototype lowpass filter to a bandpass filter via
*/
/*    the analog polynomial transformation.  The lowpass filter is */
/*   described in terms of its poles and zeros (as input to this routine).*/
/*    The output consists of the parameters for second order sections. */
/*  Input Arguments: */
/*  ---------------- */
/*    P                       Array containing poles */
/*    Z                       Array containing zeros */
/*    RTYPE                   Character array containing type information */
/*                              (SP) single real pole  or */
/*                              (CP) complex conjugate pole pair  or */
/*                              (CPZ) complex conjugate pole/zero pairs */
/*    DCVALUE                 Zero frequency value of filter */
/*    FL                      Low-frequency cutoff */
/*    FH                      High-frequency cutoff */
/*  Output Arguments: */
/*  ----------------- */
/*    SN                      Numerator polynomials for second order */
/*                              sections. */
/*    SD                      Denominator polynomials for second order */
/*                              sections. */
/*                              This subroutine doubles the number of */
/*                              sections. */

static int lptbp(p, z, rtype, dcvalue, fl, fh)
complex *p, *z;
char *rtype;
float *dcvalue;
float *fl, *fh;
{
    /* System generated locals */
    int i__1, i__2, i__3, i__4, i__5, i__6, i__7;
    double d__1;
    complex q__1, q__2, q__3, q__4, q__5, q__6, q__7, q__8, q__9, q__10;

    /* Local variables */
    int iptr;
    float a, b;
    complex h;
    int i, n;
    complex s;
    float scale;
    complex ctemp, p1, p2;
    float twopi;
    complex z1, z2;
    float pi;

    /* Parameter adjustments */
    rtype -= 3;
    --z;
    --p;

    /* Function Body */
    pi = (float)3.14159265;
    twopi = pi * (float)2.;
    a = twopi * twopi * *fl * *fh;
    b = twopi * (*fh - *fl);

    n = nsects;
    nsects = 0;
    iptr = 1;
    i__1 = n;
    for (i = 1; i <= i__1; ++i) {
    if (strncmp(rtype + i * 3, "CPZ", 3) == 0) {
        i__2 = i;
        q__3.r = b * z[i__2].r, q__3.i = b * z[i__2].i;
            q__2 = cpowi(q__3, 2);
        d__1 = a * (float)4.;
        q__1.r = q__2.r - d__1, q__1.i = q__2.i;
        ctemp.r = q__1.r, ctemp.i = q__1.i;
            q__1 = csqrt1(ctemp);
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        i__2 = i;
        q__3.r = b * z[i__2].r, q__3.i = b * z[i__2].i;
        q__2.r = q__3.r + ctemp.r, q__2.i = q__3.i + ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        z1.r = q__1.r, z1.i = q__1.i;
        i__2 = i;
        q__3.r = b * z[i__2].r, q__3.i = b * z[i__2].i;
        q__2.r = q__3.r - ctemp.r, q__2.i = q__3.i - ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        z2.r = q__1.r, z2.i = q__1.i;
        i__2 = i;
        q__3.r = b * p[i__2].r, q__3.i = b * p[i__2].i;
            q__2 = cpowi(q__3, 2);
        d__1 = a * (float)4.;
        q__1.r = q__2.r - d__1, q__1.i = q__2.i;
        ctemp.r = q__1.r, ctemp.i = q__1.i;
            q__1 = csqrt1(ctemp);
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        i__2 = i;
        q__3.r = b * p[i__2].r, q__3.i = b * p[i__2].i;
        q__2.r = q__3.r + ctemp.r, q__2.i = q__3.i + ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p1.r = q__1.r, p1.i = q__1.i;
        i__2 = i;
        q__3.r = b * p[i__2].r, q__3.i = b * p[i__2].i;
        q__2.r = q__3.r - ctemp.r, q__2.i = q__3.i - ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p2.r = q__1.r, p2.i = q__1.i;
            q__2 = conjg(z1);
        q__1.r = z1.r * q__2.r - z1.i * q__2.i, q__1.i = z1.r * q__2.i +
            z1.i * q__2.r;
        sn[iptr] = q__1.r;
        sn[iptr + 1] = z1.r * (float)-2.;
        sn[iptr + 2] = (float)1.;
            q__2 = conjg(p1);
        q__1.r = p1.r * q__2.r - p1.i * q__2.i, q__1.i = p1.r * q__2.i +
            p1.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p1.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
            q__2 = conjg(z2);
        q__1.r = z2.r * q__2.r - z2.i * q__2.i, q__1.i = z2.r * q__2.i +
            z2.i * q__2.r;
        sn[iptr] = q__1.r;
        sn[iptr + 1] = z2.r * (float)-2.;
        sn[iptr + 2] = (float)1.;
            q__2 = conjg(p2);
        q__1.r = p2.r * q__2.r - p2.i * q__2.i, q__1.i = p2.r * q__2.i +
            p2.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p2.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        nsects += 2;
    } else if (strncmp(rtype + i * 3, "CP", 2) == 0) {
        i__2 = i;
        q__3.r = b * p[i__2].r, q__3.i = b * p[i__2].i;
            q__2 = cpowi(q__3, 2);
        d__1 = a * (float)4.;
        q__1.r = q__2.r - d__1, q__1.i = q__2.i;
        ctemp.r = q__1.r, ctemp.i = q__1.i;
            q__1 = csqrt1(ctemp);
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        i__2 = i;
        q__3.r = b * p[i__2].r, q__3.i = b * p[i__2].i;
        q__2.r = q__3.r + ctemp.r, q__2.i = q__3.i + ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p1.r = q__1.r, p1.i = q__1.i;
        i__2 = i;
        q__3.r = b * p[i__2].r, q__3.i = b * p[i__2].i;
        q__2.r = q__3.r - ctemp.r, q__2.i = q__3.i - ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p2.r = q__1.r, p2.i = q__1.i;
        sn[iptr] = (float)0.;
        sn[iptr + 1] = b;
        sn[iptr + 2] = (float)0.;
            q__2 = conjg(p1);
        q__1.r = p1.r * q__2.r - p1.i * q__2.i, q__1.i = p1.r * q__2.i +
            p1.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p1.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        sn[iptr] = (float)0.;
        sn[iptr + 1] = b;
        sn[iptr + 2] = (float)0.;
            q__2 = conjg(p2);
        q__1.r = p2.r * q__2.r - p2.i * q__2.i, q__1.i = p2.r * q__2.i +
            p2.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p2.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        nsects += 2;
    } else if (strncmp(rtype + i * 3, "SP", 2) == 0) {
        sn[iptr] = (float)0.;
        sn[iptr + 1] = b;
        sn[iptr + 2] = (float)0.;
        sd[iptr] = a;
        i__2 = i;
        sd[iptr + 1] = -(double)b * p[i__2].r;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        ++(nsects);
    }
    }
/* Scaling - use fact that the bandpass filter amplitude at sqrt( omega_l **/
/*            equals the amplitude of the lowpass prototype at d.c. */
    d__1 = sqrt(a);
    q__1.r = (float)0., q__1.i = d__1;
    s.r = q__1.r, s.i = q__1.i;
    h.r = (float)1., h.i = (float)0.;

    iptr = 1;
    i__1 = nsects;
    for (i = 1; i <= i__1; ++i) {
    i__2 = iptr + 2;
    q__6.r = sn[i__2] * s.r, q__6.i = sn[i__2] * s.i;
    i__3 = iptr + 1;
    q__5.r = q__6.r + sn[i__3], q__5.i = q__6.i;
    q__4.r = q__5.r * s.r - q__5.i * s.i, q__4.i = q__5.r * s.i + q__5.i *
         s.r;
    i__4 = iptr;
    q__3.r = q__4.r + sn[i__4], q__3.i = q__4.i;
    q__2.r = h.r * q__3.r - h.i * q__3.i, q__2.i = h.r * q__3.i + h.i *
        q__3.r;
    i__5 = iptr + 2;
    q__10.r = sd[i__5] * s.r, q__10.i = sd[i__5] * s.i;
    i__6 = iptr + 1;
    q__9.r = q__10.r + sd[i__6], q__9.i = q__10.i;
    q__8.r = q__9.r * s.r - q__9.i * s.i, q__8.i = q__9.r * s.i + q__9.i *
         s.r;
    i__7 = iptr;
    q__7.r = q__8.r + sd[i__7], q__7.i = q__8.i;
        q__1 = cdiv(q__2, q__7);
    h.r = q__1.r, h.i = q__1.i;
    iptr += 3;
    }
    q__2.r = *dcvalue, q__2.i = (float)0.;
    d__1 = h.r;
    q__5 = conjg(h);
    q__4.r = d__1 * q__5.r, q__4.i = d__1 * q__5.i;
    q__3 = csqrt1(q__4);
    q__1 = cdiv(q__2, q__3);
    scale = q__1.r;
    sn[1] *= scale;
    sn[2] *= scale;
    sn[3] *= scale;
    return TRUE;
}

/*  Subroutine to generate second order section parameterization */
/*    from an pole-zero description for lowpass filters. */
/*  Input Arguments: */
/*  ---------------- */
/*    P                       Array containing poles */
/*    Z                       Array containing zeros */
/*   RTYPE                   Character array containing root type information
*/
/*                              (SP)  Single pole or */
/*                              (CP)  Complex conjugate pole pair */
/*                             (CPZ) Complex conjugate pole and zero pairs*/
/*    DCVALUE                 Zero-frequency value of prototype filter */
/*  Output Arguments: */
/*  ----------------- */
/*    SN                      Numerator polynomials for second order */
/*                              sections. */
/*    SD                      Denominator polynomials for second order */
/*                              sections. */

static int lp(p, z, rtype, dcvalue, sn, sd)
complex *p, *z;
char *rtype;
float *dcvalue;
float *sn, *sd;
{
    /* System generated locals */
    int i__1, i__2, i__3;
    complex q__1, q__2, q__3, q__4;

    /* Local variables */
    int iptr, i;
    float scale;

    /* Parameter adjustments */
    --sd;
    --sn;
    rtype -= 3;
    --z;
    --p;

    /* Function Body */
    iptr = 1;
    i__1 = nsects;
    for (i = 1; i <= i__1; ++i) {
    if (strncmp(rtype + i * 3, "CPZ", 3) == 0) {
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        i__3 = i;
        q__4 = conjg(z[i]);
        q__3.r = z[i__3].r * q__4.r - z[i__3].i * q__4.i, q__3.i = z[i__3]
            .r * q__4.i + z[i__3].i * q__4.r;
        scale = q__1.r / q__3.r;
        i__2 = i;
        q__2 = conjg(z[i]);
        q__1.r = z[i__2].r * q__2.r - z[i__2].i * q__2.i, q__1.i = z[i__2]
            .r * q__2.i + z[i__2].i * q__2.r;
        sn[iptr] = q__1.r * scale;
        i__2 = i;
        sn[iptr + 1] = z[i__2].r * (float)-2. * scale;
        sn[iptr + 2] = scale * (float)1.;
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        sd[iptr] = q__1.r;
        i__2 = i;
        sd[iptr + 1] = p[i__2].r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
    } else if (strncmp(rtype + i * 3, "CP", 2) == 0) {
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        scale = q__1.r;
        sn[iptr] = scale;
        sn[iptr + 1] = (float)0.;
        sn[iptr + 2] = (float)0.;
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        sd[iptr] = q__1.r;
        i__2 = i;
        sd[iptr + 1] = p[i__2].r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
    } else if (strncmp(rtype + i * 3, "SP", 2) == 0) {
        i__2 = i;
        scale = -(double)p[i__2].r;
        sn[iptr] = scale;
        sn[iptr + 1] = (float)0.;
        sn[iptr + 2] = (float)0.;
        i__2 = i;
        sd[iptr] = -(double)p[i__2].r;
        sd[iptr + 1] = (float)1.;
        sd[iptr + 2] = (float)0.;
        iptr += 3;
    }
    }
    sn[1] = *dcvalue * sn[1];
    sn[2] = *dcvalue * sn[2];
    sn[3] = *dcvalue * sn[3];
    return TRUE;
}

/*  Subroutine to convert a lowpass filter to a band reject filter */
/*    via an analog polynomial transformation.  The lowpass filter is */
/*   described in terms of its poles and zeros (as input to this routine).*/
/*    The output consists of the parameters for second order sections. */
/*  Input Arguments: */
/*  ---------------- */
/*    P                       Array containing poles */
/*    Z                       Array containing zeros */
/*    RTYPE                   Character array containing type information */
/*                              (SP)  single real pole or */
/*                              (CP)  complex conjugate pole pair */
/*                              (CPZ) complex conjugate pole/zero pairs */
/*    DCVALUE                 Zero-frequency value of prototype filter */
/*                              prior to transformation */
/*    FL                      Low-frequency cutoff */
/*    FH                      High-frequency cutoff */
/*  Output Arguments: */
/*  ----------------- */
/*    SN                      Numerator polynomials for second order */
/*                              sections. */
/*    SD                      Denominator polynomials for second order */
/*                              sections. */
/*    NSECTS                  Number of second order sections following */
/*                              transformation.  The number is doubled. */

static int lptbr(p, z, rtype, dcvalue, fl, fh, sn, sd)
complex *p, *z;
char *rtype;
float *dcvalue;
float *fl, *fh, *sn, *sd;
{
    /* System generated locals */
    int i__1, i__2;
    double d__1;
    complex q__1, q__2, q__3;

    /* Local variables */
    complex cinv;
    int iptr;
    float a, b, h;
    int i, n;
    float scale;
    complex ctemp, p1, p2;
    float twopi;
    complex z1, z2;
    float pi;

    /* Parameter adjustments */
    --sd;
    --sn;
    rtype -= 3;
    --z;
    --p;

    /* Function Body */
    pi = (float)3.14159265;
    twopi = pi * (float)2.;
    a = twopi * twopi * *fl * *fh;
    b = twopi * (*fh - *fl);
    n = nsects;
    nsects = 0;
    iptr = 1;
    i__1 = n;
    for (i = 1; i <= i__1; ++i) {
    if (strncmp(rtype + i * 3, "CPZ", 3) == 0) {
        q__1 = cdiv(c_b43, z[i]);
        cinv.r = q__1.r, cinv.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
            q__2 = cpowi(q__3, 2);
        d__1 = a * (float)4.;
        q__1.r = q__2.r - d__1, q__1.i = q__2.i;
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        q__1 = csqrt1(ctemp);
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
        q__2.r = q__3.r + ctemp.r, q__2.i = q__3.i + ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        z1.r = q__1.r, z1.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
        q__2.r = q__3.r - ctemp.r, q__2.i = q__3.i - ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        z2.r = q__1.r, z2.i = q__1.i;
        q__1 = cdiv(c_b43, p[i]);
        cinv.r = q__1.r, cinv.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
            q__2 = cpowi(q__3, 2);
        d__1 = a * (float)4.;
        q__1.r = q__2.r - d__1, q__1.i = q__2.i;
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        q__1 = csqrt1(ctemp);
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
        q__2.r = q__3.r + ctemp.r, q__2.i = q__3.i + ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p1.r = q__1.r, p1.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
        q__2.r = q__3.r - ctemp.r, q__2.i = q__3.i - ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p2.r = q__1.r, p2.i = q__1.i;
        q__2 = conjg(z1);
        q__1.r = z1.r * q__2.r - z1.i * q__2.i, q__1.i = z1.r * q__2.i +
            z1.i * q__2.r;
        sn[iptr] = q__1.r;
        sn[iptr + 1] = z1.r * (float)-2.;
        sn[iptr + 2] = (float)1.;
        q__2 = conjg(p1);
        q__1.r = p1.r * q__2.r - p1.i * q__2.i, q__1.i = p1.r * q__2.i +
            p1.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p1.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        q__2 = conjg(z2);
        q__1.r = z2.r * q__2.r - z2.i * q__2.i, q__1.i = z2.r * q__2.i +
            z2.i * q__2.r;
        sn[iptr] = q__1.r;
        sn[iptr + 1] = z2.r * (float)-2.;
        sn[iptr + 2] = (float)1.;
        q__2 = conjg(p2);
        q__1.r = p2.r * q__2.r - p2.i * q__2.i, q__1.i = p2.r * q__2.i +
            p2.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p2.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        nsects += 2;
    } else if (strncmp(rtype + i * 3, "CP", 2) == 0) {
        q__1 = cdiv(c_b43, p[i]);
        cinv.r = q__1.r, cinv.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
            q__2 = cpowi(q__3, 2);
        d__1 = a * (float)4.;
        q__1.r = q__2.r - d__1, q__1.i = q__2.i;
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        q__1 = csqrt1(ctemp);
        ctemp.r = q__1.r, ctemp.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
        q__2.r = q__3.r + ctemp.r, q__2.i = q__3.i + ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p1.r = q__1.r, p1.i = q__1.i;
        q__3.r = b * cinv.r, q__3.i = b * cinv.i;
        q__2.r = q__3.r - ctemp.r, q__2.i = q__3.i - ctemp.i;
        q__1.r = q__2.r * (float).5, q__1.i = q__2.i * (float).5;
        p2.r = q__1.r, p2.i = q__1.i;
        sn[iptr] = a;
        sn[iptr + 1] = (float)0.;
        sn[iptr + 2] = (float)1.;
        q__2 = conjg(p1);
        q__1.r = p1.r * q__2.r - p1.i * q__2.i, q__1.i = p1.r * q__2.i +
            p1.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p1.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        sn[iptr] = a;
        sn[iptr + 1] = (float)0.;
        sn[iptr + 2] = (float)1.;
        q__2 = conjg(p2);
        q__1.r = p2.r * q__2.r - p2.i * q__2.i, q__1.i = p2.r * q__2.i +
            p2.i * q__2.r;
        sd[iptr] = q__1.r;
        sd[iptr + 1] = p2.r * (float)-2.;
        sd[iptr + 2] = (float)1.;
        iptr += 3;
        nsects += 2;
    } else if (strncmp(rtype + i * 3, "SP", 2) == 0) {
        sn[iptr] = a;
        sn[iptr + 1] = (float)0.;
        sn[iptr + 2] = (float)1.;
        i__2 = i;
        sd[iptr] = -(double)a * p[i__2].r;
        sd[iptr + 1] = b;
        i__2 = i;
        sd[iptr + 2] = -(double)p[i__2].r;
        iptr += 3;
        ++(nsects);
    }
    }
/*  Scaling - use the fact that the bandreject filter amplitude  at d.c. */
/*            equals the lowpass prototype amplitude at d.c. */
    h = (float)1.;
    iptr = 1;
    i__1 = nsects;
    for (i = 1; i <= i__1; ++i) {
    h = h * sn[iptr] / sd[iptr];
    iptr += 3;
    }
    scale = *dcvalue / ABS(h);
    sn[1] *= scale;
    sn[2] *= scale;
    sn[3] *= scale;
    return TRUE;
}

/*  Subroutine to alter the cutoff of a filter.  Assumes that the */
/*    filter is structured as second order sections.  Changes */
/*    the cutoffs of normalized lowpass and highpass filters through */
/*    a simple polynomial transformation. */
/*  Input Arguments: */
/*  ---------------- */
/*    F                       New cutoff frequency */
/*  Input/Output Arguments: */
/*  ----------------------- */
/*    SN                      Numerator polynomials for second order */
/*                              sections. */
/*    SD                      Denominator polynomials for second order */
/*                              sections. */

static int cutoffs(sn, sd, f)
float *sn, *sd;
float *f;
{
    /* System generated locals */
    int i__1;

    /* Local variables */
    int iptr, i;
    float scale;

    /* Parameter adjustments */
    --sd;
    --sn;

    /* Function Body */
    scale = *f * (float)6.2831853000000004;

    iptr = 1;
    i__1 = nsects;
    for (i = 1; i <= i__1; ++i) {

    sn[iptr + 1] /= scale;
    sn[iptr + 2] /= scale * scale;
    sd[iptr + 1] /= scale;
    sd[iptr + 2] /= scale * scale;
    iptr += 3;
    }
    return TRUE;
}

/*  Subroutine to convert a lowpass filter to a highpass filter via */
/*    an analog polynomial transformation.  The lowpass filter is */
/*   described in terms of its poles and zeroes (as input to this routine).*/
/*    The output consists of the parameters for second order sections. */
/*  Input Arguments: */
/*  ---------------- */
/*    P                       Array containing poles */
/*    Z                       Array containing zeroes */
/*   RTYPE                   Character array containing root type information
*/
/*                              (SP) single real pole or */
/*                              (CP)  complex conjugate pair */
/*                              (CPZ) complex pole/zero pairs */
/*    DCVALUE                 Zero-frequency value of prototype filter */
/*  Output Arguments: */
/*  ----------------- */
/*    SN                      Numerator polynomials for second order */
/*                              sections. */
/*    SD                      Denominator polynomials for second order */
/*                              sections. */

static int lpthp(p, z, rtype, dcvalue, sn, sd)
complex *p, *z;
char *rtype;
float *dcvalue;
float *sn, *sd;
{
    /* System generated locals */
    int i__1, i__2, i__3;
    complex q__1, q__2, q__3, q__4;

   /* Local variables */
    int iptr, i;
    float scale;

    /* Parameter adjustments */
    --sd;
    --sn;
    rtype -= 3;
    --z;
    --p;

    /* Function Body */
    iptr = 1;
    i__1 = nsects;
    for (i = 1; i <= i__1; ++i) {
    if (strncmp(rtype + i * 3, "CPZ", 3) == 0) {
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        i__3 = i;
        q__4 = conjg(z[i]);
        q__3.r = z[i__3].r * q__4.r - z[i__3].i * q__4.i, q__3.i = z[i__3]
            .r * q__4.i + z[i__3].i * q__4.r;
        scale = q__1.r / q__3.r;
        sn[iptr] = scale * (float)1.;
        i__2 = i;
        sn[iptr + 1] = z[i__2].r * (float)-2. * scale;
        i__2 = i;
        q__2 = conjg(z[i]);
        q__1.r = z[i__2].r * q__2.r - z[i__2].i * q__2.i, q__1.i = z[i__2]
            .r * q__2.i + z[i__2].i * q__2.r;
        sn[iptr + 2] = q__1.r * scale;
        sd[iptr] = (float)1.;
        i__2 = i;
        sd[iptr + 1] = p[i__2].r * (float)-2.;
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        sd[iptr + 2] = q__1.r;
        iptr += 3;
    } else if (strncmp(rtype + i * 3, "CP", 2) == 0) {
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        scale = q__1.r;
        sn[iptr] = (float)0.;
        sn[iptr + 1] = (float)0.;
        sn[iptr + 2] = scale;
        sd[iptr] = (float)1.;
        i__2 = i;
        sd[iptr + 1] = p[i__2].r * (float)-2.;
        i__2 = i;
        q__2 = conjg(p[i]);
        q__1.r = p[i__2].r * q__2.r - p[i__2].i * q__2.i, q__1.i = p[i__2]
            .r * q__2.i + p[i__2].i * q__2.r;
        sd[iptr + 2] = q__1.r;
        iptr += 3;
    } else if (strncmp(rtype + i * 3, "SP", 2) == 0) {
        i__2 = i;
        scale = -(double)p[i__2].r;
        sn[iptr] = (float)0.;
        sn[iptr + 1] = scale;
        sn[iptr + 2] = (float)0.;
        sd[iptr] = (float)1.;
        i__2 = i;
        sd[iptr + 1] = -(double)p[i__2].r;
        sd[iptr + 2] = (float)0.;
        iptr += 3;
    }
    }
    sn[1] *= *dcvalue;
    sn[2] *= *dcvalue;
    sn[3] *= *dcvalue;
    return TRUE;
}

/* Transforms an analog filter to a digital filter via the bilinear transforma
ti*/
/*   Assumes both are stored as second order sections.  The transformation is
*/
/*    done in-place. */
/*  Input Arguments: */
/*  ---------------- */
/*   SN                   Array containing numerator polynomial coefficients f
or*/
/*                           second order sections.  Packed head-to-tail. */
/*   SD                   Array containing denominator polynomial coefficients
 f*/
/*                           second order sections.  Packed head-to-tail. */

static int bilin2(sn, sd)
float *sn, *sd;
{
    /* System generated locals */
    int i__1;

    /* Local variables */
    int iptr, i;
    float scale, a0, a1, a2;

    /* Parameter adjustments */
    --sd;
    --sn;

    /* Function Body */
    iptr = 1;
    i__1 = nsects;
    for (i = 1; i <= i__1; ++i) {
    a0 = sd[iptr];
    a1 = sd[iptr + 1];
    a2 = sd[iptr + 2];
    scale = a2 + a1 + a0;
    sd[iptr] = (float)1.;
    sd[iptr + 1] = (a0 - a2) * (float)2. / scale;
    sd[iptr + 2] = (a2 - a1 + a0) / scale;
    a0 = sn[iptr];
    a1 = sn[iptr + 1];
    a2 = sn[iptr + 2];
    sn[iptr] = (a2 + a1 + a0) / scale;
    sn[iptr + 1] = (a0 - a2) * (float)2. / scale;
    sn[iptr + 2] = (a2 - a1 + a0) / scale;
    iptr += 3;
    }
    return TRUE;
}

/* WARP -- FUNCTION, APPLIES TANGENT FREQUENCY WARPING TO COMPENSATE */
/*         FOR BILINEAR ANALOG -> DIGITAL TRANSFORMATION */
/* ARGUMENTS: */
/* ---------- */
/*      F       ORIGINAL DESIGN FREQUENCY SPECIFICATION (HERTZ) */
/*      TS      SAMPLING INTERVAL (SECONDS) */
/*  LAST MODIFIED:  SEPTEMBER 20, 1990 */

static double warp(f, ts)
float *f, *ts;
{
    /* System generated locals */
    float ret_val;

    /* Local variables */
    float angle, twopi;

    twopi = (float)6.2831853;
    angle = twopi * *f * *ts / (float)2.;
    ret_val = tan(angle) * (float)2. / *ts;
    ret_val /= twopi;
    return ret_val;
}

/* BEROOTS -- SUBROUTINE TO RETURN BESSEL POLES FOR */
/*   NORMALIZED LOWPASS FILTER */
/* LAST MODIFIED:  SEPTEMBER 7, 1990 */
/*  OUTPUT ARGUMENTS: */
/*  ----------------- */
/*      P              COMPLEX ARRAY CONTAINING POLES */
/*                       CONTAINS ONLY ONE FROM EACH */
/*                       COMPLEX CONJUGATE PAIR, AND */
/*                       ALL REAL POLES */
/*      RTYPE          CHARACTER ARRAY INDICATING 2ND ORDER SECTION */
/*                       TYPE: */
/*                         (SP)  SINGLE REAL POLE */
/*                         (CP)  COMPLEX CONJUGATE POLE PAIR */
/*                         (CPZ) COMPLEX CONJUGATE POLE-ZERO PAIRS */
/*      DCVALUE        MAGNITUDE OF FILTER AT ZERO FREQUENCY */
/*  INPUT ARGUMENTS: */
/*  ---------------- */
/*      IORD           DESIRED FILTER ORDER */

static int beroots(p, rtype, dcvalue, iord)
complex *p;
char *rtype;
float *dcvalue;
int iord;
{
    /* Parameter adjustments */
    rtype -= 3;
    --p;

    /* Function Body */
    if (iord == 1) {
    p[1].r = (float)-1., p[1].i = (float)0.;
    strncpy(rtype + 3, "SP", 2);
    } else if (iord == 2) {
    p[1].r = (float)-1.1016013, p[1].i = (float).6360098;
    strncpy(rtype + 3, "CP", 2);
    } else if (iord == 3) {
    p[1].r = (float)-1.0474091, p[1].i = (float).9992645;
    strncpy(rtype + 3, "CP", 2);
    p[2].r = (float)-1.3226758, p[2].i = (float)0.;
    strncpy(rtype + 6, "SP", 2);
    } else if (iord == 4) {
    p[1].r = (float)-.9952088, p[1].i = (float)1.2571058;
    strncpy(rtype + 3, "CP", 2);
    p[2].r = (float)-1.3700679, p[2].i = (float).4102497;
    strncpy(rtype + 6, "CP", 2);
    } else if (iord == 5) {
    p[1].r = (float)-.9576766, p[1].i = (float)1.4711244;
    strncpy(rtype + 3, "CP", 2);
    p[2].r = (float)-1.3808774, p[2].i = (float).7179096;
    strncpy(rtype + 6, "CP", 2);
    p[3].r = (float)-1.502316, p[3].i = (float)0.;
    strncpy(rtype + 9, "SP", 2);
    } else if (iord == 6) {
    p[1].r = (float)-.9306565, p[1].i = (float)1.6618633;
    strncpy(rtype + 3, "CP", 2);
    p[2].r = (float)-1.3818581, p[2].i = (float).9714719;
    strncpy(rtype + 6, "CP", 2);
    p[3].r = (float)-1.5714904, p[3].i = (float).3208964;
    strncpy(rtype + 9, "CP", 2);
    } else if (iord == 7) {
    p[1].r = (float)-.9098678, p[1].i = (float)1.8364514;
    strncpy(rtype + 3, "CP", 2);
    p[2].r = (float)-1.3789032, p[2].i = (float)1.1915667;
    strncpy(rtype + 6, "CP", 2);
    p[3].r = (float)-1.6120388, p[3].i = (float).5892445;
    strncpy(rtype + 9, "CP", 2);
    p[4].r = (float)-1.6843682, p[4].i = (float)0.;
    strncpy(rtype + 12, "SP", 2);
    } else if (iord == 8) {
    p[1].r = (float)-.892871, p[1].i = (float)1.9983286;
    strncpy(rtype + 3, "CP", 2);
    p[2].r = (float)-1.3738431, p[2].i = (float)1.3883585;
    strncpy(rtype + 6, "CP", 2);
    p[3].r = (float)-1.6369417, p[3].i = (float).8227968;
    strncpy(rtype + 9, "CP", 2);
    p[4].r = (float)-1.7574108, p[4].i = (float).2728679;
    strncpy(rtype + 12, "CP", 2);
    }
    nsects = iord - iord / 2;
    *dcvalue = (float)1.;
    return TRUE;
}

static complex cmul(a,b)
complex a,b;
{
    complex c;
    c.r = a.r * b.r - a.i * b.i;
    c.i = a.i * b.r + a.r * b.i;
    return c;
}

static complex cpowi(a,n)
complex a;
int n;
{
    int i;
    complex c;
    c.i = 0.;
    c.r = 1.;
    for (i = 1; i <= n; ++i) {
    c = cmul(c, a);
    }
    return c;

}
static complex csqrt1(z)
complex z;
{   complex c;
    float x,y,w,r;
    if ((z.r == 0.0) && (z.i == 0.0)) {
        c.r=0.0;
        c.i=0.0;
        return c;
    } else {
        x=fabs(z.r);
        y=fabs(z.i);
        if (x >= y) {
            r=y/x;
            w=sqrt(x)*sqrt(0.5*(1.0+sqrt(1.0+r*r)));
        } else {
            r=x/y;
            w=sqrt(y)*sqrt(0.5*(r+sqrt(1.0+r*r)));
        }
        if (z.r >= 0.0) {
            c.r=w;
            c.i=z.i/(2.0*w);
        } else {
            c.i=(z.i >= 0) ? w : -w;
            c.r=z.i/(2.0*c.i);
        }
        return c;
    }
}

static complex conjg(z)
complex z;
{   complex c;
    c.r=z.r;
    c.i = -z.i;
    return c;
}

static complex cdiv(a,b)
complex a,b;
{   complex c;
    float r,den;
    if (fabs(b.r) >= fabs(b.i)) {
        r=b.i/b.r;
        den=b.r+r*b.i;
        c.r=(a.r+r*a.i)/den;
        c.i=(a.i-r*a.r)/den;
    } else {
        r=b.r/b.i;
        den=b.i+r*b.r;
        c.r=(a.r*r+a.i)/den;
        c.i=(a.i*r-a.r)/den;
    }
    return c;
}

SECTIM (MSECS,YR,DOY,MTH,DAY,HR,MIN,SEC)                      
double MSECS;
int *YR;
int *DOY;
int *MTH;
int *DAY;
int *HR;
int *MIN;
float *SEC;
{
int DDAY,MMTH;
//             -- Temporary seconds         
double SSEC;
//             -- Seconds per day           
double SECDAY;
//             -- Seconds per year          
double SECYR;
//              -- Leap-year indicators      
float  IND, SIN;
//              -- Counter                   
int    I;
SECDAY=86400.0;
SECYR =31536000.0;
//*-------------------------------------------------------------------------      
//*  Find year:                                                                   
//*                                                                               
SSEC = 0.0;
for(I=1;I<201;I++)
{
    IND = 0.0;
//               -- Leap year                 
    if ((I%4) == 0) IND = 1.0;
//               -- Add years                 
    SSEC = SSEC + SECYR + IND*SECDAY;
//               -- Year found                
    if (SSEC > MSECS) goto found;              
        SIN = IND;
}
found:                                                              
*YR = I - 1;
//*                                                                               
//*  Find day-of-year and date:                                                   
//*                                                                               
//c-- Reset remaining seconds   
SSEC = MSECS - (SSEC - SECYR - IND*SECDAY);

for(I=1;I<367;I++)
{
    SSEC = SSEC - SECDAY;
    if (SSEC < 0) goto incr;                                              
}
incr:

I = I - 1;
//           -- 366 days of year          
if (SIN > 0.0) I = I + 1;
//           --                           
if (I == 0)
{                           
//           -- Justifying if change      
    *YR = *YR - 1;
//           -- of year                   
    I  = 365;                                  
    if ((*YR%4) == 0) I = 366;
}


*DOY = I;
//-- convert from doy to date  
DTE (I,&DDAY,&MMTH,*YR);
*DAY=DDAY;
*MTH=MMTH;


if(*YR >= 100) *YR=*YR-100;            /* test for year 2000 or more        */





//*                                                                               
//*  Find hour:                                                                   
//*                                                                               
SSEC = SSEC + SECDAY;

for(I=1;I<25;I++)
{
    SSEC = SSEC - 60.0*60.0;
    if (SSEC < 0) goto seks;                                              
}
seks:
*HR = I - 1;
//*                                                                               
//*  Find minutes and remaining seconds:                                          
//*                                                                               
SSEC = SSEC + 60.0*60.0;
for(I=1;I<61;I++)
{
    SSEC = SSEC - 60.0;
    if (SSEC < 0) goto otte;
}
otte:                                              
   *MIN = I - 1;
   *SEC = SSEC + 60.0;
if(*YR < 50)
{
    *YR=*YR+2000;
}else{
    *YR=*YR+1900;
}
}


/*
 * This file is part of the Anthony Lomax C Library.
 *
 * Copyright (C) 2006-2009 Anthony Lomax <anthony@alomax.net www.alomax.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */



// AJL: based on FilterPicker5.java, 2008.07.14
// AJL 20091012: Bug fix: filteredSample[k][j] initialization




/** picker memory class ***/
// _DOC_ =============================
// _DOC_ FilterPicker5_Memory object/structure
// _DOC_ =============================

/** create FilterPicker5_Memory object/structure and initialize memory */

FilterPicker5_Memory* init_filterPicker5_Memory(
        double deltaTime,
        float* sample, int length,
        const double filterWindow,
        const double longTermWindow,
        const double threshold1,
        const double threshold2,
        const double tUpEvent) {

    int j, k;


    // _DOC_ =============================
    // _DOC_ picker memory for realtime processing of packets of data

    FilterPicker5_Memory* filterPicker5_Memory = calloc(1, sizeof (FilterPicker5_Memory));

    filterPicker5_Memory->longDecayFactor = deltaTime / longTermWindow;
    filterPicker5_Memory->longDecayConst = 1.0 - filterPicker5_Memory->longDecayFactor;
    filterPicker5_Memory->nLongTermWindow = 1 + (int) (longTermWindow / deltaTime);
    filterPicker5_Memory->indexEnableTriggering = filterPicker5_Memory->nLongTermWindow;
    filterPicker5_Memory->enableTriggering = FALSE_INT;
    filterPicker5_Memory->nTotal = -1;
    // _DOC_ set up buffers and memory arrays for previous samples and their statistics
    filterPicker5_Memory->numRecursive = 1; // number of powers of 2 to process
    int nTemp = 1;

    {
        int numPrevious = (int) (filterWindow / deltaTime); // estimate of number of previous samples to bufer
        while (nTemp < numPrevious) {
            filterPicker5_Memory->numRecursive++;
            nTemp *= 2;
        }
        numPrevious = nTemp; // numPrevious is now a power of 2
        //System.out.println("TP DEBUG numPrevious, numRecursive " + numPrevious + ", " + numRecursive);
    }
    filterPicker5_Memory->xRec = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->test = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->filteredSample = calloc(filterPicker5_Memory->numRecursive, sizeof (double*));
    for (k = 0; k < filterPicker5_Memory->numRecursive; k++) {
        filterPicker5_Memory->filteredSample[k] = calloc(3, sizeof (double));
        for (j = 0; j < 3; j++) {
            filterPicker5_Memory->filteredSample[k][j] = 0.0;
        }
    }
    filterPicker5_Memory->lastFilteredSample = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->mean_xRec = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->mean_stdDev_xRec = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->mean_var_xRec = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->period = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->lowPassConst = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->highPassConst = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    double window = deltaTime / (2.0 * PI);
    for (k = 0; k < filterPicker5_Memory->numRecursive; k++) {
        filterPicker5_Memory->mean_xRec[k] = 0.0;
        filterPicker5_Memory->mean_stdDev_xRec[k] = 0.0;
        filterPicker5_Memory->mean_var_xRec[k] = 0.0;
        filterPicker5_Memory->period[k] = window * 2.0 * PI;
        filterPicker5_Memory->lowPassConst[k] = deltaTime / (window + deltaTime);
        filterPicker5_Memory->highPassConst[k] = window / (window + deltaTime);
        window *= 2.0;
    }
    filterPicker5_Memory->lastSample = DOUBLE_MAX_VALUE;
    filterPicker5_Memory->lastDiffSample = 0.0;
    // AJL 20091214
    filterPicker5_Memory->charFunctUncertainty = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->charFunctUncertaintyLast = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    filterPicker5_Memory->uncertaintyThreshold = calloc(filterPicker5_Memory->numRecursive, sizeof (double));
    for (k = 0; k < filterPicker5_Memory->numRecursive; k++) {
        filterPicker5_Memory->uncertaintyThreshold[k] = threshold1 / 2.0;
    }
    filterPicker5_Memory->maxUncertaintyThreshold = threshold1 / 2.0;
    // END - AJL 20091214
    filterPicker5_Memory->minUncertaintyThreshold = 0.5;
    filterPicker5_Memory->maxAllowNewPickThreshold = 2.0;
    filterPicker5_Memory->nTUpEvent = (int) (0.5 + tUpEvent / deltaTime) + 1;
    if (filterPicker5_Memory->nTUpEvent < 1) {
        filterPicker5_Memory->nTUpEvent = 1;
    }
    filterPicker5_Memory->indexUncertainty = calloc(filterPicker5_Memory->numRecursive, sizeof (int*)); // AJL 20091214
    filterPicker5_Memory->polarityDerivativeSum = calloc(filterPicker5_Memory->numRecursive, sizeof (double*));
    filterPicker5_Memory->polaritySumAbsDerivative = calloc(filterPicker5_Memory->numRecursive, sizeof (double*));
    for (k = 0; k < filterPicker5_Memory->numRecursive; k++) {
        filterPicker5_Memory->indexUncertainty[k] = calloc(filterPicker5_Memory->nTUpEvent, sizeof (int)); // AJL 20091214
        filterPicker5_Memory->polarityDerivativeSum[k] = calloc(filterPicker5_Memory->nTUpEvent, sizeof (double));
        filterPicker5_Memory->polaritySumAbsDerivative[k] = calloc(filterPicker5_Memory->nTUpEvent, sizeof (double));
        for (j = 0; j < filterPicker5_Memory->nTUpEvent; j++) {
            filterPicker5_Memory->indexUncertainty[k][j] = 0; // END - AJL 20091214
            filterPicker5_Memory->polarityDerivativeSum[k][j] = 0.0;
            filterPicker5_Memory->polaritySumAbsDerivative[k][j] = 0.0;
        }
    }

    // _DOC_ criticalIntegralCharFunct is tUpEvent * threshold2
    filterPicker5_Memory->criticalIntegralCharFunct = (double) (filterPicker5_Memory->nTUpEvent) * threshold2; // one less than number of samples examined
    // _DOC_ integralCharFunctClipped is integral of charFunct values for last nTUpEvent samples, charFunct values possibly limited if around trigger time
    filterPicker5_Memory->integralCharFunctClipped = calloc(filterPicker5_Memory->nTUpEvent, sizeof (double));
    // flag to prevent next trigger until charFunc drops below threshold2
    filterPicker5_Memory->allowNewPickIndex = INT_UNSET;
    filterPicker5_Memory->charFunctClippedValue = calloc(filterPicker5_Memory->nTUpEvent, sizeof (double));
    filterPicker5_Memory->charFunctValue = calloc(filterPicker5_Memory->nTUpEvent, sizeof (double));
    filterPicker5_Memory->charFuntNumRecursiveIndex = calloc(filterPicker5_Memory->nTUpEvent, sizeof (double));
    for (k = 0; k < filterPicker5_Memory->nTUpEvent; k++) {
        filterPicker5_Memory->charFunctClippedValue[k] = 0.0;
        filterPicker5_Memory->charFunctValue[k] = 0.0;
        filterPicker5_Memory->charFuntNumRecursiveIndex[k] = 0;
    }
    filterPicker5_Memory->upEventBufPtr = 0;
    filterPicker5_Memory->pickPolarity = POLARITY_UNKNOWN;
    filterPicker5_Memory->triggerNumRecursiveIndex = -1;


    // initialize previous samples to mean sample value
    int nmean = filterPicker5_Memory->nLongTermWindow < length ? filterPicker5_Memory->nLongTermWindow : length;
    double sample_mean = 0.0;
    int i;
    for (i = 0; i < nmean; i++) {
        sample_mean += sample[i];
    }
    sample_mean /= (double) nmean;
    for (k = 0; k < filterPicker5_Memory->numRecursive; k++) {
        for (j = 0; j < 3; j++) {
            filterPicker5_Memory->filteredSample[k][j] = 0.0;
        }
    }
    filterPicker5_Memory->lastSample = sample_mean;


    return (filterPicker5_Memory);

}

/** clean up memory */

void free_FilterPicker5_Memory(FilterPicker5_Memory** pfilterPicker5_Memory) {
    
    if (*pfilterPicker5_Memory == NULL)
        return;

    free((*pfilterPicker5_Memory)->xRec);
    free((*pfilterPicker5_Memory)->test);
    int k;
    for (k = 0; k < (*pfilterPicker5_Memory)->numRecursive; k++)
        free((*pfilterPicker5_Memory)->filteredSample[k]);
    free((*pfilterPicker5_Memory)->filteredSample);
    free((*pfilterPicker5_Memory)->lastFilteredSample);
    free((*pfilterPicker5_Memory)->mean_xRec);
    free((*pfilterPicker5_Memory)->mean_stdDev_xRec);
    free((*pfilterPicker5_Memory)->mean_var_xRec);
    free((*pfilterPicker5_Memory)->period);
    free((*pfilterPicker5_Memory)->lowPassConst);
    free((*pfilterPicker5_Memory)->highPassConst);

    for (k = 0; k < (*pfilterPicker5_Memory)->numRecursive; k++) {
        free((*pfilterPicker5_Memory)->polarityDerivativeSum[k]);
        free((*pfilterPicker5_Memory)->polaritySumAbsDerivative[k]);
    }
    free((*pfilterPicker5_Memory)->polarityDerivativeSum);
    free((*pfilterPicker5_Memory)->polaritySumAbsDerivative);
    free((*pfilterPicker5_Memory)->integralCharFunctClipped);
    free((*pfilterPicker5_Memory)->charFunctClippedValue);
    free((*pfilterPicker5_Memory)->charFunctValue);
    free((*pfilterPicker5_Memory)->charFuntNumRecursiveIndex);

    for (k = 0; k < (*pfilterPicker5_Memory)->numRecursive; k++) {
        free((*pfilterPicker5_Memory)->indexUncertainty[k]);
    }
    free((*pfilterPicker5_Memory)->indexUncertainty);
    free((*pfilterPicker5_Memory)->charFunctUncertainty);
    free((*pfilterPicker5_Memory)->charFunctUncertaintyLast);
    free((*pfilterPicker5_Memory)->uncertaintyThreshold);


    free(*pfilterPicker5_Memory);
    *pfilterPicker5_Memory = NULL;

}
/*
 * This file is part of the Anthony Lomax C Library.
 *
 * Copyright (C) 2006-2009 Anthony Lomax <anthony@alomax.net www.alomax.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */



// AJL: based on FilterPicker5.java, 2008.07.14




//enum ResultType resultType = PICKS;


/*** function to calculate picks  */
// _DOC_ =============================
// _DOC_ FilterPicker5
// _DOC_ =============================

//public final float[] apply(double deltaTime, float[] sample) {

void Pick(

        double deltaTime, // dt or timestep of data samples
        float sample[], // array of num_samples data samples
        int num_samples, // the number of samples in array sample

        const double filterWindow, // FilterPicker5 filter window
        // _DOC_ the filter window (filterWindow) in seconds determines how far back in time the previous samples are examined.  The filter window will be adjusted upwards to be an integer N power of 2 times the sample interval (deltaTime).  Then numRecursive = N + 1 "filter bands" are created.  For each filter band n = 0,N  the data samples are processed through a simple recursive filter backwards from the current sample, and picking statistics and characteristic function are generated.  Picks are generated based on the maximum of the characteristic funciton values over all filter bands relative to the threshold values threshold1 and threshold2.
        const double longTermWindow, // FilterPicker5 long term window
        // _DOC_ the long term window (longTermWindow) determines: a) a stabilisation delay time after the beginning of data; before this delay time picks will not be generated. b) the decay constant of a simple recursive filter to accumlate/smooth all picking statistics and characteristic functions for all filter bands.
        const double threshold1, // FilterPicker5 threshold1
        // _DOC_ threshold1 sets the threshold to trigger a pick event (potential pick).  This threshold is reached when the (clipped) characteristic function for any filter band exceeds threshold1.
        const double threshold2, // FilterPicker5 threshold1
        // _DOC_ threshold2 sets the threshold to declare a pick (pick will be accepted when tUpEvent reached).  This threshold is reached when the integral of the (clipped) characteristic function for any filter band over the window tUpEvent exceeds threshold2 * tUpEvent (i.e. the average (clipped) characteristic function over tUpEvent is greater than threshold2)..
        const double tUpEvent, // FilterPicker5 tUpEvent
        // _DOC_ tUpEvent determines the maximum time the integral of the (clipped) characteristic function is accumlated after threshold1 is reached (pick event triggered) to check for this integral exceeding threshold2 * tUpEvent (pick declared).

        FilterPicker5_Memory** pmem, // memory structure/object
        // _DOC_ pointer to a memory structure/object is used so that this function can be called repetedly for packets of data in sequence from the same channel.
        // The calling routine is responsible for managing and associating the correct mem structures/objects with each channel.  On first call to this function for each channel set mem = NULL.
        BOOLEAN_INT useMemory, // set to TRUE_INT=1 if function is called for packets of data in sequence, FALSE_INT = 0 otherwise

        PickData*** ppick_list, // returned pointer to array of num_picks PickData structures/objects containing picks
        int* pnum_picks, // the number of picks in array *ppick_list
        char* channel_id // a string identifier for the data channel
        ) {

    int k;


    // _DOC_ =============================
    // _DOC_ apply algoritm

    // initialize memory object
    FilterPicker5_Memory* mem = *pmem;
    if (mem == NULL) {
        mem = init_filterPicker5_Memory(deltaTime, sample, num_samples, filterWindow, longTermWindow, threshold1, threshold2, tUpEvent);
    }

    // create array for time-series results
    float* sampleNew = NULL;
    if (resultType == TRIGGER || resultType == CHAR_FUNC) {
        sampleNew = calloc(num_samples, sizeof (float));
        //sampleNew[0] = sample[num_samples - 1] = 0.0f;
    }

    // _DOC_ set clipped limit of maximum char funct value to 5 * threshold1 to avoid long recovery time after strong events
    double maxCharFunctValue = 5.0 * threshold1;


    // _DOC_ =============================
    // _DOC_ loop over all samples
    BOOLEAN_INT error1_not_printed = TRUE_INT;
    double charFunctValueTrigger = -1.0; // AJL 20091216
    int indexUpEventTrigger = -1;
    int indexUncertaintyPick = -1;
    int n;
    for (n = 0; n < num_samples; n++) {

        BOOLEAN_INT acceptedPick = FALSE_INT;

        // _DOC_ update index of nTUpEvent length up event window buffers
        int upEventBufPtrLast = mem->upEventBufPtr;
        mem->upEventBufPtr = (mem->upEventBufPtr + 1) % mem->nTUpEvent;

        // _DOC_ =============================
        // _DOC_ characteristic function is  (E2 - mean_E2) / mean_stdDev_E2
        // _DOC_    where E2 = (filtered band value current - filtered band value previous)**2
        // _DOC_    where value previous is taken futher back for longer filter bands
        double charFunct = 0.0;
        double charFunctClipped = 0.0;
        // _DOC_ evaluate current signal values
        double currentSample = sample[n];
        // _DOC_ filters are applied to first difference of signal values
        double currentDiffSample = currentSample - mem->lastSample;
        double currentFilteredSample;
        // _DOC_ loop over numRecursive filter bands
        for (k = mem->numRecursive - 1; k >= 0; k--) {
            // _DOC_  apply two single-pole HP filters
            // _DOC_  http://en.wikipedia.org/wiki/High-pass_filter    y[i] := α * (y[i-1] + x[i] - x[i-1])
            currentFilteredSample = mem->highPassConst[k] * (mem->filteredSample[k][0] + currentDiffSample);
            double currentDiffSample2 = currentFilteredSample - mem->filteredSample[k][0];
            mem->filteredSample[k][0] = currentFilteredSample;
            currentFilteredSample = mem->highPassConst[k] * (mem->filteredSample[k][1] + currentDiffSample2);
            mem->filteredSample[k][1] = currentFilteredSample;
            // _DOC_  apply one single-pole LP filter
            // _DOC_  http://en.wikipedia.org/wiki/Low-pass_filter    y[i] := y[i-1] + α * (x[i] - y[i-1])
            currentFilteredSample = mem->filteredSample[k][2] + mem->lowPassConst[k] * (currentFilteredSample - mem->filteredSample[k][2]);
            mem->lastFilteredSample[k] = mem->filteredSample[k][2];
            mem->filteredSample[k][2] = currentFilteredSample;
            double dy = currentFilteredSample;
            /* TEST */ //
            mem->test[k] = dy;
            //
            mem->xRec[k] = dy * dy;
            double charFunctClippedTest = 0.0; // AJL 20091214
            if (mem->mean_stdDev_xRec[k] <= DOUBLE_MIN_VALUE) {
                if (mem->enableTriggering && error1_not_printed) {
//TU                    sprintf(message_str, "WARNING: %s: mem->mean_stdDev_xRec[k] <= Float.MIN_VALUE (this should not happen! - dead trace?)\n", channel_id);
//TU                    info(message_str);
//TU                    error1_not_printed = FALSE_INT;
                }
            } else {
                double charFunctTest = (mem->xRec[k] - mem->mean_xRec[k]) / mem->mean_stdDev_xRec[k];
                charFunctClippedTest = charFunctTest; // AJL 20091214
                // _DOC_ limit maximum char funct value to avoid long recovery time after strong events
                if (charFunctClippedTest > maxCharFunctValue) {
                    charFunctClippedTest = maxCharFunctValue;
                    // save corrected mem->xRec[k]
                    mem->xRec[k] = maxCharFunctValue * mem->mean_stdDev_xRec[k] + mem->mean_xRec[k];
                }
                // _DOC_ characteristic function is maximum over numRecursive filter bands
                if (charFunctTest >= charFunct) {
                    charFunct = charFunctTest;
                    charFunctClipped = charFunctClippedTest;
                    mem->charFuntNumRecursiveIndex[mem->upEventBufPtr] = k;
                }
                // _DOC_ trigger index is highest frequency with CF >= threshold1 over numRecursive filter bands
                if (charFunctTest >= threshold1) {
                    mem->charFuntNumRecursiveIndex[mem->upEventBufPtr] = k;
                }
            }
            // AJL 20091214
            // _DOC_ =============================
            // _DOC_ update uncertainty and polarity fields
            // _DOC_ uncertaintyThreshold is at minimum char function or char funct increases past uncertaintyThreshold
            mem->charFunctUncertainty[k] = charFunctClippedTest; // no smoothing
            // AJL 20091214 mem->charFunctLast = charFunctClipped;
            BOOLEAN_INT upCharFunctUncertainty =
                    ((mem->charFunctUncertaintyLast[k] < mem->uncertaintyThreshold[k]) && (mem->charFunctUncertainty[k] >= mem->uncertaintyThreshold[k]));
            mem->charFunctUncertaintyLast[k] = mem->charFunctUncertainty[k];
            // _DOC_ each time characteristic function rises past uncertaintyThreshold store sample index and initiate polarity algoirithm
            if (upCharFunctUncertainty) {
                mem->indexUncertainty[k][mem->upEventBufPtr] = n - 1;
            } else {
                mem->indexUncertainty[k][mem->upEventBufPtr] = mem->indexUncertainty[k][upEventBufPtrLast];
            }
            // END - AJL 20091214
            if (upCharFunctUncertainty) {
                // _DOC_ initialize polarity algorithm, uses derivative of signal
                mem->polarityDerivativeSum[k][mem->upEventBufPtr] = 0.0;
                mem->polaritySumAbsDerivative[k][mem->upEventBufPtr] = 0.0;
            } else {
                mem->polarityDerivativeSum[k][mem->upEventBufPtr] = mem->polarityDerivativeSum[k][upEventBufPtrLast];
                mem->polaritySumAbsDerivative[k][mem->upEventBufPtr] = mem->polaritySumAbsDerivative[k][upEventBufPtrLast];
            }
            // _DOC_   accumulate derivative and sum of abs of derivative for polarity estimate
            // _DOC_   accumulate since last indexUncertainty
            double polarityderivativeIncrement = mem->filteredSample[k][2] - mem->lastFilteredSample[k];
            mem->polarityDerivativeSum[k][mem->upEventBufPtr] += polarityderivativeIncrement;
            mem->polaritySumAbsDerivative[k][mem->upEventBufPtr] += fabs(polarityderivativeIncrement);
        }


        // _DOC_ =============================
        // _DOC_ trigger and pick logic
        // _DOC_ only apply trigger and pick logic if past stabilisation time (longTermWindow)
        if (mem->enableTriggering || mem->nTotal++ > mem->indexEnableTriggering) { // past stabilisation time

            mem->enableTriggering = TRUE_INT;

            // _DOC_ update charFunctClipped values, subtract oldest value, and save provisional current sample charFunct value
            // _DOC_ to avoid spikes, do not use full charFunct value, may be very large, instead use charFunctClipped
            mem->integralCharFunctClipped[mem->upEventBufPtr] =
                    mem->integralCharFunctClipped[upEventBufPtrLast] - mem->charFunctClippedValue[mem->upEventBufPtr] + charFunctClipped;
            mem->charFunctClippedValue[mem->upEventBufPtr] = charFunctClipped;
            mem->charFunctValue[mem->upEventBufPtr] = charFunct;

            // _DOC_ if new picks allowd, check if integralCharFunct over last tUpEvent window is greater than threshold
            if (mem->allowNewPickIndex != INT_UNSET && mem->integralCharFunctClipped[mem->upEventBufPtr] >= mem->criticalIntegralCharFunct) {

                // _DOC_ find last point in tUpEvent window where charFunct rose past threshold1 and integralCharFunct greater than threshold back to this point
                int m = mem->upEventBufPtr;
                double integralCharFunctClippedWindow = mem->charFunctClippedValue[m];
                int k = 0;
                while (k++ < mem->nTUpEvent - 1 && n - k > mem->allowNewPickIndex) {
                    m--;
                    if (m < 0) {
                        m += mem->nTUpEvent;
                    }
                    integralCharFunctClippedWindow += mem->charFunctClippedValue[m];
                    if (mem->charFunctValue[m] >= threshold1) {
                        int l = m - 1;
                        if (l < 0) {
                            l += mem->nTUpEvent;
                        }
                        if (mem->charFunctValue[l] < threshold1) {
                            // integralCharFunct is integralCharFunct from current point back to point m
                            if (integralCharFunctClippedWindow >= mem->criticalIntegralCharFunct) {
                                acceptedPick = TRUE_INT;
                                // _DOC_ save characteristic function value as indicator of pick strenth
                                charFunctValueTrigger = mem->charFunctValue[m]; // AJL 20091216
                                mem->triggerNumRecursiveIndex = mem->charFuntNumRecursiveIndex[m];
                                // _DOC_ set index for pick uncertainty begin and end
                                indexUpEventTrigger = n - k;
                                indexUncertaintyPick = mem->indexUncertainty[mem->triggerNumRecursiveIndex][m]; // AJL 20091214
                                // _DOC_ evaluate polarity based on accumulated derivative
                                // _DOC_    (=POS if derivative_sum > 0, = NEG if derivative_sum < 0,
                                // _DOC_     and if ratio larger abs derivative_sum / abs_derivative_sum > 0.667,
                                // _DOC_     =UNK otherwise)
                                int iPolarity = m + 1; // evaluate polarity at 1 point past trigger point
                                if (iPolarity >= mem->nTUpEvent) {
                                    iPolarity -= mem->nTUpEvent;
                                }
                                mem->pickPolarity = POLARITY_UNKNOWN;
                                if (mem->polarityDerivativeSum[mem->triggerNumRecursiveIndex][iPolarity] > 0.0 &&
                                        mem->polarityDerivativeSum[mem->triggerNumRecursiveIndex][iPolarity] / mem->polaritySumAbsDerivative[mem->triggerNumRecursiveIndex][iPolarity] > 0.667) {
                                    mem->pickPolarity = POLARITY_POS;
                                } else if (mem->polarityDerivativeSum[mem->triggerNumRecursiveIndex][iPolarity] < 0.0 &&
                                        -mem->polarityDerivativeSum[mem->triggerNumRecursiveIndex][iPolarity] / mem->polaritySumAbsDerivative[mem->triggerNumRecursiveIndex][iPolarity] > 0.667) {
                                    mem->pickPolarity = POLARITY_NEG;
                                }
                                info(message_str);
                                mem->allowNewPickIndex = INT_UNSET;
                                info(message_str);
                                break;
                            }
                        }
                    }
                }
            }

            // _DOC_ if no pick, check if charFunctUncertainty has dropped below threshold maxAllowNewPickThreshold to allow new picks
            if (!acceptedPick && mem->allowNewPickIndex == INT_UNSET) { // no pick and no allow new picks
                // AJL 20091214
                int k = 0;
                for (; k < mem->numRecursive; k++) {
                    if (mem->charFunctUncertainty[k] > mem->maxAllowNewPickThreshold) // do not allow new picks
                    {
                        break;
                    }
                }
                if (k == mem->numRecursive) {
                    mem->allowNewPickIndex = n;
                }
                // END AJL 20091214
            }
        }


        // _DOC_ =============================
        // _DOC_ update "true", long-term statistic based on current signal values based on long-term window
        // long-term decay formulation
        // _DOC_ update long-term means of x, dxdt, E2, var(E2), uncertaintyThreshold
        for (k = 0; k < mem->numRecursive; k++) {
            mem->mean_xRec[k] = mem->mean_xRec[k] * mem->longDecayConst + mem->xRec[k] * mem->longDecayFactor;
            double dev = mem->xRec[k] - mem->mean_xRec[k];
            mem->mean_var_xRec[k] = mem->mean_var_xRec[k] * mem->longDecayConst + dev * dev * mem->longDecayFactor;
            // _DOC_ mean_stdDev_E2 is sqrt(long-term mean var(E2))
            mem->mean_stdDev_xRec[k] = sqrt(mem->mean_var_xRec[k]);
            mem->uncertaintyThreshold[k] = mem->uncertaintyThreshold[k] * mem->longDecayConst + mem->charFunctUncertainty[k] * mem->longDecayFactor;
            if (mem->uncertaintyThreshold[k] > mem->maxUncertaintyThreshold) {
                mem->uncertaintyThreshold[k] = mem->maxUncertaintyThreshold;
            } else if (mem->uncertaintyThreshold[k] < mem->minUncertaintyThreshold) {
                mem->uncertaintyThreshold[k] = mem->minUncertaintyThreshold;
            }
        }


        // _DOC_ =============================
        //  _DOC_ act on result, save pick if pick accepted at this sample

        if (resultType == TRIGGER) { // show triggers
            if (acceptedPick) {
                sampleNew[n] = 1.0f;
            } else {
                sampleNew[n] = 0.0f;
            }
            // TEST...
            //sampleNew[n] = (float) mem->test[0];
            //sampleNew[n] = (float) mem->test[index_recursive];
            //sampleNew[n] = (float) mem->test[mem->numRecursive - 1];
            //
        } else if (resultType == CHAR_FUNC) { // show char function
            sampleNew[n] = (float) charFunctClipped;
        } else { // generate picks
            // PICK
            if (acceptedPick) {
                // _DOC_ if pick accepted, save pick time, uncertainty, strength (integralCharFunct) and polarity
                // _DOC_    pick time is at uncertainty threshold (characteristic function rose past
                // _DOC_       uncertaintyThreshold): indexUncertaintyPick
                // _DOC_    trigger time (characteristic function >= threshold1): indexUpEventTrigger
                // _DOC_    pick begin is pick time - (trigger time - uncertainty threshold)
                int indexBeginPick = indexUncertaintyPick - (indexUpEventTrigger - indexUncertaintyPick);
                int indexEndPick = indexUpEventTrigger;
                double triggerPeriod = mem->period[mem->triggerNumRecursiveIndex];
                // check that uncertainty range is >= triggerPeriod / 20.0  // 20101014 AJL
                double uncertainty = deltaTime * ((double) (indexEndPick - indexBeginPick));
                if (uncertainty < triggerPeriod / 20.0) {
                    int ishift = (int) (0.5 * (triggerPeriod / 20.0 - uncertainty) / deltaTime);
                    // advance uncertainty index
                    indexBeginPick -= ishift;
                    // delay trigger index
                    indexEndPick += ishift;
                }
                PickData* pickData = init_PickData();
                set_PickData(pickData, (double) indexBeginPick, (double) indexEndPick,
                        mem->pickPolarity, charFunctValueTrigger, // AJL 20091216
                        CHAR_FUNCT_AMP_UNITS, triggerPeriod);
                addPickToPickList(pickData, ppick_list, pnum_picks);

            }
        }


        mem->lastSample = currentSample;
        mem->lastDiffSample = currentDiffSample;

    }


    if (useMemory) {
        // corect memory index values for sample length
        int i;
        for (i = 0; i < mem->nTUpEvent; i++) {
            // AJL 20091214
            for (k = 0; k < mem->numRecursive; k++) {
                mem->indexUncertainty[k][i] -= num_samples;
            }
            // END - AJL 20091214
        }
        if (mem->allowNewPickIndex != INT_UNSET) {
            mem->allowNewPickIndex -= num_samples;
        }
    } else {
        free_FilterPicker5_Memory(&mem);
        mem = NULL;
    }
    *pmem = mem;


    if (resultType == TRIGGER || resultType == CHAR_FUNC) {
        int n;
        for (n = 0; n < num_samples; n++)
            sample[n] = sampleNew[n];
    }
    if (sampleNew != NULL)
        free(sampleNew);


}

/*
 * This file is part of the Anthony Lomax C Library.
 *
 * Copyright (C) 2008 Anthony Lomax <anthony@alomax.net www.alomax.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */



// AJL: based on TestPicker4.java, 2008.07.14




/** picker memory class */

PickData* init_PickData() {

	PickData* pickData = calloc(1, sizeof(PickData));

	pickData->polarity = POLARITY_UNKNOWN;
	pickData->indices[0] = pickData->indices[1] = -1;
	pickData->amplitude = 0.0;
	pickData->amplitudeUnits = NO_AMP_UNITS;
	pickData->period = 0.0;

	return(pickData);

}


/** picker memory class */

void set_PickData(PickData* pickData, double index0, double index1, int polarity, double amplitude, int amplitudeUnits, double period) {

        pickData->indices[0] = index0;
        pickData->indices[1] = index1;
        pickData->polarity = polarity;
        pickData->amplitude = amplitude;
        pickData->amplitudeUnits = amplitudeUnits;
        pickData->period = period;

}



/** clean up pick memory */

void free_PickData(PickData* pickData)
{
	if (pickData == NULL)
		return;

	free(pickData);

}





/** print data */

int fprintf_PickData(PickData* pickData, FILE* pfile)
{
	if (pfile == NULL || pickData == NULL)
		return(0);

	fprintf(pfile, "%d %f %f %f %d %f ",
		pickData->polarity, pickData->indices[0], pickData->indices[1], pickData->amplitude, pickData->amplitudeUnits, pickData->period
	       );


	return(1);

}



/** print in NLLOC_OBS format */

char* printNlloc(char* pick_str, PickData* pickData, double dt, char* label, char* inst, char* comp, char* onset,
		 char* phase, int year, int month, int day, int hour, int min, double sec) {


	// first motion
	char first_mot[16];
	strcpy(first_mot, "?");
	if (pickData->polarity == POLARITY_POS)
		strcpy(first_mot, "+");
	if (pickData->polarity == POLARITY_NEG)
		strcpy(first_mot, "-");

	// add pick time to time
	sec += dt * (pickData->indices[0] + pickData->indices[1]) / 2.0;
	while (sec >= 60.0) {
		min++;
		sec-= 60.0;
	}
	while (min >= 60) {
		hour++;
		min-= 60;
	}

	// code data and time integers
	long int idate, ihrmin;
	idate = year * 10000 + month * 100 + day;
	ihrmin = hour * 100 + min;

	// error
	char error_type[] = "GAU";
        // set uncertainty to half width between right and left indices
	double error = dt * fabs(pickData->indices[1] - pickData->indices[0]);
	error /= 2.0;
	if (error < 0.0) {
		error = 0.0;
        }

	// misc
	double coda_dur = 0.0;
	double amplitude = pickData->amplitude;
	double period = pickData->period;
	//double apriori_weight = 1.0;

	// write observation part of FORMAT_PHASE_2 phase line
	//sprintf(pick_str,
	//	"%-6s %-4s %-4s %-1s %-6s %-1s %8.8ld %4.4ld %9.4lf %-3s %9.2le %9.2le %9.2le %9.2le %9.4lf",
	// write observation part of orig NLL phase line
	sprintf(pick_str,
		"%-6s %-4s %-4s %-1s %-6s %-1s %8.8ld %4.4ld %9.4lf %-3s %9.3le %9.3le %9.3le %9.3le",
			label,
			inst,
			comp,
			onset,
			phase,
			first_mot,
			/*quality, */
			idate, ihrmin,
			sec,
			error_type, error,
			coda_dur,
			amplitude,
			period//,
			//apriori_weight
		);

	return(pick_str);

}



/** add a PickData to a PickData list */

#define SIZE_INCREMENT 16

void addPickToPickList(PickData* pickData, PickData*** ppick_list, int* pnum_picks) {

	PickData** newPickList = NULL;

	if (*pnum_picks == 0 || *ppick_list == NULL) {		// list not yet created
		*ppick_list = calloc(SIZE_INCREMENT, sizeof(PickData*));
	}
	else if ((*pnum_picks % SIZE_INCREMENT) == 0) {	// list will be too small
		newPickList = calloc(*pnum_picks + SIZE_INCREMENT, sizeof(PickData*));
		int n;
		for (n = 0; n < *pnum_picks; n++)
			newPickList[n] = (*ppick_list)[n];
		free(*ppick_list);
		*ppick_list = newPickList;
	}

	// add PickData
	(*ppick_list)[*pnum_picks] = pickData;
	(*pnum_picks)++;

}





/** clean up pick list memory */

void free_PickList(PickData** pick_list, int num_picks)
{
	if (pick_list == NULL || num_picks < 1)
		return;

	int n;
	for (n = 0; n < num_picks; n++)
		free_PickData(*(pick_list + n));

	free(pick_list);

}









