Changeset 27877


Ignore:
Timestamp:
08/16/23 10:34:25 (19 months ago)
Author:
musselman
Message:

Streamlined some code in both scripts. Added functionality for multiple struct fields under the results subclass.

Location:
issm/trunk/src/m/contrib/musselman
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk/src/m/contrib/musselman/read_netCDF.m

    r27875 r27877  
    7171    for name = variables
    7272        class_instance = netcdf.inqVar(resultsGroup, name);
    73         class_instance_name = convertCharsToStrings(netcdf.getVar(resultsGroup, name, 'char'));
    74         model_copy.results = setfield(model_copy.results, class_instance, class_instance_name);
    75     end
    76     disp('Successfully recreated results struct')
     73        class_instance_names_raw = netcdf.getVar(resultsGroup, name, 'char').';
     74        class_instance_names = cellstr(class_instance_names_raw);
     75        for index = 1:numel(class_instance_names)
     76            class_instance_name = class_instance_names{index};
     77            model_copy.results = setfield(model_copy.results, class_instance_name, struct());
     78        end
     79        %model_copy.results = setfield(model_copy.results, class_instance, class_instance_name);
     80    end
     81    disp('Successfully recreated results structs:')
     82    for fieldname = string(fieldnames(model_copy.results))
     83        disp(fieldname)
     84    end
    7785end
    7886
     
    100108function walk_nested_groups(group_location_in_file)
    101109    global model_copy;
    102     global NCData;
    103     % try to find vars in current level, if it doesn't work it's because there is nothing there
    104     try
    105         % we search the current group level for variables by getting this struct
    106         variables = netcdf.inqVarIDs(group_location_in_file);   
    107    
    108         % from the variables struct get the info related to the variables
    109         for variable = variables
    110             [varname, xtype, dimids, numatts] = netcdf.inqVar(group_location_in_file, variable);
    111 
    112             % keep an eye out for nested structs:
    113             if strcmp(varname, 'this_is_a_nested')
    114                 is_nested = true;
    115                 copy_nested_struct(group_location_in_file)
    116             else
    117                 is_nested = false;
    118                 copy_variable_data_to_new_model(group_location_in_file,varname, xtype);
    119             end
    120         end
    121     catch ME
    122         rethrow(ME)
     110    global NCData;   
     111    % we search the current group level for variables by getting this struct
     112    variables = netcdf.inqVarIDs(group_location_in_file);
     113
     114    % from the variables struct get the info related to the variables
     115    for variable = variables
     116        [varname, xtype, dimids, numatts] = netcdf.inqVar(group_location_in_file, variable);
     117       
     118        % keep an eye out for nested structs:
     119        if strcmp(varname, 'this_is_a_nested')
     120            is_nested = true;
     121            copy_nested_struct(group_location_in_file)
     122        elseif strcmp(varname, 'solution')
     123            % band-aid pass..
     124        else
     125            copy_variable_data_to_new_model(group_location_in_file, varname, xtype);
     126        end
    123127    end
    124128
    125129    % try to find groups in current level, if it doesn't work it's because there is nothing there
    126     try
    127         % if it's not a nested struct, keep searching for subgroups
    128         if isnested
    129             % do nothing
    130         else
    131             % search for nested groups in the current level to feed back to this function
    132             groups = netcdf.inqGrps(group_location_in_file);
    133             if not(isempty(groups))
    134                 for group = groups
    135                     %disp('found nested group!!')
    136                     group_id = netcdf.inqNcid(group_location_in_file, netcdf.inqGrpName(group));
    137                     %disp(netcdf.inqGrpNameFull(group_id))
    138                     walk_nested_groups(group);
    139                 end
    140             end
    141         end
    142     catch % no nested groups here
    143     end
     130    %try
     131    % if it's a nested struct the function copy_nested_struct has already been called
     132    if logical(exist('is_nested', 'var'))
     133        % do nothing
     134    else
     135        % search for nested groups in the current level to feed back to this function
     136        groups = netcdf.inqGrps(group_location_in_file);
     137        if not(isempty(groups))
     138            for group = groups
     139                group_id = netcdf.inqNcid(group_location_in_file, netcdf.inqGrpName(group));
     140                %disp(netcdf.inqGrpNameFull(group_id))
     141                walk_nested_groups(group);
     142            end
     143        end
     144    end
     145    %catch % no nested groups here
     146    %end
    144147end
    145148
     
    152155        A common multidimensional struct array is the 1xn md.results.TransientSolution struct.
    153156        The process to recreate is as follows:
    154             1. Get the name of the struct from group variable name_of_struct
     157            1. Get the name of the struct from group name
    155158            2. Get the fieldnames from the subgroups
    156159            3. Recreate the struct with fieldnames
     
    159162
    160163    % step 1
    161     varid = netcdf.inqVarID(group_location_in_file, 'name_of_struct');
    162     name_of_struct = netcdf.getVar(group_location_in_file, varid)';
     164    name_of_struct = netcdf.inqGrpName(group_location_in_file);
    163165
    164166    % step 2
     
    174176
    175177    % step 3
    176     address_in_model = strrep(netcdf.inqGrpNameFull(group_location_in_file), '/', '');
     178    address_in_model_raw = split(netcdf.inqGrpNameFull(group_location_in_file), '/');
     179    address_in_model = address_in_model_raw{2};
     180   
    177181    % we cannot assign a variable to represent this object as MATLAB treats all variables as copies
    178182    % and not pointers to the same memory address
    179     % this means that if address_in_model is more than 1 item, we need to modify the code. For now,
    180     % we just hope this will do
     183    % this means that if address_in_model has more than 1 layer, we need to modify the code. For now,
     184    % we just hope this will do. An example of a no-solution would be model().abc.def.ghi.field
    181185   
    182186    model_copy.(address_in_model).(name_of_struct) = struct();
    183    
    184187    % for every fieldname in the subgroup, create an empty field
    185188    for fieldname = string(fieldnames)
     
    250253            elseif numel(data) == 1 && xtype == 3 && data == -32767
    251254                data = cell(char());
     255            elseif isempty(all(data))
     256                data = []
    252257            end
    253258            % band-aid for some cell-char-arrays:
     
    260265                data = data.';
    261266            end
    262 
     267   
    263268            % if we have a list of strings
    264269            if xtype == 2
    265270                try
    266                     if strcmp(netcdf.getAtt(group, varid, "type_is"), 'cell_array_of_strings')
    267                         data = cellstr(data)
     271                    if strcmp(netcdf.getAtt(group_location_in_file, varid, "type_is"), 'cell_array_of_strings')
     272                        data = cellstr(data);
    268273                    end
    269274                catch
     
    280285                %disp('saved int64 as int16')
    281286            else
    282                 arg_to_eval = ['model_copy', address_to_attr, '.', varname, ' = ' , 'data;'];
     287                arg_to_eval = ['model_copy', address_to_attr, '.', varname, ' = data;'];
    283288                eval(arg_to_eval);
    284289            end
     
    288293            %class(data)
    289294            fprintf('Successfully saved %s to %s\n', varname, full_addy);
    290         catch e %e is an MException struct
     295
     296        catch Me %e is an MException struct
     297            % Some error occurred if you get here.
    291298            fprintf(1,'There was an error with %s! \n', varname)
    292             fprintf('The message was:\n%s\n',e.message);
    293             fprintf(1,'The identifier was:\n%s\n',e.identifier);
    294             disp()
     299            errorMessage = sprintf('Error in function %s() at line %d.\n\nError Message:\n%s', ME.stack.name, ME.stack.line, ME.message);
     300            fprintf(1, '%s\n', errorMessage);
     301            uiwait(warndlg(errorMessage));
     302            %line = Me.stack.line
     303            %fprintf(1,'There was an error with %s! \n', varname)
     304            %fprintf('The message was:\n%s\n',Me.message);
     305            %fprintf(1,'The identifier was:\n%s\n',Me.identifier);
     306           
    295307            % more error handling...
    296308        end
  • issm/trunk/src/m/contrib/musselman/write_netCDF.m

    r27875 r27877  
    9595   
    9696    % Loop through each class instance in results
    97     class_instance_names = fieldnames(results_var);
     97    class_instance_names = fieldnames(results_var)
     98
     99    % we save lists of instances to the netcdf
     100    solutions = {}
     101    solutionsteps = {}
     102    resultsdakotas = {}
    98103   
    99104    for i = 1:numel(class_instance_names)
    100105        class_instance_name = class_instance_names{i};
    101        
     106        % there are often mutliple instances of the same class/struct so we have to number them
    102107        % Check to see if there is a solutionstep class instance
    103108        if contains(class_instance_name, 'solutionstep',IgnoreCase=true)
    104109            quality_control{end+1} = 1;
    105             write_string_to_netcdf('solutionstep', class_instance_name, groupid);
     110            solutionsteps{end+1} = class_instance_name
     111            %varname = ['solutionstep', num2str(i)]
     112            %write_string_to_netcdf(varname, class_instance_name, groupid);
    106113            disp('Successfully stored class python subclass instance: solutionstep')
    107114        end
     
    110117        if contains(class_instance_name, 'solution',IgnoreCase=true)
    111118            quality_control{end+1} = 1;
    112             write_string_to_netcdf('solution', class_instance_name, groupid);
     119            solutions{end+1} = class_instance_name
     120            %varname = ['solution', num2str(i)]
     121            %write_string_to_netcdf(varname, class_instance_name, groupid);
    113122            disp('Successfully stored class python subclass instance: solution')
    114123        end
     
    117126        if contains(class_instance_name, 'resultsdakota',IgnoreCase=true)
    118127            quality_control{end+1} = 1;
    119             write_string_to_netcdf('resultsdakota', class_instance_name, groupid);
     128            resultsdakotas{end+1} = class_instance_name
     129            %varname = ['resultsdakota', num2str(i)]
     130            %write_string_to_netcdf(varname, class_instance_name, groupid);
    120131            disp('Successfully stored class python subclass instance: resultsdakota')
    121132        end
    122133    end
    123    
     134    if ~isempty(solutionsteps)
     135        write_cell_with_strings('solutionstep', solutionsteps, groupid)
     136    end
     137    if ~isempty(solutions)
     138        write_cell_with_strings('solution', solutions, groupid)
     139    end
     140    if ~isempty(resultsdakotas)
     141        write_cell_with_strings('resultsdakota', resultsdakotas, groupid)
     142    end
     143   
     144   
     145
    124146    % Check if all class instances were processed correctly
    125147    if numel(quality_control) ~= numel(class_instance_names)
     
    319341
    320342    disp("Beginning transfer of nested MATLAB struct to the NetCDF")
    321 
     343    % make a new subgroup to contain all the others:
     344    group = netcdf.defGrp(group, parent_struct_name);
     345   
    322346    % make sure other systems can flag the nested struct type
    323347    dimID = netcdf.defDim(group, 'struct', 6);
     
    327351    netcdf.putVar(group, string_var, method_ID);
    328352
    329     % make sure other systems know the name of the parent struct
    330     uint_method=uint8(parent_struct_name).';
    331     method_ID = char(uint_method);
    332     dimID = netcdf.defDim(group, 'struct_name', [numel(method_ID)]);
    333     string_var = netcdf.defVar(group, 'name_of_struct', "NC_CHAR", dimID);
    334     netcdf.putVar(group, string_var, method_ID);
     353    % other systems know the name of the parent struct because it's covered by the results/qmu functions above
    335354   
    336355    % 'a' will always be 1 and is not useful to us
     
    339358    for substruct = 1:no_of_dims
    340359        % we start by making subgroups with nice names like "TransientSolution_substruct_44"
    341         name_of_subgroup = [parent_struct_name, '_substruct_', num2str(substruct)];
     360        name_of_subgroup = ['1x', num2str(substruct)];
    342361        subgroup = netcdf.defGrp(group, name_of_subgroup);
    343362
Note: See TracChangeset for help on using the changeset viewer.