NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/raw2proc/trunk/raw2proc/ncutil.py

Revision 320 (checked in by haines, 14 years ago)

catch-up trunk to production code running on cromwell

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2009-12-30 15:45:27 haines>
3 """
4 Create, update and load utilities for netcdf files
5 """
6
7 from pycdf import *
8 import os
9 import numpy
10
11 def nc_create(ncFile, (global_atts, var_atts, dim_inits, var_inits, var_data)):
12     """
13     Create new netcdf file
14
15     :Parameters:
16         ncFile : string
17            Path and name of file to create
18         (global_atts, var_atts, dim_inits, var_inits, var_data) : tuple
19            Global Attributes, Variable Attributes, Dimensions, Variable Dimensions, and Data
20            Everything you need to create a netCDF file.
21     """
22     try:
23         # Open new netCDF file, overwrite if it exists, create if does not
24         nc = CDF(ncFile, NC.WRITE|NC.CREATE|NC.TRUNC)
25         # Automatically set define and data modes.
26         nc.automode()
27         #
28         # GLOBALS
29         for attrName in global_atts.keys():
30             setattr(nc, attrName, global_atts[attrName])
31        
32         # DIMENSIONS
33         for dim in dim_inits:
34             dimName, dimValue = dim
35             # print '%s = %d' % (dimName, dimValue)
36             ncdim = nc.def_dim(dimName, dimValue)
37        
38         # VARIABLES
39         for var in var_inits:
40             varName, varType, varDim = var
41             ncvar = nc.def_var(varName, varType, varDim)
42             # add attributes
43             for attrName in var_atts[varName].keys():
44                 setattr(ncvar, attrName, var_atts[varName][attrName])
45             # setattr(ncvar, '_FillValue', numpy.nan)
46             
47         # add data
48         nrecs = nc.inq_unlimlen()
49         for var in var_data:
50             varName, varData = var
51             # print varName
52             # print varData
53             ncvar = nc.var(varName)
54             # e.g. lat = array(var_data['lat'])
55             # if an array
56             if type(varData) == numpy.ndarray:
57                 if ncvar.isrecord():
58                     # time, ens, u, v
59                     ncvar[nrecs:nrecs+len(varData)] = varData.tolist()
60                 else:
61                     ncvar[:] = varData.tolist() # z
62             else:
63                 # if tuple, sequence or scalar
64                 ncvar[:] = varData
65        
66         nc.close()
67     except CDFError, msg:
68         print "CDFError:", msg
69         # if nc:
70         #     nc.close()
71         #     del(nc)
72
73 def nc_update(ncFile, (global_atts, var_atts, var_data)):
74     """
75     Create new netcdf file
76
77     :Parameters:
78         ncFile : string
79           Path and name of file to create
80         (global_atts, var_atts, var_data) : tuple
81           Global Attributes, Variable Attributes and Data
82           Everything you need to update a netCDF file.
83     """
84     try:
85         # Open netCDF in write mode
86         nc = CDF(ncFile, NC.WRITE)
87         # Automatically set define and data modes.
88         nc.automode()
89         #
90         # GLOBALS
91         for attrName in global_atts.keys():
92             setattr(nc, attrName, global_atts[attrName])
93        
94         # VARIABLES
95         # update attributes
96         for var in var_atts:
97             varName, atts = var
98             ncvar = nc.var(varName)
99             for attrName in atts.keys():
100                 setattr(ncvar, attrName, atts[attrName])
101            
102         # update data
103         nrecs = nc.inq_unlimlen()
104         for var in var_data:
105             varName, varData = var
106             ncvar = nc.var(varName)
107             # e.g. lat = array(var_data['lat'])
108             # if an array
109             if type(varData) == numpy.ndarray:
110                 if ncvar.isrecord():
111                     # time, ens, u, v (with unlimited dimension)
112                     ncvar[nrecs:nrecs+len(varData)] = varData.tolist()
113                 else:
114                     ncvar[:] = varData.tolist() # z (limited dimension)
115             else:
116                 # if tuple, sequence or scalar
117                 ncvar[:] = varData
118
119         nc.close()
120     except CDFError, msg:
121         print "CDFError:", msg
122         # if nc:
123         #     nc.close()
124         #     del(nc)
125
126 def nc_get_time(ncFile):
127     """Get time array from file """
128     try:
129         nc = CDF(ncFile)
130         ncvars = nc.variables()
131         if 'time' in ncvars.keys():
132             es = nc.var('time')[:]
133             units = nc.var('time').units
134         else:
135             print "time variable not found in ", ncFile
136         nc.close()
137         return (es, units)
138     except CDFError, msg:
139         print "CDFError:", msg
140
141                    
142 def nc_find_record_vars(ncFile):
143     """Find which variable are record variables"""
144     try:
145         nc = CDF(ncFile)
146         ncvars = nc.variables()
147         # list which variables is a record variable
148         var_list = [varName for varName in ncvars.keys() if nc.var(varName).isrecord()]
149         nc.close()
150         return var_list
151     except CDFError, msg:
152         print "CDFError:", msg
153                    
154
155 def nc_replace_fillvalue(ncFile, newfillvalue=-99999.0):
156     """
157     Replaces any occurrence of old _FillValue with new one
158
159     This function is useful for replacing the _FillValue global
160     attribute and then searching the data for the old value and
161     replacing it with the new one.
162
163     :Parameters:
164         ncFile : string
165           Path and name of file to create
166
167     :Other Parameters:
168         newfillvalue : type match to data (generally float)
169           By default is -99999.0
170     
171     """
172     try:
173         nc = CDF(ncFile, NC.WRITE)
174         nc.automode()
175         oldfillvalue = nc._FillValue
176         nc._FillValue = newfillvalue
177         for v in nc.variables().keys():
178             vd = nc.var(v)[:]
179             if numpy.isnan(oldfillvalue):
180                 idx = numpy.isnan(vd)
181             else:
182                 idx = vd == oldfillvalue
183             if idx.any():
184                 vd[idx] =  nc._FillValue
185                 nc.var(v)[:] = vd       
186         nc.close()
187     except CDFError, msg:
188         print "CDFError:", msg
189
190 def nc_rename_dimension(ncFile, oldname, newname):
191     """ Rename dimension name """
192     try:
193         nc = CDF(ncFile, NC.WRITE)
194         nc.definemode()
195         for d in nc.dimensions().keys():
196             if d==oldname: nc.dim(d).rename(newname)
197         nc.close()
198     except CDFError, msg:
199         print "CDFError:", msg
200                                
201
202 def nc_file_check(fns):
203     """Check file or list of files to ensure it is a netcdf file
204     If it is not, remove a file or files from the list"""
205     if isinstance(fns, str):
206         try:
207             nc = CDF(fns)
208             nc.close()
209             new_fns = fns
210         except CDFError, msg:
211             print "CDFError:", msg, fns
212             new_fns = None
213        
214     else:
215         new_fns = []
216         for fn in fns:
217             try:
218                 nc = CDF(fn)
219                 nc.close()
220                 new_fns.append(fn)
221             except CDFError, msg:
222                 print "CDFError:", msg, fn
223        
224     return tuple(new_fns)
225    
226
227 def nc_load(ncFile, varsLoad='all', nameType='variable_name',
228             ga_flag=True, va_flag=True):
229     """
230     Load netcdf file
231
232     :Parameters:
233         ncFile : string or list of strings
234             Path and name of file to load
235             If list, then CDFMF
236
237     :Other Parameters:
238         nameType : string 'variable_name' (default) or 'standard_name'
239             Defines naming convention to use for variable names as data
240             are loaded.  Variable name is the name used to store data
241             in file.  'standard_name' means use variable name based on
242             variable attribute called 'standard_name' of netcdf variable.
243         varLoad : string or tuple of strings
244             specific variable names to be loaded into a sequence or scalar
245             in python following specification set in nameType
246             By default, all variables will be loaded.
247         ga_flag : boolean flag
248             By default, load the global file attributes
249         va_flag : boolean flag
250             By default, load the variable file attributes
251             
252     :Returns:
253         (global_atts, var_atts, dim_inits, var_inits, var_data) : tuple
254           Global Attributes, Variable Attributes, Dimensions, Variable Dimensions, and Variable Data
255           Everything you need to create a netCDF file.
256
257     """
258    
259     try:
260         if isinstance(ncFile, str):
261             # if only one file and it is a string
262             nc = CDF(ncFile)
263         else:
264             # if multiple filenames
265             nc = CDFMF(tuple(set(ncFile)))
266
267         ncdims = nc.dimensions(full=1)
268         ncvars = nc.variables()
269
270         # GLOBAL ATTRIBUTES (global_atts)
271         if ga_flag:
272             global_atts = nc.attributes()
273         else:
274             global_atts = {}
275
276         # DIMENSIONS (dim_inits)
277         dim_inits = [None for j in range(len(ncdims))]
278         if len(ncdims)>0:
279             for dimName,dimValue in ncdims.items():
280                 val,idx,isUN = dimValue
281                 if isUN:
282                     dim_inits[idx] = (dimName, NC.UNLIMITED)
283                 else:
284                     dim_inits[idx] = (dimName, val)
285
286         if varsLoad == 'all':
287             varNames = ncvars.keys()
288         else:
289             varNames = varsLoad
290
291         # VARIABLE DIMENSIONS (var_inits)
292         # gets init info for requested variables and original order
293
294         # initialize with same number of original variables
295         # so order can be preserved by idx
296         var_inits = [None for j in range(len(ncvars))]
297         if len(ncvars)>0:
298             for varName in varNames:
299                     val,shape,typ,idx = ncvars[varName]
300                     var_inits[idx] = (varName, typ, val)
301
302         # remove the None values from the list to preserve original order
303         var_inits = [v for v in var_inits if v != None]
304        
305         # VARIABLE ATTRIBUTES (var_atts)
306         # gets attributes of requested variables
307         var_atts = {}
308         if len(ncvars)>0 and va_flag:
309             for var in varNames:
310                 varAttrs = nc.var(var).attributes()
311                 var_atts[var] = varAttrs
312
313         # VARIABLE DATA (var_data)
314         # loads requested variables, original order preserved as with var_inits
315         var_data = [None for j in range(len(ncvars))]
316         if len(ncvars)>0:
317             for varName in varNames:
318                 val,shape,typ,idx = ncvars[varName]
319                 var_data[idx] = (varName, nc.var(varName)[:])
320
321         var_data = [v for v in var_data if v != None]
322
323         # type cast lists into tuples
324         dim_inits = tuple(dim_inits)
325         var_inits = tuple(var_inits)
326         var_data = tuple(var_data)
327
328         nc.close()
329         return (global_atts, var_atts, dim_inits, var_inits, var_data)
330        
331     except CDFError, msg:
332         print "CDFError:", msg
333
334        
Note: See TracBrowser for help on using the browser.