Example #1
0
/**
 * @brief Seeks a LALFrStream stream by a time offset
 * @details
 * The position of a LALFrStream is set so that the net read will
 * be at the specified time offset.  The offset @p dt is a number of
 * seconds relative to the @p whence postion, which can be
 * @p SEEK_SET to seek relative to the beginning of the stream,
 * @p SEEK_CUR to seek relative to the current position of the stream,
 * or @p SEEK_END to seek relative to the end of the stream.
 * The return codes and conditions are the same as XLALFrStreamSeek().
 * @param stream Pointer to a #LALFrStream structure.
 * @param dt The offset time in seconds.
 * @param whence The position whence to seek: one of @p SEEK_SET, @p SEEK_CUR,
 * or @p SEEK_END.
 * @retval 3 Time requested is in a gap in the data.
 * @retval 2 Time requested is after the end of the stream.
 * @retval 1 Time requested is before the beginning of the stream.
 * @retval 0 Normal success.
 * @retval <0 Failure.
 */
int XLALFrStreamSeekO(LALFrStream * stream, double dt, int whence)
{
    LIGOTimeGPS epoch;
    switch (whence) {
    case SEEK_SET:
        if (XLALFrStreamRewind(stream) < 0)
            XLAL_ERROR(XLAL_EFUNC);
        /* FALL THROUGH */
    case SEEK_CUR:
        epoch = stream->epoch;
        break;
    case SEEK_END:
        /* go to the last frame */
        XLALFrStreamFileClose(stream);
        if (XLALFrStreamFileOpen(stream, stream->cache->length - 1) < 0)
            XLAL_ERROR(XLAL_EFUNC);
        if ((stream->pos = XLALFrFileQueryNFrame(stream->file) - 1) < 0)
            XLAL_ERROR(XLAL_EFUNC);
        if (XLALFrFileQueryGTime(&epoch, stream->file, stream->pos) == NULL)
            XLAL_ERROR(XLAL_EFUNC);
        /* add duration of last frame to dt */
        dt += XLALFrFileQueryDt(stream->file, stream->pos);
        break;
    default:
        XLAL_ERROR(XLAL_EINVAL,
            "Invalid whence value: use SEEK_SET, SEEK_CUR, or SEEK_END");
    }
    XLALGPSAdd(&epoch, dt);
    if (XLALFrStreamSeek(stream, &epoch) < 0)
        XLAL_ERROR(XLAL_EFUNC);
    return 0;
}
Example #2
0
static int XLALFrStreamFileOpen(LALFrStream * stream, UINT4 fnum)
{
    if (!stream->cache || !stream->cache->list)
        XLAL_ERROR(XLAL_EINVAL, "No files in stream file cache");
    if (fnum >= stream->cache->length)
        XLAL_ERROR(XLAL_EINVAL, "File index too large");
    if (stream->file)
        XLALFrStreamFileClose(stream);
    stream->pos = 0;
    stream->fnum = fnum;
    stream->file = XLALFrFileOpenURL(stream->cache->list[fnum].url);
    if (!stream->file) {
        stream->state |= LAL_FR_STREAM_ERR | LAL_FR_STREAM_URL;
        XLAL_ERROR(XLAL_EFUNC);
    }
    if (stream->mode & LAL_FR_STREAM_CHECKSUM_MODE) {
        if (!XLALFrFileCksumValid(stream->file)) {
            stream->state |= LAL_FR_STREAM_ERR;
            XLALFrStreamFileClose(stream);
            XLAL_ERROR(XLAL_EIO, "Invalid checksum in file %s",
                stream->cache->list[fnum].url);
        }
    }
    XLALFrFileQueryGTime(&stream->epoch, stream->file, 0);
    return 0;
}
Example #3
0
/**
 * @brief Opens a LALFrStream associated with a LALCache
 * @details
 * This routine creates a #LALFrStream that is a stream associated with
 * the frame files contained in a LALCache.
 * @param cache Pointer to a LALCache structure describing the frame files to stream.
 * @returns Pointer to a newly created #LALFrStream structure.
 * @retval NULL Failure.
 */
