source: issm/trunk/src/m/contrib/musselman/read_netCDF.m@ 27874

Last change on this file since 27874 was 27874, checked in by musselman, 20 months ago

Fixed bugs so that read/write files function interchangeably on inversion notebooks

File size: 7.6 KB
Line 
1%{
2Given a NetCDF4 file, this set of functions will perform the following:
3 1. Enter each group of the file.
4 2. For each variable in each group, update an empty model with the variable's data
5 3. Enter nested groups and repeat
6
7
8If the model you saved has subclass instances that are not in the standard model() class
9you can:
10 1. Copy lines 30-35, set the "results" string to the name of the subclass instance,
11 2. Copy and modify the make_results_subclasses() function to create the new subclass
12 instances you need.
13From there, the rest of this script will automatically create the new subclass
14instance in the model you're writing to and store the data from the netcdf file there.
15%}
16
17
18function model_copy = read_netCDF(filename)
19 fprintf('NetCDF42C v1.1.13\n');
20
21 % make a model framework to fill that is in the scope of this file
22 global model_copy;
23 model_copy = model();
24
25 % Check if path exists
26 if exist(filename, 'file')
27 fprintf('Opening %s for reading\n', filename);
28
29 % Open the given netCDF4 file
30 global NCData;
31 NCData = netcdf.open(filename, 'NOWRITE');
32 % Remove masks from netCDF data for easy conversion: NOT WORKING
33 %netcdf.setMask(NCData, 'NC_NOFILL');
34
35 % see if results is in there, if it is we have to instantiate some classes
36 try
37 results_group_id = netcdf.inqNcid(NCData, "results");
38 make_results_subclasses();
39 catch
40 end % 'results' group doesn't exist
41
42 % see if inversion is in there, if it is we may have to instantiate some classes
43 try
44 inversion_group_id = netcdf.inqNcid(NCData, "inversion");
45 check_inversion_class();
46 catch
47 end % 'inversion' group doesn't exist
48
49 % loop over first layer of groups in netcdf file
50 for group = netcdf.inqGrps(NCData)
51 group_id = netcdf.inqNcid(NCData, netcdf.inqGrpName(group));
52 %disp(netcdf.inqGrpNameFull(group_id))
53 % hand off first level to recursive search
54 walk_nested_groups(group_id);
55 end
56
57 % Close the netCDF file
58 netcdf.close(NCData);
59 disp('Model Successfully Copied')
60 else
61 fprintf('File %s does not exist.\n', filename);
62 end
63end
64
65
66function make_results_subclasses()
67 global model_copy;
68 global NCData;
69 resultsGroup = netcdf.inqNcid(NCData, "results");
70 variables = netcdf.inqVarIDs(resultsGroup);
71 for name = variables
72 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')
77end
78
79
80function check_inversion_class()
81 % get the name of the inversion class: either inversion or m1qn3inversion or taoinversion
82 global model_copy;
83 global NCData;
84 inversionGroup = netcdf.inqNcid(NCData, "inversion");
85 varid = netcdf.inqVarID(inversionGroup, 'inversion_class_name');
86 inversion_class = convertCharsToStrings(netcdf.getVar(inversionGroup, varid,'char'));
87 if strcmp(inversion_class, 'm1qn3inversion')
88 model_copy.inversion = m1qn3inversion();
89 disp('Successfully created inversion class instance: m1qn3inversion')
90 elseif strcmp(inversion_class, 'taoinversion')
91 model_copy.inversion = taoinversion();
92 disp('Successfully created inversion class instance: taoinversion')
93 else
94 disp('No inversion class was found')
95 end
96end
97
98
99
100function walk_nested_groups(group_location_in_file)
101 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 copy_variable_data_to_new_model(group_location_in_file,varname, xtype);
112 end
113 catch ME
114 rethrow(ME)
115 end
116
117 % try to find groups in current level, if it doesn't work it's because there is nothing there
118 try
119 % search for nested groups in the current level to feed back to this function
120 groups = netcdf.inqGrps(group_location_in_file);
121 if not(isempty(groups))
122 for group = groups
123 %disp('found nested group!!')
124 group_id = netcdf.inqNcid(group_location_in_file, netcdf.inqGrpName(group));
125 %disp(netcdf.inqGrpNameFull(group_id))
126 walk_nested_groups(group);
127 end
128 end
129 catch
130 end
131end
132
133%{
134Since there are two types of objects that MATLAB uses (classes and structs), we have to check
135which object we're working with before we can set any fields/attributes of it. After this is completed,
136we can write the data to that location in the model.
137%}
138
139function copy_variable_data_to_new_model(group_location_in_file, varname, xtype)
140 global model_copy;
141 global NCData;
142 %disp(varname)
143 % this is an inversion band-aid
144 if strcmp(varname, 'inversion_class_name')
145 % we don't need this
146 else
147 % putting try/catch here so that any errors generated while copying data are logged and not lost by the try/catch in walk_nested_groups function
148 try
149 %disp(netcdf.inqGrpNameFull(group_location_in_file))
150 %disp(class(netcdf.inqGrpNameFull(group_location_in_file)))
151 adress_to_attr = strrep(netcdf.inqGrpNameFull(group_location_in_file), '/', '.');
152
153 data = netcdf.getVar(group_location_in_file, netcdf.inqVarID(group_location_in_file, varname));
154
155
156 % matlab needs to know that ' ' = char()
157 if xtype == 2 && isempty(all(data))
158 data = cell(char());
159 elseif numel(data) == 1 && xtype == 3 && data == -32767
160 data = cell(char());
161 end
162 % band-aid for cell-char-arrays:
163 if xtype == 2 && strcmp(data, 'default')
164 data = {'default'};
165 end
166
167 % netcdf uses Row Major Order but MATLAB uses Column Major Order so we need to transpose all arrays w/ more than 1 dim
168 if all(size(data)~=1) || xtype == 2
169 data = data.';
170 end
171
172 % the issm c compiler does not work with int64 datatypes, so we need to convert those to int16
173 % reference this (very hard to find) link for netcdf4 datatypes: https://docs.unidata.ucar.edu/netcdf-c/current/netcdf_8h_source.html
174 %xtype
175 if xtype == 10
176 arg_to_eval = ['model_copy', adress_to_attr, '.', varname, ' = ' , 'double(data);'];
177 eval(arg_to_eval);
178 %disp('saved int64 as int16')
179 else
180 arg_to_eval = ['model_copy', adress_to_attr, '.', varname, ' = ' , 'data;'];
181 eval(arg_to_eval);
182 end
183
184 full_addy = netcdf.inqGrpNameFull(group_location_in_file);
185 %disp(xtype)
186 %class(data)
187 fprintf('Successfully saved %s to %s\n', varname, full_addy);
188 catch e %e is an MException struct
189 fprintf(1,'There was an error with %s! \n', varname)
190 fprintf('The message was:\n%s\n',e.message);
191 fprintf(1,'The identifier was:\n%s\n',e.identifier);
192 disp()
193 % more error handling...
194 end
195 end
196end
197
198
199
Note: See TracBrowser for help on using the repository browser.