source: TI05-delivery/ows_framework/branches/ows_framework-refactor/ows_common/ows_common/service/imps/wms_csmllayer.py @ 3609

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/branches/ows_framework-refactor/ows_common/ows_common/service/imps/wms_csmllayer.py@3609
Revision 3609, 7.9 KB checked in by domlowe, 12 years ago (diff)

adding csml implementation code (not complete)

Line 
1"""
2implementation of ILayerMapper, ILayer, IDimension, ILayerSlab interfaces, as defined in wms_iface.py
3
4"""
5import csml
6import cdms
7import Image
8from copy import copy
9from pywms.render_imp import RGBARenderer
10from matplotlib import cm
11
12class CSMLLayerMapper(object):
13    """
14    Map keyword arguments to a collection of layers.
15    Supports the retrieval of sets of layers according to arbitary
16    keyword/value pairs.
17    Implements  ILayerMapper
18   
19    """
20   
21    def _getInfo(self, feature):
22        ''' given a csml feature, return info about the layer/feature
23        @return:   title, abstract, dimensions, units, crss '''
24
25        try:
26            title=feature.name.CONTENT
27        except:
28            title=''
29        try:
30            abstract=feature.description.CONTENT
31        except:
32            abstract=title
33       
34        units=feature.getDomainUnits()
35        dimensions={}
36        tmpunits=copy(units)
37        tmpunits.reverse()
38        domain = feature.getDomain()
39        for dim in feature.getAxisLabels():
40            dimensions[dim]=CSMLDimension(domain, dim, tmpunits.pop())
41        crs=feature.getNativeCRS()
42        crss=[self._crscat.getCRS(crs).twoD]
43        return title, abstract, dimensions, units, crss
44   
45    def map(self, file=None):
46        """
47        Given arbitary keywords/value pairs list the names of
48        all layers available.
49       
50        @return: A mapping of layer names to ILayer implementations.
51        @raise ValueError: If no layers are available for these keywords.
52        """
53        layermap={}
54        self._crscat=csml.csmllibs.csmlcrs.CRSCatalogue()
55        if file:
56            ds=csml.parser.Dataset(file)
57            for feature in csml.csmllibs.csmlextra.listify(ds.featureCollection.featureMembers):
58                title, abstract, dimensions, units, crss=self._getInfo(feature)
59                layermap[feature.id]=CSMLLayer(title,abstract, dimensions, units, crss, feature)
60        if len(layermap) > 0:
61            return layermap
62        else:
63            raise ValueError
64
65
66class CSMLLayer(object):
67    """
68     representing a WMS layer.    Implements ILayer
69
70    @ivar title: The layer title.  As seen in the Capabilities document.
71    @ivar abstract:  Abstract as seen in the Capabilities document.
72    @ivar dimensions: A dictionary of IDimension objects.
73    @ivar units: A string describing the units.
74    @ivar crss: A sequence of SRS/CRSs supported by this layer.
75
76    @todo: Do we need minValue/maxValue?
77
78    """
79
80    def __init__(self, title, abstract, dimensions, units, crss, feature):
81        self.title=title
82        self.abstract=abstract
83        self.dimensions=dimensions
84        self.units=units
85        self.crss=crss
86        self._feature=feature
87
88    def getBBox(self, crs):
89        """
90        @return: A 4-typle of the bounding box in the given coordinate
91            reference system.
92       
93        """
94        return []
95        #raise NotImplementedError
96#dimValues={'surface':'2','time':'1968-01-02T00:00:00.0Z'}
97    def getSlab(self, crs, dimValues=None, renderOpts={}):
98        """
99        Creates a slab of the layer in a particular CRS and set of
100        dimensions.
101
102        @param crs: The coordinate reference system.
103        @param dimValues: A mapping of dimension names to dimension values
104            as specified in the IDimension.extent
105        @param renderOpts: A generic mapping object for passing rendering
106            options
107        @return: An object implementing ILayerSlab
108        #create netcdf for whole lat/lon for given dimValues, use to init slab
109        """
110        if type(self._feature) == csml.parser.GridSeriesFeature:
111            randomname='tmp' + csml.csmllibs.csmlextra.getRandomID() + '.nc'
112            result= self._feature.subsetToGridSeries(outputdir='./', ncname=randomname, **dimValues)
113            #for now have to read netcdf back from disk.
114            netcdf=cdms.open(result[1])
115            bbox=self.getBBox(crs)
116            return CSMLLayerSlab(netcdf, self, crs, dimValues, renderOpts, bbox)
117        else:
118            raise NotImplementedError
119       
120    def getCacheKey(self, crs, dimValues=None, renderOpts={}):
121        """
122        Create a unique key for use in caching a slab.
123
124        The intention here is that most of the work should be done when
125        instantiating an ILayerSlab object.  These can be cached by the
126        server for future use.  The server will first call getCacheKey()
127        for the slab creation arguments and if the key is in it's cache
128        it will use a pre-generated ILayerSlab object.
129
130        """
131        raise NotImplementedError
132
133
134
135class CSMLDimension(object):
136    """
137    implements IDimension
138    @ivar units: The units string.
139    @ivar extent: Sequence of extent values.
140
141    """
142   
143    def __init__(self, domain, dimname, unit):
144        self.units = unit
145        self.extent =domain[dimname]
146       
147class CSMLLayerSlab(object):
148    """
149    Implements LayerSlab
150    Represents a particular horizontal slice of a WMS layer.
151
152    ILayerSlab objects are designed to be convenient to cache.
153    They should be pickleable to enable memcached support in the future.
154
155    @ivar layer: The source ILayer instance.
156    @ivar crs: The coordinate reference system.
157    @ivar dimValues: A mapping of dimension values of this view.
158    @ivar renderOpts: The renderOpts used to create this view.
159    @ivar bbox: The bounding box as a 4-tuple.
160    """
161   
162    def __init__(self, netcdf, layer, crs, dimValues, renderOpts, bbox):
163        self._netcdf=netcdf
164        self.layer = layer
165        self.crs = crs
166        self.dimValues = dimValues
167        self.renderOpts=renderOpts
168        self.bbox=bbox
169       
170       
171    def getImage(self, bbox, width, height):
172        """
173        Create an image of a sub-bbox of a given size.
174
175        @ivar bbox: A bbox 4-tuple.
176        @ivar width: width in pixels.
177        @ivar height: height in pixels.
178        @return: A PIL Image object.
179
180        """
181       
182
183        cmap=cm.gist_rainbow_r # where does colourmap come from?
184        grid=Grid(self.layer, self._netcdf, bbox, width, height)
185        #how to handle varmin,varmax? ..read array?
186        minval=min(min(l) for l in grid.value)
187        maxval=max(max(l) for l in grid.value)
188        renderer=RGBARenderer(minval, maxval)         
189        return renderer.renderGrid(grid, bbox, width, height, cmap)
190   
191class Grid(object):
192    """A class encapsulating a simple regularly spaced, rectilinear
193    grid.  This is the only type of grid pywms is expected to
194    understand and adaptors should be provided to connect to
195    underlying implementations such as cdms or csml.
196
197    @cvar crs: Coordinate reference system
198
199    @ivar x0: coordinate of the lower left corner.
200    @ivar y0: coordinate of the lower left corner.
201    @ivar dx: The x grid spacing.
202    @ivar dy: The y grid spacing.
203    @ivar nx: The number of x grid points.
204    @ivar ny: The number of y grid points.
205    @ivar value: A masked array of the grid values.
206    @ivar ix: The dimension index of longidude in value
207    @ivar iy: The dimension index of latitude in value
208    @ivar long_name: The name of the field.
209    @ivar units: The units of the field.
210    """
211    def __init__(self, layer, netcdf, bbox, width, height):
212        #we know the axes are called latitude and longitude as the CSML code has written it:
213        tvar=netcdf(layer.title).subRegion(latitude=(bbox[1], bbox[3]), longitude=(bbox[0],bbox[3]),squeeze=1)
214        order=tvar.getOrder()
215       
216        #array of data
217        self.value=tvar.getValue()
218       
219        #order of axes
220        if order == 'xy':
221            self.ix=0
222            self.iy=1
223        else:
224            self.ix=1
225            self.iy=0
226       
227        lat = tvar.getLatitude()
228        lon = tvar.getLongitude()
229        self.x0=lon[0]
230        self.y0=lat[0]
231        self.dx=abs(lon[0]-lon[1])
232        self.dy=abs(lat[0]-lat[1])
233        self.nx=len(lon)
234        self.ny=len(lat)
235        self.long_name=tvar.id  #TODO, get long name from feature
236        self.units=tvar.units
Note: See TracBrowser for help on using the repository browser.