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

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

name change to insertedExtract

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