% BTM 2010 Example: Creating a struct

clear all, close all, clc;

% Make a single array of data and store in a structure (struct)

% Check out linspace, ' operator, and random in the reference!
times  = linspace(1,10,10)';   
values = random('norm', 65, 20, length(times), 1);

%defining a struct 'data' that will hold 2 arrays (temperature data
%and times when measured) and 3 scalars
data = struct('t', [], 'temp', [], 'max', 0, 'min', 0, 'mean', 0);

%populating the struct
data.t    = times;
data.temp = values;

%well, maximum, minimum, and average temperatures of the dataset 
data.max  = max(data.temp);     
data.min  = min(data.temp);
data.mean = mean(data.temp);

%% SIDE TRACK START - STRUCT TO CELL AND CELL 2 STRUCT CONVERSIONS

%we can convert this to a cell array (we loose the fieldnames):
data_cell = struct2cell(data);

%accessing the maximum temperature field for struct:
data_max = data.max

%... and for the cell _array_
cell_3 = data_cell{3}

% Hence, for a cell array, you've gotta know what is in which field, then 
% you can convert back:
fieldnames = {'t', 'temp', 'max', 'min', 'mean'};  %notice: it must be a cell array, 
                                                   %because the strings are of different lengths
data_struct = cell2struct(data_cell, fieldnames, 1);

%% SIDE TRACK END

%% Now let's assume we collected data at multiple sites. Would be nice to
%  store all of this in a single data structure, wouldn't it? Well, you can
%  use a cell array or an array of structs.

% create the data structures first
cell_stations = cell(5, 1);
struct_stations(1:5) = ...    % '...' == command continues next line. 
    struct('t', [], 'temp', [], 'max', 0, 'min', 0, 'mean', 0); 
                              % this defines an array of structs of size 5

% Let us assume you know what a for loop is, we're creating artificial 
% data for 5 'stations' in a cell array of structs, and an array of
% structs.
for i = 1:5,
    struct_stations(i).t    = times;                                        %populate array of structs at index i
    struct_stations(i).temp = random('norm', 65, 20, length(times), 1);     %note that it's already defined 
    struct_stations(i).max  = max(struct_stations(i).temp);                 %before the loop.
    struct_stations(i).min  = min(struct_stations(i).temp);
    struct_stations(i).mean = mean(struct_stations(i).temp);

    cell_stations{i}        = struct_stations(i);                           %store this struct in cell array too...
end

%  Access the arrays
cell_array_3_max = cell_stations{3}.max 
struct_array_3_max = struct_stations(3).max

% calculate average maximum temperature over all stations using struct
% array ... note that you have to create an array on the fly:
means_struct_array = mean([struct_stations(:).max])

% that does not work with cell arrays (at least I haven't figured out a 
% good way, try yourself):
%means = mean(cell_stations{:}.max)

%% SIDE TRACK START

% work around: create array of structs from cell array treat accordingly,
% keep in mind though that this will only work when ALL fields in the cell
% array of structs are the same! USUALLY you use a cell array to organize
% data of different types and then this method will fail!

tmp_struct_array = [cell_stations{:}];
means_complicated = mean([tmp_struct_array(:).max])

%% SIDE TRACK END

