%% Using MDF Files Via MDF Datastore
% This example shows you how to use the MDF Datastore feature of Vehicle
% Network Toolbox to quickly and efficiently process a data set spread
% across a collection of multiple MDF files. This workflow is also valuable
% when there is too much data to fit into available memory.
%
% Copyright 2017 The MathWorks, Inc.

%% Access MDF Files in a Datastore
% Find the collection of MDF files representing logged information from 
% multiple test sequences. Note that MDF files to be used by MDF datastore
% as a set must have the same channel group and channel content structure.
dir('File*.mf4')

%% Create an MDF Datastore
% You create an MDF datastore by selecting a folder location containing a
% collection of MDF files. In this case, target all files in the current 
% working directory.
mds = mdfDatastore(pwd)

%% Configure the MDF Datastore
% Multiple options allow control of what data is read from the MDF files
% and how the reads are performed. In this case, the first channel group is
% used by default. Note that only one channel group may be selected by the
% datastore at a time. You can also specify certain channels within the selected 
% channel group to read. In this case, all channels are read by default.
mds.SelectedChannelGroupNumber
mds.SelectedChannelNames

%% MDF Datastore preview
% Using the |preview| function, you can obtain a quick view of the data 
% available in the file set. Preview always returns up to eight data points
% from the first file in the datastore.
preview(mds)

%% Using MDF Datastore readall
% You can use the |readall| function to read the entire contents of data in
% a single call. This is an efficient way to read from many files when the
% data set fits into available memory. After running |readall|, the datastore
% resets to the beginning of the data set.
data = readall(mds);
data(1:5,:)

%% Using MDF Datastore read
% You can use the |read| function to obtain data from the file set. By 
% default, reads from the MDF datastore will read an entire file's worth 
% of data per call. The power of a datastore comes from reading through 
% multiple files sequentially within the file set. As you read, the datastore
% automatically bridges from one file to the next until all data from all
% files is read. 
for ii = 1:3
    data = read(mds);
    whos('data')
    data(1:5,:)
end

%% MDF Datastore reset
% At any time, you can call the |reset| function to start over again at the
% beginning of the data set.
reset(mds)

%% Configure MDF Datastore read By Data Record
% You can use the |ReadSize| property to specify how much data to read on 
% each call. |ReadSize| can be specified as a numeric value to read a 
% fixed number of data points. |ReadSize| lets you control how much data is
% loaded into memory when you have a data set larger than available memory.
% We recommend using custom read sizes that are small enough to fit in
% memory, but still as large as possible to reduce processing overhead and
% improve performance.
mds.ReadSize = 5
for ii = 1:3
    data = read(mds)
end

%% Configure MDF Datastore read By Data Timestamp
% You can also specify |ReadSize| as a duration to read data points by
% elapsed time. Note that when the read type is changed, the datastore
% resets to the beginning of the data set.
mds.ReadSize = seconds(5)
for ii = 1:3
    data = read(mds)
end
