📄 traceutils.c
字号:
mst->endtime = endtime; } /* Add samples at the beginning of trace */ else if ( whence == 2 ) { if ( datasamples && numsamples > 0 ) { /* Move any samples to end of buffer */ if ( mst->numsamples > 0 ) { memmove ((char *)mst->datasamples + (numsamples * samplesize), mst->datasamples, mst->numsamples * samplesize); } memcpy (mst->datasamples, datasamples, numsamples * samplesize); mst->numsamples += numsamples; } mst->starttime = starttime; } /* Update MSTrace sample count */ if ( numsamples > 0 ) mst->samplecnt += numsamples; return 0;} /* End of mst_addspan() *//*************************************************************************** * mst_addmsrtogroup: * * Add data samples from a MSRecord to a MSTrace in a MSTraceGroup by * searching the group for the approriate MSTrace and either adding data * to it or creating a new MSTrace if no match found. * * Matching traces are found using the mst_findadjacent() routine. If * the dataquality flag is true the data quality bytes must also match * otherwise they are ignored. * * Return a pointer to the MSTrace updated or 0 on error. ***************************************************************************/MSTrace *mst_addmsrtogroup ( MSTraceGroup *mstg, MSRecord *msr, flag dataquality, double timetol, double sampratetol ){ MSTrace *mst = 0; hptime_t endtime; flag whence; char dq; if ( ! mstg || ! msr ) return 0; dq = ( dataquality ) ? msr->dataquality : 0; endtime = msr_endtime (msr); if ( endtime == HPTERROR ) { ms_log (2, "mst_addmsrtogroup(): Error calculating record end time\n"); return 0; } /* Find matching, time adjacent MSTrace */ mst = mst_findadjacent (mstg, &whence, dq, msr->network, msr->station, msr->location, msr->channel, msr->samprate, sampratetol, msr->starttime, endtime, timetol); /* If a match was found update it otherwise create a new MSTrace and add to end of MSTrace chain */ if ( mst ) { /* Records with no time coverage do not contribute to a trace */ if ( msr->samplecnt <= 0 || msr->samprate <= 0.0 ) return mst; if ( mst_addmsr (mst, msr, whence) ) { return 0; } } else { mst = mst_init (NULL); mst->dataquality = dq; strncpy (mst->network, msr->network, sizeof(mst->network)); strncpy (mst->station, msr->station, sizeof(mst->station)); strncpy (mst->location, msr->location, sizeof(mst->location)); strncpy (mst->channel, msr->channel, sizeof(mst->channel)); mst->starttime = msr->starttime; mst->samprate = msr->samprate; mst->sampletype = msr->sampletype; if ( mst_addmsr (mst, msr, 1) ) { mst_free (&mst); return 0; } /* Link new MSTrace into the end of the chain */ if ( ! mstg->traces ) { mstg->traces = mst; } else { MSTrace *lasttrace = mstg->traces; while ( lasttrace->next ) lasttrace = lasttrace->next; lasttrace->next = mst; } mstg->numtraces++; } return mst;} /* End of mst_addmsrtogroup() *//*************************************************************************** * mst_addtracetogroup: * * Add a MSTrace to a MSTraceGroup at the end of the MSTrace chain. * * Return a pointer to the MSTrace added or 0 on error. ***************************************************************************/MSTrace *mst_addtracetogroup ( MSTraceGroup *mstg, MSTrace *mst ){ MSTrace *lasttrace; if ( ! mstg || ! mst ) return 0; if ( ! mstg->traces ) { mstg->traces = mst; } else { lasttrace = mstg->traces; while ( lasttrace->next ) lasttrace = lasttrace->next; lasttrace->next = mst; } mst->next = 0; mstg->numtraces++; return mst;} /* End of mst_addtracetogroup() *//*************************************************************************** * mst_groupheal: * * Check if traces in MSTraceGroup can be healed, if contiguous segments * belong together they will be merged. This routine is only useful * if the trace group was assembled from segments out of time order * (e.g. a file of Mini-SEED records not in time order) but forming * contiguous time coverage. The MSTraceGroup will be sorted using * mst_groupsort() before healing. * * The time tolerance and sample rate tolerance are used to determine * if the traces are indeed the same. 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). * * Return number of trace mergings on success otherwise -1 on error. ***************************************************************************/intmst_groupheal ( MSTraceGroup *mstg, double timetol, double sampratetol ){ int mergings = 0; MSTrace *curtrace = 0; MSTrace *nexttrace = 0; MSTrace *searchtrace = 0; MSTrace *prevtrace = 0; int8_t merged = 0; double postgap, pregap, delta; if ( ! mstg ) return -1; /* Sort MSTraceGroup before any healing */ if ( mst_groupsort (mstg, 1) ) return -1; curtrace = mstg->traces; while ( curtrace ) { nexttrace = mstg->traces; prevtrace = mstg->traces; while ( nexttrace ) { searchtrace = nexttrace; nexttrace = searchtrace->next; /* Do not process the same MSTrace we are trying to match */ if ( searchtrace == curtrace ) { prevtrace = searchtrace; continue; } /* Check if this trace matches the curtrace */ if ( strcmp (searchtrace->network, curtrace->network) || strcmp (searchtrace->station, curtrace->station) || strcmp (searchtrace->location, curtrace->location) || strcmp (searchtrace->channel, curtrace->channel) ) { prevtrace = searchtrace; continue; } /* Perform default samprate tolerance check if requested */ if ( sampratetol == -1.0 ) { if ( ! MS_ISRATETOLERABLE (searchtrace->samprate, curtrace->samprate) ) { prevtrace = searchtrace; continue; } } /* Otherwise check against the specified sample rates tolerance */ else if ( ms_dabs(searchtrace->samprate - curtrace->samprate) > sampratetol ) { prevtrace = searchtrace; continue; } merged = 0; /* post/pregap are negative when searchtrace overlaps curtrace * segment and positive when there is a time gap. */ delta = ( curtrace->samprate ) ? (1.0 / curtrace->samprate) : 0.0; postgap = ((double)(searchtrace->starttime - curtrace->endtime)/HPTMODULUS) - delta; pregap = ((double)(curtrace->starttime - searchtrace->endtime)/HPTMODULUS) - delta; /* Calculate default time tolerance (1/2 sample period) if needed */ if ( timetol == -1.0 ) timetol = 0.5 * delta; /* Fits right at the end of curtrace */ if ( ms_dabs(postgap) <= timetol ) { /* Merge searchtrace with curtrace */ mst_addspan (curtrace, searchtrace->starttime, searchtrace->endtime, searchtrace->datasamples, searchtrace->numsamples, searchtrace->sampletype, 1); /* If no data is present, make sure sample count is updated */ if ( searchtrace->numsamples <= 0 ) curtrace->samplecnt += searchtrace->samplecnt; /* If qualities do not match reset the indicator */ if (curtrace->dataquality != searchtrace->dataquality) curtrace->dataquality = 0; merged = 1; } /* Fits right at the beginning of curtrace */ else if ( ms_dabs(pregap) <= timetol ) { /* Merge searchtrace with curtrace */ mst_addspan (curtrace, searchtrace->starttime, searchtrace->endtime, searchtrace->datasamples, searchtrace->numsamples, searchtrace->sampletype, 2); /* If no data is present, make sure sample count is updated */ if ( searchtrace->numsamples <= 0 ) curtrace->samplecnt += searchtrace->samplecnt; /* If qualities do not match reset the indicator */ if (curtrace->dataquality != searchtrace->dataquality) curtrace->dataquality = 0; merged = 1; } /* If searchtrace was merged with curtrace remove it from the chain */ if ( merged ) { /* Re-link trace chain and free searchtrace */ if ( searchtrace == mstg->traces ) mstg->traces = nexttrace; else prevtrace->next = nexttrace; mst_free (&searchtrace); mstg->numtraces--; mergings++; } else { prevtrace = searchtrace; } } curtrace = curtrace->next; } return mergings;} /* End of mst_groupheal() *//*************************************************************************** * mst_groupsort: * * Sort a MSTraceGroup using a mergesort algorithm. MSTrace entries * are compared using the mst_groupsort_cmp() function. * * The mergesort implementation was inspired by the listsort function * published and copyright 2001 by Simon Tatham. * * Return 0 on success and -1 on error. ***************************************************************************/intmst_groupsort ( MSTraceGroup *mstg, flag quality ){ MSTrace *p, *q, *e, *top, *tail; int nmerges; int insize, psize, qsize, i; if ( ! mstg ) return -1; if ( ! mstg->traces ) return 0; top = mstg->traces; insize = 1; for (;;) { p = top; top = NULL; tail = NULL; nmerges = 0; /* count number of merges we do in this pass */ while ( p ) { nmerges++; /* there exists a merge to be done */ /* step `insize' places along from p */ q = p; psize = 0; for (i = 0; i < insize; i++) { psize++; q = q->next; if ( ! q ) break; } /* if q hasn't fallen off end, we have two lists to merge */ qsize = insize; /* now we have two lists; merge them */ while ( psize > 0 || (qsize > 0 && q) ) { /* decide whether next element of merge comes from p or q */ if ( psize == 0 ) { /* p is empty; e must come from q. */ e = q; q = q->next; qsize--; } else if ( qsize == 0 || ! q ) { /* q is empty; e must come from p. */ e = p; p = p->next; psize--; } else if ( mst_groupsort_cmp (p, q, quality) <= 0 ) { /* First element of p is lower (or same), e must come from p. */ e = p; p = p->next; psize--; } else { /* First element of q is lower; e must come from q. */ e = q; q = q->next; qsize--; } /* add the next element to the merged list */ if ( tail ) tail->next = e; else top = e; tail = e; } /* now p has stepped `insize' places along, and q has too */ p = q; } tail->next = NULL; /* If we have done only one merge, we're finished. */ if ( nmerges <= 1 ) /* allow for nmerges==0, the empty list case */ { mstg->traces = top; return 0; } /* Otherwise repeat, merging lists twice the size */ insize *= 2; }} /* End of mst_groupsort() *//*************************************************************************** * mst_groupsort_cmp: * * Compare two MSTrace entities for the purposes of sorting a * MSTraceGroup. Criteria for MSTrace comparison are (in order of * testing): source name, start time, descending endtime (longest * trace first) and sample rate. * * Return 1 if mst1 is "greater" than mst2, otherwise return 0. ***************************************************************************/static intmst_groupsort_cmp ( MSTrace *mst1, MSTrace *mst2, flag quality ){ char src1[50], src2[50]; int strcmpval; if ( ! mst1 || ! mst2 ) return -1; mst_srcname (mst1, src1, quality); mst_srcname (mst2, src2, quality); strcmpval = strcmp (src1, src2); /* If the source names do not match make sure the "greater" string is 2nd, * otherwise, if source names do match, make sure the later start time is 2nd * otherwise, if start times match, make sure the earlier end time is 2nd * otherwise, if end times match, make sure the highest sample rate is 2nd */ if ( strcmpval > 0 ) { return 1; } else if ( strcmpval == 0 ) { if ( mst1->starttime > mst2->starttime ) { return 1; } else if ( mst1->starttime == mst2->starttime ) { if ( mst1->endtime < mst2->endtime ) { return 1; } else if ( mst1->endtime == mst2->endtime ) { if ( ! MS_ISRATETOLERABLE (mst1->samprate, mst2->samprate) && mst1->samprate > mst2->samprate ) { return 1; } } } } return 0;} /* End of mst_groupsort_cmp() *//*************************************************************************** * mst_srcname: * * Generate a source name string for a specified MSTrace in the * format: 'NET_STA_LOC_CHAN[_QUAL]'. The quality is added to the * srcname if the quality flag argument is 1 and mst->dataquality is * not zero. The passed srcname must have enough room for the * resulting string. * * Returns a pointer to the resulting string or NULL on error. ***************************************************************************/char *mst_srcname (MSTrace *mst, char *srcname, flag quality){ char *src = srcname; char *cp = srcname; if ( ! mst || ! srcname ) return NULL; /* Build the source name string */ cp = mst->network; while ( *cp ) { *src++ = *cp++; } *src++ = '_'; cp = mst->station; while ( *cp ) { *src++ = *cp++; } *src++ = '_'; cp = mst->location; while ( *cp ) { *src++ = *cp++; } *src++ = '_'; cp = mst->channel; while ( *cp ) { *src++ = *cp++; } if ( quality && mst->dataquality ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -