Changeset 27894
- Timestamp:
- 09/01/23 16:40:56 (19 months ago)
- Location:
- issm/trunk/src/m/contrib/musselman
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk/src/m/contrib/musselman/read_netCDF.m
r27889 r27894 130 130 % keep an eye out for nested structs: 131 131 if strcmp(varname, 'this_is_a_nested') 132 is_ nested= true;132 is_object = true; 133 133 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); 134 137 elseif strcmp(varname, 'solution') 135 138 % band-aid pass.. 136 139 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 138 145 end 139 146 end … … 142 149 %try 143 150 % 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')) 145 152 % do nothing 146 153 else … … 159 166 end 160 167 168 169 % to read cell arrays with objects: 170 function 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 312 end 313 314 315 316 317 function 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; 360 end 161 361 162 362 … … 192 392 % and not pointers to the same memory address 193 393 % 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 195 395 196 396 model_copy.(address_in_model).(name_of_struct) = struct(); -
issm/trunk/src/m/contrib/musselman/write_netCDF.m
r27889 r27894 159 159 if numel(quality_control) ~= numel(class_instance_names) 160 160 disp('Error: The class instance within your model.results class is not currently supported by this application'); 161 disp(class(results_var.(class_instance_name)));162 161 else 163 162 if verbose … … 299 298 300 299 function create_group(location_of_child, list_of_layers, NetCDF, verbose) 300 %disp(list_of_layers) 301 301 % location_of_child is an object 302 302 % list_of_layers is a list like {'inversion', 'StressbalanceSolution','cost_functions_coefficients'} … … 324 324 end 325 325 end 326 % we may be dealing with an object326 % sometimes objects are passed through twice so we account for that with this try/catch 327 327 try 328 % if this line works, we're still dealing with a struct and need lower levels 329 if isempty(fieldnames(location_of_child)) 330 % do nothing 331 elseif isstruct(location_of_child) && any(size(location_of_child) > 1) 332 % we have a nested struct 333 copy_nested_struct(variable_name, location_of_child, group, NetCDF, verbose) 328 % we may be dealing with an object 329 % first we screen for structs 330 if isstruct(location_of_child) % && any(size(location_of_child) > 1) -- this is being tested 331 % we have a struct 332 copy_nested_struct(variable_name, location_of_child, group, NetCDF, verbose); 333 334 % now for cell arrays of datastructures: 335 elseif logical(~isstruct(location_of_child) && iscell(location_of_child) && isobject(location_of_child{1})) 336 copy_cell_array_of_objects(variable_name, location_of_child, group, NetCDF, verbose); 337 else 338 if ~isobject(location_of_child) && ~isstruct(location_of_child) 339 % we're dealing with raw data 340 create_var(variable_name, location_of_child, group, NetCDF, verbose); 341 end 334 342 end 335 343 catch 336 % if that line doesn't work, it means we're dealing with raw data 337 % not a nested struct, so we can pass 338 create_var(variable_name, location_of_child, group, NetCDF, verbose); 339 end 340 end 341 344 % do nothing 345 end 346 end 347 348 349 350 function copy_cell_array_of_objects(variable_name, address_of_child, group, NetCDF, verbose) 351 % make subgroup to represent the array 352 [rows, cols] = size(address_of_child); 353 name_of_subgroup = [num2str(rows), 'x', num2str(cols), '_cell_array_of_objects']; 354 subgroup = netcdf.defGrp(group, name_of_subgroup); 355 356 % save the name of the cell array 357 write_string_to_netcdf('name_of_cell_array', variable_name, subgroup, NetCDF, verbose); 358 359 % save the dimensions of the cell array 360 create_var('rows', rows, subgroup, NetCDF, verbose); 361 create_var('cols', cols, subgroup, NetCDF, verbose); 362 363 % if this is a multidimensional cell array, iterate over rows here and cols in copy_objects 364 if rows>1 365 for row = 1:rows 366 % make a subgroup for each row 367 name_of_subgroup = ['Row_', num2str(row), '_of_', num2str(rows)]; 368 subgroup = netcdf.defGrp(group, name_of_subgroup); 369 copy_objects(address_of_child, subgroup, NetCDF, cols, verbose); 370 end 371 else 372 copy_objects(address_of_child, subgroup, NetCDF, cols, verbose); 373 end 374 end 375 376 377 378 function copy_objects(address_of_child, group, NetCDF, cols, verbose) 379 for col = 1:cols 380 % make subgroup to contain each col of array 381 name_of_subgroup = ['Col_', num2str(col), '_of_', num2str(cols)]; 382 subgroup = netcdf.defGrp(group, name_of_subgroup); 383 384 % get the kind of object we're working with: 385 if isstruct(address_of_child{col}) 386 % handle structs 387 name_raw = fields(address_of_child{col}); 388 variable_name = name_raw{1}; 389 copy_nested_struct(variable_name, address_of_child, subgroup, NetCDF, verbose); 390 391 elseif numel(properties(address_of_child{col})) > 0 392 % handle class instances 393 copy_class_instance(address_of_child{col}, subgroup, NetCDF, verbose); 394 else 395 disp('ERROR: Cell arrays of mixed types are not yet supported in read_netCDF!\n Deserialization will not be able to complete!') 396 % handle regular datastructures that are already supported 397 name_raw = fields(address_of_child); 398 variable_name = name_raw{col}; 399 create_var(variable_name, address_of_child, subgroup, NetCDF, verbose); 400 end 401 end 402 end 403 404 405 function copy_class_instance(address_of_child, subgroup, NetCDF, verbose) 406 % get parent class name 407 name = class(address_of_child); 408 409 % save the name of the class 410 write_string_to_netcdf('class_is_a', name, subgroup, NetCDF, verbose); 411 412 % make subgroup to contain properties 413 name_of_subgroup = ['Properties_of_', name]; 414 subgroup = netcdf.defGrp(subgroup, name_of_subgroup); 415 416 % get properties 417 props = properties(address_of_child); 418 419 for property = 1:length(props) 420 variable_name = props{property}; 421 create_var(variable_name, address_of_child.(variable_name), subgroup, NetCDF, verbose); 422 end 423 424 end 342 425 343 426 … … 345 428 %{ 346 429 This function takes a struct of structs and saves them to netcdf. 430 431 It also works with single structs. 347 432 348 433 To do this, we get the number of dimensions (substructs) of the parent struct. … … 352 437 %} 353 438 354 if verbose355 disp("Beginning transfer of nested MATLAB struct to the NetCDF")356 end357 439 % make a new subgroup to contain all the others: 358 440 group = netcdf.defGrp(group, parent_struct_name); … … 386 468 end 387 469 if verbose 388 fprintf( 'Succesfully transferred nested MATLAB struct %s to the NetCDF\n', parent_struct_name)470 fprintf(["Succesfully transferred nested MATLAB struct ", parent_struct_name, " to the NetCDF\n"]) 389 471 end 390 472 end … … 583 665 584 666 function write_numeric_array_to_netcdf(variable_name, address_of_child, group, NetCDF, verbose) 667 585 668 % get the dimensions we'll need 586 669 intdim = netcdf.inqDimID(NetCDF,'int');
Note:
See TracChangeset
for help on using the changeset viewer.