Ignore:
Timestamp:
09/06/23 20:20:00 (19 months ago)
Author:
musselman
Message:

Added functionality for arrays of objects like outputdefinition.defintions to all files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/m/netcdf/read_netCDF.m

    r27891 r27900  
    130130        % keep an eye out for nested structs:
    131131        if strcmp(varname, 'this_is_a_nested')
    132             is_nested = true;
     132            is_object = true;
    133133            model_copy = copy_nested_struct(group_location_in_file, model_copy, NCData, verbose);
     134        elseif strcmp(varname, 'name_of_cell_array')
     135            is_object = true;
     136            model_copy = copy_cell_array_of_objects(variables, group_location_in_file, model_copy, NCData, verbose);
    134137        elseif strcmp(varname, 'solution')
    135138            % band-aid pass..
    136139        else
    137             model_copy = copy_variable_data_to_new_model(group_location_in_file, varname, xtype, model_copy, NCData, verbose);
     140            if logical(exist('is_object', 'var'))
     141                % already handled
     142            else
     143                model_copy = copy_variable_data_to_new_model(group_location_in_file, varname, xtype, model_copy, NCData, verbose);
     144            end
    138145        end
    139146    end
     
    142149    %try
    143150    % if it's a nested struct the function copy_nested_struct has already been called
    144     if logical(exist('is_nested', 'var'))
     151    if logical(exist('is_object', 'var'))
    145152        % do nothing
    146153    else
     
    159166end
    160167
     168
     169% to read cell arrays with objects:
     170function model_copy = copy_cell_array_of_objects(variables, group_location_in_file, model_copy, NCData, verbose);
     171    %{
     172        The structure in netcdf for groups with the name_of_cell_array variable is like:
     173
     174        group: 2x6_cell_array_of_objects {
     175            name_of_cell_array = <name_of_cell_array>
     176
     177            group: Row_1_of_2 {
     178                group: Col_1_of_6 {
     179                    ... other groups can be here that refer to objects
     180                } // group Col_6_of_6
     181            } // group Row_1_of_2
     182
     183            group: Row_2_of_2 {
     184                group: Col_1_of_6 {
     185                    ... other groups can be here that refer to objects
     186                } // group Col_6_of_6
     187            } // group Row_2_of_2
     188        } // group 2x6_cell_array_of_objects
     189
     190        We have to navigate this structure to extract all the data and recreate the
     191        original structure when the model was saved
     192    %}
     193
     194    % get the name_of_cell_array, rows and cols vars
     195    name_of_cell_array_varID = netcdf.inqVarID(group_location_in_file, 'name_of_cell_array');
     196    rows_varID = netcdf.inqVarID(group_location_in_file, 'rows');
     197    cols_varID = netcdf.inqVarID(group_location_in_file, 'cols');
     198
     199    name_of_cell_array = netcdf.getVar(group_location_in_file, name_of_cell_array_varID).'; % transpose
     200    rows = netcdf.getVar(group_location_in_file, rows_varID);
     201    cols = netcdf.getVar(group_location_in_file, cols_varID);
     202
     203    % now we work backwards: make the cell array, fill it in, and assign it to the model
     204
     205    % make the cell array
     206    cell_array_placeholder = cell(rows, cols);
     207
     208    % get subgroups which are elements of the cell array
     209    subgroups = netcdf.inqGrps(group_location_in_file); % numerical cell array with ID's of subgroups
     210
     211    % enter each subgroup, get the data, assign it to the corresponding index of cell array
     212    if rows > 1
     213        % we go over rows
     214        % set index for cell array rows
     215        row_idx = 1;
     216        for row = subgroups
     217            % now columns
     218            columns = netcdf.inqGrps(group_location_in_file);
     219           
     220            % set index for cell array cols
     221            col_idx = 1;
     222            for column = columns
     223                % now variables
     224                current_column_varids = netcdf.inqVarIDs(column);
     225
     226                % if 'class_is_a' or 'this_is_a_nested' variables is present at this level we have to handle them accordingly
     227                try
     228                    class_is_aID = netcdf.inqVarID(column, 'class_is_a');
     229                    col_data = deserialize_class(column, NCData, verbose);
     230                    is_object = true;
     231                catch
     232                end
     233               
     234                try
     235                    this_is_a_nestedID = netcdf.inqVarID(column, 'this_is_a_nested');
     236                    % functionality not supported
     237                    disp('Error: Cell Arrays of structs not yet supported!')
     238                    % copy_nested_struct(column, model_copy, NCData, verbose)
     239                    is_object = true;
     240                catch
     241                end
     242
     243                if logical(exist('is_object', 'var'))
     244                    % already taken care of
     245                else
     246                    % store the variables as normal -- to be added later
     247                    disp('Error: Cell Arrays of mixed objects not yet supported!')
     248                    for var = current_column_varids
     249                        % not supported
     250                    end
     251                end
     252
     253                cell_array_placeholder{row_idx, col_idx} = col_data;
     254                col_idx = col_idx + 1;
     255            end
     256            row_idx = row_idx + 1;
     257        end
     258    else
     259        % set index for cell array
     260        col_idx = 1;
     261        for column = subgroups
     262            % now variables
     263            current_column_varids = netcdf.inqVarIDs(column);
     264
     265            % if 'class_is_a' or 'this_is_a_nested' variables is present at this level we have to handle them accordingly
     266            try
     267                classID = netcdf.inqVarID(column, 'class_is_a');
     268                col_data = deserialize_class(classID, column, NCData, verbose);
     269                is_object = true;
     270            catch ME
     271                rethrow(ME)
     272            end
     273           
     274            try
     275                this_is_a_nestedID = netcdf.inqVarID(column, 'this_is_a_nested');
     276                % functionality not supported
     277                disp('Error: Cell Arrays of structs not yet supported!')
     278                % col_data = copy_nested_struct(column, model_copy, NCData, verbose);
     279                is_object = true;
     280            catch
     281            end
     282            if logical(exist('is_object', 'var'))
     283                % already taken care of
     284            else
     285                % store the variables as normal -- to be added later
     286                disp('Error: Cell Arrays of mixed objects not yet supported!')
     287                for var = current_column_varids
     288                    % col_data = not supported
     289                end
     290            end
     291
     292            cell_array_placeholder{col_idx} = col_data;
     293            col_idx = col_idx + 1;
     294
     295        end
     296    end
     297   
     298
     299    % Like in copy_nested_struct, we can only handle things 1 layer deep.
     300    % assign cell array to model
     301    address_to_attr_list = split(netcdf.inqGrpNameFull(group_location_in_file), '/');
     302    address_to_attr = address_to_attr_list{2};
     303    if isprop(model_copy.(address_to_attr), name_of_cell_array);
     304        model_copy.(address_to_attr).(name_of_cell_array) = cell_array_placeholder;
     305    else
     306        model_copy = addprop(model_copy.(address_to_attr), name_of_cell_array, cell_array_placeholder);
     307    end
     308
     309    if verbose
     310        fprintf("Successfully loaded cell array %s to %s\n", name_of_cell_array,address_to_attr_list{2})
     311    end
     312end
     313
     314
     315
     316
     317function output = deserialize_class(classID, group, NCData, verbose)
     318    %{
     319        This function will recreate a class
     320    %}
     321
     322    % get the name of the class
     323    name = netcdf.getVar(group, classID).';
     324
     325    % instantiate it
     326    class_instance = eval([name, '()']);
     327
     328    % get and assign properties
     329    subgroups = netcdf.inqGrps(group); % numerical cell array with ID's of subgroups
     330
     331    if numel(subgroups) == 1
     332        % get properties
     333        varIDs = netcdf.inqVarIDs(subgroups);
     334        for varID = varIDs
     335            % var metadata
     336            [varname, xtype, dimids, numatts] = netcdf.inqVar(subgroups, varID);
     337            % data
     338            data = netcdf.getVar(subgroups, varID);
     339
     340            % netcdf uses Row Major Order but MATLAB uses Column Major Order so we need to transpose all arrays w/ more than 1 dim
     341            if all(size(data)~=1) || xtype == 2
     342                data = data.';
     343            end
     344
     345            % some classes have permissions... so we skip those
     346            try
     347                % if property already exists, assign new value
     348                if isprop(class_instance, varname)
     349                    class_instance.(varname) = data;
     350                else
     351                    addprop(class_instance, varname, data);
     352                end
     353            catch
     354            end
     355        end
     356    else
     357        % not supported
     358    end
     359    output = class_instance;
     360end
    161361
    162362
     
    192392    % and not pointers to the same memory address
    193393    % this means that if address_in_model has more than 1 layer, we need to modify the code. For now,
    194     % we just hope this will do. An example of a no-solution would be model().abc.def.ghi.field
     394    % we just hope this will do. An example of a no-solution would be model().abc.def.ghi.field whereas we're only assuming model().abc.field now
    195395   
    196396    model_copy.(address_in_model).(name_of_struct) = struct();
Note: See TracChangeset for help on using the changeset viewer.