STYPE *STREAMREADSERIES(LALFrStream * stream, const char *chname, const LIGOTimeGPS * epoch) { STYPE *series; /* seek to the relevant point in the stream */ if (XLALFrStreamSeek(stream, epoch)) XLAL_ERROR_NULL(XLAL_EFUNC); series = READSERIES(stream->file, chname, stream->pos); if (!series) XLAL_ERROR_NULL(XLAL_EFUNC); return series; }
int STREAMGETSERIES(STYPE * series, LALFrStream * stream) { STYPE *tmpser; /* seek to the relevant point in the stream */ if (XLALFrStreamSeek(stream, &series->epoch)) XLAL_ERROR(XLAL_EFUNC); tmpser = READSERIES(stream->file, series->name, stream->pos); if (!tmpser) XLAL_ERROR(XLAL_EFUNC); *series = *tmpser; LALFree(tmpser); return 0; }
int STREAMGETSERIES(STYPE * series, LALFrStream * stream) { const REAL8 fuzz = 0.1 / 16384.0; /* smallest discernable time */ const size_t size = sizeof(TYPE); size_t noff; size_t need; size_t ncpy; TYPE *dest; STYPE *buffer; LIGOTimeGPS tend; INT8 tnow; INT8 tbeg; int gap = 0; XLAL_CHECK(!(stream->state & LAL_FR_STREAM_END), XLAL_EIO); XLAL_CHECK(!(stream->state & LAL_FR_STREAM_ERR), XLAL_EIO); /* if series does not have allocation for data, * we are to return metadata only, so we don't * need to load data in the next call */ if (series->data && series->data->length) buffer = READSERIES(stream->file, series->name, stream->pos); else buffer = READSERIESMETA(stream->file, series->name, stream->pos); if (!buffer) XLAL_ERROR(XLAL_EFUNC); tnow = XLALGPSToINT8NS(&stream->epoch); tbeg = XLALGPSToINT8NS(&buffer->epoch); /* Make sure that we aren't requesting data * that comes before the current frame. * Allow 1 millisecond padding to account * for double precision */ if (tnow + 1000 < tbeg) { DESTROYSERIES(buffer); XLAL_ERROR(XLAL_ETIME); } /* compute number of points offset very carefully: * if current time is within fuzz of a sample, get * that sample; otherwise get the sample just after * the requested time */ noff = ceil((1e-9 * (tnow - tbeg) - fuzz) / buffer->deltaT); /* adjust current time to be exactly the first sample * (rounded to nearest nanosecond) */ tnow = tbeg + floor(1e9 * noff * buffer->deltaT + 0.5); XLALINT8NSToGPS(&series->epoch, tnow); series->deltaT = buffer->deltaT; series->sampleUnits = buffer->sampleUnits; /* end here if all you want is metadata */ if (!series->data || !series->data->length) { DESTROYSERIES(buffer); return 0; } /* the rest of this function is to get the required * amount of data and copy it into the series */ dest = series->data->data; /* pointer to where to put the data */ need = series->data->length; /* number of points that are needed */ if (noff > buffer->data->length) { /* invalid time offset */ DESTROYSERIES(buffer); XLAL_ERROR(XLAL_ETIME); } /* copy as much of the buffer is needed */ ncpy = (buffer->data->length - noff) < need ? buffer->data->length - noff : need; memcpy(dest, buffer->data->data + noff, ncpy * size); dest += ncpy; need -= ncpy; DESTROYSERIES(buffer); /* continue while data is required */ while (need) { /* goto next frame */ if (XLALFrStreamNext(stream) < 0) XLAL_ERROR(XLAL_EFUNC); if (stream->state & LAL_FR_STREAM_END) XLAL_ERROR(XLAL_EIO, "End of frame stream while %zd points remain to be read", need); /* load more data */ buffer = READSERIES(stream->file, series->name, stream->pos); if (!buffer) XLAL_ERROR(XLAL_EFUNC); if (stream->state & LAL_FR_STREAM_GAP) { /* gap in data: reset dest and need and set epoch */ dest = series->data->data; need = series->data->length; series->epoch = buffer->epoch; gap = 1; } /* copy data */ ncpy = buffer->data->length < need ? buffer->data->length : need; memcpy(dest, buffer->data->data, ncpy * size); dest += ncpy; need -= ncpy; DESTROYSERIES(buffer); } /* update stream start time so that it corresponds to the * exact time of the next sample to be read */ stream->epoch = series->epoch; XLALGPSAdd(&stream->epoch, series->data->length * series->deltaT); /* are we still within the current frame? */ XLALFrFileQueryGTime(&tend, stream->file, stream->pos); XLALGPSAdd(&tend, XLALFrFileQueryDt(stream->file, stream->pos)); if (XLALGPSCmp(&tend, &stream->epoch) <= 0) { /* advance a frame... note that failure here is * benign so we suppress gap warnings: these will * be triggered on the next read (if one is done) */ int savemode = stream->mode; LIGOTimeGPS saveepoch = stream->epoch; stream->mode |= LAL_FR_STREAM_IGNOREGAP_MODE; /* ignore gaps for now */ if (XLALFrStreamNext(stream) < 0) { stream->mode = savemode; XLAL_ERROR(XLAL_EFUNC); } if (!(stream->state & LAL_FR_STREAM_GAP)) /* no gap: reset epoch */ stream->epoch = saveepoch; stream->mode = savemode; } /* make sure to set the gap flag in the stream state * if a gap had been encountered during the reading */ if (gap) stream->state |= LAL_FR_STREAM_GAP; /* FIXME: * does this need to cause a failure if mode is set to fail on gaps? */ /* if the stream state is an error then fail */ if (stream->state & LAL_FR_STREAM_ERR) XLAL_ERROR(XLAL_EIO); return 0; }