NeurodataWithoutBorders / matnwb

A Matlab interface for reading and writing NWB files
BSD 2-Clause "Simplified" License
50 stars 32 forks source link

timeseries data loader #51

Closed bendichter closed 6 years ago

bendichter commented 6 years ago

I made this for myself. Any interest in adding it to this project, or should I make this type of stuff in a separate repo? I think this would work nicely as a method of TimeSeries (e.g. LFP.load), but I'm not sure the best way to do that since it's generated code.

function data = loadTimeSeriesData(timeseries, interval, downsample_factor, electrode)
%LOADTIMESERIESDATA loads data within a time interval from a timeseries
%
%   DATA = loadTimeSeriesData(TIMESERIES, INTERVAL, DOWNSAMPLE_FACTOR)
%   TIMESERIES: matnwb TimeSeries object
%   INTERVAL: [start end] in seconds
%   DOWNSAMPLE_FACTOR: default = 1
%   ELECTRODE: detault = [] (all electrodes). Takes a 1-indexed integer,
%   (NOT AN ARRAY)
%   Works whether timestamps or starting_time & rate are stored. Assumes
%   timestamps are sorted in ascending order.

if ~exist('interval','var')
    interval = [0 Inf];
end

if ~exist('downsample_factor','var') || isempty(downsample_factor)
    downsample_factor = 1;
end

if ~exist('electrode','var')
    electrode = [];
end

dims = timeseries.data.dims;

if interval(1)
    if isempty(timeseries.starting_time)
        start_ind = fastsearch(timeseries.timestamps, interval(1), 1);
    else
        fs = timeseries.starting_time_rate;
        t0 = timeseries.starting_time;
        if interval(1) < t0
            error('interval bounds outside of time range');
        end
        start_ind = (interval(1) - t0) * fs;
    end
else
    start_ind = 1;
end

if isfinite(interval(2))

    if isempty(timeseries.starting_time)
        end_ind = fastsearch(timeseries.timestamps, interval(2), -1);
    else
        fs = timeseries.starting_time_rate;
        t0 = timeseries.starting_time;
        if interval(2) > (dims(1) * fs + t0)
            error('interval bounds outside of time range');
        end
        end_ind = (interval(2) - t0) * fs;
    end
else
    end_ind = Inf;
end

start = ones(1, length(dims));
start(end) = start_ind;

count = fliplr(dims);
count(end) = floor((end_ind - start_ind) / downsample_factor);

if ~isempty(electrode)
    start(end-1) = electrode;
    count(end-1) = 1;
end

if downsample_factor == 1
    data = timeseries.data.load(start, count)';
else
    stride = ones(1, length(dims));
    stride(end) = downsample_factor;
    data = timeseries.data.load(start, count, stride)';
end
lawrence-mbf commented 6 years ago

Sorry for the delay Ben. Go ahead and make a pull request with this file. We're still figuring out where we want the API stuff but for now, go ahead and put it in the +util directory.