LALFrStream *XLALFrStreamCacheOpen(LALCache * cache)
{
    LALFrStream *stream;
    size_t i;

    if (!cache)
        XLAL_ERROR_NULL(XLAL_EFAULT);

    stream = LALCalloc(1, sizeof(*stream));
    if (!stream)
        XLAL_ERROR_NULL(XLAL_ENOMEM);
    stream->cache = XLALCacheDuplicate(cache);

    /* check cache entries for t0 and dt; if these are not set then read
     * the framefile to try to get them */
    for (i = 0; i < stream->cache->length; ++i) {
        if (stream->cache->list[i].t0 == 0 || stream->cache->list[i].dt == 0) {
            LIGOTimeGPS end;
            size_t nFrame;
            if (XLALFrStreamFileOpen(stream, i) < 0) {
                XLALFrStreamClose(stream);
                XLAL_ERROR_NULL(XLAL_EIO);
            }
            nFrame = XLALFrFileQueryNFrame(stream->file);
            stream->cache->list[i].t0 = stream->epoch.gpsSeconds;
            XLALFrFileQueryGTime(&end, stream->file, nFrame - 1);
            XLALGPSAdd(&end, XLALFrFileQueryDt(stream->file, nFrame - 1));
            stream->cache->list[i].dt =
                ceil(XLALGPSGetREAL8(&end)) - stream->cache->list[i].t0;
            XLALFrStreamFileClose(stream);
        }
    }

    /* sort and uniqify the cache */
    if (XLALCacheSort(stream->cache) || XLALCacheUniq(stream->cache)) {
        XLALFrStreamClose(stream);
        XLAL_ERROR_NULL(XLAL_EFUNC);
    }

    stream->mode = LAL_FR_STREAM_DEFAULT_MODE;

    /* open up the first file */
    if (XLALFrStreamFileOpen(stream, 0) < 0) {
        XLALFrStreamClose(stream);
        XLAL_ERROR_NULL(XLAL_EFUNC);
    }
    return stream;
}
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;
}
Example #5
0
/**
 * @brief Seeks a LALFrStream stream to data at a given time
 * @details
 * The position of a LALFrStream is set so that the net read will
 * be at the specified time.  #LAL_FR_STREAM_END and #LAL_FR_STREAM_GAP
 * bits are turned off in the #LALFrStreamState state.  If the time is before
 * the beginning of the stream, the stream position is set to the beginning of
 * the stream and the routine returns with code 1.  If the time is after the
 * end of the stream, the #LAL_FR_STREAM_END bit is set in the
 * #LALFrStreamState state, and the routine returns with code 2.  If the time
 * is in a gap in the data, the #LAL_FR_STREAM_GAP bit is set in the
 * #LALFrStreamState state, the position is advanced to the next data, and the
 * routine returns with code 3.  If, however, the
 * #LAL_FR_STREAM_IGNORETIME_MODE bit is not set in the LALFrStreamMode mode
 * then these conditions result in an error.
 * @param stream Pointer to a #LALFrStream structure.
 * @param epoch The LIGOTimeGPS time of the next data to read.
 * @retval 3 Time requested is in a gap in the data.
 * @retval 2 Time requested is after the end of the stream.
 * @retval 1 Time requested is before the beginning of the stream.
 * @retval 0 Normal success.
 * @retval <0 Failure.
 */
