source: SH_SHM/trunk/source/gcf/gcflib.c @ 358

Revision 341, 46.9 KB checked in by marcus, 12 years ago (diff)

r180 | walther | 2011-03-09 16:27:03 +0100 (Mi, 09 Mär 2011) | 3 lines

Merging most of the changes from marcus' branch. For full details please see
http://www.seismic-handler.org/portal/log/SH_SHM/branches/marcus?revs=101-106,123-171

Line 
1
2/* file gcflib.c
3 *      ========
4 *
5 * version 5, 5-Nov-2006
6 *
7 * interface for GCF data
8 * K. Stammler, 18-Oct-2003
9 */
10
11
12#include <stdio.h>
13#include <string.h>
14#include "basecnst.h"
15#ifdef BC_INC_STDLIB
16#include BC_INC_STDLIB
17#endif
18#include "sysbase.h"
19#include "tcusrdef.h"
20#include "gcflib.h"
21#include "../seed_io/seedcfg.h"
22#include "../seed_io/seed_lib.h"
23
24#define GcfMAXTAP 20
25#define DEFAULT_BLKLTH 1024
26#define ROOTDIR "$ROOT"
27#define ROOTDIRLTH 5
28#define MAX_SMP_PER_BLK 5000
29
30/* global variables */
31static int gcfv_byteorder[4] = { 0, 1, 2, 3 };  /* 4byte order */
32static TSyBoolean gcfv_capfiles=FALSE;   /* capitalized filenames in gfd */
33static GcfFileDescrT  gcfv_fd[Gcf_C_MAXCHAN];    /* file descriptors */
34static TSyBoolean gcfv_logrec=FALSE;
35static char gcfv_last_fname[cBcFileLth+1]; /* last file read */
36
37/* default list for translation of tap numbers into channel names: */
38static char gcfv_tapcode[GcfMAXTAP][GcfCHAN_LENGTH+1] = {
39        "HH", "HH", "HH", "BH", "BH", "BH", "LH", "LH", "LH", "UH",
40        "VH", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9"
41};
42
43
44/* prototypes of local routines */
45static TSyBoolean GcfIsLeapYear( int year );
46static void GcfAdjustFilename( GcfFileDescrT *dsc, TSyStatus *status );
47
48
49
50/*----------------------------------------------------------------------------*/
51
52
53
54void GcfSetByteorder( char byteorder[], TSyStatus *status )
55
56/* Sets byte order.  Bytes are counted from 1 to 4, Legal strings are
57 * e.g. "1234" or "2143".
58 *
59 * parameters of routine
60 * char       byteorder[]; input; byte order string of length 4 (+term char)
61 * TSyStatus  *status; output; return status
62 */
63{
64        /* local variables */
65        int      chk[4];     /* check occurence of all numbers */
66        int      bo[4];      /* new byteorder */
67        int      i;          /* counter */
68
69        /* executable code */
70
71        if  (strlen(byteorder) != 4)  {
72                *status = GcfERR_ILLBYTEORDER;
73                return;
74        } /*endif*/
75
76        /* reset check array */
77        for  (i=0; i<4; i++)  chk[i] = 0;
78
79        for  (i=0; i<4; i++)  {
80
81                if  (byteorder[i] < '1' || byteorder[i] > '4')  {
82                        *status = GcfERR_ILLBYTEORDER;
83                        return;
84                } /*endif*/
85
86                bo[i] = byteorder[i] - '1';
87                chk[bo[i]] = 1;
88
89        } /*endif*/
90
91        /* check wether all numbers specified */
92        for  (i=0; i<4; i++)
93                if  (chk[i] != 1)  {
94                        *status = GcfERR_ILLBYTEORDER;
95                        return;
96                } /*endif*/
97
98        /* copy new byteorder to global variable */
99        for  (i=0; i<4; i++)
100                gcfv_byteorder[i] = byteorder[i];
101
102} /* end of GcfSetByteorder */
103
104
105
106/*----------------------------------------------------------------------------*/
107
108
109
110void GcfSetTapcode( int tapnum, char chan[], TSyStatus *status )
111
112/* sets tap code, i.e. mapping from tap number to channel name
113 *
114 * parameters of routine
115 * int        tapnum;     tap number to be set
116 * char       chan[];     2 char channel code
117 */
118{
119        /* executable code */
120
121        if  (tapnum < 0 || tapnum >= GcfMAXTAP)  {
122                *status = GcfERR_ILLTAP;
123                return;
124        } /*endif*/
125
126        gcfv_tapcode[tapnum][0] = chan[0];
127        gcfv_tapcode[tapnum][1] = chan[1];
128        gcfv_tapcode[tapnum][2] = '\0';
129
130} /* end of GcfSetTapcode */
131
132
133
134/*----------------------------------------------------------------------------*/
135
136
137
138void GcfReadUserTapcodes( char fname[], TSyStatus *status )
139
140/* Reads tap code names from file
141 *
142 * parameters of routine
143 * char       fname[];    input; name of file or NULL
144 *                              (then read from $HOME/.tapcodes)
145 * TSyStatus  *status;    output; return status
146 */
147{
148        /* local variables */
149        char     fn[cBcFileLth+1];   /* name of input file */
150        char     *env;               /* pointer to environment */
151        FILE     *fp;                /* pointer to input file */
152        char     line[cBcLineLth+1]; /* current line of file */
153        int      tc;                 /* tapcode */
154        char     chan[cBcLineLth+1]; /* channel name */
155
156        /* executable code */
157
158        if  (fname == NULL)  {
159                env = (char *)getenv( "HOME" );
160                if  (strlen(env) >= cBcFileLth-10)  {
161                        *status = GcfERR_STROVFL;
162                        return;
163                } /*endif*/
164                strcpy( fn, env );
165                strcat( fn, "/.tapcodes" );
166        } else {
167                if  (strlen(fname) >= cBcFileLth)  {
168                        *status = GcfERR_STROVFL;
169                        return;
170                } /*endif*/
171                strcpy( fn, fname );
172        } /*endif*/
173
174        fp = fopen( fn, "r" );
175        if  (fp == NULL)  {
176                fprintf( stderr,
177                        "gcf: no user defined tapcodes found, using defaults\n" );
178                return;
179        } /*endif*/
180
181        while  (fgets(line,cBcLineLth,fp) != NULL)  {
182                if  (*line == '!' || *line == '#' || *line == '\n')  continue;
183                if  (sscanf(line,"%d %s",&tc,chan) != 2)  {
184                        *status = GcfERR_TAPCODEFILE;
185                        return;
186                } /*endif*/
187                if  (tc < 0 || tc > 9)  {
188                        *status = GcfERR_ILLTAPCODE;
189                        return;
190                } /*endif*/
191                if  (strlen(chan) > 2)  {
192                        *status = GcfERR_TAPCODEFILE;
193                        return;
194                } /*endif*/
195                gcfv_tapcode[tc][0] = chan[0];
196                gcfv_tapcode[tc][1] = chan[1];
197                gcfv_tapcode[tc][2] = '\0';
198        } /*endwhile*/
199
200        fclose( fp );
201
202} /* end of GcfReadUserTapcodes */
203
204
205
206/*----------------------------------------------------------------------------*/
207
208
209
210void GcfReadRawHeader( FILE *gcf, GcfRawHeaderT *rhdr, TSyStatus *status )
211
212/* Reads raw header from GCF file.
213 *
214 * parameters of routine
215 * FILE          *gcf;      input; pointer to input GCF file (should be rewound)
216 * GcfRawHeaderT *rhdr;     output; header longwords read from file
217 * TSyStatus     *status;   output; return status
218 */
219{
220        /* local variables */
221
222        /* executable code */
223
224        rhdr->system_id = GcfGet4Bytes( gcf, status );
225        if  (SySevere(status))  {
226                *status = GcfERR_EOF_FOUND;
227                return;
228        } /*endif*/
229        rhdr->stream_id = GcfGet4Bytes( gcf, status );
230        if  (SySevere(status))  return;
231        rhdr->date_code = GcfGet4Bytes( gcf, status );
232        if  (SySevere(status))  return;
233        rhdr->data_format = GcfGet4Bytes( gcf, status );
234        if  (SySevere(&status))  return;
235
236} /* end of GcfReadRawHeader */
237
238
239
240/*----------------------------------------------------------------------------*/
241
242
243
244void GcfDecodeHeader( GcfRawHeaderT *rhdr, GcfHeaderT *hdr, TSyStatus *status )
245
246/* Decodes raw header
247 *
248 * parameters fo routine
249 * GcfRawHeaderT *rhdr;       input; raw header
250 * GcfHeaderT    *hdr;        output; decoded header
251 * TSyStatus     *status;     output; return status
252 */
253{
254        /* local variables */
255        int           i;           /* counter */
256        NTIME         ntime;       /* numeric start time */
257        int           offset;      /* time offset */
258        int           denom;       /* denominator of fraction of seconds */
259        float         secoff;      /* offset in seconds */
260
261        /* executable code */
262
263        /* decode two base36 strings */
264        GcfBase36ToString( rhdr->system_id, hdr->system_id );
265        GcfBase36ToString( rhdr->stream_id, hdr->stream_id );
266
267        /* get station, chan, comp */
268        strncpy( hdr->station, hdr->stream_id, GcfSTATION_LENGTH );
269        i = GcfSTATION_LENGTH;
270        while  (i > 0 && hdr->station[i] <= ' ')
271                hdr->station[i--] = '\0';
272        i = hdr->stream_id[GcfSTATION_LENGTH+1] - '0';
273        if  (i < 0 || i >= GcfMAXTAP)  {
274                *status = GcfERR_ILLTAP;
275                return;
276        } /*endif*/
277        hdr->chan[0] = gcfv_tapcode[i][0];
278        hdr->chan[1] = gcfv_tapcode[i][1];
279        hdr->chan[2] = '\0';
280        hdr->chan[GcfCHAN_LENGTH] = '\0';
281        hdr->comp = hdr->stream_id[GcfSTATION_LENGTH];
282
283        /* get time info */
284        GcfDecodeTime( rhdr->date_code, &ntime );
285        tc_n2t( &ntime, hdr->blktime, status );
286        if  (SySevere(status))  return;
287        i = strlen( hdr->blktime ) - 4;
288        if  (strcmp(hdr->blktime+i,".000") == 0)  hdr->blktime[i] = '\0';
289
290        /* data format bytes */
291        hdr->smprate = (rhdr->data_format & 0x00ff0000) >> 16;
292        hdr->cmpcode = (rhdr->data_format & 0x00000f00) >>  8;
293        hdr->numrec  = (rhdr->data_format & 0x000000ff);
294
295        /* extended settings */
296        offset       = (rhdr->data_format & 0x0000f000) >> 12; /* time offset */
297        switch (hdr->smprate) {
298        case 157:   hdr->smprate =    0; /* should be 0.1   */ denom=0;  break;
299        case 161:   hdr->smprate =    0; /* should be 0.125 */ denom=0;  break;
300        case 162:   hdr->smprate =    0; /* should be 0.2   */ denom=0;  break;
301        case 164:   hdr->smprate =    0; /* should be 0.25  */ denom=0;  break;
302        case 167:   hdr->smprate =    0; /* should be 0.5   */ denom=0;  break;
303        case 171:   hdr->smprate =  400;                       denom=8;  break;
304        case 174:   hdr->smprate =  500;                       denom=2;  break;
305        case 176:   hdr->smprate = 1000;                       denom=4;  break;
306        case 179:   hdr->smprate = 2000;                       denom=8;  break;
307        case 181:   hdr->smprate = 4000;                       denom=16; break;
308        } /*endswitch*/
309
310        /* add fraction of seconds to start time, if specified */
311        if  (denom != 0 && offset > 0)  {
312                NTIME     corrtime;    /* corrected time */
313                secoff = (float)offset / (float)denom;
314                tc_nadd( &ntime, secoff, &corrtime, status );
315                if  (SySevere(status))  return;
316                tc_n2t( &corrtime, hdr->blktime, status );
317        } /*endif*/
318
319} /* end of GcfDecodeHeader */
320
321
322
323/*----------------------------------------------------------------------------*/
324
325
326
327void GcfPrintHeader( FILE *out, GcfHeaderT *hdr )
328
329/* Prints header infomration in one line to given output stream
330 *
331 * parameters of routine
332 * FILE       *out;      input; output stream
333 * GcfHeaderT *hdr;      input; header to be printed
334 */
335{
336        /* local variables */
337        int      numbits;       /* number of bits */
338
339        /* executable code */
340
341        switch (hdr->cmpcode)  {
342        case GcfCMP_8BIT:
343                numbits = 8;
344                break;
345        case GcfCMP_16BIT:
346                numbits = 16;
347                break;
348        case GcfCMP_32BIT:
349                numbits = 32;
350                break;
351        default:
352                numbits = 0;
353                break;
354        } /*endswitch*/
355
356        fprintf( out, "%6s %6s %4s-%2s-%c %20s %3dHz %2dbit %3dr",
357                hdr->system_id, hdr->stream_id, hdr->station, hdr->chan, hdr->comp,
358                hdr->blktime, hdr->smprate, numbits, hdr->numrec );
359
360} /* end of GcfPrintHeader */
361
362
363
364/*----------------------------------------------------------------------------*/
365
366
367
368void GcfSkipDataBlock( FILE *gcf, GcfRawHeaderT *rhdr )
369
370/* skips data block (jumps to next header or EOF) after a raw header has been
371 * read
372 *
373 * parameters of routine
374 * FILE          *gcf; input; GCF data input file
375 * GcfRawHeaderT *rhdr; input; raw header previously read
376 */
377{
378        /* local variables */
379        int      numrec;     /* number of records (longwords) following */
380
381        /* executable code */
382
383        numrec  = (rhdr->data_format & 0x000000ff);
384
385        /*fseek( gcf, (numrec+2)*sizeof(unsigned INT32), SEEK_CUR );*/
386        fseek( gcf, 252*sizeof(unsigned INT32), SEEK_CUR );
387
388} /* GcfSkipDataBlock */
389
390
391
392/*----------------------------------------------------------------------------*/
393
394
395
396GcfLongT *GcfAllocBlockMem( TSyStatus *status )
397
398/* allocates memory for raw (coded) data block
399 *
400 * parameters of routine
401 * TSyStatus  *status;      output; return status
402 *                          returns pointer to block memory
403 */
404{
405        /* local variables */
406        GcfLongT *blockmem;
407
408        /* executable code */
409
410        /* 1kB is enough for max 250 records */
411        blockmem = (GcfLongT *)malloc( 1024 );
412
413        if  (blockmem == NULL)  *status = GcfERR_ALLOCMEM;
414        return blockmem;
415
416} /* end of GcfAllocBlockMem */
417
418
419
420/*----------------------------------------------------------------------------*/
421
422
423
424int *GcfAllocBlockSamples( TSyStatus *status )
425
426/* allocates memory for decoded samples of a block
427 *
428 * parameters of routine
429 * TSyStatus  *status;      output; return status
430 *                          returns pointer to memory for samples
431 */
432{
433        /* local variables */
434        int *mem;
435
436        /* executable code */
437
438        /* 4kB is enough for max 250 records of 8bit each */
439        mem = (int *)malloc( 4096 );
440
441        if  (mem == NULL)  *status = GcfERR_ALLOCMEM;
442        return mem;
443
444} /* end of GcfAllocBlockSamples */
445
446
447
448/*----------------------------------------------------------------------------*/
449
450
451
452void GcfReadDataBlock( FILE *gcf, GcfRawHeaderT *rhdr, GcfLongT *mem,
453        TSyStatus *status )
454
455/* read in single data block from GCF file.  Corresponding header must
456 * be already read in.
457 *
458 * parameters of routine
459 * FILE       *gcf;      input; pointer to input GCF file
460 * GcfRawHeaderT *rhdr;  input; GCF raw header previously read
461 * GcfLongT   *mem;      output; block read in
462 * TSyStatus  *status;   output; return status
463 */
464{
465        /* local variables */
466        int      i;            /* counter */
467        int      numrecs=252;  /* number of records to read */
468
469        /* executable code */
470
471        /* assume 1kB data blocks and header already read in */
472        for  (i=0; i<numrecs; i++)  {
473                mem[i] = GcfGet4Bytes( gcf, status );
474                if  (SySevere(status))  return;
475        } /*endif*/
476
477} /* end of GcfReadDataBlock */
478
479
480
481/*----------------------------------------------------------------------------*/
482
483
484
485void GcfDecodeBlock( GcfRawHeaderT *rhdr, GcfLongT *block, int *samples,
486        int *smpnum, TSyStatus *status )
487
488/* Decodes samples of a block.  Memory must be already allocated using
489 * appropriate routines
490 *
491 * paramters of routine
492 * GcfRawHeaderT *rhdr;      input; GCF raw header previously read
493 * GcfLongT      *block;     input; data block previously read
494 * int           *samples;   output; samples decoded
495 * int           *smpnum;    output; number of samples
496 * TSyStatus     *status;    output; return status
497 */
498{
499        /* local variables */
500        int      i, j;     /* counters */
501        int      numrec;   /* number of records */
502        int      cmpcode;  /* compression code */
503        int      cursmp;   /* current sample */
504        signed char sbyte; /* byte diff */
505        signed short si;   /* 16 bit diff */
506
507        /* executable code */
508
509        cmpcode = (rhdr->data_format & 0x00000f00) >>  8;
510        numrec  = (rhdr->data_format & 0x000000ff);
511
512        cursmp = block[0];
513
514        j = 0;
515        if  (cmpcode == GcfCMP_8BIT)  {
516                for  (i=1; i<=numrec; i++)  {
517                        sbyte = (block[i] & 0xff000000) >> 24;
518                        cursmp += sbyte;
519                        samples[j++] = cursmp;
520                        sbyte = (block[i] & 0x00ff0000) >> 16;
521                        cursmp += sbyte;
522                        samples[j++] = cursmp;
523                        sbyte = (block[i] & 0x0000ff00) >>  8;
524                        cursmp += sbyte;
525                        samples[j++] = cursmp;
526                        sbyte = (block[i] & 0x000000ff);
527                        cursmp += sbyte;
528                        samples[j++] = cursmp;
529                } /*endif*/
530        } else if  (cmpcode == GcfCMP_16BIT)  {
531                for  (i=1; i<=numrec; i++)  {
532                        si = (block[i] & 0xffff0000) >> 16;
533                        cursmp += si;
534                        samples[j++] = cursmp;
535                        si = (block[i] & 0x0000ffff);
536                        cursmp += si;
537                        samples[j++] = cursmp;
538                } /*endif*/
539        } else if  (cmpcode == GcfCMP_32BIT)  {
540                for  (i=1; i<=numrec; i++)  {
541                        cursmp += block[i];
542                        samples[j++] = cursmp;
543                } /*endif*/
544        } else {
545                /* no data block */
546        } /*endif*/
547
548        *smpnum = j;
549
550        if  (samples[j-1] != block[numrec+1])
551                /* *status = GcfERR_CHKSUM; */
552                printf( "Gcf checksum error (%d != %d)\n", samples[j-1], block[numrec+1] );
553
554} /* GcfDecodeBlock */
555
556
557
558/*---------------------------------------------------------------------*/
559
560
561
562void GcfFindFileInGfd( char stream_str[], char start[], char gfdfile[],
563        GcfFileDescrT *fdescr, TSyStatus *status )
564
565/* Finds GCF file in gfd-file of given stream and containing given
566 * start time.  If no file is found the file with the next possible
567 * time is returned
568 *
569 * parameters of routine
570 * char       stream_str[];      input; stream string like "bfo-vbb-z"
571 * char       start[];           input; start time
572 * char       gfdfile[];         input; GCF file directory
573 * GcfFileDescrT *fdescr;        output; GCF file descriptor
574 * TSyStatus  *status;           output; return status
575 */
576{
577        /* local variables */
578        FILE     *gfd;                          /* pointer to gfd-file */
579        char     line[Gcf_C_GFDLINELTH+1];      /* current line */
580        float    tdiff;                         /* time difference */
581        float    min_tdiff;                     /* minimum tdiff */
582        GcfFileDescrT next;                     /* file with next time */
583        GcfFileDescrT curr;                     /* current line */
584        char     lstream_str[cBcShortStrLth+1]; /* local lowercase stream string */
585
586        /* executable code */
587
588        if  (strlen(stream_str) > cBcShortStrLth)  {
589                *status = GcfERR_STROVFL;
590                err_setcontext( " ## stream " );
591                err_setcontext( stream_str );
592                return;
593        } /*endif*/
594
595        /* make stream string lowercase */
596        strcpy( lstream_str, stream_str );
597        ut_uncap( lstream_str );
598
599        /* initialize local descriptors */
600        strcpy( next.stream, lstream_str );
601        strcpy( curr.stream, lstream_str );
602        next.t_start[0] = curr.t_start[0] = '\0';
603        next.t_end[0] = curr.t_end[0] = '\0';
604        next.name[0] = curr.name[0] = '\0';
605        strcpy( next.gfdfile, gfdfile );
606        strcpy( curr.gfdfile, gfdfile );
607        next.blkno = curr.blkno = 0;
608        next.fp = curr.fp = NULL;
609        next.pos = curr.pos = 0;
610        next.sample = curr.sample = 0;
611        next.calib = curr.calib = 0.0;
612        next.dataflags = curr.dataflags = 0;
613        next.blklth = curr.blklth = DEFAULT_BLKLTH;
614
615        gfd = sy_fopen( gfdfile, "r" );
616        if  (gfd == NULL)  {
617                *status = GcfERR_OPENINPUT;
618                err_setcontext( " ## file " );
619                err_setcontext( gfdfile );
620                return;
621        } /*endif*/
622
623        /* find requested stream and time in gfd-file */
624        next.name[0] = '\0';
625        min_tdiff = 1.0e10;
626        while  (fgets(line,Gcf_C_GFDLINELTH,gfd) != NULL)  {
627                if  (*line == '!')  continue;
628                GcfParseGfdLine( line, &curr, status );
629                if  (SySevere(status))  {fclose(gfd); return;}
630                if  (strcmp(curr.stream,lstream_str) != 0)  continue;
631                tdiff = tc_tdiff( start, curr.t_start, status );
632                if  (SySevere(status))  {fclose(gfd); return;}
633                if  (tdiff >= 0.0 && tc_tdiff(start,curr.t_end,status) < 0.0)  {
634                        /* found it ! */
635                        *fdescr = curr;
636                        fclose( gfd );
637                        if  (fdescr->calib == 0.0)  {
638                                fdescr->calib =
639                                        GcfFindStreamCalibration( fdescr->stream, start, status );
640                                if  (*status == GcfERR_NOCALIB)  {
641                                        *status = cBcNoError;
642                                        fdescr->dataflags |= Gcf_F_QUAL_NOCALIB;
643                                } /*endif*/
644                        } /*endif*/
645                        if  (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0)
646                                GcfAdjustFilename( fdescr, status );
647                        return;
648                } else if  (tdiff < 0.0)  {
649                        /* store file with time next to requested */
650                        if  (SySevere(status))  {fclose(gfd); return;}
651                        if  (next.name[0] == '\0' || tdiff > min_tdiff)  {
652                                min_tdiff = tdiff;
653                                next = curr;
654                        } /*endif*/
655                        if  (next.calib == 0.0)  {
656                                next.calib =
657                                        GcfFindStreamCalibration( next.stream, start, status );
658                                if  (*status == GcfERR_NOCALIB)  {
659                                        *status = cBcNoError;
660                                        next.dataflags |= Gcf_F_QUAL_NOCALIB;
661                                } /*endif*/
662                        } /*endif*/
663                } /*endif*/
664                if  (SySevere(status))  {fclose(gfd); return;}
665        } /*endwhile*/
666
667        *status = (next.name[0] == '\0') ? GcfERR_GFD_NOTFOUND : GcfERR_GFD_NEXT;
668        if  (*status == GcfERR_GFD_NOTFOUND)  {
669                err_setcontext( " ## stream " );
670                err_setcontext( lstream_str );
671                err_setcontext( ", time " );
672                err_setcontext( start );
673        } /*endif*/
674        fclose( gfd );
675        *fdescr = next;
676        if  (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0)
677                GcfAdjustFilename( fdescr, status );
678        return;
679
680} /* end of GcfFindFileInGfd */
681
682
683
684/*---------------------------------------------------------------------*/
685
686
687
688void GcfSearchPosition( int chan, char gfdfile[], char stream_str[],
689        char req_start[], char act_start[], TSyStatus *status )
690
691/* Searches for given time position in a stream file.  The corresponding
692 * GCF file is opened and positioned, its file descriptor stored
693 * in an internal variable.  'chan' must range from 0..Gcf_C_MAXCHAN-1.
694 * If the channel is already used the previously opened file is closed.
695 *
696 * parameters of routine
697 * int        chan;             input; channel number
698 * char       gfdfile[];        input; gfd-file
699 * char       stream_str[];     input; stream string
700 * char       req_start[];      input; requested start time
701 * char       act_start[];      output; actual start time
702 * TSyStatus  *status;          output; return status
703 */
704{
705        /* local variables */
706        TSyBoolean  next_time;   /* only next time possible */
707        float    tdiff_tot;      /* total time window of file */
708        float    tdiff_start;    /* difference to request time */
709        GcfFileDescrT *fd;       /* pointer to file descriptor */
710        INT32    seek_pos;       /* seek position */
711        NTIME    req_ntime;      /* requested time in NTIME format */
712        NTIME    cur_ntime;      /* start time of current GCF block */
713        float    cur_span;       /* time span (sec) of current GCF block */
714        float    dt;             /* sample distance in sec */
715        int      jump_blk;       /* number of blocks to jump */
716        int      new_pos;        /* new block position */
717        int      jump_cnt;       /* jump counter */
718        GcfRawHeaderT rhdr;      /* GCF raw header */
719        GcfHeaderT hdr;          /* GCF decoded header */
720
721        /* executable code */
722
723        if  (chan < 0 || chan >= Gcf_C_MAXCHAN)  {
724                *status = GcfERR_CHAN_OOR;
725                return;
726        } /*endif*/
727        fd = gcfv_fd + chan;
728
729        if  (fd->fp != NULL)  {
730                fclose( fd->fp );
731                fd->fp = NULL;
732        } /*endif*/
733
734        GcfFindFileInGfd( stream_str, req_start, gfdfile, fd, status );
735        next_time =  (*status == GcfERR_GFD_NEXT);
736        if  (next_time)  *status = cBcNoError;
737        if  (SySevere(status))  return;
738
739        if  (gcfv_logrec)  printf( "{%s}", fd->name );
740        fd->fp = fopen( fd->name, "r" );
741        if  (fd->fp == NULL)  {
742                *status = GcfERR_OPENINPUT;
743                err_setcontext( " ## file " );
744                err_setcontext( fd->name );
745                fd->fp = NULL;
746                return;
747        } /*endif*/
748
749        if  (next_time)  {
750                strcpy( act_start, fd->t_start );
751                *status = GcfERR_NEXTTIMEPOS;
752                return;
753        } /*endif*/
754        tc_t2n( req_start, &req_ntime, status );
755        if  (SySevere(status))  return;
756
757        /* compute approximate block position */
758        tdiff_tot = tc_tdiff( fd->t_end, fd->t_start, status );
759        if  (SySevere(status))  return;
760        tdiff_start = tc_tdiff( req_start, fd->t_start, status );
761        if  (SySevere(status))  return;
762        new_pos = Nint( (float)((fd->blkno)-1)/tdiff_tot * tdiff_start );
763
764        for  (jump_cnt=0; jump_cnt<4; jump_cnt++)  {
765
766                /* position GCF file */
767                if  (new_pos != fd->pos)  {
768                        if  (new_pos >= fd->blkno)  new_pos = fd->blkno-1;
769                        if  (new_pos < 0)  new_pos = 0;
770                        fd->pos = new_pos;
771                        seek_pos = (INT32)(fd->pos) * (INT32)(fd->blklth);
772                        if  (gcfv_logrec)  printf( "-" );
773                        if  (fseek(fd->fp,seek_pos,SEEK_SET) != 0/*seek_pos*/)  {
774                                *status = GcfERR_GCFSEEK;
775                                err_setcontext( " ## file " );
776                                err_setcontext( fd->name );
777                                return;
778                        } /*endif*/
779                } /*endif*/
780
781                /* read current GCF block */
782                if  (gcfv_logrec)  printf( "[%d]", fd->pos );  /* log */
783                GcfReadRawHeader( fd->fp, &rhdr, status );
784                if  (SySevere(status)) {
785                        err_setcontext( " ## file " );
786                        err_setcontext( fd->name );
787                        return;
788                } /*endif*/
789                GcfSkipDataBlock( fd->fp, &rhdr );
790                GcfDecodeHeader( &rhdr, &hdr, status );
791                if  (SySevere(status)) {
792                        err_setcontext( " ## file " );
793                        err_setcontext( fd->name );
794                        return;
795                } /*endif*/
796                (fd->pos)++;
797                dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate;
798
799                /* check time found (return if time found) */
800                tc_t2n( hdr.blktime, &cur_ntime, status );
801                if  (SySevere(status))  return;
802                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
803                if  (SySevere(status))  return;
804                cur_span = (hdr.smprate == 0)
805                        ? 0.0 : (float)(hdr.numrec*hdr.cmpcode/hdr.smprate);
806                if  (tdiff_start >= 0.0)  {
807                        if  (cur_span > tdiff_start)  {
808                                /* found it ! */
809                                seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->blklth);
810                                fseek( fd->fp, seek_pos, SEEK_SET );
811                                fd->sample = Nint( tdiff_start/dt );
812                                if  (fd->sample >/*=*/ (hdr.numrec*hdr.cmpcode))  {
813                                        printf( "! GcfSearchPosition: sample position adjusted (1)\n" );
814                                        fd->sample = hdr.numrec*hdr.cmpcode /*- 1*/;
815                                } /*endif*/
816                                tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status );
817                                if  (Severe(status))  return;
818                                tc_n2t( &req_ntime, act_start, status );
819                                return;
820                        } /*endif*/
821                } /*endif*/
822
823                /* estimate next jump */
824                if  (tdiff_start > 0.0)  tdiff_start -= cur_span;
825                jump_blk = Nint( (tdiff_start/cur_span) - 0.5 );
826                if  (jump_blk >= 0)  jump_blk++;  else  jump_blk--;
827                new_pos = fd->pos - 1 + jump_blk;
828
829        } /*endfor*/
830
831        /* if still not found then read block by block */
832        if  (gcfv_logrec)  printf( "|" );
833
834        /* go back to time before */
835        tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
836        while  (tdiff_start < 0.0)  {
837                fd->pos -= 2;
838                if  (fd->pos < 0)  {
839                                fprintf( stderr, "*** GcfSearchPosition: check gfdfile\n" );
840                                *status = GcfERR_BUG;
841                                return;
842                } /*endif*/
843                seek_pos = (INT32)(fd->pos) * (INT32)(fd->blklth);
844                if  (gcfv_logrec)  printf( "-" );
845                if  (fseek(fd->fp,seek_pos,SEEK_SET) != 0/*seek_pos*/)  {
846                        *status = GcfERR_GCFSEEK;
847                        err_setcontext( " ## file " );
848                        err_setcontext( fd->name );
849                        return;
850                } /*endif*/
851                if  (gcfv_logrec)  printf( "[%d]", fd->pos );  /* log */
852                GcfReadRawHeader( fd->fp, &rhdr, status );
853                if  (SySevere(status))  {
854                        err_setcontext( " ## file " );
855                        err_setcontext( fd->name );
856                        return;
857                } /*endif*/
858                GcfSkipDataBlock( fd->fp, &rhdr );
859                GcfDecodeHeader( &rhdr, &hdr, status );
860                if  (SySevere(status))  return;
861                (fd->pos)++;
862                dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate;
863                tc_t2n( hdr.blktime, &cur_ntime, status );
864                if  (Severe(status))  return;
865                /* check for time correction, K.S. 16-Mar-99 */
866                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
867                if  (Severe(status))  return;
868                cur_span = (float)(hdr.numrec*hdr.cmpcode/hdr.smprate);
869        } /*endwhile*/
870
871        /* now find forward */
872        while  (tdiff_start >= cur_span)  {
873                if  (gcfv_logrec)  printf( "[%d]", fd->pos );  /* log */
874                GcfReadRawHeader( fd->fp, &rhdr, status );
875                if  (SySevere(status))  {
876                        err_setcontext( " ## file " );
877                        err_setcontext( fd->name );
878                        return;
879                } /*endif*/
880                (fd->pos)++;
881                GcfSkipDataBlock( fd->fp, &rhdr );
882                GcfDecodeHeader( &rhdr, &hdr, status );
883                if  (SySevere(status))  return;
884                dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate;
885                tc_t2n( hdr.blktime, &cur_ntime, status );
886                if  (Severe(status))  return;
887                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
888                if  (Severe(status))  return;
889                cur_span = (hdr.smprate == 0)
890                        ? 0.0 : (float)(hdr.numrec*hdr.cmpcode/hdr.smprate);
891        } /*endwhile*/
892
893        /* step one block back to get it again on next read command */
894        seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->blklth);
895        fseek( fd->fp, seek_pos, SEEK_SET );
896
897        if  (tdiff_start >= 0.0)  {
898                /* now found it */
899                fd->sample = Nint( tdiff_start/dt );
900                if  (fd->sample >/*=*/ (int)(hdr.numrec*hdr.cmpcode))  {
901                        printf( "! GcfSearchPosition: sample position adjusted (2)\n" );
902                        fd->sample = hdr.numrec*hdr.cmpcode /*- 1*/;
903                } /*endif*/
904                tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status );
905                if  (Severe(status))  return;
906                tc_n2t( &req_ntime, act_start, status );
907        } else {
908                /* time gap */
909                /* printf( "*** time gap: next possible time positioned ***\n" ); */
910                tc_n2t( &cur_ntime, act_start, status );
911                *status = GcfERR_NEXTTIMEPOS;
912        } /*endif*/
913
914} /* end of GcfSearchPosition */
915
916
917
918/*---------------------------------------------------------------------*/
919
920
921
922void GcfReadNextBlock( int chan, GcfRawHeaderT *rhdr, GcfLongT *blk,
923        TSyStatus *status )
924
925/* Reads next available block (header and data) from GCF file.
926 *
927 * parameters of routine
928 * int        chan;               input; channel number
929 * GcfRawHeaderT *rhdr;           output; coded header of block
930 * GcfLongT   *blk;               output; coded data of block
931 * TSyStatus  *status;            output; return status
932 */
933{
934        /* local variables */
935        GcfFileDescrT *fd;                   /* GCF file descriptor */
936        char     l_gfdfile[cBcFileLth+1];    /* local sfdfile */
937        char     l_stream[cBcShortStrLth+1]; /* local stream string */
938        char     l_t_end[cBcTimeLth+1];      /* end of file time */
939        char     act_time[cBcTimeLth+1];     /* positioned time */
940        TSyBoolean time_gap;                 /* time gap found */
941
942        /* executable code */
943
944        /* check channel number */
945        if  (chan < 0 || chan >= Gcf_C_MAXCHAN)  {
946                *status = GcfERR_CHAN_OOR;
947                return;
948        } /*endif*/
949        fd = gcfv_fd + chan;
950
951        if  (fd->fp == NULL)  {
952                *status = GcfERR_NOT_OPEN;
953                return;
954        } /*endif*/
955
956        /* store filename for last used file request */
957        strcpy( gcfv_last_fname, fd->name );
958
959        time_gap = FALSE;
960        if  (fd->pos >= fd->blkno)  {
961                /* is at end of file */
962                strcpy( l_gfdfile, fd->gfdfile );
963                strcpy( l_stream, fd->stream );
964                strcpy( l_t_end, fd->t_end );
965                GcfSearchPosition( chan, l_gfdfile, l_stream, l_t_end,
966                        act_time, status );
967                time_gap = (*status == GcfERR_NEXTTIMEPOS);
968                if  (time_gap)  *status = cBcNoError;
969                if  (SySevere(status))  return;
970        } /*endif*/
971
972        if  (gcfv_logrec)  printf( "<%d>", fd->pos );  /* log */
973        GcfReadRawHeader( fd->fp, rhdr, status );
974        if  (SySevere(status)) return;
975        GcfReadDataBlock( fd->fp, rhdr, blk, status );
976        if  (SySevere(status)) return;
977        (fd->pos)++;
978
979        if  (time_gap)  *status = GcfERR_NEXTTIMEPOS;
980
981} /* end of GcfReadNextBlock */
982
983
984
985/*---------------------------------------------------------------------*/
986
987
988
989#define ON_ERROR_RETURN  \
990        if  (SySevere(status))  { \
991                GcfFreeMem(blk); \
992                GcfFreeMem(blksmp); \
993                return; \
994        }
995
996
997
998void GcfReadStream( int chan, char gfdfile[], char stream_str[],
999        TSyBoolean unused, char req_start[], float seclth, INT32 **ldat,
1000        INT32 *smplth, char act_start[], float *dt, float *calib,
1001        int *flags, TSyStatus *status )
1002
1003/* Reads sample data from GCF file.  The memory for the sample
1004 * data is allocated by the routine.  The channel number is chosen
1005 * by the caller of the routine.  It is legal to use always channel
1006 * number 0 but it is faster to use a separate channel number for
1007 * each stream used if the streams are read repeatedly.
1008 *
1009 * parameters of routine
1010 * int        chan;         input; channel number (0..Gcf_C_MAXCHAN-1)
1011 * char       gfdfile[];    input; name of gfd file to use
1012 * char       stream_str[]; input; stream string (like "bfo-vbb-z")
1013 * TSyBoolean unused;
1014 * char       req_start[];  input; requested start time
1015 * float      seclth;       input; number of seconds to be read
1016 * INT32      **ldat;       output; sample array read
1017 * INT32      *smplth;      output; number of samples read
1018 * char       act_start[];  output; actual start time
1019 * float      *dt;          output; sample distance in sec
1020 * float      *calib;       output; calibration constant
1021 * int        *flags;       output; data flags found
1022 * TSyStatus  *status;      output; return status
1023 */
1024{
1025        /* local variables */
1026        GcfFileDescrT *fd;    /* pointer to SEED file descriptor */
1027        INT32    getlth;      /* number of samples to read */
1028        INT32    maxblksmp;   /* maximum number of samples per block */
1029        int      actblksmp;   /* actual number of samples in block */
1030        int      *lsrc, *ldst;/* moving pointers */
1031        NTIME    blkstart;    /* block start time */
1032        NTIME    blkend;      /* block end time */
1033        NTIME    expectime;   /* expected time */
1034        float    tdiff;       /* time gap in sec */
1035        INT32    padcnt;      /* counter for zero padding */
1036        char     str[cBcTimeLth+1];  /* scratch string for time output */
1037        int      i;           /* counter */
1038        GcfLongT *blk;        /* coded block data */
1039        int      *blksmp;     /* decoded samples of a block */
1040        GcfRawHeaderT rhdr;   /* coded GCF header */
1041        GcfHeaderT hdr;       /* decoded GCF header */
1042        int      lastsmp;     /* value of last sample (for padding) */
1043
1044        /* executable code */
1045
1046        GcfReadUserTapcodes( NULL, status );
1047        if  (SySevere(status))  return;
1048
1049        /* check channel number */
1050        if  (chan < 0 || chan >= Gcf_C_MAXCHAN)  {
1051                *status = GcfERR_CHAN_OOR;
1052                return;
1053        } /*endif*/
1054        fd = gcfv_fd + chan;
1055
1056        /* find requested position */
1057        tdiff = 0.0;
1058        GcfSearchPosition( chan, gfdfile, stream_str, req_start,
1059                act_start, status );
1060        if  (*status == GcfERR_NEXTTIMEPOS)  {
1061                *status = cBcNoError;
1062                tdiff = tc_tdiff( act_start, req_start, status );
1063                if  (SySevere(status))  return;
1064                if  (tdiff >= seclth)  {*status = GcfERR_DATA_UNAVAIL; return;}
1065                fprintf( stderr,
1066                        "GcfReadStream: time %s not found, start at %s\n",
1067                        req_start, act_start );
1068        } /*endif*/
1069        if  (SySevere(status))  return;
1070
1071        maxblksmp = MAX_SMP_PER_BLK;
1072        *smplth = 0;
1073        *ldat = NULL;
1074        *dt = 0.0;
1075        expectime.year = 0;
1076        blk = GcfAllocBlockMem( status );
1077        if  (SySevere(status))  return;
1078        blksmp = GcfAllocBlockSamples( status );
1079        if  (SySevere(status))  {
1080                GcfFreeMem( blk );
1081                return;
1082        } /*endif*/
1083        lastsmp = 0;
1084
1085        FOREVER  {
1086
1087                /* read next block */
1088                GcfReadNextBlock( chan, &rhdr, blk, status );
1089                if  (*status == GcfERR_NEXTTIMEPOS)  *status = cBcNoError;
1090                ON_ERROR_RETURN
1091                GcfDecodeHeader( &rhdr, &hdr, status );
1092                ON_ERROR_RETURN
1093
1094                /* decode GCF block and select samples */
1095                /* ------------------------------------- */
1096                if  (*ldat == NULL)  {
1097
1098                        /* this is for first loop only */
1099                        /* --------------------------- */
1100                        *calib = fd->calib;
1101                        *dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate;
1102                        getlth = (hdr.smprate == 0) ? 0 : Nint32( seclth / *dt );
1103                        if  (getlth <= 0)  {*status = GcfERR_ZEROLTH; return;}
1104                        *ldat = (INT32 *)sy_allocmem( getlth, (int)sizeof(INT32), status );
1105                        ON_ERROR_RETURN
1106                        ldst = (int *)*ldat;
1107                        /* if time gap at beginning, pad zeroes */
1108                        if  (tdiff > 0.0)  {
1109                                /* pad with zeroes and adjust start time */
1110                                padcnt = Nint32( tdiff / (*dt) );
1111                                fprintf( stderr, "GcfReadStream: stream %s, time %s\n",
1112                                        hdr.stream_id, act_start );
1113                                fprintf( stderr, "   gap %5.3f sec, start with %ld zeroes\n",
1114                                        tdiff, padcnt );
1115                                tc_tadd( act_start, -(*dt)*(float)padcnt, act_start, status );
1116                                if  (SySevere(status))  *status = cBcNoError; /* ok, not elegant */
1117                                while  (padcnt-- > 0)  {
1118                                        ldst[(*smplth)++] = 0;
1119                                        if  (*smplth == getlth)  {
1120                                                GcfFreeMem( blksmp );
1121                                                fprintf( stderr,
1122                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
1123                                                strcpy( act_start, req_start );
1124                                                return;
1125                                        } /*endif*/
1126                                } /*endwhile*/
1127                        } /*endif*/
1128                        GcfDecodeBlock( &rhdr, blk, blksmp, &actblksmp, status );
1129                        ON_ERROR_RETURN
1130                        lsrc = blksmp + fd->sample;
1131                        actblksmp -= fd->sample;
1132                        if  (actblksmp < 0)  {
1133                                sy_deallocmem( *ldat );
1134                                *ldat = NULL;
1135                                GcfFreeMem( blksmp );
1136                                GcfFreeMem( blk );
1137                                *status = GcfERR_BUG;
1138                                fprintf( stderr,
1139                                        "*** GcfReadStream: bug (1) [sample: %d, actblksmp %d] ***\n",
1140                                        fd->sample, actblksmp );
1141                                return;
1142                        } /*endif*/
1143                        tc_t2n( hdr.blktime, &blkstart, status );
1144                        ON_ERROR_RETURN
1145                        tc_nadd( &blkstart, (float)(hdr.numrec*hdr.cmpcode/hdr.smprate),
1146                                &expectime, status );
1147                        ON_ERROR_RETURN
1148
1149                } else {
1150
1151                        /* this is for all other loops */
1152                        /* --------------------------- */
1153
1154                        /* decode block */
1155                        GcfDecodeBlock( &rhdr, blk, blksmp, &actblksmp, status );
1156                        ON_ERROR_RETURN
1157                        lsrc = blksmp;
1158
1159                        /* check for time gaps, pad with zeroes */
1160                        tc_t2n( hdr.blktime, &blkstart, status );
1161                        ON_ERROR_RETURN
1162                        tc_nadd( &blkstart, (float)(hdr.numrec*hdr.cmpcode/hdr.smprate),
1163                                &blkend, status );
1164                        ON_ERROR_RETURN
1165                        tdiff = tc_ndiff( &blkstart, &expectime, status );
1166                        ON_ERROR_RETURN
1167                        if  (tdiff <= -(*dt))  {
1168                                /* double data */
1169                                padcnt = Nint32( -tdiff / (*dt) );
1170                                tc_n2t( &blkstart, str, status );
1171                                fprintf( stderr, "SeedReadStream: stream %s, time %s\n",
1172                                        hdr.stream_id, str );
1173                                fprintf( stderr, "   double data, %ld samples skipped\n",
1174                                        padcnt );
1175                                if  (padcnt > (INT32)(hdr.numrec*hdr.cmpcode))  {
1176                                        /*
1177                                        *status = GcfERR_DOUBLEDATA;
1178                                        GcfFreeMem( blk );
1179                                        GcfFreeMem( blksmp );
1180                                        return;
1181                                        */
1182                                        /* throw way this block */
1183                                        continue;
1184                                } /*endif*/
1185                                /* skip samples */
1186                                lsrc += padcnt;
1187                                actblksmp -= padcnt;
1188                        } else if  (tdiff >= (*dt))  {
1189                                /* time gap */
1190                                padcnt = Nint32( tdiff / (*dt) );
1191                                tc_n2t( &blkstart, str, status );
1192                                fprintf( stderr, "GcfReadStream: stream %s, time %s\n",
1193                                        hdr.stream_id, str );
1194                                fprintf( stderr,
1195                                        "   gap %5.3f sec, padding %ld zeroes at sample %ld\n",
1196                                        tdiff, padcnt, *smplth );
1197                                /* pad zeroes */
1198                                while  (padcnt-- > 0)  {
1199                                        ldst[(*smplth)++] = lastsmp;
1200                                        if  (*smplth == getlth)  {
1201                                                GcfFreeMem( blksmp );
1202                                                GcfFreeMem( blk );
1203                                                fprintf( stderr,
1204                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
1205                                                return;
1206                                        } /*endif*/
1207                                } /*endwhile*/
1208                        } /*endif*/
1209                        expectime = blkend;
1210
1211                } /*endif*/
1212
1213                /* copy samples to output array */
1214                while  (actblksmp-- > 0)  {
1215                        ldst[(*smplth)++] = *lsrc++;
1216                        if  (*smplth == getlth)  {  /* finished ! */
1217                                GcfFreeMem( blksmp );
1218                                GcfFreeMem( blk );
1219                                return;
1220                        } /*endif*/
1221                } /*endwhile*/
1222                if  (*smplth > 0)
1223                        lastsmp = ldst[(*smplth)-1];
1224
1225        } /*endfor*/
1226
1227} /* end of GcfReadStream */
1228
1229
1230
1231/*---------------------------------------------------------------------*/
1232
1233
1234
1235void GcfOrSeedReadStream( int chan, char gfdfile[], char stream_str[],
1236        TSyBoolean swap, char req_start[], float seclth, INT32 **ldat,
1237        INT32 *smplth, char act_start[], float *dt, float *calib,
1238        int *flags, TSyStatus *status )
1239
1240/* Reads sample data from GCF or MiniSEED file.  Checks gfdfile for deciding
1241 * GCF or MiniSEED: if the the first character in gfdfile is 'g', GCF format
1242 * is read, otherwise MiniSEED format assumed. The memory for the sample
1243 * data is allocated by the routine.  The channel number is chosen
1244 * by the caller of the routine.  It is legal to use always channel
1245 * number 0 but it is faster to use a separate channel number for
1246 * each stream used if the streams are read repeatedly.
1247 *
1248 * parameters of routine
1249 * int        chan;         input; channel number (0..Gcf_C_MAXCHAN-1)
1250 * char       gfdfile[];    input; name of gfd file to use
1251 * char       stream_str[]; input; stream string (like "bfo-vbb-z")
1252 * TSyBoolean swap;         input; swap data in input
1253 * char       req_start[];  input; requested start time
1254 * float      seclth;       input; number of seconds to be read
1255 * INT32      **ldat;       output; sample array read
1256 * INT32      *smplth;      output; number of samples read
1257 * char       act_start[];  output; actual start time
1258 * float      *dt;          output; sample distance in sec
1259 * float      *calib;       output; calibration constant
1260 * TSyStatus  *status;      output; return status
1261 */
1262{
1263        /* local variables */
1264        FILE     *gfd;          /* pointer to gfdfile */
1265        char     fc;            /* first character */
1266
1267        /* executable code */
1268
1269        if  (strncmp(gfdfile,"DB:",3) == 0 || strncmp(gfdfile,"db:",3) == 0)  {
1270                /* db: works for seed only */
1271                fc = 's';
1272        } else {
1273                /* check first character in gfdfile */
1274                gfd = sy_fopen( gfdfile, "r" );
1275                if  (gfd == NULL)  {
1276                        err_setcontext( " ## file " );
1277                        err_setcontext( gfdfile );
1278                        *status = GcfERR_OPENINPUT;
1279                        return;
1280                } /*endif*/
1281                fc = (char)fgetc( gfd );
1282                sy_fclose( gfd );
1283        } /*endif*/
1284
1285        if  (fc == 'g')  {
1286
1287                GcfReadStream( chan, gfdfile, stream_str, swap, req_start,
1288                        seclth, ldat, smplth, act_start, dt, calib, flags, status );
1289
1290        } else {
1291
1292                SeedReadStream( chan, gfdfile, stream_str, swap, req_start,
1293                        seclth, ldat, smplth, act_start, dt, calib, flags, status );
1294
1295        } /*endif*/
1296
1297} /* end of GcfOrSeedReadStream */
1298
1299
1300
1301/*---------------------------------------------------------------------*/
1302
1303
1304
1305float GcfFindStreamCalibration( char stream[], char stime[], TSyStatus *status )
1306
1307/* returns calibration value for counts for given stream 'stream' at time
1308 * 'stime'.
1309 *
1310 * parameters of routine
1311 * char           stream[];     input; stream string
1312 * char           stime[];      input; time
1313 * TSyStatus      *status;      output; return status
1314 *                              returns calibration or 0.0
1315 */
1316{
1317        /* local variables */
1318        char     calfile[cBcFileLth+1];    /* name of calibration file */
1319        char     *eptr;                    /* pointer to environment variable */
1320        FILE     *fp;                      /* pointer to input file */
1321        char     line[cBcLineLth+1];       /* current line of input file */
1322        char     v_start[cBcLineLth+1];    /* start of valid time */
1323        char     v_end[cBcLineLth+1];      /* end of valid time */
1324        float    lcalib;                   /* current value of calibration */
1325
1326        /* executable code */
1327
1328        /* build filename */
1329        *calfile = '\0';
1330        eptr = (char *)getenv( "SEED_INPUTS" );
1331        if  (eptr != NULL)  {
1332                if  (strlen(eptr)+strlen(stream)+11 > cBcFileLth)  {
1333                        *status = GcfERR_STROVFL;
1334                        return 0.0;
1335                } /*endif*/
1336                strcpy( calfile, eptr );
1337                strcat( calfile, "/" );
1338        } /*endif*/
1339        strcat( calfile, "seedcalib_" );
1340        strcat( calfile, stream );
1341
1342        /* open file */
1343        fp = sy_fopen( calfile, "r" );
1344        if  (fp == NULL)  {
1345                fprintf( stderr, "--> no calibration for %s, set to 1.0\n", stream );
1346                *status = GcfERR_NOCALIB;
1347                return 1.0;
1348        } /*endif*/
1349
1350        while  (fgets(line,cBcLineLth,fp) != NULL)  {
1351                if  (*line == '!' || *line == '\n')  continue;
1352                if  (sscanf(line,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
1353                        fprintf( stderr, "--> format error in calibration file %s\n", stream );
1354                        continue;
1355                } /*endif*/
1356                if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
1357                if  (SySevere(status))  return 0.0;
1358                if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
1359                if  (SySevere(status))  return 0.0;
1360                sy_fclose( fp );
1361                return lcalib;
1362        } /*endwhile*/
1363
1364        sy_fclose( fp );
1365        fprintf( stderr, "--> no valid calibration for %s %s, set to 1.0\n",
1366                stream, stime );
1367        *status = GcfERR_NOCALIB;
1368        return 1.0;
1369
1370} /* end of GcfFindStreamCalibration */
1371
1372
1373
1374/*---------------------------------------------------------------------*/
1375
1376
1377
1378#define DO_ABORT \
1379        *status = GcfERR_GFD_READ; \
1380        err_setcontext( " ## string " ); err_setcontext( line-1 ); \
1381        return;
1382
1383
1384
1385
1386void GcfParseGfdLine( char line[], GcfFileDescrT *fd, TSyStatus *status )
1387
1388/* parses line of GFD file.  Returns structure elements 'stream',
1389 * 't_start', 't_end', 'name', 'blkno' and 'calib'.
1390 *
1391 * parameters of routine
1392 * char       line[];       input; GFD line
1393 * GcfFileDescrT *fd;       output; GCF file descriptor
1394 * TSyStatus  *status;      output; return status
1395 */
1396{
1397        /* local variables */
1398
1399        /* executable code */
1400
1401        fd->t_start[0] = '\0';
1402        fd->t_end[0] = '\0';
1403        fd->name[0] = '\0';
1404        fd->stream[0] = '\0';
1405        fd->blkno = 0;
1406        fd->blklth = DEFAULT_BLKLTH;
1407        fd->calib = 0.0;
1408        fd->dataflags = 0;
1409
1410        FOREVER  {
1411
1412                if  (*line == '>')  line++;
1413                line = strchr( line, '>' );
1414                if  (line == NULL)  break;
1415                switch  (*(line-1))  {
1416                case Gcf_C_GfdTStart:
1417                        if  (sscanf(line+1,"%s",fd->t_start) != 1)  { DO_ABORT }
1418                        break;
1419                case Gcf_C_GfdTEnd:
1420                        if  (sscanf(line+1,"%s",fd->t_end) != 1)  { DO_ABORT }
1421                        break;
1422                case Gcf_C_GfdName:
1423                        if  (sscanf(line+1,"%s",fd->name) != 1)  { DO_ABORT }
1424                        break;
1425                case Gcf_C_GfdStream:
1426                        if  (sscanf(line+1,"%s",fd->stream) != 1)  { DO_ABORT }
1427                        break;
1428                case Gcf_C_GfdBlkno:
1429                        if  (sscanf(line+1,"%d",&(fd->blkno)) != 1)  { DO_ABORT }
1430                        break;
1431                case Gcf_C_GfdBlklth:
1432                        if  (sscanf(line+1,"%d",&(fd->blklth)) != 1)  { DO_ABORT }
1433                        break;
1434                case Gcf_C_GfdCalib:
1435                        if  (sscanf(line+1,"%f",&(fd->calib)) != 1)  { DO_ABORT }
1436                        break;
1437                } /*endswitch*/
1438
1439        } /*endfor*/
1440
1441} /* end of GcfParseGfdLine */
1442
1443
1444
1445#undef DO_ABORT
1446
1447
1448
1449/*----------------------------------------------------------------------------*/
1450
1451
1452
1453GcfLongT GcfGet4Bytes( FILE *fp, TSyStatus *status )
1454
1455/* Reads 4 bytes from file
1456 *
1457 * parameters of routine
1458 * FILE       *fp;     input; pointer to file
1459 * TSyStatus  *status; output; return status
1460 *                     returns 4 bytes read
1461 */
1462{
1463        /* local variables */
1464        unsigned char  b[4];             /* bytes read */
1465        GcfLongT  val;                   /* return value */
1466
1467        /* executable code */
1468
1469        if  (fread(b,1,4,fp) != 4)  {
1470                *status = GcfERR_READFILE;
1471                return 0;
1472        } /*endif*/
1473
1474        val = (b[gcfv_byteorder[0]] << 24) + (b[gcfv_byteorder[1]] << 16)
1475                + (b[gcfv_byteorder[2]] << 8) + b[gcfv_byteorder[3]];
1476
1477        return val;
1478
1479} /* end of GcfGet4Bytes */
1480
1481
1482
1483/*----------------------------------------------------------------------------*/
1484
1485
1486
1487GcfLongT GcfOrder4Bytes( unsigned char b[] )
1488
1489/* Reorders 4 bytes read from stream to get longword
1490 *
1491 * parameters of routine
1492 * unsigned char b[];  input; 4 bytes read from file as char string
1493 *                     returns 4 bytes for longword
1494 */
1495{
1496        /* local variables */
1497        GcfLongT  val;                   /* return value */
1498
1499        /* executable code */
1500
1501        val = (b[gcfv_byteorder[0]] << 24) + (b[gcfv_byteorder[1]] << 16)
1502                + (b[gcfv_byteorder[2]] << 8) + b[gcfv_byteorder[3]];
1503
1504        return val;
1505
1506} /* end of GcfOrder4Bytes */
1507
1508
1509
1510/*----------------------------------------------------------------------------*/
1511
1512
1513
1514void GcfDecodeTime( GcfTimeT gcftime, NTIME *ntime )
1515
1516/* decodes GCF time
1517 *
1518 * parameters of routine
1519 * GcfTimeT   gcftime;      input; GCF encoded time
1520 * NTIME      *ntime;       output; numeric time
1521 */
1522{
1523        /* local variables */
1524        unsigned  wday;    /* word containing days */
1525        unsigned  wsec;    /* word containing seconds */
1526        int       daycount[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1527
1528        /* executable code */
1529
1530        wsec = gcftime & 0x0001ffff;
1531        wday = (gcftime & 0xfffe0000) >> 17;
1532
1533        /* date is referenced from 17-Nov-1989 */
1534        ntime->year = 1989;
1535        ntime->month = 10;
1536        ntime->day = 0;
1537        wday += 16;
1538        while  (wday >= daycount[ntime->month])  {
1539                wday -= daycount[ntime->month];
1540                ntime->year += (ntime->month + 1) / 12;
1541                ntime->month = (ntime->month + 1) % 12;
1542                if  (GcfIsLeapYear(ntime->year))  {
1543                        daycount[1] = 29;
1544                } else {
1545                        daycount[1] = 28;
1546                } /*endif*/
1547        } /*endwhile*/
1548        (ntime->month)++;
1549        ntime->day = wday+1;
1550
1551        ntime->hour = wsec / 3600;
1552        ntime->min = (wsec % 3600) / 60;
1553        ntime->sec = wsec % 60;
1554        ntime->ms = 0;
1555
1556} /* end of GcfDecodeTime */
1557
1558
1559
1560/*----------------------------------------------------------------------------*/
1561
1562
1563void GcfBase36ToString( GcfLongT id, char str[] )
1564
1565/* Converts base36 number to string.  Routine taken from Guralp manual.
1566 *
1567 * parameters of routine
1568 * unsigned INT32 id;       input; base36 number
1569 * char          str[];    output; decoded string
1570 */
1571{
1572        /* local variables */
1573        int      imed;    /* some counter */
1574        int      i;       /* another counter */
1575
1576        /* executable code */
1577
1578        str[6] = '\0';
1579        for  (i=5; i>=0; i--)  {
1580                imed = id % 36;
1581                if  (imed > 9)
1582                        imed += 7;
1583                str[i] = imed + '0';
1584                id /= 36;
1585        } /*endfor*/
1586
1587} /* end of GcfBase36ToString */
1588
1589
1590
1591/*---------------------------------------------------------------------*/
1592
1593
1594
1595void GcfAcceptCapfiles( TSyBoolean on_off )
1596
1597/* switches on/off whether capitalized filenames on $ROOT-paths are accepted
1598 *
1599 * parameters of routine
1600 * TSyBoolean    on_off;       input; switch
1601 */
1602{
1603        /* executable code */
1604
1605        gcfv_capfiles = on_off;
1606
1607} /* end of GcfAcceptCapfiles */
1608
1609
1610
1611/*----------------------------------------------------------------------------*/
1612
1613
1614
1615static TSyBoolean GcfIsLeapYear( int year )
1616
1617/* Returns whether year is leap year or not.
1618 *
1619 * parameters of routine
1620 * int        year;      input; year
1621 *                       returns TRUE if year is leap year
1622 */
1623{
1624        /* executable code */
1625
1626        return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
1627
1628} /* end of GcfIsLeapYear */
1629
1630
1631
1632/*---------------------------------------------------------------------*/
1633
1634
1635
1636static void GcfAdjustFilename( GcfFileDescrT *dsc, TSyStatus *status )
1637
1638/* copies directory of gfd-file to data filename
1639 *
1640 * parameters of routine
1641 * GcfFileDescrT   *dsc;        modify; GCF file descriptor
1642 * TSyStatus       *status;     output; return status
1643 */
1644{
1645        /* local variables */
1646        int      i;                      /* counter */
1647        int      strlth;                 /* string length */
1648        char     path[cBcFileLth+1];     /* path name */
1649        BOOLEAN  iscolon;                /* is there a colon ? */
1650        char     upname[cBcFileLth+1];   /* uppercase filename */
1651
1652        /* executable code */
1653
1654        /* find path in gfdfile */
1655        i = strlen( dsc->gfdfile ) - 1;
1656        while  (i >= 0 && dsc->gfdfile[i] != '/' && dsc->gfdfile[i] != ':'
1657                && dsc->gfdfile[i] != '\\')  i--;
1658        if  (i > 0)  {
1659                strncpy( path, dsc->gfdfile, i );
1660                path[i] = '\0';
1661                iscolon = (dsc->gfdfile[i] == ':');
1662        } else {
1663                *path = '\0';
1664                iscolon = FALSE;
1665        } /*endif*/
1666
1667        if  (strlen(dsc->name)-ROOTDIRLTH+strlen(path) > cBcFileLth)  {
1668                *status = GcfERR_STROVFL;
1669                return;
1670        } /*endif*/
1671
1672        if  (*path != '\0')  {
1673                strlth = strlen( path );
1674                for  (i=0; i<strlth; i++)
1675                        if  (path[i] == '\\')  path[i] = '/';
1676                if  (iscolon)  {
1677                        strcat( path, ":" );
1678                        if  (gcfv_capfiles)  {
1679                                strcpy( upname, dsc->name+ROOTDIRLTH+1 );
1680                                ut_cap( upname );
1681                                strcat( path, upname );
1682                        } else {
1683                                strcat( path, dsc->name+ROOTDIRLTH+1 );
1684                        } /*endif*/
1685                } else {
1686                        if  (gcfv_capfiles)  {
1687                                strcpy( upname, dsc->name+ROOTDIRLTH );
1688                                ut_cap( upname );
1689                                strcat( path, upname );
1690                        } else {
1691                                strcat( path, dsc->name+ROOTDIRLTH );
1692                        } /*endif*/
1693                } /*endif*/
1694        } else {
1695                strcpy( path, dsc->name+ROOTDIRLTH+1 );
1696        } /*endif*/
1697        strcpy( dsc->name, path );
1698
1699} /* end of GcfAdjustFilename */
1700
1701
1702
1703/*----------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.