📄 traceutils.c
字号:
/*************************************************************************** * traceutils.c: * * Generic routines to handle Traces. * * Written by Chad Trabant, IRIS Data Management Center * * modified: 2008.161 ***************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "libmseed.h"static int mst_groupsort_cmp ( MSTrace *mst1, MSTrace *mst2, flag quality );/*************************************************************************** * mst_init: * * Initialize and return a MSTrace struct, allocating memory if needed. * If the specified MSTrace includes data samples they will be freed. * * Returns a pointer to a MSTrace struct on success or NULL on error. ***************************************************************************/MSTrace *mst_init ( MSTrace *mst ){ /* Free datasamples if present */ if ( mst ) { if ( mst->datasamples ) free (mst->datasamples); if ( mst->prvtptr ) free (mst->prvtptr); if ( mst->ststate ) free (mst->ststate); } else { mst = (MSTrace *) malloc (sizeof(MSTrace)); } if ( mst == NULL ) { ms_log (2, "mst_init(): Cannot allocate memory\n"); return NULL; } memset (mst, 0, sizeof (MSTrace)); return mst;} /* End of mst_init() *//*************************************************************************** * mst_free: * * Free all memory associated with a MSTrace struct and set the pointer * to 0. ***************************************************************************/voidmst_free ( MSTrace **ppmst ){ if ( ppmst && *ppmst ) { /* Free datasamples if present */ if ( (*ppmst)->datasamples ) free ((*ppmst)->datasamples); /* Free private memory if present */ if ( (*ppmst)->prvtptr ) free ((*ppmst)->prvtptr); /* Free stream processing state if present */ if ( (*ppmst)->ststate ) free ((*ppmst)->ststate); free (*ppmst); *ppmst = 0; }} /* End of mst_free() *//*************************************************************************** * mst_initgroup: * * Initialize and return a MSTraceGroup struct, allocating memory if * needed. If the supplied MSTraceGroup is not NULL any associated * memory it will be freed. * * Returns a pointer to a MSTraceGroup struct on success or NULL on error. ***************************************************************************/MSTraceGroup *mst_initgroup ( MSTraceGroup *mstg ){ MSTrace *mst = 0; MSTrace *next = 0; if ( mstg ) { mst = mstg->traces; while ( mst ) { next = mst->next; mst_free (&mst); mst = next; } } else { mstg = (MSTraceGroup *) malloc (sizeof(MSTraceGroup)); } if ( mstg == NULL ) { ms_log (2, "mst_initgroup(): Cannot allocate memory\n"); return NULL; } memset (mstg, 0, sizeof (MSTraceGroup)); return mstg;} /* End of mst_initgroup() *//*************************************************************************** * mst_freegroup: * * Free all memory associated with a MSTraceGroup struct and set the * pointer to 0. ***************************************************************************/voidmst_freegroup ( MSTraceGroup **ppmstg ){ MSTrace *mst = 0; MSTrace *next = 0; if ( *ppmstg ) { mst = (*ppmstg)->traces; while ( mst ) { next = mst->next; mst_free (&mst); mst = next; } free (*ppmstg); *ppmstg = 0; }} /* End of mst_freegroup() *//*************************************************************************** * mst_findmatch: * * Traverse the MSTrace chain starting at 'startmst' until a MSTrace * is found that matches the given name identifiers. If the dataquality * byte is not 0 it must also match. * * Return a pointer a matching MSTrace otherwise 0 if no match found. ***************************************************************************/MSTrace *mst_findmatch ( MSTrace *startmst, char dataquality, char *network, char *station, char *location, char *channel ){ int idx; if ( ! startmst ) return 0; while ( startmst ) { if ( dataquality && dataquality != startmst->dataquality ) { startmst = startmst->next; continue; } /* Compare network */ idx = 0; while ( network[idx] == startmst->network[idx] ) { if ( network[idx] == '\0' ) break; idx++; } if ( network[idx] != '\0' || startmst->network[idx] != '\0' ) { startmst = startmst->next; continue; } /* Compare station */ idx = 0; while ( station[idx] == startmst->station[idx] ) { if ( station[idx] == '\0' ) break; idx++; } if ( station[idx] != '\0' || startmst->station[idx] != '\0' ) { startmst = startmst->next; continue; } /* Compare location */ idx = 0; while ( location[idx] == startmst->location[idx] ) { if ( location[idx] == '\0' ) break; idx++; } if ( location[idx] != '\0' || startmst->location[idx] != '\0' ) { startmst = startmst->next; continue; } /* Compare channel */ idx = 0; while ( channel[idx] == startmst->channel[idx] ) { if ( channel[idx] == '\0' ) break; idx++; } if ( channel[idx] != '\0' || startmst->channel[idx] != '\0' ) { startmst = startmst->next; continue; } /* A match was found if we made it this far */ break; } return startmst;} /* End of mst_findmatch() *//*************************************************************************** * mst_findadjacent: * * Find a MSTrace in a MSTraceGroup matching the given name * identifiers, samplerate and is adjacent with a time span. If the * dataquality byte is not 0 it must also match. * * The time tolerance and sample rate tolerance are used to determine * if traces abut. If timetol is -1.0 the default tolerance of 1/2 * the sample period will be used. If samprratetol is -1.0 the * default tolerance check of abs(1-sr1/sr2) < 0.0001 is used (defined * in libmseed.h). If timetol or sampratetol is -2.0 the respective * tolerance check will not be performed. * * The 'whence' flag will be set, when a matching MSTrace is found, to * indicate where the indicated time span is adjacent to the MSTrace * using the following values: * 1: time span fits at the end of the MSTrace * 2: time span fits at the beginning of the MSTrace * * Return a pointer a matching MSTrace and set the 'whence' flag * otherwise 0 if no match found. ***************************************************************************/MSTrace *mst_findadjacent ( MSTraceGroup *mstg, flag *whence, char dataquality, char *network, char *station, char *location, char *channel, double samprate, double sampratetol, hptime_t starttime, hptime_t endtime, double timetol ){ MSTrace *mst = 0; double pregap, postgap, delta; if ( ! mstg ) return 0; *whence = 0; mst = mstg->traces; while ( (mst = mst_findmatch (mst, dataquality, network, station, location, channel)) ) { /* Perform samprate tolerance check if requested */ if ( sampratetol != -2.0 ) { /* Perform default samprate tolerance check if requested */ if ( sampratetol == -1.0 ) { if ( ! MS_ISRATETOLERABLE (samprate, mst->samprate) ) { mst = mst->next; continue; } } /* Otherwise check against the specified sample rate tolerance */ else if ( ms_dabs(samprate - mst->samprate) > sampratetol ) { mst = mst->next; continue; } } /* post/pregap are negative when the record overlaps the trace * segment and positive when there is a time gap. */ delta = ( samprate ) ? (1.0 / samprate) : 0.0; postgap = ((double)(starttime - mst->endtime)/HPTMODULUS) - delta; pregap = ((double)(mst->starttime - endtime)/HPTMODULUS) - delta; /* If not checking the time tolerance decide if beginning or end is a better fit */ if ( timetol == -2.0 ) { if ( ms_dabs(postgap) < ms_dabs(pregap) ) *whence = 1; else *whence = 2; break; } else { /* Calculate default time tolerance (1/2 sample period) if needed */ if ( timetol == -1.0 ) timetol = 0.5 * delta; if ( ms_dabs(postgap) <= timetol ) /* Span fits right at the end of the trace */ { *whence = 1; break; } else if ( ms_dabs(pregap) <= timetol ) /* Span fits right at the beginning of the trace */ { *whence = 2; break; } } mst = mst->next; } return mst;} /* End of mst_findadjacent() *//*************************************************************************** * mst_addmsr: * * Add MSRecord time coverage to a MSTrace. The start or end time will * be updated and samples will be copied if they exist. No checking * is done to verify that the record matches the trace in any way. * * If whence is 1 the coverage will be added at the end of the trace, * whereas if whence is 2 the coverage will be added at the beginning * of the trace. * * Return 0 on success and -1 on error. ***************************************************************************/intmst_addmsr ( MSTrace *mst, MSRecord *msr, flag whence ){ int samplesize = 0; if ( ! mst || ! msr ) return -1; /* Reallocate data sample buffer if samples are present */ if ( msr->datasamples && msr->numsamples >= 0 ) { /* Check that the entire record was decompressed */ if ( msr->samplecnt != msr->numsamples ) { ms_log (2, "mst_addmsr(): Sample counts do not match, record not fully decompressed?\n"); ms_log (2, " The sample buffer will likely contain a discontinuity.\n"); } if ( (samplesize = ms_samplesize(msr->sampletype)) == 0 ) { ms_log (2, "mst_addmsr(): Unrecognized sample type: '%c'\n", msr->sampletype); return -1; } if ( msr->sampletype != mst->sampletype ) { ms_log (2, "mst_addmsr(): Mismatched sample type, '%c' and '%c'\n", msr->sampletype, mst->sampletype); return -1; } mst->datasamples = realloc (mst->datasamples, mst->numsamples * samplesize + msr->numsamples * samplesize ); if ( mst->datasamples == NULL ) { ms_log (2, "mst_addmsr(): Cannot allocate memory\n"); return -1; } } /* Add samples at end of trace */ if ( whence == 1 ) { if ( msr->datasamples && msr->numsamples >= 0 ) { memcpy ((char *)mst->datasamples + (mst->numsamples * samplesize), msr->datasamples, msr->numsamples * samplesize); mst->numsamples += msr->numsamples; } mst->endtime = msr_endtime (msr); if ( mst->endtime == HPTERROR ) { ms_log (2, "mst_addmsr(): Error calculating record end time\n"); return -1; } } /* Add samples at the beginning of trace */ else if ( whence == 2 ) { if ( msr->datasamples && msr->numsamples >= 0 ) { /* Move any samples to end of buffer */ if ( mst->numsamples > 0 ) { memmove ((char *)mst->datasamples + (msr->numsamples * samplesize), mst->datasamples, mst->numsamples * samplesize); } memcpy (mst->datasamples, msr->datasamples, msr->numsamples * samplesize); mst->numsamples += msr->numsamples; } mst->starttime = msr->starttime; } /* If two different data qualities reset the MSTrace.dataquality to 0 */ if ( mst->dataquality && msr->dataquality && mst->dataquality != msr->dataquality ) mst->dataquality = 0; /* Update MSTrace sample count */ mst->samplecnt += msr->samplecnt; return 0;} /* End of mst_addmsr() *//*************************************************************************** * mst_addspan: * * Add a time span to a MSTrace. The start or end time will be updated * and samples will be copied if they are provided. No checking is done to * verify that the record matches the trace in any way. * * If whence is 1 the coverage will be added at the end of the trace, * whereas if whence is 2 the coverage will be added at the beginning * of the trace. * * Return 0 on success and -1 on error. ***************************************************************************/intmst_addspan ( MSTrace *mst, hptime_t starttime, hptime_t endtime, void *datasamples, int numsamples, char sampletype, flag whence ){ int samplesize = 0; if ( ! mst ) return -1; if ( datasamples && numsamples > 0 ) { if ( (samplesize = ms_samplesize(sampletype)) == 0 ) { ms_log (2, "mst_addspan(): Unrecognized sample type: '%c'\n", sampletype); return -1; } if ( sampletype != mst->sampletype ) { ms_log (2, "mst_addspan(): Mismatched sample type, '%c' and '%c'\n", sampletype, mst->sampletype); return -1; } mst->datasamples = realloc (mst->datasamples, mst->numsamples * samplesize + numsamples * samplesize); if ( mst->datasamples == NULL ) { ms_log (2, "mst_addspan(): Cannot allocate memory\n"); return -1; } } /* Add samples at end of trace */ if ( whence == 1 ) { if ( datasamples && numsamples > 0 ) { memcpy ((char *)mst->datasamples + (mst->numsamples * samplesize), datasamples, numsamples * samplesize); mst->numsamples += numsamples; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -