source: trunk/src/libsrc/util/cosmos0putaway.c @ 7980

Revision 7980, 28.1 KB checked in by stefan, 6 months ago (diff)

struct for cosmos

  • Property svn:executable set to *
Line 
1/*
2*
3*    Based on SUDS putaway and Geomag WDC putaway.
4*    For Erol Kalcan
5*
6*/
7
8/* cosmos0putaway.c
9
10Routines for writing trace data in COSMOS V0 format.
11
12Volume 0 files have raw data values in digital counts, obtained directly from the native binary files of
13the recording instrument. (Records obtained by digitizing analog film generally do not have a V0
14file.) V0 files may have almost no quality control or checking, and so they may be treated as internal
15files by networks. V0 files have adequate information in the headers to be converted to files with
16physical values. There is one component per file, so one record obtained by a triaxial recorder will
17result in three files.
18
19Header information is populated by a database of files. We don't need to know
20about it after we use the SCNL to find the right file and prepend it.
21
22Count data is extracted from a wave server:
23
24Data Section:
25• The first line of the data section includes the type of data (accel., velocity, displ., etc.) and its
26units, the number of data points, and the format to be used in reading the data. The format
27will type be for integer or real values, as appropriate; the format for real values can be
28floating point (e.g., 8f10.5) or exponential (e.g., 5e16.7). Although not required, 80-character
29line lengths are most convenient for many engineering strong motion data users.
30• The first line is followed by as many lines of data as are needed to accommodate the number
31of points, given the format in which the data values are written.
32
33In our case we'll alway use units=counts, and interger Format=(10I8):
34First line example followed by a data line.
3517629    raw accel.   pts, approx  176 secs, units=counts (50),Format=(10I8)
36-28596  -28611  -28630  -28617  -28609  -28550  -28543  -28654  -28698  -28661
37
38*/
39
40#include <errno.h>
41#include <limits.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <time.h>
46
47#include "earthworm.h"
48#include "trace_buf.h"
49#include "swap.h"
50#include "ws_clientII.h"
51#include "cosmos0head.h"
52#include "cosmos0putaway.h"
53#include "pa_subs.h"
54#include "earthworm_simple_funcs.h"
55#include "chron3.h"
56 
57
58
59
60// just testing
61// sprintf(global_outputdir, "e:\earthworm\memphis\data\database_v0");
62
63
64
65static  long   *COSMOS0Buffer;           /* write out COSMOS0 data as long integers */
66static  char    COSMOS0OutputFormat[MAXTXT];
67static  long    LineMean;            /* average of the 60 samples in the line */
68
69
70
71/* Internal Function Prototypes */
72static int StructMakeLocal(void *, int, char, int);
73/************************************************************************
74* Initialization function,                                              *
75*       This is the Put Away startup intializer. This is called when    *
76*       the system first comes up. Here is a chance to look around      *
77*       and see if it's possible to do business, and to complain        *
78*       if not ,BEFORE an event has to be processed.                    *
79*                                                                       *
80*       For COSMOS0, all we want to do is to make sure that the       *
81*       directory where files should be written exists.                 *
82*************************************************************************/
83int COSMOS0PA_init(int OutBufferLen, char *OutDir, char *OutputFormat,
84        int debug)
85{
86        /** Allocate COSMOS0Buffer and COSMOS0BufferShort
87        We waste RAM by allocating both the long and short buffers here
88        at the beginning of the code because some fluke (feature?) of NT
89        which I don't understand becomes unhappy if we do the allocation
90        later. Win2000, of course, behaves differently, and is quite happy
91        with buffer allocation after we have determined the format of the
92        incoming data */
93        if ((COSMOS0Buffer = (long *)malloc(OutBufferLen * sizeof(char))) == NULL)
94        {
95                logit("et", "COSMOS0PA_init: couldn't malloc COSMOS0Buffer\n");
96                return EW_FAILURE;
97        }
98
99        /* Make sure that the top level output directory exists */
100        if (RecursiveCreateDir(OutDir) != EW_SUCCESS)
101        {
102                logit("e", "COSMOS0PA_init: Call to RecursiveCreateDir failed\n");
103                return EW_FAILURE;
104        }
105
106        if (strlen(OutputFormat) >= sizeof(COSMOS0OutputFormat))
107        {
108                logit("", "COSMOS0PA_init: Error: OutputFormat(%s) is too long! Quitting!\n",
109                        OutputFormat);
110                return(EW_FAILURE);
111        }
112        else
113        {
114                strcpy(COSMOS0OutputFormat, OutputFormat);
115        }
116        return EW_SUCCESS;
117}
118
119/************************************************************************
120*   This is the Put Away event initializer. It's called when a snippet  *
121*   has been received, and is about to be processed.                    *
122*   It gets to see the pointer to the TraceRequest array,               *
123*   and the number of loaded trace structures.                          *
124*                                                                       *
125*   We need to make sure that the target directory                      *
126*   exists, create it if it does not, then open the COSMOS0 file        *
127*   for writing.                                                        *
128*                                                                       *
129*   This also opens the library file, and writes its contents to our    *
130*   output file                                                         *
131*************************************************************************/
132int COSMOS0PA_next_ev(TRACE_REQ *ptrReq,
133        char *OutDir, char *LibDir, char *EventDate, char *EventTime,
134        int cadence, int debug, double Multiplier)
135
136{
137        char    COSMOS0File[4 * MAXTXT];
138        char    COSMOS0LibFile[4 * MAXTXT];
139        char    EventArcFile[4 * MAXTXT];
140/*      char    c; */
141        char    year[5];
142        char    yr[3];
143        char    mo[3];
144        char    dy[3];
145        char    hr[3];
146        char    mn[3];
147        char    sec[7];
148        char    cos_date[35]; /* Start date of data requested */
149        char    record_id[35];
150        char    str[COSMOSLINELEN];
151        char    tempstr[COSMOSLINELEN];
152        char    tempstr2[COSMOSLINELEN];
153        int     LineNumber = 0;
154        time_t  rawtime;
155        struct tm * timeinfo;
156        size_t  nfbuffer;               /* Read bytes */
157        char    *fbuffer;               /* File read buffer */
158        static long      MaxMessageSize = 100000;  /* size (bytes) of largest msg */
159        HypoArc                 arcmsg;                 /* ARC message */
160        char            timestr[80];                                    /* Holds time messages */
161        time_t          ot;
162        struct tm * (*timefunc)(const time_t *);
163        char            time_type[30] = { 0 };                                  /* Time type UTC or local */
164
165
166        /* Grab the date-related substrings that we need for filenames. */
167        strncpy(year, EventDate, 4);
168        year[4] = '\0';
169        strncpy(yr, EventDate + 2, 2);
170        yr[2] = '\0';
171        strncpy(mo, EventDate + 4, 2);
172        mo[2] = '\0';
173        strncpy(dy, EventDate + 6, 2);
174        dy[2] = '\0';
175
176        strncpy(hr, EventTime, 2);
177        hr[2] = '\0';
178        strncpy(mn, EventTime + 2, 2);
179        mn[2] = '\0';
180        strncpy(sec, EventTime + 4, 5);
181        sec[5] = '\0';
182
183        cos_date[34] = '\0';
184        record_id[34] = '\0';   
185        tempstr[0]='\0';
186
187
188        sprintf(COSMOS0File, "%s/%s%s%s%s.v0", OutDir,
189                ptrReq->sta, yr, mo, dy);
190
191        /* cos_date "06/17/2018, 18:34:38.004 GMT (Q=5) "<-35 chars; Q stands for Quality, we have no way to know that */
192        sprintf(cos_date, "%s/%s/%s, %s:%s:%s  UTC", mo, dy, year, hr, mn, sec);
193
194        RecursiveCreateDir(OutDir);
195        sprintf(COSMOS0LibFile, "%s/%s_%s_%s_%s.dlv0", 
196                LibDir, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan);
197
198        if (debug == 1)
199                logit("t", "Opening COSMOS0 library file header %s\n", COSMOS0LibFile);
200
201        /* open library file just for reading */
202        if ((COSMOS0Libfp = fopen(COSMOS0LibFile, "r")) == NULL)
203        {
204                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\n",
205                        COSMOS0LibFile, strerror(errno));
206                return EW_FAILURE;
207        }
208
209        if (debug == 1)
210                logit("et", "Opening COSMOS0 file %s\n", COSMOS0File);
211
212        /* open file */
213        if ((COSMOS0fp = fopen(COSMOS0File, "wt")) == NULL)
214        {
215                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\n",
216                        COSMOS0File, strerror(errno));
217                return EW_FAILURE;
218        }
219        /* If there's enough time to implement, this filename should be able to be specified in the dot D file. */
220        sprintf(EventArcFile, "%s/event.arc", LibDir);
221        if (debug == 1)
222                logit("t", "Attempting to open event file which always must be named event.arc and located in the LibraryDirectory. \n LibraryDirectory is currently configured as: %s\n", LibDir);
223
224        /* open Event file just for reading */
225        if ((EVENTARCfp = fopen(EventArcFile, "r")) == NULL)
226        {
227                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\nAn .arc file is required to set event information in the COSMOS file format.",
228                        EventArcFile, strerror(errno));
229                return EW_FAILURE;
230        }
231
232        /* Read file to buffer
233        *********************/
234        fbuffer = (char*)malloc(sizeof(char) * MaxMessageSize); /*check logic*/
235        if (fbuffer == NULL)
236        {
237                logit("et", "Unable to allocate memory for filter buffer\n");
238                return -1;
239        }
240
241        nfbuffer = fread(fbuffer, sizeof(char),
242                (size_t)MaxMessageSize, EVENTARCfp);
243        fclose(EVENTARCfp); // Done reading
244        if (nfbuffer == 0)
245        {
246                logit( "eto", "COSMOS0PA_next_ev: No data read from %s\n\nAn .arc file is required to set event information in the COSMOS file format.",
247                        EventArcFile);
248                return EW_FAILURE;
249        }
250        /* We should be able to do something like               origintime = arcmsg.sum.ot - GSEC1970; after parse_arc */
251        if (debug == 1) logit("et", "COSMOS0PA_next_ev: Debug: Arc parsing %s\n", EventArcFile);
252        if (parse_arc(fbuffer, &arcmsg) != 0 )
253        {
254                logit("et", "COSMOS0PA_next_ev: Error parsing %s\n",
255                        EventArcFile);
256        }
257        timefunc = localtime;
258        ot = (time_t)(arcmsg.sum.ot - GSEC1970); 
259        timeinfo = timefunc(&ot);
260        /* Copy the library file to the putaway file*/
261/*      c = fgetc(COSMOS0Libfp);
262        while (c != EOF)
263        {
264                fputc(c, COSMOS0fp);
265                c = fgetc(COSMOS0Libfp);
266        }
267*/
268        while (fgets(str, COSMOSLINELEN, COSMOS0Libfp) != NULL) {
269                LineNumber++ ;
270                switch (LineNumber) {
271                case 2: /*  2 1-40 Earthquake name (before a name has been assigned, may appear as “Record of”; test
272                                        records may use “Test Record of”, etc.).
273                                        41-80 Earthquake date and time (including time zone). */
274                        strftime(timestr, 80, "Record of                 Earthquake of %B %d, %Y, %H:%M:%S   UTC", timeinfo);
275                        fprintf(COSMOS0fp, "%s\n", timestr);
276                        break;
277                case 3: /*3 12-46 Hypocenter: 12-20 Latitude (positive North); 22-31 Longitude (positive East); and
278                                        35-37 Depth (km); 40-46 Source agency for hypocenter information.
279                                        47-80 Magnitude(s), including source agency for values (may be entered manually, so
280                                        spacing may be variable).**/
281                        sprintf(tempstr, "Hypocenter: %9.4f %9.4f H=%3.0fkm M=%3.1f, Md=%3.1f",
282                                arcmsg.sum.lat, arcmsg.sum.lon, arcmsg.sum.z, arcmsg.sum.Mpref, arcmsg.sum.Md);
283                        fprintf(COSMOS0fp, "%s\n", tempstr);
284                        break;
285                case 4: /*      4 9-42 Earthquake origin date and time, in UTC (i.e., GMT), with source agency; 43-80,
286                                        For use by preparing agency; may include note, e.g., “Preliminary Processing”, etc.*/
287
288                        /* Prepare origin time. Second can have tenths place, so leaving two spaces here to indicate
289                           we're not going to that level of precision, the timestruct doesn't have tenths. Probably worth revisiting.*/
290                        strftime(timestr, 80, "%m/%d/%Y, %H:%M:%S  ", timeinfo); 
291                        sprintf(tempstr, "Origin: %s UTC", timestr);
292                        fprintf(COSMOS0fp, "%s\n", tempstr);
293                        break;
294                case 8: /*  Record information:
295                                        8 17-50 Record start time (date and time of first sample; may be approximate - precise value
296                                        should be obtained from real header) and time quality (0 through 5 correspond to
297                                        lowest through highest quality).
298                                        59-80 Record identification, assigned by preparing agency.
299                                    "06/17/2018, 18:34:38.004 GMT (Q=5) "<- 35 chars   " (Q=5) " "38199368.SB.WLA.00.HN " <- 22char*/ 
300                        /* strncpy(record_id, str + 45, 34); no, we're not going to use any of the prev string */
301                        /* We pad with white space, because we're going to overwrite some of it, and we'll only copy
302                           the relevant characters to go up to 80, andything too long will get truncated. */
303                        sprintf(tempstr, "Rcrd start time:%s                             ", cos_date);
304                        sprintf(tempstr2, "RcrdId:%d.%s.%s.%s.%s                  ", 
305                                arcmsg.sum.qid,ptrReq->net,  ptrReq->sta, ptrReq->loc, ptrReq->chan);
306                        strncpy(tempstr + 51, tempstr2, 29);
307                        tempstr[80] = '\0'; /* Chop off any extra junk */
308                        fprintf(COSMOS0fp, "%s\n", tempstr);
309                        break;
310                case 10: /* 10 20-27 Length of raw record, as recorded (seconds); 45-54 Maximum of raw (uncorrected)
311                                        record in g (or other units);* 60-67 Time max occurs in raw record (secs after start).
312                                        Example:
313                                        Raw record length = 175.340  sec, Uncor max = 100000000, at   40.220 sec. */
314                        sprintf(tempstr, "Raw record length = %f", (ptrReq->reqEndtime - ptrReq->reqStarttime));
315                        strncpy(tempstr + 28, "sec, Uncor max =                                    ", 53);
316                        fprintf(COSMOS0fp, "%s\n", tempstr);
317                        break;
318                case 11: /*"Record Information; Line 11
319                                        11-40 Processing/release date, time and agency.
320                                        48-80 Maximum of data series in file, units, and time of maximum (seconds after start).*"
321                                        What should I put here? An example file looks like:
322                                        "Processed: 06/17/18 12:00 PDT UCB                                   "
323                                */
324                        time(&rawtime);
325                        timeinfo = gmtime(&rawtime);
326                        sprintf(tempstr, "Processed: %d/%d/%d %d:%d UTC                                       ", 
327                                (timeinfo->tm_mon + 1),
328                                timeinfo->tm_mday,
329                                (timeinfo->tm_year + 1900),
330                                timeinfo->tm_hour, 
331                                timeinfo->tm_min
332                        );
333                        fprintf(COSMOS0fp, "%s\n", tempstr);
334                        break;
335                case 47: /*AQMS normally writes this comment, but we're not using AQMS*/
336                        /* Example: | RcrdId: NC.72282711.NC.C031.HNE.01 */
337                        sprintf(tempstr, "| RcrdId: %s.%d.%s.%s.%s.%s ", /* FIX: If anyone knows what I can put here instead of 72282711, I'll do it!*/
338                                ptrReq->net, arcmsg.sum.qid, ptrReq->net, ptrReq->sta, ptrReq->chan, ptrReq->loc);
339                        fprintf(COSMOS0fp, "%s\n", tempstr);
340                        break;
341                case 48: /*AQMS normally writes this comment, but we're not using AQMS*/
342                        /*Example:|<SCNL>C031.HNE.NC.01    <AUTH> 2015/03/01 16:46:25.000*/
343                        sprintf(tempstr, "|<SCNL> %s.%s.%s.%s    <AUTH> %d/%d/%d %d:%d:%d.000",
344                                ptrReq->sta, ptrReq->chan, ptrReq->net, ptrReq->loc,
345                                (timeinfo->tm_year + 1900),     (timeinfo->tm_mon + 1), timeinfo->tm_mday,
346                                timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
347                        fprintf(COSMOS0fp, "%s", tempstr);
348                        break;
349                default: 
350                        fprintf(COSMOS0fp, "%s", str);         
351                }
352
353        }
354        fclose(COSMOS0Libfp);
355        return (EW_SUCCESS);
356}
357
358/************************************************************************
359* This is the working entry point into the disposal system. This        *
360* routine gets called for each trace snippet which has been recovered.  *
361* It gets to see the corresponding SNIPPET structure, and the event id  *
362*                                                                       *
363* For COSMOS0, this routine writes to the COSMOS0 file, pointed to by   *
364* the COSMOS0fp pointer, all of the received trace data in COSMOS0      *
365* format:                                                               *
366*                                                                       *
367*      1. COSMOS0 tag - indicating what follows                         *
368*      2. COSMOS0_STATIONCOMP struct - describe the station             *
369*      3. COSMOS0 tag - indicating what follows                         *
370*      4. COSMOS0_DESCRIPTRACE struct - describe the trace data         *
371*      5. trace data                                                    *
372*                                                                       *
373*  One bit of complexity is that we need to write the files in the      *
374*  correct byte-order. Based on the OutputFormat parameter, determine   *
375*  whether or not to swap bytes before writing the COSMOS0 file.        *
376*                                                                       *
377* WARNING: we clip trace data to -2147483648 - +2147483647 so it will   *
378*  fit in a long int. Any incoming data that is longer than 32 bits     *
379*  will be CLIPPED. cjb 5/18/2001                                       *
380*************************************************************************/
381/* Process one channel of data */
382int COSMOS0PA_next(TRACE_REQ *getThis, double GapThresh,
383        long OutBufferLen, int debug,
384        int Cadence, double Multiplier)
385{
386        TRACE2_HEADER *wf;
387        char    datatype;
388        char    day_line[122];
389        char    fourdigits[5];
390        char    hour_line[81] = ";                                                                                "; 
391        char    sample[12];
392        char    elevendigits[12];
393        char   *msg_p;        /* pointer into tracebuf data */
394        double  begintime = 0, starttime = 0, endtime = 0, currenttime = 0;
395        double  samprate, unrounded;
396        float  *f_data;
397        int     gap_count = 0;
398        int     i, j;
399        int     seconds = 0;
400        int     s_place = 0;
401        int     tabular_base;
402        int     total, raw_counts;
403        long    nfill_max = 0l;
404        long    nsamp, nfill;
405        long    nsamp_this_scn = 0l;
406        long    this_size;
407        long   *l_data;
408        short  *s_data;
409        int    current_int;
410        char    tempstr[COSMOSLINELEN];
411        char    tempstr2[COSMOSLINELEN];
412
413        /* Put this in the .d file once we know we want it. */
414        /*  double multiplier = 0.001; */
415
416        /* Check arguments */
417        if (getThis == NULL)
418        {
419                logit("e", "COSMOS0PA_next: invalid argument passed in.\n");
420                return EW_FAILURE;
421        }
422        /* Used for computing trace statistics */
423        total = 0;
424
425        if ((msg_p = getThis->pBuf) == NULL)   /* pointer to first message */
426        {
427                logit("e", "COSMOS0PA_next: Message buffer is NULL.\n");
428                return EW_FAILURE;
429        }
430        wf = (TRACE2_HEADER *)msg_p;
431
432        /* Look at the first TRACE2_HEADER and get set up of action */
433        if (WaveMsg2MakeLocal(wf) < 0)
434        {
435                logit("e", "COSMOS0PA_next: unknown trace data type: %s\n",
436                        wf->datatype);
437                return(EW_FAILURE);
438        }
439
440        nsamp = wf->nsamp;
441        starttime = wf->starttime;
442        endtime = wf->endtime;
443        samprate = wf->samprate;
444        if (samprate < 0.0001)
445        {
446                logit("et", "unreasonable samplerate (%f) for <%s.%s.%s.%s>\n",
447                        samprate, wf->sta, wf->chan, wf->net, wf->loc);
448                return(EW_FAILURE);
449        }
450        /* LAST header line now that we know sample rate*/
451        /* WRITE Dynamic header; this probably can't be here though because we need to calculate these results */
452        /* First we'll write a line that looks like this: */
453        /* 17770    raw accel.pts, approx  178 secs, units = counts(50), Format = (7I11) */
454        /*Line Cols
455        1st 1 - 8 Number of data points following; 10 - 21 Physical parameter of the data.
456        35 - 38 Approximate length of record(rounded to nearest sec; see Rhdr(66) for precise value).
457        52 - 58 Units of the data values(e.g., cm / sec2); 60 - 61 Index code for units
458        71-80 Format of the data values written on the following lines.
459        */
460        /*sprintf(hour_line, "17770    raw accel.pts, approx  178 secs, units=counts (50),Format=(10I8)\r\n"); /* we want leading spaces */
461
462/*      sprintf(tempstr, "17770    raw accel.pts,   approx  178  secs, units=counts (50),Format=(10I8)   \n");*/
463        sprintf(tempstr, "         raw accel.pts,   approx           , units=counts (50),Format=(10I8)    \n");
464        raw_counts = (getThis->reqEndtime - getThis->reqStarttime ) * samprate;
465        sprintf(tempstr2, "%d", raw_counts);
466        strncpy(tempstr, tempstr2, strlen(tempstr2));
467        seconds = (getThis->reqEndtime - getThis->reqStarttime);
468        sprintf(tempstr2, "%d secs", seconds);
469        strncpy(tempstr + 34, tempstr2, strlen(tempstr2));
470        if (fwrite(tempstr, 81, 1, COSMOS0fp) != 1)
471        {
472                logit("et", "COSMOS0PA_next: error writing COSMOS0 dynamic header line. \n");
473                return EW_FAILURE;
474        }
475        begintime = starttime;
476        /* datatype i4 = intel byte order 4 bytes, s2 = sparc byte order; 2 bytes */
477        datatype = 'n';
478        if (wf->datatype[0] == 's' || wf->datatype[0] == 'i')
479        {
480                if (wf->datatype[1] == '2') datatype = 's';
481                else if (wf->datatype[1] == '4') datatype = 'l';
482        }
483        else if (wf->datatype[0] == 't' || wf->datatype[0] == 'f')
484        {
485                if (wf->datatype[1] == '4') datatype = 'f';
486        }
487        if (datatype == 'n')
488        {
489                logit( "et", "COSMOS0PA_next: unsupported datatype: %s\n", wf->datatype );
490                return(EW_FAILURE);
491        }
492
493        if (debug == 1)
494                logit("et", "COSMOS0PA_next: working on <%s/%s/%s/%s> datatype: %c \n",
495                        wf->sta, wf->chan, wf->net, wf->loc, datatype);
496
497        /********************** loop through all the messages for this s-c-n **********************/
498        while (1)
499        {
500                /* advance message pointer to the data */
501                msg_p += sizeof(TRACE2_HEADER);
502
503                /* check for sufficient memory in output buffer */
504                this_size = (nsamp_this_scn + nsamp) * sizeof(long);
505                if (OutBufferLen < this_size)
506                {
507                        logit("e", "out of space for <%s.%s.%s.%s>; saving long trace.\n",
508                                wf->sta, wf->chan, wf->net, wf->loc);
509                        break;
510                }
511
512                /* if data are floats, clip to longs cjb 5/18/2001 */
513                switch (datatype)
514                {
515                case 's':
516                        s_data = (short *)msg_p;
517                        for (j = 0; j < nsamp; j++, nsamp_this_scn++)
518                                COSMOS0Buffer[nsamp_this_scn] = (long)s_data[j];
519                        msg_p += sizeof(short) * nsamp;
520                        break;
521                case 'l':
522                        l_data = (long *)msg_p;
523                        for (j = 0; j < nsamp; j++, nsamp_this_scn++)
524                                COSMOS0Buffer[nsamp_this_scn] = l_data[j];
525                        msg_p += sizeof(long) * nsamp;
526                        break;
527                case 'f':
528                        f_data = (float *)msg_p;
529                        /* CLIP the data to long int */
530                        for (j = 0; j < nsamp; j++, nsamp_this_scn++)
531                        {
532                                if (l_data[j] < (float)LONG_MIN)
533                                        COSMOS0Buffer[nsamp_this_scn] = LONG_MIN;
534                                else if (l_data[j] > (float)LONG_MAX)
535                                        COSMOS0Buffer[nsamp_this_scn] = LONG_MAX;
536                                else
537                                        COSMOS0Buffer[nsamp_this_scn] = (long)l_data[j];
538                        }
539                        msg_p += sizeof(float) * nsamp;
540                        break;
541                }
542
543                /* msg_p has been advanced to the next TRACE_BUF; localize bytes *
544                * and check for gaps.                                            */
545                wf = (TRACE2_HEADER *)msg_p;
546                if (WaveMsg2MakeLocal(wf) < 0)
547                {
548                        if (debug == 1)
549                                logit("e", "COSMOS0PA_next: unknown trace data type or unexpected end of data: %s\n",
550                                        wf->datatype);
551                        else
552                                logit("e", "COSMOS0PA_next: unknown trace data type or unexpected end of data.\n");
553                        break;
554                        //return(EW_FAILURE);
555                }
556                nsamp = wf->nsamp;
557                starttime = wf->starttime;
558                /* starttime is set for new packet; endtime is still set for old packet */
559                if (endtime + (1.0 / samprate) * GapThresh < starttime)
560                {
561                        /* there's a gap, so fill it */
562                        if (debug == 1)
563                                logit("e", "gap in %s.%s.%s.%s: %lf: %lf\n", wf->sta, wf->chan, wf->net,
564                                        wf->loc, endtime, starttime - endtime);
565                        nfill = (long)(samprate * (starttime - endtime) - 1);
566                        if ((nsamp_this_scn + nfill) * (long)sizeof(long) > OutBufferLen)
567                        {
568                                logit( "e", "bogus gap (%ld); skipping\n", nfill );
569                                return(EW_FAILURE);
570                        }
571                        /* do the filling */
572                        for (j = 0; j < nfill; j++, nsamp_this_scn++)
573                                COSMOS0Buffer[nsamp_this_scn] = getThis->fill; // changed from local variable fill swl
574                                                                                                                   /* keep track of how many gaps and the largest one */
575                        gap_count++;
576                        if (nfill_max < nfill)
577                                nfill_max = nfill;
578                }
579                /* Advance endtime to the new packet;        *
580                * process this packet in the next iteration */
581                endtime = wf->endtime;
582        } /******************** end while(1) ***************************************************/
583
584          /* If the sample rate is 1 sample per minute then we'll have a sample rate of .016 */
585          /* For minute data we want 24 rows of 60 samples each, 1440 samples in a day. */
586          /* A single file fills the month of October for SJG, and includes four trace types */
587          /* FYXZ, so there are a total of 2976 lines in this file. */
588
589          /* Match our metadata with our waveserver request, if possible.
590          * observatory's value is -1 if there isn't a match. */
591
592        currenttime = begintime;
593        j = 0;
594
595
596        while ((j < nsamp_this_scn) && (currenttime < getThis->reqEndtime))
597        {
598                /* Only give them what they asked for, not each sample we got back.
599                Tracebufs contain multiple samples, and we may need to request
600                an earlier one to get the start sample we need, or a later one
601                for the last sample*/
602                while (currenttime < getThis->reqStarttime) {
603                        currenttime = currenttime + 1 / samprate;
604                        j++;
605                }
606
607                s_place = 0;
608
609                /* 35-394 60I6   60 6-digit 1-minute values for the given element for that data hour.
610                *               The values are in tenth-minutes for D and I, and in
611                *               nanoTeslas for the intensity elements.
612                */
613                total = 0;
614                LineMean = 0;
615
616                i = 0;
617
618                /* WRITE DATA */
619
620                while (i < 7 && j < nsamp_this_scn)
621                {
622                        if (COSMOS0Buffer[j] != getThis->fill) {
623                                sprintf(elevendigits, "           "); /* we want leading spaces */
624                                if (((int)(COSMOS0Buffer[j] * Multiplier) > 999999) || ((int)(COSMOS0Buffer[j] * Multiplier) < -99999)) {
625                                        sprintf(sample, GAP_FILL);
626                                        /* prevent out of range string */
627                                }
628                                else {
629                                        sprintf(sample, "%d", (int)(COSMOS0Buffer[j] * Multiplier));
630                                }
631                                strcpy(elevendigits + 11 - strlen(sample), sample);
632                                strcpy(hour_line + s_place, elevendigits);
633                        }
634                        else {
635                                /* We have a gap, this is where gap data is written */
636                                //strcpy(hour_line + s_place, "  9999");
637                                sprintf(sample, GAP_FILL);
638                                strcpy(elevendigits + 11 - strlen(sample), sample);
639                                strcpy(hour_line + s_place, elevendigits);                             
640                        }
641                        s_place = s_place + 11;
642
643                        total += (int)(COSMOS0Buffer[j] * Multiplier);
644
645                        j++; i++;
646                }
647
648
649                /* 401-402       Record end marker.
650                *               Two chars 'cr'= 13 and 'nl'= 10.
651                */
652                hour_line[77] = ' '; /*Replace that null that sprintf got us*/
653                hour_line[80] = '\n';
654
655                /* Write out line */
656                if (fwrite(&hour_line, sizeof(hour_line), 1, COSMOS0fp) != 1)
657                {
658                        logit("et", "COSMOS0PA_next: error writing COSMOS0 line. \n");
659                        return EW_FAILURE;
660                }
661        }
662        return EW_SUCCESS;
663}
664
665
666
667/************************************************************************
668* This is the Put Away end event routine. It's called after we've       *
669* finished processing one event                                         *
670*                                                                       *
671* For PC-COSMOS0 - close the COSMOS0 file, pointed to by COSMOS0fp      *
672*               free COSMOS0Buffer memory to be nice to everyone else   *
673*************************************************************************/
674int COSMOS0PA_end_ev(int debug)
675{
676        fclose(COSMOS0fp);
677
678        if (debug == 1)
679                logit("t", "Closing COSMOS0 file \n");
680
681        return(EW_SUCCESS);
682}
683
684/************************************************************************
685*       This is the Put Away close routine. It's called after when      *
686*       we're being shut down.                                          *
687*************************************************************************/
688int COSMOS0PA_close(int debug)
689{
690
691        free((char *)COSMOS0Buffer);
692        return(EW_SUCCESS);
693}
694
695/*
696*
697*  Byte swapping functions
698*/
699
700/* swap bytes if necessary, depending on what machine */
701/* we have been compiled, and what machine the data   */
702/* is being read from/being written to                */
703
704static int StructMakeLocal(void *ptr, int struct_type, char data_type,
705        int debug)
706{
707        if (ptr == NULL)
708        {
709                logit("e", "StructMakeLocal: NULL pointer passed in\n");
710                return EW_FAILURE;
711        }
712
713#if defined (_INTEL)
714        if (data_type != '6')
715        {
716                if (debug == 1)
717                        logit("et", "Hoping we don't really have to do any swapping from Intel to Sun \n");
718
719        }
720
721#elif defined (_SPARC)
722        if (data_type == '6')
723        {
724                if (debug == 1)
725                        logit("et", "Hoping we don't really have to do any swapping from Sun to Intel because we've deleted from COSMOS0 the SwapDo function that suds used. \n");
726        }
727
728#endif
729        return EW_SUCCESS;
730}
731
732long Median(int number_of_array_elements, long *Array)
733{
734        long *LocalArray;
735
736        LocalArray = (long*)malloc(number_of_array_elements * sizeof(long));
737
738        qsort(&LocalArray[0], number_of_array_elements, sizeof(long), longCompareForQsort);
739        /* Get Median */
740        return(LocalArray[(long)(number_of_array_elements / 2)]);
741}
742/*****************************************************************/
743/* Just a simple compare function so that Q sort does it's thing */
744/*****************************************************************/
745int longCompareForQsort(const void *x, const void *y)
746{
747        /* compare must have const void ptr params for qsort to work */
748        const long   *ix = (const long *)x;
749        const long   *iy = (const long *)y;
750        /* returns 1, -1 or 0 */
751        return (*ix > *iy) - (*ix < *iy);
752}
Note: See TracBrowser for help on using the repository browser.