int XLALFrStreamSeek(LALFrStream * stream, const LIGOTimeGPS * epoch)
{
    double twant = XLALGPSGetREAL8(epoch);
    LALCacheEntry *entry;

    /* close file if one is open */
    XLALFrStreamFileClose(stream);

    /* clear EOF or GAP states; preserve ERR state */
    if (stream->state & LAL_FR_STREAM_ERR)
        stream->state = LAL_FR_STREAM_ERR;
    else
        stream->state = LAL_FR_STREAM_OK;

    /* is epoch before first file? */
    if (epoch->gpsSeconds < stream->cache->list->t0) {
        XLALFrStreamRewind(stream);
        stream->state |= LAL_FR_STREAM_GAP;
        /* is this reported as an error? */
        if (!(stream->mode & LAL_FR_STREAM_IGNORETIME_MODE)) {
            /* FIXME:  if this is an error, should the stream state say so? */
            /* stream->state |= LAL_FR_STREAM_ERR; */
            XLAL_ERROR(XLAL_ETIME);
        }
        if (stream->mode & LAL_FR_STREAM_TIMEWARN_MODE)
            XLAL_PRINT_WARNING("Requested time %d before first frame",
                epoch->gpsSeconds);
        return 1;       /* before first file code */
    }

    /* seek for the time in the cache */
    entry = XLALCacheEntrySeek(stream->cache, twant);
    if (!entry) {       /* seek failed: only happens if time is past end of cache */
        stream->fnum = stream->cache->length;
        stream->epoch = *epoch;
        stream->state |= LAL_FR_STREAM_END;
        /* is this reported as an error? */
        if (!(stream->mode & LAL_FR_STREAM_IGNORETIME_MODE)) {
            /* FIXME:  if this is an error, should the stream state say so? */
            /* stream->state |= LAL_FR_STREAM_ERR; */
            XLAL_ERROR(XLAL_ETIME);
        }
        if (stream->mode & LAL_FR_STREAM_TIMEWARN_MODE)
            XLAL_PRINT_WARNING("Requested time %d after last frame",
                epoch->gpsSeconds);
        return 2;       /* after last file code */
    }

    /* now we must find the position within the frame file */
    for (stream->fnum = entry - stream->cache->list;
        stream->fnum < stream->cache->length; ++stream->fnum) {
        /* check the file contents to determine the position that matches */
        size_t nFrame;
        if (XLALFrStreamFileOpen(stream, stream->fnum) < 0)
            XLAL_ERROR(XLAL_EFUNC);
        if (epoch->gpsSeconds < stream->cache->list[stream->fnum].t0) {
            /* detect a gap between files */
            stream->state |= LAL_FR_STREAM_GAP;
            break;
        }
        nFrame = XLALFrFileQueryNFrame(stream->file);
        for (stream->pos = 0; stream->pos < (int)nFrame; ++stream->pos) {
            LIGOTimeGPS start;
            int cmp;
            XLALFrFileQueryGTime(&start, stream->file, stream->pos);
            cmp = XLALGPSCmp(epoch, &start);
            if (cmp >= 0
                && XLALGPSDiff(epoch,
                    &start) < XLALFrFileQueryDt(stream->file, stream->pos))
                break;  /* this is the frame! */
            if (cmp < 0) {
                /* detect a gap between frames within a file */
                stream->state |= LAL_FR_STREAM_GAP;
                break;
            }
        }
        if (stream->pos < (int)nFrame)  /* we've found the frame */
            break;
        /* oops... not in this frame file, go on to the next one */
        /* probably the frame file was mis-named.... */
        XLALFrStreamFileClose(stream);
    }

    if (stream->fnum >= stream->cache->length) {
        /* we've gone right to the end without finding it! */
        stream->fnum = stream->cache->length;
        stream->epoch = *epoch;
        stream->state |= LAL_FR_STREAM_END;
        /* is this reported as an error? */
        if (!(stream->mode & LAL_FR_STREAM_IGNORETIME_MODE)) {
            /* FIXME:  if this is an error, should the stream state say so? */
            /* stream->state |= LAL_FR_STREAM_ERR; */
            XLAL_ERROR(XLAL_ETIME);
        }
        if (stream->mode & LAL_FR_STREAM_TIMEWARN_MODE)
            XLAL_PRINT_WARNING("Requested time %d after last frame",
                epoch->gpsSeconds);
        return 2;       /* after last file code */
    }

    /* set the time of the stream */
    if (stream->state & LAL_FR_STREAM_GAP) {
        XLALFrFileQueryGTime(&stream->epoch, stream->file, stream->pos);
        if (stream->mode & LAL_FR_STREAM_TIMEWARN_MODE)
            XLAL_PRINT_WARNING("Requested time %.6f in gap in frame data",
                twant);
        if (!(stream->mode & LAL_FR_STREAM_IGNORETIME_MODE))
            XLAL_ERROR(XLAL_ETIME);
        return 3;       /* in a gap code */
    }
    stream->epoch = *epoch;
    return 0;
}
Example #6
0
/**
 * @brief Advance a LALFrStream stream to the beginning of the next frame
 * @details
 * The position of a LALFrStream is advanced so that the next read will
 * be at the next frame.  If the stream is at the end, the #LAL_FR_STREAM_END
 * bit of the LALFrStreamState state is set, and the routine returns the
 * return code 1.  If there is a gap in the data before the next frame,
 * the #LAL_FR_STREAM_GAP bit of the LALFrStreamState state is set, and the
 * routine returns the return code 2.  If, however, the
 * #LAL_FR_STREAM_IGNOREGAP_MODE bit is not set in the LALFrStreamMode mode
 * then the routine produces an error if a gap is encountered.
 * @param stream Pointer to a #LALFrStream structure.
 * @retval 2 Gap in the data is encountered.
 * @retval 1 End of stream encountered.
 * @retval 0 Normal success.
 * @retval <0 Failure.
 */
