source: TI02-CSML/trunk/csml/csmllibs/csmldataiface.py @ 1673

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/csml/csmllibs/csmldataiface.py@1673
Revision 1673, 13.6 KB checked in by domlowe, 14 years ago (diff)

subclassed cdunifdatainterface to create cdmldatainterface. This takes into account differences in the cdml and cdms apis

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/env python
2
3#**************************************************************************************
4#csmldataIface.py
5#contains classes for interfacing with various files
6#currently supports cdunif (NetCDF, PP, Grib(untested)) And Nappy (NASAAmes)
7#use by instantiating the factory class: DataInterface
8#v0.00 30th November 2005
9#Dominic Lowe, BADC
10#**************************************************************************************
11
12
13import cdms 
14try:
15    import nappy 
16except ImportError:
17    print 'could not import NASAAmes interface'
18import string
19import sys
20
21class DataInterface(object):
22        #Use DataInterface and setInterfaceType to instantiate the correct
23        #subclass for data
24        def __init__(self):
25                self.iface ='None'
26               
27        def setInterfaceType(self,interfaceType):
28                # function returns approprate data interface
29                #set interfaceType: should correspond to available datainterface subclasses
30                self.iface =interfaceType
31                if self.iface == 'nappy':
32                        return NappyInterface()
33                elif self.iface == 'cdunif':
34                        return cdunifInterface()
35               
36               
37        def getUnknownInterfaceType(self, filename):
38                #if the interface type is not known at the time of instantiation, then use
39                #this function to examine the file and return the correct interface (if it exists).
40                fileExtension = str(filename)[-3:]
41                print 'fe: %s'%fileExtension
42                if fileExtension == '.nc':
43                        return cdunifInterface()
44                if fileExtension == '.qxf':
45                        return cdunifInterface()
46                elif fileExtension == '.pp':
47                        return cdunifInterface()
48                elif fileExtension == 'ctl':
49                        return cdunifInterface()
50                elif fileExtension == 'xml':
51                        return cdmlInterface()
52                else:
53                        try:
54                                nappy.readFFI(filename) in [1001,1010,1020,2010,2110,2160,2310,3010,4010]
55                                return NappyInterface()
56                        except:
57                                print "Could not establish file type"
58                                print "See csmldataiface.py"
59                       
60       
61                                                       
62class AbstractDI(object):               
63        #Abstract data interface class
64        #does nothing, but contains templates for methods required for a data interface class
65        #individual interfaces (e.g NappyInterface) should override these methods
66
67        def __init__(self):
68                self.extractType=''
69                self.extractPrefix = ''
70                                       
71        def openFile(self, filename):
72                #opens file
73                self.file=''
74               
75        def closeFile(self):
76                #closes file
77                self.file.close()
78                       
79               
80               
81class NappyInterface(AbstractDI):       
82        # Data Interface for Nappy (NASA Ames Processing in Python)
83   
84        def __init__(self):
85                self.extractType='NASAAmesExtract'
86                self.extractPrefix = '_naextract_'
87                                         
88        def openFile(self, filename):
89                #print 'opening NA file: ' + str(filename)
90                self.file=nappy.openNAFile(filename)
91                #print 'reading data....'
92                #self.file.readData()
93                #print 'nappyopen ' + filename
94
95        def getListOfAxes(self):
96                axes=self.file.XNAME
97                #print 'before units stripped' + str(axes)
98                axes=self.stripunits(axes)
99                #print 'after units stripped' + str(axes)
100                return axes
101
102        def setAxis(self,axis):
103                axes = self.getListOfAxes()
104                self.axisstub=axes.index(axis)
105
106        def getAxisAttribute(self, att):
107                        #need to do something here...? maybe
108                pass
109                return attValue
110
111        def getTimeUnits(self):
112                axes = self.getListOfAxes()
113                for axis in axes:
114                        if string.find(string.upper(axis),'SECONDS SINCE') != -1:
115                                #found possible time axis.
116                                if axis[-3:]=='UTC':
117                                    units =string.lower(axis[:-4]) #hack!
118                                    units=units.replace('/','-') #try and clean it up
119                                else:
120                                    units=string.lower(axis)
121                                break
122                        elif string.find(string.upper(axis),'HOURS SINCE') != -1:
123                                #found possible time axis.
124                                units =(str(axis))
125                                break
126                        elif string.find(string.upper(axis),'DAYS SINCE') != -1:
127                                #found possible time axis.
128                                units =(str(axis))
129                                break
130                       
131                #revisit with udunits python library?
132                return units
133
134
135        def getDataForAxis(self):
136
137                if self.file.X == None:
138                        #print 'reading data....'
139                        self.file.readData()
140
141                if type(self.file.X[1])==list:
142                #if len(self.file.X) > 0:
143                        data = self.file.X[self.axisstub]
144                else:
145                        data =self.file.X
146                return data
147
148        def getSizeOfAxis(self,axis):
149
150                #check this function is okay
151                #is time always the first dimension in NA??
152                axes = self.getListOfAxes()
153                axisPosition=axes.index(axis)
154                #print "axis position" + str( axisPosition)
155                #print "NX" + str(self.file.NX)
156                try :
157                        axisSize=self.file.NX[axisPosition-1]
158                except:
159                        axisSize ='Unknown axis size'
160                return axisSize
161
162        def getListofVariables(self):
163                variableList=self.stripunits(self.file.VNAME)
164                return variableList
165
166        def setVariable(self,varname):
167                vlist=self.getListofVariables()
168                self.varstub=vlist.index(varname)
169
170        def getVariableAxes(self):
171                #hmm, now with Nasa Ames the Axis will be the same for all variables.
172                #so just use the getListOfAxes function again
173                #I think... check this!
174                varAxesList=self.getListOfAxes()
175                return varAxesList
176
177        def getVariableAttribute(self,attName):
178                if attName =='units':
179                        #strip the units (attribute) from the variable
180                        unitslist=self.getUnits(self.file.VNAME)
181                        attribValue = unitslist[self.varstub]
182                        try:
183                                attribValue = unitslist[self.varstub]
184                        except:
185                                attribValue = 'unknown'
186                else:
187                        attribValue = 'unknown'
188                return attribValue
189
190        def getDataForVar(self):
191            #NOTE TO SELF:
192            #Review this function (and in fact all of nasa ames data interface...)
193                if self.file.V == None:
194                        #print 'reading data....'
195                        self.file.readData()
196
197                try:
198                    if type(self.file.V[1])==list:
199                        data = self.file.V[self.varstub]
200                #else:
201                #       data =self.file.X
202                #       print data
203                    return data
204                except:
205                    data = self.file.X
206                   # print data
207                    return data
208
209        def getArraySizeOfVar(self):
210        #iterates through all dimensions in variable to get array size i.e a 3x3x3 array would have a size of 27
211
212                dimlist=self.file.NX
213                varsize =1
214                for item in dimlist:
215                        varsize = varsize * item
216                        #print "VARSISZE" + str(varsize)
217                return varsize
218
219        def getShapeOfVar(self):
220            #this should return a list.
221            varShape = []
222            for item in self.file.NX:
223                varShape.append(item)
224            return varShape
225
226        def getLowLimits(self):
227                lowlims = ""
228                for i in range (0, len(self.file.NX)):
229                        #for now, assume low limit is always of form 1 1 1 ..
230                        lowlims =lowlims + str(1)  +' '
231                return lowlims
232
233        def getHighLimits(self):
234                highlims = ""
235                for i in range (0, len(self.file.NX)):
236                        dimValue = self.file.NX[i]
237                        highlims =highlims  + str(dimValue) +' '
238                return highlims
239
240
241        def stripunits(self,listtostrip):
242                #strips units of measure from list
243                #eg ['Universal time (hours)', 'Altitude (km)', 'Latitude (degrees)', 'Longitude (degrees)']
244                #becomes ['Universal time', 'Altitude', 'Latitude', 'Longitude']
245                cleanlist = []
246                for item in listtostrip:
247                        openbracket=string.find(item,'(')
248                        if openbracket != -1:
249                                #if brackets exist, strip units.
250                                item=item[:openbracket-1]
251                        cleanlist.append(item)
252                return cleanlist
253
254        def getUnits(self,listwithunits):
255                #gets units from list
256                #eg ['Universal time (hours)', 'Altitude (km)', 'Latitude (degrees)', 'Longitude (degrees)']
257                #becomes ['hours', 'km', 'degrees', 'degrees']
258                unitlist=[]
259                for item in listwithunits:
260                        openbracket=string.find(item,'(')
261                        item = item[openbracket+1:-1]
262                        unitlist.append(item)
263                return unitlist
264
265        def getTimes(self):
266                #This function attempts to determine the time axis and read the time data
267                #it may well not manage it.
268                axes = self.getListOfAxes()
269                for axis in axes:
270                        if string.find(string.upper(axis),'TIME') != -1:
271                                #found possible time axis.
272                                self.setAxis(axis)
273                                times=self.getDataForAxis()
274                                break
275                        elif string.find(string.upper(axis),'SECONDS SINCE') != -1:
276                                #found possible time axis.
277                                self.setAxis(axis)
278                                times=self.getDataForAxis()
279                                break
280                        elif string.find(string.upper(axis),'HOURS SINCE') != -1:
281                                #found possible time axis.
282                                self.setAxis(axis)
283                                times=self.getDataForAxis()
284                                break
285                        elif string.find(string.upper(axis),'DAYS SINCE') != -1:
286                                #found possible time axis.
287                                self.setAxis(axis)
288                                times=self.getDataForAxis()
289                                break
290                return times
291
292
293
294class cdunifInterface(AbstractDI):
295    #Data Interface for cdunif (netcdf & pp formats & grib (not tested with grib)
296
297    def __init__(self):
298        #these are just temporary values until we can determine whether the
299        #file is netcdf pp or grib
300        self.extractType='cdunifExtract'
301        self.extractPrefix = '_cdunifextract_'
302
303    def openFile(self, filename):
304        self.file=cdms.open(filename)
305        #print 'cdunifopen ' + filename
306
307        #now we have the file name can properly determine extractType/Prefix
308        fileExtension = str(filename)[-3:]
309        if fileExtension == '.nc':
310            self.extractType = 'NetCDFExtract'
311            self.extractPrefix = '_ncextract_'
312        elif fileExtension == '.qxf':
313            self.extractType = 'NetCDFExtract'
314            self.extractPrefix = '_ncextract_'
315        elif fileExtension == '.pp':
316            self.extractType  = 'PPExtract'
317            self.extractPrefix = '_ppextract_'
318        elif fileExtension == 'ctl':
319            self.extractType = 'GRIBExtract'
320            self.extractPrefix = '_gribextract_'
321        elif fileExtension == 'xml': 
322            self.extractType = 'NetCDFExtract'  #okay this isn't true, but ok for testing
323            self.extractPrefix = '_ncextract__' 
324    def getListOfAxes(self):
325        axes=self.file.dimensions.keys()
326        return axes
327
328    def getSizeOfAxis(self,axis):
329        axisSize=self.file.dimensions[axis]
330        return axisSize
331
332    def getListofVariables(self):
333        variableList=self.file.variables.keys()
334        return variableList
335
336    def setAxis(self,axis):
337        self.axisobj=self.file.getAxis(axis)
338
339    def getAxisAttribute(self, att):
340        attValue=self.axisobj.attributes[att]
341        return attValue
342
343    def getTimeUnits(self):
344        #this does the same as getAxisAttribute, but is a separate function as different formats handle time differently.
345        return self.getAxisAttribute('units')
346
347    def getDataForAxis(self):
348        data = self.axisobj.getValue()
349        return data
350
351    def setVariable(self,varname):
352        self.varobj=self.file.variables[varname]
353
354    def getVariableAxes(self):
355        varAxesList=self.varobj.getAxisIds()
356        return varAxesList
357
358    def getVariableAttribute(self,attName):
359
360        #atts=self.varobj.getattributes(attName)
361        #print atts
362        if attName == 'long_name':
363            try:
364                attribValue = self.varobj.long_name
365            except:
366                attribValue=''
367        elif attName == 'units':
368            try:
369                attribValue = self.varobj.units
370            except:
371                attribValue=''
372
373        return attribValue
374
375    def getDataForVar(self):
376        data = self.varobj.getValue()
377        return data
378
379    def getSubsetOfDataForVar(self, **kwargs):
380        #takes keyword args defining subset eg
381        #subset=getSubsetOfDataForVar(latitude=(0.,10.0), longitude=(90, 100.0))
382        for key in kwargs:
383            if key == 'longitude':   #this test needs to be more robust...
384                if kwargs[key][0] > kwargs[key][1]:
385                    #subsetting greenwich meridian around 0
386                    lonMin = kwargs[key][0]
387                    lonMax =kwargs[key][1]
388                    kwargs[key]=(0.0, lonMax)
389                    sel=cdms.selectors.Selector(**kwargs)
390                    subset1=self.file(self.varobj.name,sel)
391                    kwargs[key]=(lonMin,359.9999)
392                    sel=cdms.selectors.Selector(**kwargs)
393                    subset2=self.file(self.varobj.name,sel)
394                    #concatenate arrays along longitude
395                    longitudeAxis=subset1.getAxisIndex('longitude') # this needs to be more robust test.
396                    subset = cdms.MV.concatenate([subset1,subset2],axis=longitudeAxis)
397                else:
398                    sel=cdms.selectors.Selector(**kwargs)
399                    subset=self.file(self.varobj.name,sel)
400        data = subset
401        return data
402
403    def getArraySizeOfVar(self):
404    #iterates through all dimensions in variable to get array size i.e a 3x3x3 array would have a size of 27
405        var = self.varobj
406        size = var.shape
407        varsize = 1
408        for item in size:
409            varsize = item *varsize
410        return varsize
411
412    def getShapeOfVar(self):
413        varShape = []
414        for item in self.varobj.shape:
415            varShape.append(item)
416        return varShape
417
418    def getLowLimits(self):
419        dimNames = self.varobj.getAxisIds()
420        lowlims = ""
421        for i in range (1, len(dimNames)):
422            #for now, assume low limit is always of form 1 1 1 ..
423            lowlims =lowlims + str(1)  +' '
424        return lowlims
425
426    def getHighLimits(self):
427        dimNames = self.varobj.getAxisIds()
428        highlims = ""
429        for i in range (1, len(dimNames)):
430            dimValue = self.file.dimensions[dimNames[i]]
431            highlims =highlims  + str(dimValue) +' '
432        return highlims
433       
434   
435class cdmlInterface(cdunifInterface):
436    #this is more  or less the cdunif interface but a few methods have been overwritten
437    def __init__(self):
438        #this all needs to be revisited in csml v2.
439        self.extractType='cdmlExtract'
440        self.extractPrefix = '_cdmlextract_'
441       
442    def getListOfAxes(self):
443        axes=self.file.axes.keys() 
444        return axes
445
446    def getSizeOfAxis(self,axis):
447        axisSize=self.file.axes[axis].length
448        return axisSize
Note: See TracBrowser for help on using the repository browser.