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

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

fixed subsetting bug when handling times, and also removed dependence on longitude/latitude names

  • 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
15
16try:
17    import nappy 
18except ImportError:
19    print "NASAAmes interface not available. CSML will still work, but won't support NASA Ames files"
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# Generic mathematical expression solver, required by the raw and image
28# interfaces
29import NumericTransform
30
31try:
32    # Part of the PIL. Required for ImageFileInterface:
33    import Image
34except ImportError:
35    print "Python Image Library not available. CSML will still work, but won't support image files"
36
37try:
38    # Required for RawFileInterface:
39    import struct
40except ImportError:
41    print 'could not import struct'
42    pass
43
44
45class DataInterface(object):
46        #Use DataInterface and setInterfaceType to instantiate the correct
47        #subclass for data
48        def __init__(self):
49                self.iface ='None'
50               
51        def setInterfaceType(self,interfaceType):
52                # function returns approprate data interface
53                #set interfaceType: should correspond to available datainterface subclasses
54                self.iface =interfaceType
55                if self.iface == 'nappy':
56                        return NappyInterface()
57                elif self.iface == 'cdunif':
58                        return cdunifInterface()
59                elif self.iface == 'raw':
60                        return RawFileInterface()
61                elif self.iface == 'image':
62                        return ImageFileInterface()
63               
64               
65        def getUnknownInterfaceType(self, filename):
66                #if the interface type is not known at the time of instantiation, then use
67                #this function to examine the file and return the correct interface (if it exists).
68                fileExtension = str(filename)[-3:]
69                if fileExtension == '.nc':
70                        return cdunifInterface()
71                if fileExtension == 'qxf':
72                        return cdunifInterface()
73                elif fileExtension == '.pp':
74                        return cdunifInterface()
75                elif fileExtension == 'ctl':
76                        return cdunifInterface()
77                elif fileExtension == 'xml':
78                        return cdmlInterface()
79                elif fileExtensions == 'png' or fileExtension == 'gif':
80                        return ImageFileInterface()
81                else:
82                        try:
83                                nappy.readFFI(filename) in [1001,1010,1020,2010,2110,2160,2310,3010,4010]
84                                return NappyInterface()
85                        except:
86                                print "Could not establish file type"
87                                print "See csmldataiface.py"
88                       
89       
90                                                       
91class AbstractDI(object):               
92        #Abstract data interface class
93        #does nothing, but contains templates for methods required for a data interface class
94        #individual interfaces (e.g NappyInterface) should override these methods
95
96        def __init__(self):
97                self.extractType=''
98                self.extractPrefix = ''
99                                       
100        def openFile(self, filename):
101           #opens file, must be overwritten by subclass
102            raise NotImplementedError 
103               
104        def closeFile(self):
105           #closes file, probably needs to be overwritten by subclass
106            try:
107                self.file.close()
108            except:
109                raise NotImplementedError
110         
111        def setAxis(self,axis):
112           #'set' the name of the current axis , must be overwritten by subclass
113           #this may just involve a stub (see NASAAmes interface) or may involve
114           #calling a real set method of the underlying api (see cdunif Interface)
115           raise NotImplementedError 
116                       
117        def getDataForAxis(self):
118            #return all data for axis, must be overwritten by subclass
119           raise NotImplementedError   
120       
121        def setVariable(self,varname):
122             #As for setAxis, 'set' the name of the current axis , must be overwritten by subclass
123             raise NotImplementedError
124       
125        def getDataForVar(self):
126            #return all data for variable, must be overwritten by subclass
127           raise NotImplementedError   
128       
129        def getSubsetOfDataForVar(self,**kwargs):
130            #return subset of data for variable, must be overwritten by subclass
131            raise NotImplementedError
132       
133       
134class NappyInterface(AbstractDI):       
135        # Data Interface for Nappy (NASA Ames Processing in Python)
136   
137        def __init__(self):
138                self.extractType='NASAAmesExtract'
139                self.extractPrefix = '_naextract_'
140                                         
141        def openFile(self, filename):
142                #print 'opening NA file: ' + str(filename)
143                self.file=nappy.openNAFile(filename)
144                #print 'reading data....'
145                #self.file.readData()
146                #print 'nappyopen ' + filename
147
148        def getListOfAxes(self):
149                axes=self.file.XNAME
150                #print 'before units stripped' + str(axes)
151                axes=self.stripunits(axes)
152                #print 'after units stripped' + str(axes)
153                return axes
154
155        def setAxis(self,axis):
156                axes = self.getListOfAxes()
157                self.axisstub=axes.index(axis)
158
159        def getAxisAttribute(self, att):
160                #need to do something here...? maybe
161                attValue=None
162                return attValue
163
164        def getTimeUnits(self):
165                axes = self.getListOfAxes()
166                for axis in axes:
167                        if string.find(string.upper(axis),'SECONDS SINCE') != -1:
168                                #found possible time axis.
169                                if axis[-3:]=='UTC':
170                                    units =string.lower(axis[:-4]) #hack!
171                                    units=units.replace('/','-') #try and clean it up
172                                else:
173                                    units=string.lower(axis)
174                                break
175                        elif string.find(string.upper(axis),'HOURS SINCE') != -1:
176                                #found possible time axis.
177                                units =(str(axis))
178                                break
179                        elif string.find(string.upper(axis),'DAYS SINCE') != -1:
180                                #found possible time axis.
181                                units =(str(axis))
182                                break
183                       
184                #revisit with udunits python library?
185                return units
186
187
188        def getDataForAxis(self):           
189            if self.file.X == None:
190                    #print 'reading data....'
191                    self.file.readData()
192            for x in self.file.X:
193                pass
194                #print type(x)
195           
196           
197            d=Numeric.array(self.file.X)
198           
199            if type(self.file.X[1])==list:
200            #if len(self.file.X) > 0:
201                    data = self.file.X[self.axisstub]
202            else:
203                    data =self.file.X
204            #print data
205            data=Numeric.array(data)
206            return data
207
208        def getSizeOfAxis(self,axis):
209
210                #check this function is okay
211                #is time always the first dimension in NA??
212                axes = self.getListOfAxes()
213                axisPosition=axes.index(axis)
214                #print "axis position" + str( axisPosition)
215                #print "NX" + str(self.file.NX)
216                try :
217                        axisSize=self.file.NX[axisPosition-1]
218                except:
219                        axisSize ='Unknown axis size'
220                return axisSize
221
222        def getListofVariables(self):
223                variableList=self.stripunits(self.file.VNAME)
224                return variableList
225
226        def setVariable(self,varname):
227                vlist=self.getListofVariables()
228                self.varstub=vlist.index(varname)
229
230        def getVariableAxes(self):
231                #hmm, now with Nasa Ames the Axis will be the same for all variables.
232                #so just use the getListOfAxes function again
233                #I think... check this!
234                varAxesList=self.getListOfAxes()
235                return varAxesList
236
237        def getVariableAttribute(self,attName):
238                if attName =='units':
239                        #strip the units (attribute) from the variable
240                        unitslist=self.getUnits(self.file.VNAME)
241                        attribValue = unitslist[self.varstub]
242                        try:
243                                attribValue = unitslist[self.varstub]
244                        except:
245                                attribValue = 'unknown'
246                else:
247                        attribValue = 'unknown'
248                return attribValue
249
250        def getDataForVar(self):
251            #NOTE TO SELF:
252            #Review this function (and in fact all of nasa ames data interface...)
253                if self.file.V == None:
254                        #print 'reading data....'
255                        self.file.readData()
256
257                try:
258                    if type(self.file.V[1])==list:
259                        data = self.file.V[self.varstub]
260                #else:
261                #       data =self.file.X
262                #       print data
263                    return data
264                except:
265                    data = self.file.X
266                   # print data
267                    return data
268
269        def getArraySizeOfVar(self):
270        #iterates through all dimensions in variable to get array size i.e a 3x3x3 array would have a size of 27
271
272                dimlist=self.file.NX
273                varsize =1
274                for item in dimlist:
275                        varsize = varsize * item
276                        #print "VARSISZE" + str(varsize)
277                return varsize
278
279        def getShapeOfVar(self):
280            #this should return a list.
281            varShape = []
282            for item in self.file.NX:
283                varShape.append(item)
284            return varShape
285
286        def getLowLimits(self):
287                lowlims = ""
288                for i in range (0, len(self.file.NX)):
289                        #for now, assume low limit is always of form 1 1 1 ..
290                        lowlims =lowlims + str(1)  +' '
291                return lowlims
292
293        def getHighLimits(self):
294                highlims = ""
295                for i in range (0, len(self.file.NX)):
296                        dimValue = self.file.NX[i]
297                        highlims =highlims  + str(dimValue) +' '
298                return highlims
299
300
301        def stripunits(self,listtostrip):
302                #strips units of measure from list
303                #eg ['Universal time (hours)', 'Altitude (km)', 'Latitude (degrees)', 'Longitude (degrees)']
304                #becomes ['Universal time', 'Altitude', 'Latitude', 'Longitude']
305                cleanlist = []
306                for item in listtostrip:
307                        openbracket=string.find(item,'(')
308                        if openbracket != -1:
309                                #if brackets exist, strip units.
310                                item=item[:openbracket-1]
311                        cleanlist.append(item)
312                return cleanlist
313
314        def getUnits(self,listwithunits):
315                #gets units from list
316                #eg ['Universal time (hours)', 'Altitude (km)', 'Latitude (degrees)', 'Longitude (degrees)']
317                #becomes ['hours', 'km', 'degrees', 'degrees']
318                unitlist=[]
319                for item in listwithunits:
320                        openbracket=string.find(item,'(')
321                        item = item[openbracket+1:-1]
322                        unitlist.append(item)
323                return unitlist
324
325        def getTimes(self):
326                #This function attempts to determine the time axis and read the time data
327                #it may well not manage it.
328                axes = self.getListOfAxes()
329                for axis in axes:
330                        if string.find(string.upper(axis),'TIME') != -1:
331                                #found possible time axis.
332                                self.setAxis(axis)
333                                times=self.getDataForAxis()
334                                break
335                        elif string.find(string.upper(axis),'SECONDS SINCE') != -1:
336                                #found possible time axis.
337                                self.setAxis(axis)
338                                times=self.getDataForAxis()
339                                break
340                        elif string.find(string.upper(axis),'HOURS SINCE') != -1:
341                                #found possible time axis.
342                                self.setAxis(axis)
343                                times=self.getDataForAxis()
344                                break
345                        elif string.find(string.upper(axis),'DAYS SINCE') != -1:
346                                #found possible time axis.
347                                self.setAxis(axis)
348                                times=self.getDataForAxis()
349                                break
350                times=Numeric.array(times)
351                return times
352
353
354
355class cdunifInterface(AbstractDI):
356    #Data Interface for cdunif (netcdf & pp formats & grib (not tested with grib)
357
358    def __init__(self):
359        #these are just temporary values until we can determine whether the
360        #file is netcdf pp or grib
361        self.extractType='cdunifExtract'
362        self.extractPrefix = '_cdunifextract_'
363   
364    def openFile(self, filename):
365        self._filename=filename
366        self.file=cdms.open(filename)
367       
368        #now we have the file name can properly determine extractType/Prefix
369        fileExtension = str(filename)[-3:]
370        if fileExtension == '.nc':
371            self.extractType = 'NetCDFExtract'
372            self.extractPrefix = '_ncextract_'
373        elif fileExtension == '.qxf':
374            self.extractType = 'NetCDFExtract'
375            self.extractPrefix = '_ncextract_'
376        elif fileExtension == '.pp':
377            self.extractType  = 'PPExtract'
378            self.extractPrefix = '_ppextract_'
379        elif fileExtension == 'ctl':
380            self.extractType = 'GRIBExtract'
381            self.extractPrefix = '_gribextract_'
382        elif fileExtension == 'xml': 
383            self.extractType = 'NetCDFExtract'  #okay this isn't true, but ok for testing
384            self.extractPrefix = '_ncextract__' 
385    def getListOfAxes(self):
386        axes=self.file.dimensions.keys()
387        return axes
388
389    def getSizeOfAxis(self,axis):
390        axisSize=self.file.dimensions[axis]
391        return axisSize
392
393    def getListofVariables(self):
394        variableList=self.file.variables.keys()
395
396        # Hack to test if removing climatology_bounds fixes pywms bug
397        if 'climatology_bounds' in variableList:
398            variableList.remove('climatology_bounds')
399
400        return variableList
401
402    def setAxis(self,axis):
403        if not hasattr(self, 'file'):
404            raise Exception, 'Could not open/find underlying file: %s  -  If you are the system maintainer check file paths and permissions'%self._filename
405        self.axisobj=self.file.getAxis(axis)
406
407           
408
409    def getAxisAttribute(self, att):
410        attValue=self.axisobj.attributes[att]
411        return attValue
412   
413    def getTimeUnits(self):
414        #this does the same as getAxisAttribute, but is a separate function as different formats handle time differently.
415        return self.getAxisAttribute('units')
416
417    def getDataForAxis(self):
418        data = self.axisobj.getValue()
419        return data
420
421    def setVariable(self,varname):
422        self.varobj=self.file.variables[varname]
423
424    def getVariableAxes(self):
425        varAxesList=self.varobj.getAxisIds()
426        return varAxesList
427
428    def getVariableAttribute(self,attName):
429        if attName == '_FillValue':
430            try:
431                attribValue=self.varobj._FillValue
432                attribValue=attribValue.toscalar()
433            except:
434                try:
435                    attribValue=self.varobj.missing_value
436                    attribValue=attribValue.toscalar()
437                except:
438                    attribValue = None 
439        else:
440            attribValue = self.varobj.getattribute(attName)
441        return attribValue
442
443    def getDataForVar(self):
444        data = self.varobj.getValue()
445        return data
446   
447    def _fixLongitudeRequest(self, **kwargs):
448        lonkey='longitude'
449        if lonkey in kwargs.keys():   #this test needs to be much more robust...!
450            if  type(kwargs[lonkey]) is tuple:
451                newkws=[]
452                for val in kwargs[lonkey]:
453                    newval=((val + 180) % 360) - 180
454                    newkws.append(newval)
455               
456                 #lon = ((t_lon + 180) % 360) - 180
457                #lonmin=kwargs[lonkey][0] - (kwargs[lonkey][0]/180)*360.0
458                #lonmax=kwargs[lonkey][1] - (kwargs[lonkey][1]/180)*360.0
459               
460                #if newkws[0] > newkws[1]:
461                    #flip=[newkws[1], newkws[0]]
462                    #newkws=flip
463                kwargs[lonkey]=tuple(newkws)
464        return kwargs
465
466    def getSubsetOfDataForVar(self, **kwargs):     
467        #put any slicing indices aside for later and use names           
468        try:
469            upper=kwargs['upper']
470            del kwargs['upper']
471        except:
472            pass
473        try:
474            lower=kwargs['lower']
475            del kwargs['lower']
476        except:
477            pass
478        #kwargs=self._fixLongitudeRequest(**kwargs)
479        #return self.file(self.varobj.id,**kwargs)
480        try:
481            #takes keyword args defining subset eg
482            #subset=getSubsetOfDataForVar(latitude=(0.,10.0), longitude=(90, 100.0))
483            subset=None
484            lonkey='longitude'
485            if lonkey in kwargs.keys():   #this test needs to be much more robust...!
486                if  type(kwargs[lonkey]) is tuple:
487                    if kwargs[lonkey][0] > kwargs[lonkey][1]:
488                        #subsetting greenwich meridian around 0
489                        lonMin = kwargs[lonkey][0]
490                        lonMax =kwargs[lonkey][1]
491                        kwargs[lonkey]=(0.1, lonMax)
492                        subset1=self.file(self.varobj.id,**kwargs)
493                        kwargs[lonkey]=(lonMin,360)
494                        try:
495                            subset2=self.file(self.varobj.id,**kwargs)
496                            longitudeAxis=subset1.getAxisIndex(lonkey)
497                            #concatenate arrays along longitude             
498                            subset = cdms.MV.concatenate([subset2,subset1],axis=longitudeAxis)
499                        except:
500                            subset=subset1
501            if type(subset) is not cdms.tvariable.TransientVariable:
502                for k in kwargs:
503                    if k=='time':
504                        kwargs[k]=(kwargs[k][0],kwargs[k][1],'ocb') #see cdms docs: 'mysterious third argument'
505                subset=self.file(self.varobj.id,**kwargs)
506        except:             
507                return None
508                #try and slice with indices instead
509        return subset
510   
511   
512    def getArraySizeOfVar(self):
513    #iterates through all dimensions in variable to get array size i.e a 3x3x3 array would have a size of 27
514        var = self.varobj
515        size = var.shape
516        varsize = 1
517        for item in size:
518            varsize = item *varsize
519        return varsize
520
521    def getShapeOfVar(self):
522        varShape = []
523        for item in self.varobj.shape:
524            varShape.append(item)
525        return varShape
526
527    def getLowLimits(self):
528        dimNames = self.varobj.getAxisIds()
529        lowlims = ""
530        for i in range (1, len(dimNames)):
531            #for now, assume low limit is always of form 1 1 1 ..
532            lowlims =lowlims + str(1)  +' '
533        return lowlims
534
535    def getHighLimits(self):
536        dimNames = self.varobj.getAxisIds()
537        highlims = ""
538        for i in range (1, len(dimNames)):
539            dimValue = self.file.dimensions[dimNames[i]]
540            highlims =highlims  + str(dimValue) +' '
541        return highlims
542       
543   
544class cdmlInterface(cdunifInterface):
545    #this is more  or less the cdunif interface but a few methods have been overwritten
546    def __init__(self):
547        #this all needs to be revisited in csml v2.
548        self.extractType='cdmlExtract'
549        self.extractPrefix = '_cdmlextract_'
550       
551    def getListOfAxes(self):
552        axes=self.file.axes.keys() 
553        return axes
554
555    def getSizeOfAxis(self,axis):
556        axisSize=self.file.axes[axis].length
557        return axisSize
558
559
560class RawFileInterface(AbstractDI):
561
562   def __init__(self):
563      self.extractType   = 'rawExtract'
564      self.extractPrefix = '_rawextract_'
565 
566 
567   def openFile(self, filename):
568      self.file = open(filename, "rb")
569
570
571   def closeFile(self):
572      self.file.close()
573
574
575   # Read the data from the raw file into a multidimensional Numeric array
576   def readFile(self, **kwargs):
577        # Determine the numeric type:
578        if 'numericType' in kwargs:
579            try:
580                numericTypeCode = {
581                    'uint8':Numeric.UInt8,
582                    'uint16':Numeric.UInt16,
583                    'uint32':Numeric.UInt32,
584                    'int8':Numeric.Int8,
585                    'int16':Numeric.Int16,
586                    'int32':Numeric.Int32,
587                    'float':Numeric.Float32,
588                    'double':Numeric.Float64
589                }[kwargs['numericType']]
590            except KeyError:
591                raise TypeError("Invalid numericType: " + str(kwargs['numericType']))
592        else:
593            raise KeyError("numericType is mandatory.")
594       
595        # Read the file into a numpy array:
596        self.data = Numeric.fromstring(self.file.read(), numericTypeCode)
597        # If necessary, swap the byte order:
598        if 'endianess' in kwargs:
599            if ((kwargs['endianness'] == 'little' and not Numeric.LittleEndian) or (kwargs['endianness'] == 'big' and Numeric.LittleEndian)):
600                self.data = self.data.byteswapped()   
601        # Declare the shape of the array:
602        dimensions = map(int,kwargs['dimensions'])
603        dimensions.reverse()
604        self.data.shape = tuple(dimensions)
605        # If numericTransform or fillValue were provided, store them as
606        # attributes.
607        if 'numericTransform' in kwargs:
608            self.numericTransform = NumericTransform.infixExpression(kwargs['numericTransform'])
609        if 'fillValue' in kwargs:
610            self.fillValue = kwargs['fillValue']
611   
612   # Return the fill value, if set, and transform if necessary:
613   def getFillValue(self):
614      # Both fillValue and numericTransform attributes may or may
615      # not exist...
616      try:
617         return self.numericTransform.solve( n = float(self.fillValue) )
618      except AttributeError:
619         try:
620            return self.fillValue
621         except AttributeError:
622            return None
623
624
625   # This is a just a special case of getSubsetOfDataForVar. To avoid
626   # duplication of code, just subset the entire array. (getSubset.. is
627   # optimised for this case)
628   def getDataForVar(self):
629      return self.getSubsetOfDataForVar(lower = (0,)*len(self.data.shape),
630                                        upper = self.data.shape)
631
632
633   # Subset the n-dimensional file based on array indices. Accepts parameters
634   # in the form of e.g.
635   #
636   # getSubsetOfDataForVar( lower=(0,0), upper=(1,2) )
637   #
638   # Note: The rank of the required subset, must exactly match the
639   # rank of the original data: len(lower) == len(upper) == rank of file
640   #
641   def getSubsetOfDataForVar(self, **kwargs):
642      # Assume subset parameters are passed as: lower=(0,0) upper=(512,512)
643      if 'lower' not in kwargs or 'upper' not in kwargs:
644         # Have not specified any subset parameters that we recognise, so raise
645         # an exception:
646         raise NotImplementedError("Only supports subsetting with lower+upper array indices")
647      elif not len(kwargs['lower']) == len(kwargs['upper']) == len(self.data.shape):
648         # Rank of subset is not the same as rank of full data array. so raise
649         # an exception:
650         raise NotImplementedError("Only supports subsets of same rank as full dataset")
651      elif Numeric.sometrue(Numeric.greater(kwargs['upper'], self.data.shape)):
652         # Requested upper bound of subset is beyond the size of the the full
653         # data array, so raise an exception
654         raise IndexError("Subset out of range")
655      elif Numeric.sometrue(Numeric.less( kwargs['upper'], Numeric.zeros(len(self.data.shape)))):
656         # Requested lower bound of subset is beyond the size of the the full
657         # data array, so raise an exception
658         raise IndexError("Subset out of range")
659      elif Numeric.sometrue(Numeric.less_equal(kwargs['upper'], kwargs['lower'])):
660         # lower bound <= upper_bound for at least one dimension, so raise an
661         # exception
662         raise IndexError("Upper bound less than lower bound")
663      elif tuple(kwargs['lower']) == (0,)*len(self.data.shape) and tuple(kwargs['upper']) == self.data.shape:
664         # Special case of requested subset == entire data file.
665         subset = self.data
666      else:
667         # We are okay to subset.
668
669         # I cant see any nice (and speedy) way of subsetting a Numeric
670         # array of arbitrary rank without the use of eval. By doing it
671         # this way, we can make use of the (possible) acceleration provided
672         # by Numeric/NumPy.
673         slices = []
674         for i in range(len(self.data.shape)):
675            lower = int(kwargs['lower'][i])
676            upper = int(kwargs['upper'][i]) 
677            slices.append(str(lower)+':'+str(upper))
678         subset = eval("self.data["+','.join(slices)+"]")
679
680      # Attempt to perform the numericTransform on the data array, if we get
681      # AttributeError, it most likely means that numericTransform was not
682      # specified, so return the data as-is
683      try:
684         return self.numericTransform.solve( n = subset )
685      except AttributeError:
686         return subset.copy()
687
688
689# Interface for reading data from image files. Requires PIL Image module.
690class ImageFileInterface(RawFileInterface):
691   def __init__(self):
692      self.extractType   = 'imageExtract'
693      self.extractPrefix = '_imageextract_'
694   
695   def image2array(self,im):
696       #Adapted from code by Fredrik Lundh, http://www.pythonware.com
697       #http://effbot.org/zone/pil-numpy.htm
698        if im.mode not in ("L", "F"):
699            raise ValueError, "can only convert single-layer images"
700        if im.mode == "L":
701            a = Numeric.fromstring(im.tostring(), Numeric.UnsignedInt8)
702        else:
703            a = Numeric.fromstring(im.tostring(), Numeric.Float32)
704        a.shape = im.size[1], im.size[0]
705        return a
706
707   def openFile(self, filename):
708      self.file = Image.open(filename)
709
710   def closeFile(self):
711      self.file = None #...Image does not seem to have a close() method.
712
713   def readFile(self, **kwargs):
714      # Convert the image to a Numeric array
715     
716      self.data=self.image2array(self.file)
717      #slower method:
718      #self.data = Numeric.array(self.file.getdata())
719
720      if 'numericTransform' in kwargs:
721         # numericTransform was specified, so compile the expression:
722         self.numericTransform = NumericTransform.infixExpression(kwargs['numericTransform'])
723      if 'fillValue' in kwargs:
724         self.fillValue = kwargs['fillValue']
725
726class HDF5Interface(AbstractDI):
727    #Data Interface for HDF5
728    def __init__(self):
729        self.extractType='hdfExtract'
730        self.extractPrefix='_hdfextract_'
731   
732    def openFile(self, filename):
733        #some code to open the file
734        pass
735
736    def setAxis(self,axis):
737        #some code to set an axis to be queried, may not need to do much, depending on your format
738        pass
739       
740    def getDataForAxis(self):
741        #some code to return the values for an axis
742        return data
743
744    def setVariable(self,varname):
745        #some code to set a variable to be queried, may not need to do much, depending on your format
746        pass
747
748    def getDataForVar(self):
749        #some code to return all values for a variable
750        return data
751
752    def getSubsetOfDataForVar(self, **kwargs):
753        #takes keyword args defining subset eg
754        #subset=getSubsetOfDataForVar(latitude=(0.,10.0), longitude=(90, 100.0), ...)
755        #and returns a subset of data for tha variable
756        return data
757
758    def closeFile(self):
759        #some code to close the file
760        pass
Note: See TracBrowser for help on using the repository browser.