function [TSout, data_ind] = CreateTsArrayFromBusObject(top_bus, data, time, varargin)
% CreateTsArrayFromBusObject
% Mike Anthony
% Mark McBroom
% Copyright 2008-2010 The MathWorks, Inc.
%
% [TSout,data_ind]=CreateTsArrayFromBusObject(BusObject, DataMatrix, TimeVector, StartCol(optional) )
%
% This function take a matrix of data and creates the necessary TimeSeriesArray with appropriate data types
% based on the definitions in the bus object.
%
% Inputs
% =======
% BusObject: The Bus Object variable defined in the base workspace that corresponds to the input bus
% DataMatrix: The data matrix in the base workspace with the data corresponding
% to the bus input. IE. if the base workspace variable is data, the input should be 'data'.
% TimeVector: A column vector of data representing the evenly spaced time corresponding to the data in the matrix.
% StartCol: The starting column in DataMatrix. Optional. 1 will be used if not specified. Used when function is called
% recursively for nested buses.
%
% Outputs
% ========
% TSout: The TimeSeries or TimeSeries array structured according to the bus object containing the data in the input
% data matrix.
% data_ind: Last column in DataMatrix that was processed
%
% Limitations
% ============
% Assumes the time vector is evenly spaced
% Assumes the data matrix is columns of variables, rows of data
% Note that this requires the time vector as a separate arguement. If the time vector is a column of the data
% matrix, some pre-processing may be required. Also note that this assumes all the signals in the bus are the
% same sample time. This function does not handle buses with multiple sample times, as this is difficult to
% express via a matrix of data.
% Assumes that if the bus element is a vector, then contiguous columns in
% the data matrix will hold data for each element of the vector.
% Assumes that if the bus element is a matrix, then contiguous columns in
% the data matrix will hold data in row major order for each element of
% the matrix.
% Only supports 1 and 2D data.
% Cell array that will hold collection of timeseries and TSArrays for this
% level of the bus.
tsVector = {};
% if last arg not specified, start at the first column in the data matrix.
if size(varargin,2) == 0
data_ind = 1;
else
data_ind = varargin{1};
end
for i = 1:length(top_bus.Elements)
% Check to see if this bus element is itself a bus ( i.e. nested bus )
% First, look to see if the element type is a workspace data object
ElementType = top_bus.Elements(i).DataType;
tStr = ['exist(''',ElementType,''',''var'')'];
isDO = evalin('base',tStr);
if isDO > 0
% check to see if the type of this element is a Bus
isBus = evalin('base',['isa(',ElementType,',''Simulink.Bus'')']);
else
isBus = 0;
end
% If this element is a bus, process recursively.
if isBus
bus_do = evalin('base', ElementType);
[tsa, data_ind] = CreateTsArrayFromBusObject( bus_do, data, time, data_ind);
% add returned tsarray to collection of tsarray/timeseries
tsVector{end+1} = tsa; %#ok<AGROW>
else
name = top_bus.Elements(i).Name;
% handle widths > 1.
dims = top_bus.Elements(i).Dimensions;
if length(dims) > 2
fprintf(1,'## Error. %s is greater than 2D and not supported.\n', name);
end
totalWidth = 1;
for j=1:length(dims)
totalWidth = totalWidth * dims(j);
end
% cast to proper data type
dType = top_bus.Elements(i).DataType;
locData = eval([dType '(data(:,data_ind:data_ind+totalWidth-1))']);
% For scalar data, Simulink expects a column vector with a value
% for each time step, Tx1 For 500 time steps, size is 500x1.
% For a vector of data, Simulink expects format of TxC. For
% exmaple, for a vector of size 3, the data must be 500x3.
% However, for a matrix, data must be RxCxT. For example, a 3x5
% matrix with 500 timesteps would be 3x5x500.
% Reshape the data to fit this format.
if totalWidth > 1 && length(dims) > 1
if dims(1) > 1 && dims(2) > 1
time_dims = size(time);
% reshape to match the dimensions of the bus element.
% i.e. change from 500x15 to 500x5x3
locData = reshape(locData, time_dims(1), dims(2), dims(1) );
% change from 500x5x3 to 3x5x500
locData = permute(locData,[3 2 1]);
end
end
sampleTime = time(3)-time(2);
tsVector{end+1} = CreateTimeSeries(locData, time(1), sampleTime,'Name', name,'SignalName', name ); %#ok<AGROW>
data_ind = data_ind+totalWidth;
end
end
TSout = CreateTsArray(tsVector{:});