source: branches/cosmos/src/libsrc/util/cosmos0putaway.c @ 7987

Revision 7987, 33.0 KB checked in by stefan, 4 months ago (diff)

needed more real header values

  • 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        /* Allocate the meta structures */
100        if ((cosmos_info = (COSMOS *)calloc(1, sizeof(COSMOS)))
101                == (COSMOS *)NULL) {
102                logit("e",
103                        "Out of memory for COSMOS structures.\n");
104                return EW_FAILURE;
105        }
106        sprintf(cosmos_info->OutDir, "%s", OutDir);
107        /* Make sure that the top level output directory exists */
108        if (RecursiveCreateDir(cosmos_info->OutDir) != EW_SUCCESS)
109        {
110                logit("e", "COSMOS0PA_init: Call to RecursiveCreateDir failed\n");
111                return EW_FAILURE;
112        }
113
114        if (strlen(OutputFormat) >= sizeof(COSMOS0OutputFormat))
115        {
116                logit("", "COSMOS0PA_init: Error: OutputFormat(%s) is too long! Quitting!\n",
117                        OutputFormat);
118                return(EW_FAILURE);
119        }
120        else
121        {
122                strcpy(COSMOS0OutputFormat, OutputFormat);
123        }
124        return EW_SUCCESS;
125}
126
127/************************************************************************
128*   This is the Put Away event initializer. It's called when a snippet  *
129*   has been received, and is about to be processed.                    *
130*   It gets to see the pointer to the TraceRequest array,               *
131*   and the number of loaded trace structures.                          *
132*                                                                       *
133*   We need to make sure that the target directory                      *
134*   exists, create it if it does not, then open the COSMOS0 file        *
135*   for writing.                                                        *
136*                                                                       *
137*   This also opens the arc hypo file, and writes its struct to our     *
138*   struct                                                              *
139*************************************************************************/
140int COSMOS0PA_next_ev(TRACE_REQ *ptrReq,
141        char *OutDir, char *LibDir, char *EventDate, char *EventTime,
142        int cadence, int debug, double Multiplier)
143
144{
145        char    COSMOS0File[4 * MAXTXT];
146        char    COSMOS0LibFile[4 * MAXTXT];
147        char    EventArcFile[4 * MAXTXT];
148/*      char    c; */
149        char    year[5];
150        char    yr[3];
151        char    mo[3];
152        char    dy[3];
153        char    hr[3];
154        char    mn[3];
155        char    sec[7];
156        char    cos_date[35]; /* Start date of data requested */
157        char    record_id[35];
158        char    str[COSMOSLINELEN];
159        char    tempstr[COSMOSLINELEN];
160        char    tempstr2[COSMOSLINELEN];
161        int     LineNumber = 0;
162        time_t  rawtime;
163        struct tm * timeinfo;
164        size_t  nfbuffer;               /* Read bytes */
165        char    *fbuffer;               /* File read buffer */
166        static long      MaxMessageSize = 100000;  /* size (bytes) of largest msg */
167        HypoArc                 arcmsg;                 /* ARC message */
168        char            timestr[80];                                    /* Holds time messages */
169        time_t          ot;
170        struct tm * (*timefunc)(const time_t *);
171        char            time_type[30] = { 0 };                                  /* Time type UTC or local */
172
173
174        /* Grab the date-related substrings that we need for filenames. */
175        strncpy(year, EventDate, 4);
176        year[4] = '\0';
177        strncpy(yr, EventDate + 2, 2);
178        yr[2] = '\0';
179        strncpy(mo, EventDate + 4, 2);
180        mo[2] = '\0';
181        strncpy(dy, EventDate + 6, 2);
182        dy[2] = '\0';
183
184        strncpy(hr, EventTime, 2);
185        hr[2] = '\0';
186        strncpy(mn, EventTime + 2, 2);
187        mn[2] = '\0';
188        strncpy(sec, EventTime + 4, 5);
189        sec[5] = '\0';
190
191        cos_date[34] = '\0';
192        record_id[34] = '\0';   
193        tempstr[0]='\0';
194
195
196        sprintf(cosmos_info->LibDir, "%s", LibDir);
197        sprintf(cosmos_info->EventTime, "%s", EventTime);
198        sprintf(cosmos_info->EventDate, "%s", EventDate);
199
200        /* I think we already created this, but, it is OK to try again. */
201        RecursiveCreateDir(OutDir);
202        sprintf(COSMOS0LibFile, "%s/%s_%s_%s_%s.dlv0", 
203                LibDir, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan);
204
205        /* If there's enough time to implement, this filename should be able to be specified in the dot D file. */
206        sprintf(EventArcFile, "%s/event.arc", LibDir);
207        if (debug == 1)
208                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);
209
210        /* open Event file just for reading */
211        if ((EVENTARCfp = fopen(EventArcFile, "r")) == NULL)
212        {
213                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.",
214                        EventArcFile, strerror(errno));
215                return EW_FAILURE;
216        }
217
218        /* Read file to buffer
219        *********************/
220        fbuffer = (char*)malloc(sizeof(char) * MaxMessageSize); /*check logic*/
221        if (fbuffer == NULL)
222        {
223                logit("et", "Unable to allocate memory for filter buffer\n");
224                return -1;
225        }
226
227        nfbuffer = fread(fbuffer, sizeof(char),
228                (size_t)MaxMessageSize, EVENTARCfp);
229        fclose(EVENTARCfp); // Done reading
230        if (nfbuffer == 0)
231        {
232                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.",
233                        EventArcFile);
234                return EW_FAILURE;
235        }
236        /* We should be able to do something like               origintime = arcmsg.sum.ot - GSEC1970; after parse_arc */
237        if (debug == 1) logit("et", "COSMOS0PA_next_ev: Debug: Arc parsing %s\n", EventArcFile);
238        if (parse_arc(fbuffer, &cosmos_info->arcmsg) != 0 )
239        {
240                logit("et", "COSMOS0PA_next_ev: Error parsing %s\n",
241                        EventArcFile);
242        }
243
244        return (EW_SUCCESS);
245}
246
247
248/************************************************************************
249*   This we open the COSMOS0 file                                       *
250*   for writing.                                                        *
251*                                                                       *
252*   This also opens the library file, and writes its contents to our    *
253*   output file                                                         *
254*************************************************************************/
255int COSMOS0PA_header(TRACE_REQ *ptrReq,
256        char *OutDir, char *LibDir, char *EventDate, char *EventTime,
257        int cadence, int debug, double Multiplier)
258
259{
260        char    COSMOS0File[4 * MAXTXT];
261        char    COSMOS0LibFile[4 * MAXTXT];
262        char    EventArcFile[4 * MAXTXT];
263        /*      char    c; */
264        char    year[5];
265        char    yr[3];
266        char    mo[3];
267        char    dy[3];
268        char    hr[3];
269        char    mn[3];
270        char    sec[7];
271        char    cos_date[35]; /* Start date of data requested */
272        char    record_id[35];
273        char    str[COSMOSLINELEN];
274        char    tempstr[COSMOSLINELEN];
275        char    tempstr2[COSMOSLINELEN];
276        char    fifteen[16];
277        int     LineNumber = 0;
278        time_t  rawtime;
279        struct tm * timeinfo;
280        size_t  nfbuffer;               /* Read bytes */
281        char    *fbuffer;               /* File read buffer */
282        static long      MaxMessageSize = 100000;  /* size (bytes) of largest msg */
283        HypoArc                 arcmsg;                 /* ARC message */
284        char            timestr[80];                                    /* Holds time messages */
285        time_t          ot;
286        struct tm * (*timefunc)(const time_t *);
287        char            time_type[30] = { 0 };                                  /* Time type UTC or local */
288
289
290                                                                                                                /* Grab the date-related substrings that we need for filenames. */
291        strncpy(year, EventDate, 4);
292        year[4] = '\0';
293        strncpy(yr, EventDate + 2, 2);
294        yr[2] = '\0';
295        strncpy(mo, EventDate + 4, 2);
296        mo[2] = '\0';
297        strncpy(dy, EventDate + 6, 2);
298        dy[2] = '\0';
299
300        strncpy(hr, EventTime, 2);
301        hr[2] = '\0';
302        strncpy(mn, EventTime + 2, 2);
303        mn[2] = '\0';
304        strncpy(sec, EventTime + 4, 5);
305        sec[5] = '\0';
306
307        cos_date[34] = '\0';
308        record_id[34] = '\0';
309        tempstr[0] = '\0';
310
311
312        sprintf(COSMOS0File, "%s/%s_%s_%s_%s_%s%s%s_%s%s.v0", OutDir,
313                ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan, year, mo, dy, hr, mn);
314
315        /* 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 */
316        sprintf(cos_date, "%s/%s/%s, %s:%s:%s  UTC", mo, dy, year, hr, mn, sec);
317
318        RecursiveCreateDir(OutDir);
319        sprintf(COSMOS0LibFile, "%s/%s_%s_%s_%s.dlv0",
320                LibDir, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan);
321
322        if (debug == 1)
323                logit("t", "Opening COSMOS0 library file header %s\n", COSMOS0LibFile);
324
325        /* open library file just for reading */
326        if ((COSMOS0Libfp = fopen(COSMOS0LibFile, "r")) == NULL)
327        {
328                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\n",
329                        COSMOS0LibFile, strerror(errno));
330                return EW_FAILURE;
331        }
332
333        if (debug == 1)
334                logit("et", "Opening COSMOS0 file %s\n", COSMOS0File);
335
336        /* open file */
337        if ((COSMOS0fp = fopen(COSMOS0File, "wt")) == NULL)
338        {
339                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\n",
340                        COSMOS0File, strerror(errno));
341                return EW_FAILURE;
342        }
343        arcmsg = cosmos_info->arcmsg;
344        timefunc = localtime;
345        ot = (time_t)(arcmsg.sum.ot - GSEC1970);
346        timeinfo = timefunc(&ot);
347        /* Copy the library file to the putaway file*/
348        /*      c = fgetc(COSMOS0Libfp);
349        while (c != EOF)
350        {
351        fputc(c, COSMOS0fp);
352        c = fgetc(COSMOS0Libfp);
353        }
354        */
355        while (fgets(str, COSMOSLINELEN, COSMOS0Libfp) != NULL) {
356                LineNumber++;
357                sprintf(tempstr, "                                                                                ");/*clear it*/
358                sprintf(fifteen, "               ");
359                switch (LineNumber) {
360                case 2: /*  2 1-40 Earthquake name (before a name has been assigned, may appear as “Record of”; test
361                                records may use “Test Record of”, etc.).
362                                41-80 Earthquake date and time (including time zone). */
363                        strftime(timestr, 80, "Record of                 Earthquake of %B %d, %Y, %H:%M:%S   UTC", timeinfo);
364                        fprintf(COSMOS0fp, "%s\n", timestr);
365                        break;
366                case 3: /*3 12-46 Hypocenter: 12-20 Latitude (positive North); 22-31 Longitude (positive East); and
367                                35-37 Depth (km); 40-46 Source agency for hypocenter information.
368                                47-80 Magnitude(s), including source agency for values (may be entered manually, so
369                                spacing may be variable).**/
370                        sprintf(tempstr, "Hypocenter: %9.4f %9.4f H=%3.0fkm Md=%3.1f, Ml=%3.1f",
371                                arcmsg.sum.lat, arcmsg.sum.lon, arcmsg.sum.z, arcmsg.sum.Md, arcmsg.sum.Mpref); 
372                        fprintf(COSMOS0fp, "%s\n", tempstr);
373                        break;
374                case 4: /*      4 9-42 Earthquake origin date and time, in UTC (i.e., GMT), with source agency; 43-80,
375                                For use by preparing agency; may include note, e.g., “Preliminary Processing”, etc.*/
376
377                                /* Prepare origin time. Second can have tenths place, so leaving two spaces here to indicate
378                                we're not going to that level of precision, the timestruct doesn't have tenths. Probably worth revisiting.*/
379                        strftime(timestr, 80, "%m/%d/%Y, %H:%M:%S  ", timeinfo);
380                        sprintf(tempstr, "Origin: %s UTC", timestr);
381                        fprintf(COSMOS0fp, "%s\n", tempstr);
382                        break;
383                case 8: /*  Record information:
384                                8 17-50 Record start time (date and time of first sample; may be approximate - precise value
385                                should be obtained from real header) and time quality (0 through 5 correspond to
386                                lowest through highest quality).
387                                59-80 Record identification, assigned by preparing agency.
388                                "06/17/2018, 18:34:38.004 GMT (Q=5) "<- 35 chars   " (Q=5) " "38199368.SB.WLA.00.HN " <- 22char*/
389                                /* strncpy(record_id, str + 45, 34); no, we're not going to use any of the prev string */
390                                /* We pad with white space, because we're going to overwrite some of it, and we'll only copy
391                                the relevant characters to go up to 80, andything too long will get truncated. */
392                        sprintf(tempstr, "Rcrd start time:%s                             ", cos_date);
393                        sprintf(tempstr2, "RcrdId:%lu.%s.%s.%s.%s                  ",
394                                arcmsg.sum.qid, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan);
395                        strncpy(tempstr + 51, tempstr2, 29);
396                        tempstr[80] = '\0'; /* Chop off any extra junk */
397                        fprintf(COSMOS0fp, "%s\n", tempstr);
398                        break;
399                case 10: /* 10 20-27 Length of raw record, as recorded (seconds); 45-54 Maximum of raw (uncorrected)
400                                 record in g (or other units);* 60-67 Time max occurs in raw record (secs after start).
401                                 Example:
402                                 Raw record length = 175.340  sec, Uncor max = 100000000, at   40.220 sec. */
403                        sprintf(tempstr, "Raw record length = %f", (ptrReq->reqEndtime - ptrReq->reqStarttime));
404                        strncpy(tempstr + 28, "sec, Uncor max =                                    ", 53);
405                        fprintf(COSMOS0fp, "%s\n", tempstr);
406                        break;
407                case 11: /*"Record Information; Line 11
408                                 11-40 Processing/release date, time and agency.
409                                 48-80 Maximum of data series in file, units, and time of maximum (seconds after start).*"
410                                 What should I put here? An example file looks like:
411                                 "Processed: 06/17/18 12:00 PDT UCB                                   "
412                                 */
413                        time(&rawtime);
414                        timeinfo = gmtime(&rawtime);
415                        sprintf(tempstr, "Processed: %d/%d/%d %d:%d UTC                                       ",
416                                (timeinfo->tm_mon + 1),
417                                timeinfo->tm_mday,
418                                (timeinfo->tm_year + 1900),
419                                timeinfo->tm_hour,
420                                timeinfo->tm_min
421                        );
422                        fprintf(COSMOS0fp, "%s\n", tempstr);
423                        break;
424                /* Real Headers include Earthquake information similar to comments above, comments for humans, below for PRISM*/
425                case 27: /* Site geology stuff from the database are the first 4 params in this line, so read them in and leave
426                                    them be. But the 5th param we'll overwrite here with Earthquake latitude (decimal degrees, North positive)*/
427                        sprintf(fifteen, "%15.6f", arcmsg.sum.lat);
428                        strncpy(str + 60, fifteen, 15);
429                        fprintf(COSMOS0fp, "%s", str);
430                        break;
431                case 28: /* Earthquake longitude (decimal degrees, East positive), Earthquake depth (km)., Moment magnitude, M., Surface-wave magnitude, MS., Local magnitude, ML.*/
432                        sprintf(tempstr, "%15.6f%15.6f%15.6f%15.6f%15.6f", arcmsg.sum.lon, arcmsg.sum.z, -999.0, -999.0, arcmsg.sum.Mpref);
433                        fprintf(COSMOS0fp, "%s\n", tempstr);
434                        break;
435                case 29: /* Other magnitude; I guess I'll put Md here, Epicentral distance to station (km)., Epicenter-to-station azimuth (CW from north) <- we don't have those two, so -999 */
436                        sprintf(fifteen, "%15.6f", arcmsg.sum.Md);
437                        strncpy(str, fifteen, 15);                     
438                        sprintf(fifteen, "%15.6f", -999.0);
439                        strncpy(str + 15, fifteen, 15);
440                        strncpy(str + 30, fifteen, 15);
441                        fprintf(COSMOS0fp, "%s", str);
442                        break;
443                case 47: /*AQMS normally writes this comment, but we're not using AQMS*/
444                                 /* Example: | RcrdId: NC.72282711.NC.C031.HNE.01 */
445                        sprintf(tempstr, "| RcrdId: %s.%lu.%s.%s.%s.%s ", /* FIX: If anyone knows what I can put here instead of 72282711, I'll do it!*/
446                                ptrReq->net, arcmsg.sum.qid, ptrReq->net, ptrReq->sta, ptrReq->chan, ptrReq->loc);
447                        fprintf(COSMOS0fp, "%s\n", tempstr);
448                        break;
449                case 48: /*AQMS normally writes this comment, but we're not using AQMS*/
450                                 /*Example:|<SCNL>C031.HNE.NC.01    <AUTH> 2015/03/01 16:46:25.000*/
451                        sprintf(tempstr, "|<SCNL> %s.%s.%s.%s    <AUTH> %d/%d/%d %d:%d:%d.000",
452                                ptrReq->sta, ptrReq->chan, ptrReq->net, ptrReq->loc,
453                                (timeinfo->tm_year + 1900), (timeinfo->tm_mon + 1), timeinfo->tm_mday,
454                                timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
455                        fprintf(COSMOS0fp, "%s", tempstr);
456                        break;
457                default:
458                        fprintf(COSMOS0fp, "%s", str);
459                }
460
461        }
462        fclose(COSMOS0Libfp);
463        return (EW_SUCCESS);
464}
465
466/************************************************************************
467* This is the working entry point into the disposal system. This        *
468* routine gets called for each trace snippet which has been recovered.  *
469* It gets to see the corresponding SNIPPET structure, and the event id  *
470*                                                                       *
471* For COSMOS0, this routine writes to the COSMOS0 file, pointed to by   *
472* the COSMOS0fp pointer, all of the received trace data in COSMOS0      *
473* format:                                                               *
474*                                                                       *
475*      1. COSMOS0 tag - indicating what follows                         *
476*      2. COSMOS0_STATIONCOMP struct - describe the station             *
477*      3. COSMOS0 tag - indicating what follows                         *
478*      4. COSMOS0_DESCRIPTRACE struct - describe the trace data         *
479*      5. trace data                                                    *
480*                                                                       *
481*  One bit of complexity is that we need to write the files in the      *
482*  correct byte-order. Based on the OutputFormat parameter, determine   *
483*  whether or not to swap bytes before writing the COSMOS0 file.        *
484*                                                                       *
485* WARNING: we clip trace data to -2147483648 - +2147483647 so it will   *
486*  fit in a long int. Any incoming data that is longer than 32 bits     *
487*  will be CLIPPED. cjb 5/18/2001                                       *
488*************************************************************************/
489/* Process one channel of data */
490int COSMOS0PA_next(TRACE_REQ *getThis, double GapThresh,
491        long OutBufferLen, int debug,
492        int Cadence, double Multiplier)
493{
494        TRACE2_HEADER *wf;
495        char    datatype;
496        char    day_line[122];
497        char    fourdigits[5];
498        char    hour_line[81] = ";                                                                                "; 
499        char    sample[12];
500        char    elevendigits[12];
501        char    eightdigits[9];
502        char   *msg_p;        /* pointer into tracebuf data */
503        double  begintime = 0, starttime = 0, endtime = 0, currenttime = 0;
504        double  samprate, unrounded;
505        float  *f_data;
506        int     gap_count = 0;
507        int     i, j;
508        int     seconds = 0;
509        int     s_place = 0;
510        int     tabular_base;
511        int     total, raw_counts;
512        long    nfill_max = 0l;
513        long    nsamp, nfill;
514        long    nsamp_this_scn = 0l;
515        long    this_size;
516        long   *l_data;
517        short  *s_data;
518        int    current_int;
519        char    tempstr[COSMOSLINELEN];
520        char    tempstr2[COSMOSLINELEN];
521
522        /* Put this in the .d file once we know we want it. */
523        /*  double multiplier = 0.001; */
524
525        /* Check arguments */
526        if (getThis == NULL)
527        {
528                logit("e", "COSMOS0PA_next: invalid argument passed in.\n");
529                return EW_FAILURE;
530        }
531
532
533        COSMOS0PA_header(getThis, cosmos_info->OutDir, cosmos_info->LibDir, cosmos_info->EventDate, cosmos_info->EventTime, Cadence, debug, Multiplier);
534        /* Used for computing trace statistics */
535        total = 0;
536
537        if ((msg_p = getThis->pBuf) == NULL)   /* pointer to first message */
538        {
539                logit("e", "COSMOS0PA_next: Message buffer is NULL.\n");
540                return EW_FAILURE;
541        }
542        wf = (TRACE2_HEADER *)msg_p;
543
544        /* Look at the first TRACE2_HEADER and get set up of action */
545        if (WaveMsg2MakeLocal(wf) < 0)
546        {
547                logit("e", "COSMOS0PA_next: unknown trace data type: %s\n",
548                        wf->datatype);
549                return(EW_FAILURE);
550        }
551
552        nsamp = wf->nsamp;
553        starttime = wf->starttime;
554        endtime = wf->endtime;
555        samprate = wf->samprate;
556        if (samprate < 0.0001)
557        {
558                logit("et", "unreasonable samplerate (%f) for <%s.%s.%s.%s>\n",
559                        samprate, wf->sta, wf->chan, wf->net, wf->loc);
560                return(EW_FAILURE);
561        }
562        /* LAST header line now that we know sample rate*/
563        /* WRITE Dynamic header; this probably can't be here though because we need to calculate these results */
564        /* First we'll write a line that looks like this: */
565        /* 17770    raw accel.pts, approx  178 secs, units = counts(50), Format = (7I11) */
566        /*Line Cols
567        1st 1 - 8 Number of data points following; 10 - 21 Physical parameter of the data.
568        35 - 38 Approximate length of record(rounded to nearest sec; see Rhdr(66) for precise value).
569        52 - 58 Units of the data values(e.g., cm / sec2); 60 - 61 Index code for units
570        71-80 Format of the data values written on the following lines.
571        */
572        /*sprintf(hour_line, "17770    raw accel.pts, approx  178 secs, units=counts (50),Format=(10I8)\r\n"); /* we want leading spaces */
573
574/*      sprintf(tempstr, "17770    raw accel.pts,   approx  178  secs, units=counts (50),Format=(10I8)   \n");*/
575        sprintf(tempstr, "         raw accel.pts,   approx           , units=counts (50),Format=(10I8)    \n");
576        raw_counts = (getThis->reqEndtime - getThis->reqStarttime ) * samprate; 
577        sprintf(tempstr2, "%d", raw_counts);
578        strncpy(tempstr, tempstr2, strlen(tempstr2));
579        seconds = (getThis->reqEndtime - getThis->reqStarttime);
580        sprintf(tempstr2, "%d secs", seconds);
581        strncpy(tempstr + 34, tempstr2, strlen(tempstr2));
582        if (fwrite(tempstr, 81, 1, COSMOS0fp) != 1)
583        {
584                logit("et", "COSMOS0PA_next: error writing COSMOS0 dynamic header line. \n");
585                return EW_FAILURE;
586        }
587        begintime = starttime;
588        /* datatype i4 = intel byte order 4 bytes, s2 = sparc byte order; 2 bytes */
589        datatype = 'n';
590        if (wf->datatype[0] == 's' || wf->datatype[0] == 'i')
591        {
592                if (wf->datatype[1] == '2') datatype = 's';
593                else if (wf->datatype[1] == '4') datatype = 'l';
594        }
595        else if (wf->datatype[0] == 't' || wf->datatype[0] == 'f')
596        {
597                if (wf->datatype[1] == '4') datatype = 'f';
598        }
599        if (datatype == 'n')
600        {
601                logit( "et", "COSMOS0PA_next: unsupported datatype: %s\n", wf->datatype );
602                return(EW_FAILURE);
603        }
604
605        if (debug == 1)
606                logit("et", "COSMOS0PA_next: working on <%s/%s/%s/%s> datatype: %c \n",
607                        wf->sta, wf->chan, wf->net, wf->loc, datatype);
608
609        /********************** loop through all the messages for this s-c-n **********************/
610        while (1)
611        {
612                /* advance message pointer to the data */
613                msg_p += sizeof(TRACE2_HEADER);
614
615                /* check for sufficient memory in output buffer */
616                this_size = (nsamp_this_scn + nsamp) * sizeof(long);
617                if (OutBufferLen < this_size)
618                {
619                        logit("e", "out of space for <%s.%s.%s.%s>; saving long trace.\n",
620                                wf->sta, wf->chan, wf->net, wf->loc);
621                        break;
622                }
623
624                /* if data are floats, clip to longs cjb 5/18/2001 */
625                switch (datatype)
626                {
627                case 's':
628                        s_data = (short *)msg_p;
629                        for (j = 0; j < nsamp; j++, nsamp_this_scn++)
630                                COSMOS0Buffer[nsamp_this_scn] = (long)s_data[j];
631                        msg_p += sizeof(short) * nsamp;
632                        break;
633                case 'l':
634                        l_data = (long *)msg_p;
635                        for (j = 0; j < nsamp; j++, nsamp_this_scn++)
636                                COSMOS0Buffer[nsamp_this_scn] = l_data[j];
637                        msg_p += sizeof(long) * nsamp;
638                        break;
639                case 'f':
640                        f_data = (float *)msg_p;
641                        /* CLIP the data to long int */
642                        for (j = 0; j < nsamp; j++, nsamp_this_scn++)
643                        {
644                                if (l_data[j] < (float)LONG_MIN)
645                                        COSMOS0Buffer[nsamp_this_scn] = LONG_MIN;
646                                else if (l_data[j] > (float)LONG_MAX)
647                                        COSMOS0Buffer[nsamp_this_scn] = LONG_MAX;
648                                else
649                                        COSMOS0Buffer[nsamp_this_scn] = (long)l_data[j];
650                        }
651                        msg_p += sizeof(float) * nsamp;
652                        break;
653                }
654
655                /* msg_p has been advanced to the next TRACE_BUF; localize bytes *
656                * and check for gaps.                                            */
657                wf = (TRACE2_HEADER *)msg_p;
658                if (WaveMsg2MakeLocal(wf) < 0)
659                {
660                        if (debug == 1)
661                                logit("e", "COSMOS0PA_next: unknown trace data type or unexpected end of data: %s\n",
662                                        wf->datatype);
663                        else
664                                logit("e", "COSMOS0PA_next: unknown trace data type or unexpected end of data.\n");
665                        break;
666                        //return(EW_FAILURE);
667                }
668                nsamp = wf->nsamp;
669                starttime = wf->starttime;
670                /* starttime is set for new packet; endtime is still set for old packet */
671                if (endtime + (1.0 / samprate) * GapThresh < starttime)
672                {
673                        /* there's a gap, so fill it */
674                        if (debug == 1)
675                                logit("e", "gap in %s.%s.%s.%s: %lf: %lf\n", wf->sta, wf->chan, wf->net,
676                                        wf->loc, endtime, starttime - endtime);
677                        nfill = (long)(samprate * (starttime - endtime) - 1);
678                        if ((nsamp_this_scn + nfill) * (long)sizeof(long) > OutBufferLen)
679                        {
680                                logit( "e", "bogus gap (%ld); skipping\n", nfill );
681                                return(EW_FAILURE);
682                        }
683                        /* do the filling */
684                        for (j = 0; j < nfill; j++, nsamp_this_scn++)
685                                COSMOS0Buffer[nsamp_this_scn] = getThis->fill; // changed from local variable fill swl
686                                                                                                                   /* keep track of how many gaps and the largest one */
687                        gap_count++;
688                        if (nfill_max < nfill)
689                                nfill_max = nfill;
690                }
691                /* Advance endtime to the new packet;        *
692                * process this packet in the next iteration */
693                endtime = wf->endtime;
694        } /******************** end while(1) ***************************************************/
695
696          /* If the sample rate is 1 sample per minute then we'll have a sample rate of .016 */
697          /* For minute data we want 24 rows of 60 samples each, 1440 samples in a day. */
698          /* A single file fills the month of October for SJG, and includes four trace types */
699          /* FYXZ, so there are a total of 2976 lines in this file. */
700
701          /* Match our metadata with our waveserver request, if possible.
702          * observatory's value is -1 if there isn't a match. */
703
704        currenttime = begintime;
705        j = 0;
706
707
708        while ((j < nsamp_this_scn) && (currenttime < getThis->reqEndtime))
709        {
710                /* Only give them what they asked for, not each sample we got back.
711                Tracebufs contain multiple samples, and we may need to request
712                an earlier one to get the start sample we need, or a later one
713                for the last sample*/
714                while (currenttime < getThis->reqStarttime) {
715                        currenttime = currenttime + 1 / samprate;
716                        j++;
717                }
718
719                s_place = 0;
720
721                /* 35-394 60I6   60 6-digit 1-minute values for the given element for that data hour.
722                *               The values are in tenth-minutes for D and I, and in
723                *               nanoTeslas for the intensity elements.
724                */
725                total = 0;
726                LineMean = 0;
727
728                i = 0;
729
730                /* WRITE DATA */
731
732                while (i < 10 && j < nsamp_this_scn)
733                {
734                        sprintf(eightdigits, "        "); /* we want leading spaces */
735                        if (COSMOS0Buffer[j] != getThis->fill) {
736                                if (((int)(COSMOS0Buffer[j] * Multiplier) > 999999) || ((int)(COSMOS0Buffer[j] * Multiplier) < -99999)) {
737                                        sprintf(sample, GAP_FILL);
738                                        /* prevent out of range string */
739                                }
740                                else {
741                                        sprintf(sample, "%d", (int)(COSMOS0Buffer[j] * Multiplier));
742                                }
743                                strcpy(eightdigits + 8 - strlen(sample), sample);
744                                strcpy(hour_line + s_place, eightdigits);
745                        }
746                        else {
747                                /* We have a gap, this is where gap data is written */
748                                //strcpy(hour_line + s_place, "  9999");
749                                sprintf(sample, GAP_FILL);
750                                strcpy(eightdigits + 8 - strlen(sample), sample);
751                                strcpy(hour_line + s_place, eightdigits);                               
752                        }
753                        s_place = s_place + 8;
754
755                        total += (int)(COSMOS0Buffer[j] * Multiplier);
756
757                        j++; i++;
758                }
759
760
761                /* 401-402       Record end marker.
762                *               Two chars 'cr'= 13 and 'nl'= 10.
763                */
764                /*hour_line[77] = ' '; /*Replace that null that sprintf got us*/
765                hour_line[80] = '\n';
766
767                /* Write out line */
768                if (fwrite(&hour_line, sizeof(hour_line), 1, COSMOS0fp) != 1)
769                {
770                        logit("et", "COSMOS0PA_next: error writing COSMOS0 line. \n");
771                        return EW_FAILURE;
772                }
773        }
774        /* After we process all of the data, we have to write:
775                        End-of-Data Flag Line:
776                N+1 1 -11 End of data flag string, “End-of-data for..”.
777                21-36 Station channel number and physical parameter of data (a checksum may optionally
778                be included on the remainder of this line).  */
779        sprintf(tempstr, "                                                                                ");/*clear it*/
780        sprintf(tempstr, "End-of-data for %s.%s.%s.%s acceleration", getThis->sta, getThis->chan, getThis->net, getThis->loc );
781
782        if (fwrite(tempstr, 81, 1, COSMOS0fp) != 1)
783        {
784                logit("et", "COSMOS0PA_next: error writing COSMOS0 dynamic header line. \n");
785                return EW_FAILURE;
786        }
787        return EW_SUCCESS;
788}
789
790
791
792/************************************************************************
793* This is the Put Away end event routine. It's called after we've       *
794* finished processing one event                                         *
795*                                                                       *
796* For PC-COSMOS0 - close the COSMOS0 file, pointed to by COSMOS0fp      *
797*               free COSMOS0Buffer memory to be nice to everyone else   *
798*************************************************************************/
799int COSMOS0PA_end_ev(int debug)
800{
801        fclose(COSMOS0fp);
802
803        if (debug == 1)
804                logit("t", "Closing COSMOS0 file \n");
805
806        return(EW_SUCCESS);
807}
808
809/************************************************************************
810*       This is the Put Away close routine. It's called after when      *
811*       we're being shut down.                                          *
812*************************************************************************/
813int COSMOS0PA_close(int debug)
814{
815
816        free((char *)COSMOS0Buffer);
817        return(EW_SUCCESS);
818}
819
820/*
821*
822*  Byte swapping functions
823*/
824
825/* swap bytes if necessary, depending on what machine */
826/* we have been compiled, and what machine the data   */
827/* is being read from/being written to                */
828
829static int StructMakeLocal(void *ptr, int struct_type, char data_type,
830        int debug)
831{
832        if (ptr == NULL)
833        {
834                logit("e", "StructMakeLocal: NULL pointer passed in\n");
835                return EW_FAILURE;
836        }
837
838#if defined (_INTEL)
839        if (data_type != '6')
840        {
841                if (debug == 1)
842                        logit("et", "Hoping we don't really have to do any swapping from Intel to Sun \n");
843
844        }
845
846#elif defined (_SPARC)
847        if (data_type == '6')
848        {
849                if (debug == 1)
850                        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");
851        }
852
853#endif
854        return EW_SUCCESS;
855}
856
857long Median(int number_of_array_elements, long *Array)
858{
859        long *LocalArray;
860
861        LocalArray = (long*)malloc(number_of_array_elements * sizeof(long));
862
863        qsort(&LocalArray[0], number_of_array_elements, sizeof(long), longCompareForQsort);
864        /* Get Median */
865        return(LocalArray[(long)(number_of_array_elements / 2)]);
866}
867/*****************************************************************/
868/* Just a simple compare function so that Q sort does it's thing */
869/*****************************************************************/
870int longCompareForQsort(const void *x, const void *y)
871{
872        /* compare must have const void ptr params for qsort to work */
873        const long   *ix = (const long *)x;
874        const long   *iy = (const long *)y;
875        /* returns 1, -1 or 0 */
876        return (*ix > *iy) - (*ix < *iy);
877}
Note: See TracBrowser for help on using the repository browser.