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

Revision 8040, 33.5 KB checked in by stefan, 4 months ago (diff)

cosmos0putaway.c latest working version from cosmos branch

  • 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
125
126        return EW_SUCCESS;
127}
128
129/************************************************************************
130*   This is the Put Away event initializer. It's called when a snippet  *
131*   has been received, and is about to be processed.                    *
132*   It gets to see the pointer to the TraceRequest array,               *
133*   and the number of loaded trace structures.                          *
134*                                                                       *
135*   We need to make sure that the target directory                      *
136*   exists, create it if it does not, then open the COSMOS0 file        *
137*   for writing.                                                        *
138*                                                                       *
139*   This also opens the arc hypo file, and writes its struct to our     *
140*   struct                                                              *
141*************************************************************************/
142int COSMOS0PA_next_ev(TRACE_REQ *ptrReq,
143        char *OutDir, char *LibDir, char *EventDate, char *EventTime,
144        int cadence, int debug, double Multiplier)
145
146{
147        char    COSMOS0LibFile[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    tempstr[COSMOSLINELEN];
159        int     LineNumber = 0;
160        char            time_type[30] = { 0 };                                  /* Time type UTC or local */
161        size_t  nfbuffer;               /* Read bytes */
162        char    *fbuffer;               /* File read buffer */
163        static long      MaxMessageSize = 100000;  /* size (bytes) of largest msg */
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(cosmos_info->LibDir, "%s", LibDir);
189        sprintf(cosmos_info->EventTime, "%s", EventTime);
190        sprintf(cosmos_info->EventDate, "%s", EventDate);
191
192        /* I think we already created this, but, it is OK to try again. */
193        RecursiveCreateDir(OutDir);
194        sprintf(COSMOS0LibFile, "%s/%s_%s_%s_%s.dlv0", 
195                LibDir, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan);
196
197        /* If there's enough time to implement, this filename should be able to be specified in the dot D file. */
198        sprintf(cosmos_info->EventArcFile, "%s/event.arc", cosmos_info->LibDir);
199        if (debug == 1)
200                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",
201                        cosmos_info->LibDir);
202
203        /* open Event file just for reading */
204        if ((EVENTARCfp = fopen(cosmos_info->EventArcFile, "r")) == NULL)
205        {
206                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.",
207                        cosmos_info->EventArcFile, strerror(errno));
208                return EW_FAILURE;
209        }
210
211        /* Read file to buffer
212        *********************/
213        fbuffer = (char*)malloc(sizeof(char) * MaxMessageSize); /*check logic*/
214        if (fbuffer == NULL)
215        {
216                logit("et", "Unable to allocate memory for filter buffer\n");
217                return -1;
218        }
219
220        nfbuffer = fread(fbuffer, sizeof(char),
221                (size_t)MaxMessageSize, EVENTARCfp);
222        fclose(EVENTARCfp); // Done reading
223        if (nfbuffer == 0)
224        {
225                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.",
226                        cosmos_info->EventArcFile);
227                return EW_FAILURE;
228        }
229        /* We should be able to do something like               origintime = arcmsg.sum.ot - GSEC1970; after parse_arc */
230        if (debug == 1) logit("et", "COSMOS0PA_next_ev: Debug: Arc parsing %s\n", cosmos_info->EventArcFile);
231        //if (parse_arc(fbuffer, &cosmos_info->arcmsg) != 0)
232        if (parse_arc_no_shdw(fbuffer, &cosmos_info->arcmsg) != 0)
233        {
234                logit("et", "COSMOS0PA_next_ev: Error parsing %s\n",
235                        cosmos_info->EventArcFile);
236        }
237
238
239
240        return (EW_SUCCESS);
241}
242
243
244/************************************************************************
245*   This we open the COSMOS0 file                                       *
246*   for writing.                                                        *
247*                                                                       *
248*   This also opens the library file, and writes its contents to our    *
249*   output file                                                         *
250*************************************************************************/
251int COSMOS0PA_header(TRACE_REQ *ptrReq,
252        char *OutDir, char *LibDir, char *EventDate, char *EventTime,
253        int cadence, int debug, double Multiplier)
254
255{
256        char    COSMOS0File[4 * MAXTXT];
257        char    COSMOS0LibFile[4 * MAXTXT];
258        /*      char    c; */
259        char    year[5];
260        char    yr[3];
261        char    mo[3];
262        char    dy[3];
263        char    hr[3];
264        char    mn[3];
265        char    sec[7];
266        char    cos_date[35]; /* Start date of data requested */
267        char    record_id[35];
268        char    str[COSMOSLINELEN];
269        char    tempstr[COSMOSLINELEN];
270        char    tempstr2[COSMOSLINELEN];
271        char    fifteen[16];
272        int     LineNumber = 0;
273        time_t  rawtime;
274        struct tm * timeinfo;
275        static long      MaxMessageSize = 100000;  /* size (bytes) of largest msg */
276        HypoArc                 arcmsg;                 /* ARC message */
277        char            timestr[80];                                    /* Holds time messages */
278        time_t          ot;
279        struct tm * (*timefunc)(const time_t *);
280        char            time_type[30] = { 0 };                                  /* Time type UTC or local */
281
282
283                                                                                                                /* Grab the date-related substrings that we need for filenames. */
284        strncpy(year, EventDate, 4);
285        year[4] = '\0';
286        strncpy(yr, EventDate + 2, 2);
287        yr[2] = '\0';
288        strncpy(mo, EventDate + 4, 2);
289        mo[2] = '\0';
290        strncpy(dy, EventDate + 6, 2);
291        dy[2] = '\0';
292
293        strncpy(hr, EventTime, 2);
294        hr[2] = '\0';
295        strncpy(mn, EventTime + 2, 2);
296        mn[2] = '\0';
297        strncpy(sec, EventTime + 4, 5);
298        sec[5] = '\0';
299
300        cos_date[34] = '\0';
301        record_id[34] = '\0';
302        tempstr[0] = '\0';
303
304
305        sprintf(COSMOS0File, "%s/%s_%s_%s_%s_%s%s%s_%s%s.v0", OutDir,
306                ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan, year, mo, dy, hr, mn);
307
308        /* 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 */
309        sprintf(cos_date, "%s/%s/%s, %s:%s:%s  UTC", mo, dy, year, hr, mn, sec);
310
311        RecursiveCreateDir(OutDir);
312        sprintf(COSMOS0LibFile, "%s/%s_%s_%s_%s.dlv0",
313                LibDir, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan);
314
315        if (debug == 1)
316                logit("t", "Opening COSMOS0 library file header %s\n", COSMOS0LibFile);
317
318        /* open library file just for reading */
319        if ((COSMOS0Libfp = fopen(COSMOS0LibFile, "r")) == NULL)
320        {
321                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\n",
322                        COSMOS0LibFile, strerror(errno));
323                return EW_FAILURE;
324        }
325        else {
326                logit("e", "COSMOS0PA_next_ev: Opened file %s\n",
327                        COSMOS0LibFile);
328        }
329
330        if (debug == 1)
331                logit("et", "Opening COSMOS0 file %s\n", COSMOS0File);
332
333        /* open file */
334        if ((COSMOS0fp = fopen(COSMOS0File, "wt")) == NULL)
335        {
336                logit("e", "COSMOS0PA_next_ev: unable to open file %s: %s\n",
337                        COSMOS0File, strerror(errno));
338                return EW_FAILURE;
339        }
340        arcmsg = cosmos_info->arcmsg;
341        timefunc = localtime;
342        ot = (time_t)(arcmsg.sum.ot - GSEC1970);
343        timeinfo = timefunc(&ot);
344        /* Copy the library file to the putaway file*/
345        /*      c = fgetc(COSMOS0Libfp);
346        while (c != EOF)
347        {
348        fputc(c, COSMOS0fp);
349        c = fgetc(COSMOS0Libfp);
350        }
351        */
352        while ((fgets(str, COSMOSLINELEN, COSMOS0Libfp) != NULL) && (LineNumber < 48)) {
353                LineNumber++;
354                sprintf(tempstr, "                                                                                ");/*clear it*/
355                sprintf(fifteen, "               ");
356                switch (LineNumber) {
357                case 2: /*  2 1-40 Earthquake name (before a name has been assigned, may appear as “Record of”; test
358                                records may use “Test Record of”, etc.).
359                                41-80 Earthquake date and time (including time zone). */
360                        strftime(timestr, 80, "Record of                 Earthquake of %B %d, %Y, %H:%M:%S   UTC", timeinfo);
361                        fprintf(COSMOS0fp, "%s\n", timestr);
362                        break;
363                case 3: /*3 12-46 Hypocenter: 12-20 Latitude (positive North); 22-31 Longitude (positive East); and
364                                35-37 Depth (km); 40-46 Source agency for hypocenter information.
365                                47-80 Magnitude(s), including source agency for values (may be entered manually, so
366                                spacing may be variable).**/
367                        sprintf(tempstr, "Hypocenter: %9.4f %9.4f H=%3.0fkm Md=%3.1f, M=%3.1f",
368                                arcmsg.sum.lat, arcmsg.sum.lon, arcmsg.sum.z, arcmsg.sum.Md, arcmsg.sum.Mpref); 
369                        fprintf(COSMOS0fp, "%s\n", tempstr);
370                        break;
371                case 4: /*      4 9-42 Earthquake origin date and time, in UTC (i.e., GMT), with source agency; 43-80,
372                                For use by preparing agency; may include note, e.g., “Preliminary Processing”, etc.*/
373
374                                /* Prepare origin time. Second can have tenths place, so leaving two spaces here to indicate
375                                we're not going to that level of precision, the timestruct doesn't have tenths. Probably worth revisiting.*/
376                        strftime(timestr, 80, "%m/%d/%Y, %H:%M:%S  ", timeinfo);
377                        sprintf(tempstr, "Origin: %s UTC", timestr);
378                        fprintf(COSMOS0fp, "%s\n", tempstr);
379                        break;
380                case 8: /*  Record information:
381                                8 17-50 Record start time (date and time of first sample; may be approximate - precise value
382                                should be obtained from real header) and time quality (0 through 5 correspond to
383                                lowest through highest quality).
384                                59-80 Record identification, assigned by preparing agency.
385                                "06/17/2018, 18:34:38.004 GMT (Q=5) "<- 35 chars   " (Q=5) " "38199368.SB.WLA.00.HN " <- 22char*/
386                                /* strncpy(record_id, str + 45, 34); no, we're not going to use any of the prev string */
387                                /* We pad with white space, because we're going to overwrite some of it, and we'll only copy
388                                the relevant characters to go up to 80, andything too long will get truncated. */
389                        sprintf(tempstr, "Rcrd start time:%s                             ", cos_date);
390                        /* sprintf(tempstr2, "RcrdId:%lu.%s.%s.%s.%s                  ",
391                                arcmsg.sum.qid, ptrReq->net, ptrReq->sta, ptrReq->loc, ptrReq->chan); <- prism doesn't like this*/
392                        /* sprintf(tempstr2,    "RcrdId:%s.%lu.%s.%s.%s.%s     ",
393                                ptrReq->net, arcmsg.sum.qid, ptrReq->net, ptrReq->sta, ptrReq->chan, ptrReq->loc); <- prism likes this but it might go beyond legal 80 chars/line */
394                        sprintf(tempstr2, "RcrdId: (see comment)                   ");
395
396                        strncpy(tempstr + 51, tempstr2, 29);
397                        tempstr[80] = '\0'; /* Chop off any extra junk */
398                        fprintf(COSMOS0fp, "%s\n", tempstr);
399                        break;
400                case 10: /* 10 20-27 Length of raw record, as recorded (seconds); 45-54 Maximum of raw (uncorrected)
401                                 record in g (or other units);* 60-67 Time max occurs in raw record (secs after start).
402                                 Example:
403                                 Raw record length = 175.340  sec, Uncor max = 100000000, at   40.220 sec. */
404                        sprintf(tempstr, "Raw record length = %f", (ptrReq->reqEndtime - ptrReq->reqStarttime));
405                        strncpy(tempstr + 28, "sec, Uncor max =                                    ", 53);
406                        fprintf(COSMOS0fp, "%s\n", tempstr);
407                        break;
408                case 11: /*"Record Information; Line 11
409                                 11-40 Processing/release date, time and agency.
410                                 48-80 Maximum of data series in file, units, and time of maximum (seconds after start).*"
411                                 What should I put here? An example file looks like:
412                                 "Processed: 06/17/18 12:00 PDT UCB                                   "
413                                 */
414                        time(&rawtime);
415                        timeinfo = gmtime(&rawtime);
416                        sprintf(tempstr, "Processed: %d/%d/%d %d:%01d UTC                                       ",
417                                (timeinfo->tm_mon + 1),
418                                timeinfo->tm_mday,
419                                (timeinfo->tm_year + 1900),
420                                timeinfo->tm_hour,
421                                timeinfo->tm_min
422                        );
423                        fprintf(COSMOS0fp, "%s\n", tempstr);
424                        break;
425                /* Real Headers include Earthquake information similar to comments above, comments for humans, below for PRISM*/
426                case 27: /* Site geology stuff from the database are the first 4 params in this line, so read them in and leave
427                                    them be. But the 5th param we'll overwrite here with Earthquake latitude (decimal degrees, North positive)*/
428                        sprintf(fifteen, "%15.6f", arcmsg.sum.lat);
429                        strncpy(str + 60, fifteen, 15);
430                        fprintf(COSMOS0fp, "%s", str);
431                        break;
432                case 28: /* Earthquake longitude (decimal degrees, East positive), Earthquake depth (km)., Moment magnitude, M., Surface-wave magnitude, MS., Local magnitude, ML.*/
433                        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);
434                        fprintf(COSMOS0fp, "%s\n", tempstr);
435                        break;
436                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 */
437                        sprintf(fifteen, "%15.6f", arcmsg.sum.Md);
438                        strncpy(str, fifteen, 15);                     
439                        sprintf(fifteen, "%15.6f", -999.0);
440                        strncpy(str + 15, fifteen, 15);
441                        strncpy(str + 30, fifteen, 15);
442                        fprintf(COSMOS0fp, "%s", str);
443                        break;
444                case 47: /*AQMS normally writes this comment, but we're not using AQMS*/
445                                 /* Example: | RcrdId: NC.72282711.NC.C031.HNE.01 */
446                        sprintf(tempstr, "| RcrdId: %s.%lu.%s.%s.%s.%s ", 
447                                ptrReq->net, arcmsg.sum.qid, ptrReq->net, ptrReq->sta, ptrReq->chan, ptrReq->loc);
448                        fprintf(COSMOS0fp, "%s\n", tempstr);
449                        break;
450                case 48: /*AQMS normally writes this comment, but we're not using AQMS*/
451                                 /*Example:|<SCNL>C031.HNE.NC.01    <AUTH> 2015/03/01 16:46:25.000*/
452                        sprintf(tempstr, "|<SCNL> %s.%s.%s.%s    <AUTH> %d/%d/%d %d:%d:%d.000",
453                                ptrReq->sta, ptrReq->chan, ptrReq->net, ptrReq->loc,
454                                (timeinfo->tm_year + 1900), (timeinfo->tm_mon + 1), timeinfo->tm_mday,
455                                timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
456                        fprintf(COSMOS0fp, "%s\n", tempstr);
457                        break;
458                default:
459                        fprintf(COSMOS0fp, "%s", str);
460                }
461
462        }
463        fclose(COSMOS0Libfp);
464        return (EW_SUCCESS);
465}
466
467/************************************************************************
468* This is the working entry point into the disposal system. This        *
469* routine gets called for each trace snippet which has been recovered.  *
470* It gets to see the corresponding SNIPPET structure, and the event id  *
471*                                                                       *
472* For COSMOS0, this routine writes to the COSMOS0 file, pointed to by   *
473* the COSMOS0fp pointer, all of the received trace data in COSMOS0      *
474* format:                                                               *
475*                                                                       *
476*      1. COSMOS0 tag - indicating what follows                         *
477*      2. COSMOS0_STATIONCOMP struct - describe the station             *
478*      3. COSMOS0 tag - indicating what follows                         *
479*      4. COSMOS0_DESCRIPTRACE struct - describe the trace data         *
480*      5. trace data                                                    *
481*                                                                       *
482*  One bit of complexity is that we need to write the files in the      *
483*  correct byte-order. Based on the OutputFormat parameter, determine   *
484*  whether or not to swap bytes before writing the COSMOS0 file.        *
485*                                                                       *
486* WARNING: we clip trace data to -2147483648 - +2147483647 so it will   *
487*  fit in a long int. Any incoming data that is longer than 32 bits     *
488*  will be CLIPPED. cjb 5/18/2001                                       *
489*************************************************************************/
490/* Process one channel of data */
491int COSMOS0PA_next(TRACE_REQ *getThis, double GapThresh,
492        long OutBufferLen, int debug,
493        int Cadence, double Multiplier)
494{
495        TRACE2_HEADER *wf;
496        char    datatype;
497        char    hour_line[81] = ";                                                                                "; 
498        char    sample[12];
499        char    eightdigits[9];
500        char   *msg_p;        /* pointer into tracebuf data */
501        double  begintime = 0, starttime = 0, endtime = 0, currenttime = 0;
502        double  samprate;
503        float  *f_data;
504        int     gap_count = 0;
505        int     i, j;
506        int     seconds = 0;
507        int     s_place = 0;
508        int     total, raw_counts;
509        long    nfill_max = 0l;
510        long    nsamp, nfill;
511        long    nsamp_this_scn = 0l;
512        long    this_size;
513        long   *l_data;
514        short  *s_data;
515        char    tempstr[COSMOSLINELEN];
516        char    tempstr2[COSMOSLINELEN];
517
518        /* Put this in the .d file once we know we want it. */
519        /*  double multiplier = 0.001; */
520
521        /* Check arguments */
522        if (getThis == NULL)
523        {
524                logit("e", "COSMOS0PA_next: invalid argument passed in.\n");
525                return EW_FAILURE;
526        }
527
528
529        COSMOS0PA_header(getThis, cosmos_info->OutDir, cosmos_info->LibDir, cosmos_info->EventDate, cosmos_info->EventTime, Cadence, debug, Multiplier);
530        /* Used for computing trace statistics */
531        total = 0;
532
533        if ((msg_p = getThis->pBuf) == NULL)   /* pointer to first message */
534        {
535                logit("e", "COSMOS0PA_next: Message buffer is NULL.\n");
536                return EW_FAILURE;
537        }
538        wf = (TRACE2_HEADER *)msg_p;
539
540        /* Look at the first TRACE2_HEADER and get set up of action */
541        if (WaveMsg2MakeLocal(wf) < 0)
542        {
543                logit("e", "COSMOS0PA_next: unknown trace data type: %s\n",
544                        wf->datatype);
545                return(EW_FAILURE);
546        }
547
548        nsamp = wf->nsamp;
549        starttime = wf->starttime;
550        endtime = wf->endtime;
551        samprate = wf->samprate;
552        if (samprate < 0.0001)
553        {
554                logit("et", "unreasonable samplerate (%f) for <%s.%s.%s.%s>\n",
555                        samprate, wf->sta, wf->chan, wf->net, wf->loc);
556                return(EW_FAILURE);
557        }
558        /* LAST header line now that we know sample rate*/
559        /* WRITE Dynamic header; this probably can't be here though because we need to calculate these results */
560        /* First we'll write a line that looks like this: */
561        /* 17770    raw accel.pts, approx  178 secs, units = counts(50), Format = (7I11) */
562        /*Line Cols
563        1st 1 - 8 Number of data points following; 10 - 21 Physical parameter of the data.
564        35 - 38 Approximate length of record(rounded to nearest sec; see Rhdr(66) for precise value).
565        52 - 58 Units of the data values(e.g., cm / sec2); 60 - 61 Index code for units
566        71-80 Format of the data values written on the following lines.
567        */
568        /*sprintf(hour_line, "17770    raw accel.pts, approx  178 secs, units=counts (50),Format=(10I8)\r\n"); /* we want leading spaces */
569
570/*      sprintf(tempstr, "17770    raw accel.pts,   approx  178  secs, units=counts (50),Format=(10I8)   \n");*/
571        sprintf(tempstr, "         raw accel.pts,   approx           , units=counts (50),Format=(10I8)    \n");
572        raw_counts = (getThis->reqEndtime - getThis->reqStarttime ) * samprate; 
573        sprintf(tempstr2, "%d", raw_counts);
574        strncpy(tempstr, tempstr2, strlen(tempstr2));
575        seconds = (getThis->reqEndtime - getThis->reqStarttime);
576        sprintf(tempstr2, "%d secs", seconds);
577        strncpy(tempstr + 34, tempstr2, strlen(tempstr2));
578        if (!COSMOS0fp) {
579                logit("et", "Tried to write to a null file pointer, exiting. Does your library match your waveserver request?\n");
580                exit(0);
581        }
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) && (j < raw_counts))
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                /* Even if there are more samples in this scn, we shouldn't have more than the raw counts the user asked for*/
732                while (i < 10 && j < nsamp_this_scn && j < raw_counts)
733                {
734                        sprintf(eightdigits, "        "); /* we want leading spaces */
735                        if (COSMOS0Buffer[j] != getThis->fill) {
736                                if (((int)(COSMOS0Buffer[j] * Multiplier) > 99999999) || ((int)(COSMOS0Buffer[j] * Multiplier) < -9999999)) {
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        /* Actually we opened multiple files, one for each SCNL, and they should
802          all be closed by the time we get here; we don't know who they all are to
803          close them here. */
804/*      fclose(COSMOS0fp);
805
806        if (debug == 1)
807                logit("t", "Closing COSMOS0 file \n"); */
808
809        return(EW_SUCCESS);
810}
811
812/************************************************************************
813*       This is the Put Away close routine. It's called after when      *
814*       we're being shut down.                                          *
815*************************************************************************/
816int COSMOS0PA_close(int debug)
817{
818
819        free((char *)COSMOS0Buffer);
820        return(EW_SUCCESS);
821}
822
823/*
824*
825*  Byte swapping functions
826*/
827
828/* swap bytes if necessary, depending on what machine */
829/* we have been compiled, and what machine the data   */
830/* is being read from/being written to                */
831
832static int StructMakeLocal(void *ptr, int struct_type, char data_type,
833        int debug)
834{
835        if (ptr == NULL)
836        {
837                logit("e", "StructMakeLocal: NULL pointer passed in\n");
838                return EW_FAILURE;
839        }
840
841#if defined (_INTEL)
842        if (data_type != '6')
843        {
844                if (debug == 1)
845                        logit("et", "Hoping we don't really have to do any swapping from Intel to Sun \n");
846
847        }
848
849#elif defined (_SPARC)
850        if (data_type == '6')
851        {
852                if (debug == 1)
853                        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");
854        }
855
856#endif
857        return EW_SUCCESS;
858}
859
860long Median(int number_of_array_elements, long *Array)
861{
862        long *LocalArray;
863
864        LocalArray = (long*)malloc(number_of_array_elements * sizeof(long));
865
866        qsort(&LocalArray[0], number_of_array_elements, sizeof(long), longCompareForQsort);
867        /* Get Median */
868        return(LocalArray[(long)(number_of_array_elements / 2)]);
869}
870/*****************************************************************/
871/* Just a simple compare function so that Q sort does it's thing */
872/*****************************************************************/
873int longCompareForQsort(const void *x, const void *y)
874{
875        /* compare must have const void ptr params for qsort to work */
876        const long   *ix = (const long *)x;
877        const long   *iy = (const long *)y;
878        /* returns 1, -1 or 0 */
879        return (*ix > *iy) - (*ix < *iy);
880}
Note: See TracBrowser for help on using the repository browser.