int XLALFrStreamNext(LALFrStream * stream)
{
    /* timing accuracy: tenth of a sample interval for a 16kHz fast channel */
    const INT8 tacc = (INT8) floor(0.1 * 1e9 / 16384.0);
    const char *url1;
    const char *url2;
    int pos1;
    int pos2;
    INT8 texp = 0;
    INT8 tact;

    if (stream->state & LAL_FR_STREAM_END)
        return 1;       /* end code */

    /* turn off gap bit */
    stream->state &= ~LAL_FR_STREAM_GAP;

    url2 = url1 = stream->cache->list[stream->fnum].url;
    pos2 = pos1 = stream->pos;

    /* open a new file if necessary */
    if (!stream->file) {
        if (stream->fnum >= stream->cache->length) {
            stream->state |= LAL_FR_STREAM_END;
            return 1;
        }
        if (XLALFrStreamFileOpen(stream, stream->fnum) < 0)
            XLAL_ERROR(XLAL_EFUNC);
    }
    if (stream->file) {
        INT4 nFrame = XLALFrFileQueryNFrame(stream->file);
        if (stream->pos < nFrame) {
            LIGOTimeGPS gpstime;
            XLALGPSToINT8NS(XLALFrFileQueryGTime(&gpstime, stream->file,
                  stream->pos));
            texp =
                XLALGPSToINT8NS(XLALGPSAdd(&gpstime,
                    XLALFrFileQueryDt(stream->file, stream->pos)));
            ++stream->pos;
        }
        if (stream->pos >= nFrame) {
            XLALFrStreamFileClose(stream);
            ++stream->fnum;
        }
        pos2 = stream->pos;
    }
    /* open a new file if necessary */
    if (!stream->file) {
        if (stream->fnum >= stream->cache->length) {
            stream->state |= LAL_FR_STREAM_END;
            return 1;
        }
        if (XLALFrStreamFileOpen(stream, stream->fnum) < 0)
            XLAL_ERROR(XLAL_EFUNC);
        url2 = stream->cache->list[stream->fnum].url;
        pos2 = stream->pos;
    }
    /* compute actual start time of this new frame */
    tact =
        XLALGPSToINT8NS(XLALFrFileQueryGTime(&stream->epoch, stream->file,
            stream->pos));

    /* INT8 is platform dependent, cast to long long for llabs() call */
    if (llabs((long long)(texp - tact)) > tacc) { /* there is a gap */
        stream->state |= LAL_FR_STREAM_GAP;
        if (stream->mode & LAL_FR_STREAM_GAPINFO_MODE) {
            XLAL_PRINT_INFO("Gap in frame data between times %.6f and %.6f",
                1e-9 * texp, 1e-9 * tact);
        }
        if (!(stream->mode & LAL_FR_STREAM_IGNOREGAP_MODE)) {
            XLAL_PRINT_ERROR("Gap in frame data");
            XLAL_PRINT_ERROR("Time %.6f is end of frame %d of file %s",
                1e-9 * texp, pos1, url1);
            XLAL_PRINT_ERROR("Time %.6f is start of frame %d of file %s",
                1e-9 * tact, pos2, url2);
            XLAL_ERROR(XLAL_ETIME);
        }
        return 2;       /* gap code */
    }
    return 0;
}