source: CCCC/trunk/file_utils.py @ 153

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CCCC/trunk/file_utils.py@153
Revision 153, 9.3 KB checked in by mjuckes, 6 years ago (diff)

added option to use dtype instead of datatype in netcdf4 module

Line 
1
2# Standard library imports
3import string, pkgutil
4
5# Third party imports
6
7#### netcdf --- currently support cdms2, python-netCDF4 and Scientific
8
9l = pkgutil.iter_modules()
10ll = map( lambda x: x[1], l )
11
12supportedNetcdf = ['cdms2','netCDF4','Scientific']
13
14installedSupportedNetcdf = []
15
16for x in supportedNetcdf:
17  if x in ll:
18    installedSupportedNetcdf.append( x )
19
20if len(installedSupportedNetcdf) > 0:
21  try: 
22    exec 'import %s' % installedSupportedNetcdf[0]
23    ncLib = installedSupportedNetcdf[0]
24  except:
25    print 'Failed to install %s' % installedSupportedNetcdf[0]
26    ncLib = None
27else:
28  print """No supported netcdf module found.
29         Supported modules are %s.
30         Execution my fail, depending on options chosen.
31         """ % str(supportedNetcdf)
32  ncLib = None
33
34if ncLib == 'Scientific':
35  from Scientific.IO import NetCDF as ncdf
36
37## end of netcdf import.
38
39class fileMetadata:
40
41  def __init__(self,dummy=False,attributeMappingsLog=None):
42     
43     self.dummy = dummy
44     self.atMapLog = attributeMappingsLog
45     if self.atMapLog == None:
46       self.atMapLog = open( '/tmp/cccc_atMapLog.txt', 'a' )
47
48  def close(self):
49    self.atMapLog.close()
50
51  def loadNc(self,fpath):
52    self.fpath = fpath
53    self.fn = string.split( fpath, '/' )[-1]
54    self.fparts = string.split( self.fn[:-3], '_' )
55    self.ga = {}
56    self.va = {}
57    self.da = {}
58    if self.dummy:
59      self.makeDummyFileImage()
60      return
61    if ncLib == 'cdms2':
62      self.loadNc__Cdms(fpath)
63    elif ncLib == 'netCDF4':
64      self.loadNc__Netcdf4(fpath)
65    elif ncLib == 'Scientific':
66      self.loadNc__Scientific(fpath)
67    else:
68      raise 'No supported netcdf module assigned'
69
70  def loadNc__Cdms(self,fpath):
71    self.nc = cdms2.open( fpath )
72    for k in self.nc.attributes.keys():
73      self.ga[k] = self.nc.attributes[k]
74      if len( self.ga[k] ) == 1:
75        self.ga[k] = self.ga[k][0]
76    for v in self.nc.variables.keys():
77      self.va[v] = {}
78      for k in self.nc.variables[v].attributes.keys():
79        x = self.nc.variables[v].attributes[k]
80     ## returns a list for some scalar attributes.
81        if type(x) == type([]) and len(x) == 1:
82          x = x[0]
83        self.va[v][k] = x
84      self.va[v]['_type'] = str( self.nc.variables[v].dtype )
85      if v in ['plev','plev_bnds','height']:
86        x = self.nc.variables[v].getValue().tolist()
87        if type(x) != type([]):
88          x = [x]
89        self.va[v]['_data'] = x
90        ### Note: returns a scalar if data has a scalar value.
91
92    for v in self.nc.axes.keys():
93      self.da[v] = {}
94      for k in self.nc.axes[v].attributes.keys():
95        self.da[v][k] = self.nc.axes[v].attributes[k]
96      self.da[v]['_type'] = str( self.nc.axes[v].getValue().dtype )
97      self.da[v]['_data'] = self.nc.axes[v].getValue().tolist()
98     
99    self.nc.close()
100
101###
102### attributes in .__dict__ dictionary
103### variables in .variables dicttionary
104### dimension lengths in .dimensions
105### <variable>.getValue() returns an numpy.ndarray
106### data type in <variable>.getValue().dtype
107### for scalar variables, <variable>.getValue().tolist() returns a scalar.
108###
109  def loadNc__Scientific(self,fpath):
110    self.nc = ncdf.NetCDFFile( fpath, 'r' )
111    for k in self.nc.__dict__.keys():
112      self.ga[k] = self.nc.__dict__[k]
113      ##if len( self.ga[k] ) == 1:
114        ##self.ga[k] = self.ga[k][0]
115    for v in self.nc.variables.keys():
116      if v not in self.nc.dimensions.keys():
117        self.va[v] = {}
118        for k in self.nc.variables[v].__dict__.keys():
119          self.va[v][k] = self.nc.variables[v].__dict__[k]
120        self.va[v]['_type'] = str( self.nc.variables[v].getValue().dtype )
121        if v in ['plev','plev_bnds','height']:
122        ### Note: returns a scalar if data has a scalar value.
123          x = self.nc.variables[v].getValue().tolist()
124          if type(x) != type([]):
125            x = [x]
126          self.va[v]['_data'] = x
127
128    for v in self.nc.dimensions.keys():
129      self.da[v] = {}
130      if v in self.nc.variables.keys():
131        for k in self.nc.variables[v].__dict__.keys():
132          self.da[v][k] = self.nc.variables[v].__dict__[k]
133        self.da[v]['_type'] = str( self.nc.variables[v].getValue().dtype )
134        self.da[v]['_data'] = self.nc.variables[v].getValue().tolist()
135      else:
136        self.da[v]['_type'] = 'index (no data variable)'
137     
138    self.nc.close()
139
140  def loadNc__Netcdf4(self,fpath):
141    self.nc = netCDF4.Dataset(fpath, 'r')
142    for k in self.nc.ncattrs():
143      self.ga[k] = self.nc.getncattr(k)
144      if len( self.ga[k] ) == 1:
145        self.ga[k] = self.ga[k][0]
146    for v in self.nc.variables.keys():
147      if v not in self.nc.dimensions.keys():
148        self.va[v] = {}
149        for k in self.nc.variables[v].ncattrs():
150          self.va[v][k] = self.nc.variables[v].getncattr(k)
151        self.va[v]['_type'] = str( self.nc.variables[v].datatype )
152        if v in ['plev','plev_bnds','height']:
153          self.va[v]['_data'] = self.nc.variables[v][:].tolist()
154
155    for v in self.nc.dimensions.keys():
156      self.da[v] = {}
157      if v in self.nc.variables.keys():
158        for k in self.nc.variables[v].ncattrs():
159          self.da[v][k] = self.nc.variables[v].getncattr(k)
160        try:
161          self.da[v]['_type'] = str( self.nc.variables[v].dtype )
162        except:
163          self.da[v]['_type'] = str( self.nc.variables[v].datatype )
164
165        self.da[v]['_data'] = self.nc.variables[v][:].tolist()
166      else:
167        self.da[v]['_type'] = 'index (no data variable)'
168     
169    self.nc.close()
170
171  def makeDummyFileImage(self):
172    for k in range(10):
173      self.ga['ga%s' % k] =  str(k)
174    for v in [self.fparts[0],]:
175      self.va[v] = {}
176      self.va[v]['standard_name'] = 's%s' % v
177      self.va[v]['long_name'] = v
178      self.va[v]['cell_methods'] = 'time: point'
179      self.va[v]['units'] = '1'
180      self.va[v]['_type'] = 'float32'
181
182    for v in ['lat','lon','time']:
183      self.da[v] = {}
184      self.da[v]['_type'] = 'float64'
185      self.da[v]['_data'] = range(5)
186    dlist = ['lat','lon','time']
187    svals = lambda p,q: map( lambda y,z: self.da[y].__setitem__(p, z), dlist, q )
188    svals( 'standard_name', ['latitude', 'longitude','time'] )
189    svals( 'long_name', ['latitude', 'longitude','time'] )
190    svals( 'units', ['degrees_north', 'degrees_east','days since 19590101'] )
191
192  def applyMap( self, mapList, globalAttributesInFn, log=None ):
193    for m in mapList:
194      if m[0] == 'am001':
195        if m[1][0][0] == "@var":
196          if m[1][0][1] in self.va.keys():
197            this = self.va[m[1][0][1]]
198            apThis = True
199            for c in m[1][1:]:
200              if c[0] not in this.keys():
201                apThis = False
202              elif c[1] != this[c[0]]:
203                apThis = False
204            if m[2][0] != '':
205              targ = m[2][0]
206            else:
207              targ = m[1][-1][0]
208            if apThis:
209              if log != None:
210                log.info( 'Setting %s to %s' % (targ,m[2][1]) )
211              ##print 'Setting %s:%s to %s' % (m[1][0][1],targ,m[2][1])
212              thisval = self.va[m[1][0][1]].get( targ, None )
213              self.va[m[1][0][1]][targ] = m[2][1]
214              self.atMapLog.write( '@var:"%s","%s","%s","%s","%s"\n' % (self.fpath, m[1][0][1], targ, thisval, m[2][1] ) )
215
216        elif m[1][0][0] == "@ax":
217          ##print 'checking dimension ',m[1][0][1], self.da.keys()
218          if m[1][0][1] in self.da.keys():
219            ##print 'checking dimension [2]',m[1][0][1]
220            this = self.da[m[1][0][1]]
221            apThis = True
222            for c in m[1][1:]:
223              if c[0] not in this.keys():
224                apThis = False
225              elif c[1] != this[c[0]]:
226                apThis = False
227            if m[2][0] != '':
228              targ = m[2][0]
229            else:
230              targ = m[1][-1][0]
231            if apThis:
232              if log != None:
233                log.info( 'Setting %s to %s' % (targ,m[2][1]) )
234              ##print 'Setting %s:%s to %s' % (m[1][0][1],targ,m[2][1])
235              thisval = self.va[m[1][0][1]].get( targ, None )
236              self.da[m[1][0][1]][targ] = m[2][1]
237              self.atMapLog.write( '@ax:"%s","%s","%s","%s","%s"\n' % (self.fpath, m[1][0][1], targ, thisval, m[2][1]) )
238        elif m[1][0][0] == "@":
239            this = self.ga
240            apThis = True
241## apply change where attribute absent only
242            for c in m[1][1:]:
243              if c[0] not in this.keys():
244                if c[1] != '__absent__':
245                  apThis = False
246              elif c[1] == '__absent__' or c[1] != this[c[0]]:
247                apThis = False
248            if m[2][0] != '':
249              targ = m[2][0]
250            else:
251              targ = m[1][-1][0]
252            if apThis:
253              if log != None:
254                log.info( 'Setting %s to %s' % (targ,m[2][1]) )
255              ##print 'Setting %s to %s' % (targ,m[2][1])
256              thisval = self.ga.get( targ, None )
257              self.ga[targ] = m[2][1]
258              self.atMapLog.write( '@:"%s","%s","%s","%s","%s"\n' % (self.fpath, 'ga', targ, thisval, m[2][1]) )
259##
260              if targ in globalAttributesInFn:
261                i = globalAttributesInFn.index(targ)
262                thisval = self.fparts[ i ]
263                self.fparts[ i ] = m[2][1]
264                self.fn = string.join( self.fparts, '_' ) + '.nc'
265                self.atMapLog.write( '@fn:"%s","%s","%s"\n' % (self.fpath, thisval, m[2][1]) )
266        else:
267          print 'Token %s not recognised' % m[1][0][0]
Note: See TracBrowser for help on using the repository browser.