source: CCCC/trunk/file_utils.py @ 147

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

Support for netCDF4 added. File metadata module move to new file_utils.py file

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