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

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

Moving stuff that probably shouldn't be in the package heirarchy up a directory.

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