Changeset 27838


Ignore:
Timestamp:
07/19/23 10:40:00 (20 months ago)
Author:
musselman
Message:

write_netCDF.py: modified an exception statement to pass an expected AttributeError instead of printing them on log. read_netCDF.py: added _FillValue catch so that when reading netCDF4 to model _FillValue is stored as [].

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

Legend:

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

    r27836 r27838  
    2222
    2323def read_netCDF(filename):
     24    print('NetCDF42C v1.1.12')
     25
    2426    # check if path exists
    2527    if path.exists(filename):
     
    9395    # as simple as navigating to the location_of_variable_in_model and setting it equal to the location_of_variable_in_file
    9496
     97    # NetCDF4 has a property called "_FillValue" that sometimes saves empty lists, so we have to catch those
     98    FillValue = -9223372036854775806
     99   
    95100    # but there are a couple of cases we need to compensate for, like an arrary of a single integer should just be an integer and not an array
    96101    if len(eval(location_of_variable_in_file))>1:
     
    99104    if 'char' in eval(location_of_variable_in_file + '.dimensions[0]'):
    100105        setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:][...].tobytes().decode()'))
    101     # catch everything else (lists, arrays, etc.)
     106    # catch everything else (lists, 1-D arrays, etc.)
    102107    else:
    103         setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:][0]')) # note the [0] on the end
     108        # check for FillValue. use try/except because try block will only work on datatypes than like int64, float, single element lists/arrays ect and not nd-arrays/n-lists etc
     109        print(eval(location_of_variable_in_file + '[:][0]'))
     110        try:
     111            if FillValue == eval(location_of_variable_in_file + '[:][0]'):
     112                setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, [])
     113        except:
     114            setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:][0]')) # note the [0] on the end
    104115       
    105116    print('Successfully saved ' + location_of_variable_in_model + '.' + variable_name + ' to model.')
  • issm/trunk/src/m/contrib/musselman/write_netCDF_commit.py

    r27836 r27838  
    11# imports
     2import netCDF4
    23from netCDF4 import Dataset
    34import numpy as np
     
    67from os import path, remove
    78from model import *
     9from results import *
    810
    911
     
    2022
    2123def write_netCDF(model_var, model_name: str, filename: str):
     24    print('C2NetCDF4 v1.1.12')
    2225    '''
    2326    model_var = class object to be saved
     
    3740    # Walk through the model_var class and compare subclass states to empty_model
    3841    walk_through_model(model_var, model_name)
    39    
     42
     43    # in order to handle some subclasses in the results class, we have to utilize this band-aid
     44    # 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 model
     45    try:
     46        # if results has meaningful data, save the name of the subclass and class instance
     47        NetCDF.groups['results']
     48        results_subclasses_bandaid(model_var)
     49        # otherwise, ignore
     50    except KeyError:
     51        pass
     52       
    4053    NetCDF.close()
    4154    print('Model successfully saved as NetCDF4')
    4255   
     56
     57
     58def results_subclasses_bandaid(model_var):
     59    # since the results class may have nested classes within it, we need to record the name of the
     60    # nested class instance variable as it appears in the model that we're trying to save
     61    quality_control = []
     62    for class_instance_name in model_var.results.__dict__.keys():
     63        # for each class instance in results, see which class its from and record that info in the netcdf to recreate structure later
     64        # check to see if there is a solutionstep class instance
     65        if isinstance(model_var.results.__dict__[class_instance_name],solutionstep):
     66            quality_control.append(1)
     67            write_string_to_netcdf(variable_name=str('solutionstep'), adress_of_child=str(class_instance_name), group=NetCDF.groups['results'])
     68        # check to see if there is a solution class instance
     69        if isinstance(model_var.results.__dict__[class_instance_name],solution):
     70            quality_control.append(1)
     71            write_string_to_netcdf(variable_name=str('solution'), adress_of_child=str(class_instance_name), group=NetCDF.groups['results'])
     72        # check to see if there is a resultsdakota class instance
     73        if isinstance(model_var.results.__dict__[class_instance_name],resultsdakota):
     74            quality_control.append(1)
     75            write_string_to_netcdf(variable_name=str('resultsdakota'), adress_of_child=str(class_instance_name), group=NetCDF.groups['results'])
     76    if len(quality_control) != len(model_var.results.__dict__.keys()):
     77        print('Error: The class instance within your model.results class is not currently supported by this application')
     78        print(type(model_var.results.__dict__[class_instance_name]))
     79    else:
     80        print('The results class was successfully stored on disk')
     81
    4382
    4483   
     
    79118def walk_through_subclasses(model_var, adress: str, model_name: str):
    80119    # Iterate over each subclass' attributes
    81     # Use try/except since it's either a class or it's not, no unknown exceptions
     120    # Use try/except since it's either a class w/ attributes or it's not, no unknown exceptions
    82121    try:
    83122        # enter the subclass, see if it has nested classes and/or attributes
    84         # then compare attribute states between models and write to netCDF if they differ
    85         # repeat starting from new location
     123        # then compare attributes between models and write to netCDF if they differ
     124        # if subclass found, walk through it and repeat
    86125        for child in eval(adress + '.__dict__.keys()'):
    87126            # make a string variable so we can send thru this func again
     
    101140                create_group(model_var, adress_of_child)
    102141                walk_through_subclasses(model_var, adress_of_child, model_name)
    103     except: pass
    104 
    105  
     142    except AttributeError: pass
     143    except Exception as e: print(e)
     144
     145
     146       
    106147def create_group(model_var, adress_of_child):
    107148    # start by splitting the adress_of_child into its components
     
    139180        variable = group.createVariable(variable_name, float, ('float',))
    140181        variable[:] = eval(adress_of_child)
    141        
     182
    142183    # or a string
    143184    elif isinstance(eval(adress_of_child), str):
    144185        write_string_to_netcdf(variable_name, adress_of_child, group)
    145186       
    146     # or a list of strings -- this needs work as it can only handle a list of 1 string
    147     elif isinstance(eval(adress_of_child)[0],str):
    148         for string in eval(adress_of_child):
    149             write_string_to_netcdf(variable_name, string, group)
    150        
    151     # or a list
    152     elif isinstance(eval(adress_of_child), list):
    153         variable = group.createVariable(variable_name, type(eval(adress_of_child)[0]), ('Unlim',))
    154         variable[:] = eval(adress_of_child)
    155        
    156187    # or an empty list
    157188    elif isinstance(eval(adress_of_child), list) and len(eval(adress_of_child))==0:
    158189        variable = group.createVariable(variable_name, int, ('int',))
     190
     191    # or a list of strings -- this needs work as it can only handle a list of 1 string
     192    elif isinstance(eval(adress_of_child),list) and isinstance(eval(adress_of_child)[0],str):
     193        for string in eval(adress_of_child):
     194            write_string_to_netcdf(variable_name, string, group)
     195
     196    # or a regular list
     197    elif isinstance(eval(adress_of_child), list):
     198        variable = group.createVariable(variable_name, type(eval(adress_of_child)[0]), ('Unlim',))
     199        variable[:] = eval(adress_of_child)
    159200
    160201    # anything else... (will likely need to add more cases; ie dict)
     
    169210    print('Successfully transferred data from ' + adress_of_child + ' to the NetCDF')
    170211   
     212
     213
    171214
    172215def write_string_to_netcdf(variable_name, adress_of_child, group):
     
    177220        length_of_the_string = len(the_string_to_save)
    178221        numpy_datatype = 'S' + str(length_of_the_string)
    179         str_out = netCDF4.stringtochar(np.array(['the_string_to_save'], dtype=numpy_datatype))
     222        str_out = netCDF4.stringtochar(np.array([the_string_to_save], dtype=numpy_datatype))
    180223    #otherwise we need to treat it like a string:
    181224    except:
     
    183226        length_of_the_string = len(the_string_to_save)
    184227        numpy_datatype = 'S' + str(length_of_the_string)
    185         str_out = netCDF4.stringtochar(np.array(['the_string_to_save'], dtype=numpy_datatype))       
     228        str_out = netCDF4.stringtochar(np.array([the_string_to_save], dtype=numpy_datatype))       
    186229
    187230    # we'll need to make a new dimension for the string if it doesn't already exist
     231    name_of_dimension = 'char' + str(length_of_the_string)
    188232    try:
    189         name_of_dimension = 'char' + str(length_of_the_string)
    190233        group.createDimension(name_of_dimension, length_of_the_string)
    191234    except: pass
    192235    # now we can make a variable in this dimension:
    193     string = group.createVariable(variable_name, 'S1', ('nchar'))
     236    string = group.createVariable(variable_name, 'S1', (name_of_dimension))
    194237    #finally we can write the variable:
    195     string[:] = the_string_to_save   
     238    string[:] = str_out
    196239
    197240
Note: See TracChangeset for help on using the changeset viewer.