Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}