%% Logging States in Structure Format
% Logging states using the |Structure| format can provide advantages over
% the |Array| format. When you log states using the |Array| format, the
% ordering of the states along the columns in the logged array depends on
% the block sorted order. Various factors can affect the block sorted
% order, which can alter the ordering of the states from one simulation to
% the next. When you use the |Structure| format, the block names are stored
% along with the logged state data for that block, so you can process your
% data without considering the block sorted order.
%

% Copyright 1990-2012 The MathWorks, Inc.

%% Logging States in Array Format 
% When you log states using the |Array| format, the logged data is stored
% in an array with |N| columns, where |N| is the number of states, and |M|
% rows, one for each simulation time step. This M-by-N matrix form is easy
% to manipulate in MATLAB(R). However, the ordering of the state variables
% along the columns of the logged matrix depends on the block sorted order.
% Therefore, any MATLAB code which expects a fixed mapping between the
% states of blocks in the model and the columns of the states matrix is
% prone to breaking when the block sorted order changes due to changes in
% the model.
% 
% For example, consider the models |sldemo_state_logging1| and
% |sldemo_state_logging2|.

mdl1 = 'sldemo_state_logging1';
mdl2 = 'sldemo_state_logging2';
open_system(mdl1);
open_system(mdl2);

%%
% The two models contain the same blocks, connected the same way. The only
% difference is the order of the output ports. Simulate the models and log
% the states using the |Array| format.

simOut1 = sim(mdl1, 'SaveFormat','Array');
simOut2 = sim(mdl2, 'SaveFormat','Array');

%%
% Extract the states vectors from the |Simulink.SimulationOutput| object,
% which contains all data logged in the simulation.

x1 = simOut1.get('xout');
x2 = simOut2.get('xout');

%%
% The logged states data for |x1| and |x2| are different because the blocks
% are ordered differently, so the mapping between the columns in the logged
% array and the blocks in the model is different.

isequal(x1, x2)

%% Log States Using the Structure Format
% Simulate the models again, but this time log the states in structure
% format.

simOut1=sim(mdl1,'SaveFormat','Structure');
simOut2=sim(mdl2,'SaveFormat','Structure');

%%
% Extract the structures, which contain the logged states, from the
% |SimulationOutput| object.

x1s = simOut1.get('xout');
x2s = simOut2.get('xout');

%%
% Display these structures, which contain two fields:
% |time| and |signals|. The |time| field is empty because the data was
% logged using the |Structure| format and not the |StructureWithTime|
% format. You can use the |StructureWithTime| format when you need to save
% the time data along with the states data.

disp(x1s);
disp(x2s);

%%
% The structure |signals| field is an array of structures, with one
% structure for each block in the model that has state data. Each block
% data structure within the |signals| field contains a |values| field with
% the states data and a |blockName| field with the name of the block that
% produced that state data. You can extract the states data into a matrix
% that you can process similar to how you would had you logged the states
% using the |Array| format.
%%
% To fix the state ordering problem, first use the block names to sort the
% states data into a fixed order. For example, you could sort the states
% data so that the blocks are in alphabetical order, which will stay the
% same from one simulation to the next, regardless of the block sorted
% order.

[~, idx1] = sort({x1s.signals.blockName});
x1 = [x1s.signals(idx1).values];

[~, idx2] = sort({x2s.signals.blockName});
x2 = [x2s.signals(idx2).values];

isequal(x1, x2)

%%
% Once you reorder the signals fields alphabetically by block name, if you
% extract the values field data in the same order, you can then process the
% data similar to how you would when you use the |Array| format, but the
% order of the block states data does not change from one simulation to the
% next.
