Changeset 27899
- Timestamp:
- 09/06/23 20:15:43 (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.py
r27898 r27899 28 28 def read_netCDF(filename, verbose = False): 29 29 if verbose: 30 print('NetCDF42C v1.1.13') 30 print('NetCDF42C v1.2.0') 31 32 ''' 33 filename = path and name to save file under 34 verbose = T/F = show or muted log statements. Naturally muted 35 ''' 31 36 32 37 # this is a precaution so that data is not lost … … 43 48 NCData.set_auto_mask(False) 44 49 else: 45 print('The file you entered does not exist or cannot be found in the current directory') 46 return print() 50 return 'The file you entered does not exist or cannot be found in the current directory' 47 51 48 # continuation of band-aid for results class 52 # in order to handle some subclasses in the results class, we have to utilize this band-aid 53 # there will likely be more band-aids added unless a class name library is created with all class names that might be added to a md 49 54 try: 55 # if results has meaningful data, save the name of the subclass and class instance 50 56 NCData.groups['results'] 51 57 make_results_subclasses(NCData, verbose) … … 76 82 return model_copy 77 83 78 except Error: 79 NCData.close() 80 return Error 81 84 # just in case something unexpected happens 85 except Exception as e: 86 if 'NCData' in locals(): 87 NCData.close() 88 raise e 82 89 83 90 def make_results_subclasses(NCData, verbose = False): … … 123 130 # first, we enter the group by: filename.groups['group_name'] 124 131 # second we search the current level for variables: filename.groups['group_name'].variables.keys() 125 # at this step we check for multidimensional structure arrays and filter them out132 # at this step we check for multidimensional structure arrays/ arrays of objects and filter them out 126 133 # third we get nested group keys by: filename.groups['group_name'].groups.keys() 127 # if a variables exists, copy the data to the model framework by calling copy function128 134 # if a nested groups exist, repeat all 129 135 … … 170 176 171 177 178 179 ''' 180 MATLAB has Multidimensional Structure Arrays in 2 known classes: results and qmu. 181 The python classes results.py and qmu.py emulate this MATLAB object in their own 182 unique ways. The functions in this script will assign data to either of these 183 classes such that the final structure is compatible with its parent class. 184 ''' 185 186 def deserialize_nested_results_struct(group_location_in_file, name_of_struct, NCData, verbose = False): 187 ''' 188 A common multidimensional array is the 1xn md.results.TransientSolution object. 189 190 The way that this object emulates the MATLAB mutli-dim. struct. array is with 191 the solution().steps attr. which is a list of solutionstep() instances 192 The process to recreate is as follows: 193 1. Get instance of solution() with solution variable (the instance is made in make_results_subclasses) 194 2. For each subgroup, create a solutionstep() class instance 195 2a. Populate the instance with the key:value pairs 196 2b. Append the instance to the solution().steps list 197 ''' 198 # step 1 199 class_instance_name = name_of_struct 200 201 # for some reason steps is not already a list 202 setattr(model_copy.results.__dict__[class_instance_name], 'steps', list()) 203 204 steps = model_copy.results.__dict__[class_instance_name].steps 205 206 # step 2 207 layer = 1 208 for subgroup in eval(group_location_in_file + ".groups.keys()"): 209 solutionstep_instance = solutionstep() 210 # step 2a 211 subgroup_location_in_file = group_location_in_file + ".groups['" + subgroup + "']" 212 for key in eval(subgroup_location_in_file + ".variables.keys()"): 213 value = eval(subgroup_location_in_file + ".variables['" + str(key) + "'][:]") 214 setattr(solutionstep_instance, key, value) 215 # step 2b 216 steps.append(solutionstep_instance) 217 if verbose: 218 print('Succesfully loaded layer ' + str(layer) + ' to results.' + str(class_instance_name) + ' struct.') 219 else: pass 220 layer += 1 221 222 if verbose: 223 print('Successfully recreated results structure ' + str(class_instance_name)) 224 225 226 172 227 def deserialize_array_of_objects(group_location_in_file, model_copy, NCData, verbose): 173 228 ''' … … 193 248 original structure when the model was saved 194 249 ''' 250 251 if verbose: 252 print(f"Loading array of objects.") 195 253 196 254 # get the name_of_cell_array, rows and cols vars … … 231 289 if "class_is_a" in current_col_vars: 232 290 class_name = subgroups[str(col)].variables['class_is_a'][:][...].tobytes().decode() 233 col_data = deserialize_class (class_name, columns.groups[str(col)], NCData, verbose)291 col_data = deserialize_class_instance(class_name, columns.groups[str(col)], NCData, verbose) 234 292 is_object = True 235 293 elif "this_is_a_nested" in current_col_vars: … … 267 325 if "class_is_a" in current_col_vars: 268 326 class_name = subgroups[str(col)].variables['class_is_a'][:][...].tobytes().decode() 269 col_data = deserialize_class (class_name, subgroups[str(col)], NCData, verbose)327 col_data = deserialize_class_instance(class_name, subgroups[str(col)], NCData, verbose) 270 328 is_object = True 271 329 elif "this_is_a_nested" in current_col_vars: … … 288 346 289 347 # finally, add the attribute to the model 290 # borrow some code from above:291 348 pattern = r"\['(.*?)'\]" 292 349 matches = re.findall(pattern, group_location_in_file) … … 294 351 setattr(model_copy.__dict__[variable_name], name_of_cell_array, array) 295 352 296 297 298 def deserialize_class(class_name, group, NCData, verbose=False): 299 353 if verbose: 354 print(f"Successfully loaded array of objects: {name_of_cell_array} to {variable_name}") 355 356 357 358 def deserialize_class_instance(class_name, group, NCData, verbose=False): 359 360 if verbose: 361 print(f"Loading class: {class_name}") 362 363 # this function requires the class module to be imported into the namespace of this file. 364 # we make a custom error in case the class module is not in the list of imported classes. 300 365 # most ISSM classes are imported by from <name> import <name> 301 366 class ModuleError(Exception): … … 333 398 # Not supported 334 399 pass 335 400 401 if verbose: 402 print(f"Successfully loaded class instance {class_name} to model") 336 403 return class_instance 337 404 338 339 340 '''341 MATLAB has Multidimensional Structure Arrays in 2 known classes: results and qmu.342 The python classes results.py and qmu.py emulate this MATLAB object in their own343 unique ways. The functions in this script will assign data to either of these344 classes such that the final structure is compatible with its parent class.345 '''346 347 def deserialize_nested_results_struct(group_location_in_file, name_of_struct, NCData, verbose = False):348 '''349 A common multidimensional array is the 1xn md.results.TransientSolution object.350 351 The way that this object emulates the MATLAB mutli-dim. struct. array is with352 the solution().steps attr. which is a list of solutionstep() instances353 The process to recreate is as follows:354 1. Get instance of solution() with solution variable (the instance is made in make_results_subclasses)355 2. For each subgroup, create a solutionstep() class instance356 2a. Populate the instance with the key:value pairs357 2b. Append the instance to the solution().steps list358 '''359 # step 1360 class_instance_name = name_of_struct361 362 # for some reason steps is not already a list363 setattr(model_copy.results.__dict__[class_instance_name], 'steps', list())364 365 steps = model_copy.results.__dict__[class_instance_name].steps366 367 # step 2368 layer = 1369 for subgroup in eval(group_location_in_file + ".groups.keys()"):370 solutionstep_instance = solutionstep()371 # step 2a372 subgroup_location_in_file = group_location_in_file + ".groups['" + subgroup + "']"373 for key in eval(subgroup_location_in_file + ".variables.keys()"):374 value = eval(subgroup_location_in_file + ".variables['" + str(key) + "'][:]")375 setattr(solutionstep_instance, key, value)376 # step 2b377 steps.append(solutionstep_instance)378 if verbose:379 print('Succesfully loaded layer ' + str(layer) + ' to results.' + str(class_instance_name) + ' struct.')380 else: pass381 layer += 1382 383 if verbose:384 print('Successfully recreated results structure ' + str(class_instance_name))385 405 386 406 … … 434 454 435 455 def deserialize_dict(location_of_variable_in_file, location_of_variable_in_model, NCData, verbose = False): 436 # as simple as navigating to the location_of_variable_in_model and setting it equal to the location_of_variable_in_file437 438 # NetCDF4 has a property called "_FillValue" that sometimes saves empty lists, so we have to catch those439 456 FillValue = -9223372036854775806 440 457 -
issm/trunk/src/m/contrib/musselman/write_netCDF.py
r27898 r27899 1 1 # imports 2 import NCData43 from NCData4 import Dataset2 import netCDF4 3 from netCDF4 import Dataset 4 4 import numpy as np 5 5 import numpy.ma as ma … … 23 23 24 24 25 def write_ NCData(md, filename: str, verbose = False):25 def write_netCDF(md, filename: str, verbose = False): 26 26 if verbose: 27 print('Python C2N CData4 v1.1.14')27 print('Python C2NetCDF4 v1.2.0') 28 28 else: pass 29 29 ''' 30 md = model ()class instance to be saved30 md = model class instance to be saved 31 31 filename = path and name to save file under 32 verbose = T/F muted or showlog statements. Naturally muted32 verbose = T/F = show or muted log statements. Naturally muted 33 33 ''' 34 34 # this is a precaution so that data is not lost 35 35 try: 36 36 # Create a NCData file to write to 37 NCData = create_N CData(filename, verbose)37 NCData = create_NetCDF(filename, verbose) 38 38 39 39 # Create an instance of an empty md class to compare md_var against … … 55 55 NCData.close() 56 56 if verbose: 57 print('Model successfully saved as N CData4')57 print('Model successfully saved as NetCDF4') 58 58 else: pass 59 60 except Error: 61 NCData.close() 62 return Error 59 60 # just in case something unexpected happens 61 except Exception as e: 62 if 'NCData' in locals(): 63 NCData.close() 64 raise e 63 65 64 66 … … 111 113 112 114 113 def create_N CData(filename: str, verbose = False):115 def create_NetCDF(filename: str, verbose = False): 114 116 # If file already exists delete / rename it 115 117 if os.path.exists(filename): … … 126 128 else: 127 129 # Otherwise create the file and define it globally so other functions can call it 128 NCData = Dataset(filename, 'w', format='N CData4')130 NCData = Dataset(filename, 'w', format='NETCDF4') 129 131 NCData.history = 'Created ' + time.ctime(time.time()) 130 132 NCData.createDimension('Unlim', None) # unlimited dimension … … 272 274 273 275 274 def 276 def serialize_nested_results_struct(parent_struct_name, address_of_struct, group, NCData, verbose = False): 275 277 ''' 276 This function takes a solution class instance and saves the solutionstep instances from <solution>.steps to the NCData.277 278 To do this, we get the number of dimensions (substructs) of the parent struct .278 This function takes a results.solution class instance and saves the solutionstep instances from <solution>.steps to the NCData. 279 280 To do this, we get the number of dimensions (substructs) of the parent struct (list). 279 281 Next, we iterate through each substruct and record the data. 280 282 For each substruct, we create a subgroup of the main struct. … … 313 315 314 316 def serialize_array_of_objects(list_name, address_of_child, group, NCData, verbose): 317 if verbose: 318 print(f"Serializing array of objects.") 319 315 320 # Get the dimensions of the cell array 316 321 if len(np.shape(address_of_child)) > 1: … … 341 346 else: 342 347 serialize_objects(address_of_child, subgroup, NCData, cols, verbose) 343 348 349 if verbose: 350 print(f"Successfully serialized array of objects: {list_name}") 344 351 345 352 … … 358 365 pass 359 366 # this needs more work... 360 #name_raw = list(address_of_child[col - 1].keys())[0]361 #variable_name = name_raw362 #serialize_nested_struct(variable_name, variable, subgroup, NCData, verbose)363 367 364 368 # see if it's a general class -- assume ISSM classes all have __dict__ … … 373 377 374 378 375 376 377 379 def serialize_class_instance(instance, group, NCData, verbose): 378 380 # get parent class name: … … 418 420 #or a bool 419 421 elif isinstance(address_of_child, bool) or isinstance(address_of_child, np.bool_): 420 # N CData4can't handle bool types like True/False so we convert all to int 1/0 and add an attribute named units with value 'bool'422 # NetCDF can't handle bool types like True/False so we convert all to int 1/0 and add an attribute named units with value 'bool' 421 423 variable = group.createVariable(variable_name, int, ('int',)) 422 424 variable[:] = int(address_of_child) … … 457 459 # NCData and strings dont get along.. we have to do it 'custom': 458 460 # if we hand it an address we need to do it this way: 459 if list == True: 460 """ 461 Save a list of strings to a NCData file. 462 461 if list: 462 """ 463 463 Convert a list of strings to a numpy.char_array with utf-8 encoded elements 464 464 and size rows x cols with each row the same # of cols and save to NCData … … 511 511 length_of_the_string = len(the_string_to_save) 512 512 numpy_datatype = 'S' + str(length_of_the_string) 513 str_out = NCData4.stringtochar(np.array([the_string_to_save], dtype=numpy_datatype))513 str_out = netCDF4.stringtochar(np.array([the_string_to_save], dtype=numpy_datatype)) 514 514 515 515 # we'll need to make a new dimension for the string if it doesn't already exist
Note:
See TracChangeset
for help on using the changeset viewer.