source: qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/controllers/csmlwms.py @ 5483

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/controllers/csmlwms.py@5483
Revision 5483, 9.5 KB checked in by pnorton, 10 years ago (diff)

Modified the GetCapabilities? response so that the styles are added to the data summary and picked up by the genshi template.

Line 
1import logging
2import Image
3import re
4from StringIO import StringIO
5from pylons import request, response, c
6
7from cows import bbox_util
8
9from wms_ddc_vis.model.ddc_layer_mapper import DDCLayerMapper
10from wms_ddc_vis.model.ddc_wms_layer import STYLES, RENDERING_OPTIONS
11
12from cows.pylons.wms_controller import WMSController
13from cows.pylons import ows_controller
14
15from cows.model.wms import Style, LegendURL, FormattedURL
16from cows.xml.iso19115_subset import OnlineResource
17
18from genshi.template import TemplateLoader, NewTextTemplate
19from pkg_resources import resource_filename
20from routes import url_for
21
22log = logging.getLogger(__name__)
23
24class CsmlwmsController(WMSController):
25    layerMapper = DDCLayerMapper()
26
27    loader = TemplateLoader( resource_filename('wms_ddc_vis', 'templates'),
28                             auto_reload=True,
29                           )
30
31    JSON_CAPABILITIES_TEMPLATE = "wms_capabilities_json.txt"
32    XML_CAPABILITIES_V1_1_1 = "wms_capabilities_1_1_1.xml"
33    XML_CAPABILITIES_V1_1_3 = "wms_capabilities_1_3_0.xml"
34   
35
36    def _renderCapabilities(self, version, format):
37       
38        for ds in c.capabilities.contents.datasetSummaries:
39           
40            onlineRes = OnlineResource(url_for(qualified=True, action='index') + "?request=GetLegend&layers=%s" % ds.identifier)
41           
42            legendURL = LegendURL(630, 80, format='img/png', onlineResource=onlineRes )
43           
44            gridStyle = Style('grid', 'Grid Boxes', legendURLs=[legendURL] )
45            contourStyle = Style('contour', 'Contour Lines', legendURLs=[legendURL] )
46           
47            ds.styles = [gridStyle, contourStyle]
48           
49            log.debug("dir(ds) = %s" % (dir(ds),))
50            log.debug("ds.identifier = %s" % (ds.identifier,))
51            log.debug("ds.styles = %s" % (ds.styles,))
52            log.debug("ds.metadata = %s" % (ds.metadata,))
53       
54        if format == 'application/json':
55           
56            t = self.loader.load(self.JSON_CAPABILITIES_TEMPLATE,
57                                                   cls=NewTextTemplate)
58        elif version == '1.1.1':
59            t = self.loader.load(self.XML_CAPABILITIES_V1_1_1)
60        elif version == '1.3.0':
61            t = self.loader.load(self.XML_CAPABILITIES_V1_1_3)
62        else:
63            # We should never get here!  The framework should raise an exception before now.
64            raise RuntimeError("Version %s not supported" % version)
65       
66        return t.generate(c=c).render()
67
68    def _getLayerParam(self, paramName='layers'):
69        """
70        Retrieve the layers parameter enforcing the rule of only
71        selecting one layer.
72
73        @param paramName: Overrides the query string parameter name to
74            look for.  This is usefull for implementing GetFeatureInfo.
75
76        """
77        layers = {}
78        layerNames = self.getOwsParam(paramName)
79       
80        # Select the first layer if several are requested.
81        # This plays nicer with mapClient.
82        layerNames = layerNames.split(',')
83       
84        layerObjects = []
85       
86        for layerName in layerNames:
87            try:
88                layerObj = self.layers[layerName]
89                layerObjects.append(layerObj)
90#                layers[layerName] = layerObj
91            except KeyError:
92                raise InvalidParameterValue('Layer %s not found' % layerName,
93                                        paramName)
94
95        return layerNames, layerObjects
96        #return layers
97
98
99       
100    def _retrieveSlab(self, layerObj, srs, dimValues, style, transparent, renderOpts):
101       
102        # Find the slab in the cache first
103        cacheKey = layerObj.getCacheKey(srs, style, transparent, dimValues, renderOpts)
104        slab = self._layerSlabCache.get(cacheKey)
105       
106        if slab is None:
107           
108            slab = layerObj.getSlab(srs, style, transparent, dimValues, renderOpts)
109           
110            if cacheKey is not None:
111                self._layerSlabCache[cacheKey] = slab
112
113        return slab
114
115    #-------------------------------------------------------------------------
116    # OWS Operation methods
117   
118    def GetMap(self):
119
120        # Housekeeping
121        version = self.getOwsParam('version', default=self.validVersions[0])
122       
123        if version not in self.validVersions:
124            raise InvalidParameterValue('Version %s not supported' % version,
125                                        'version')
126       
127       
128        renderingOptions = {}
129        for opt in RENDERING_OPTIONS:
130            if self.getOwsParam(opt, default=None) != None:
131                renderingOptions[opt] = self.getOwsParam(opt)
132       
133        log.debug("renderingOptions = %s" % (renderingOptions,))
134       
135
136       
137        transparent = self.getOwsParam('transparent', default='FALSE')
138       
139        transparent = transparent.lower() == 'true'
140       
141        bgcolor = self.getOwsParam('bgcolor', default='0xFFFFFF')
142
143        # Layer handling
144        layerNames, layerObjects = self._getLayerParam()
145#        layers = self._getLayerParam()
146       
147        log.debug("layerNames = %s" % (layerNames,))
148        log.debug("layerObjects = %s" % (layerObjects,))
149       
150        styles = self.getOwsParam('styles', default='')
151       
152        if styles != None:
153            styles = styles.split(',')
154            assert len(styles) == len(layerNames)
155       
156        log.debug("style = %s" % (styles,))       
157       
158        # Coordinate parameters
159        bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(','))
160        width = int(self.getOwsParam('width'))
161        height = int(self.getOwsParam('height'))
162
163        if version == '1.1.1':
164            srs = self.getOwsParam('srs')
165        else:
166            srs = self.getOwsParam('crs')
167
168        #if srs not in layerObj.crss:
169         #   raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs))
170
171        # Get format
172        format = self.getOwsParam('format')
173        if format not in self._pilImageFormats:
174            raise InvalidParameterValue(
175                'Format %s not supported' % format, 'format')
176
177
178        finalImg = Image.new('RGBA', (width, height), (0,0,0,0))
179
180        # Multiple Layers handling.. 
181#        for layerName, layerObj in layers.iteritems():
182        for i in range(len(layerNames)):
183           
184            layerName = layerNames[i]
185            layerObj = layerObjects[i]
186            if styles != None:
187                style = styles[i]
188            else:
189                style = ""
190               
191            if style == "":
192                style = STYLES.DEFAULT
193               
194           
195            if srs not in layerObj.crss:
196                raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs))
197
198            dimValues = self._getDimValues(layerObj)
199           
200            #now need to revert modified dim values (e.g. height_dim) back to dim values the layerMapper understands (e.g. height)
201            restoredDimValues={}
202            for dim in dimValues:
203                restoredDim=self._mapParamToDim(dim)
204                restoredDimValues[restoredDim]=dimValues[dim]
205               
206            #-------------------------------------------------------
207            # The real work
208            #!TODO: Minimum and maximum values
209
210            slab = self._retrieveSlab(layerObj, srs, restoredDimValues, style,
211                                      transparent, renderingOptions)
212
213            # We must request a bbox within the layer's bbox.
214            lbbox = layerObj.getBBox(srs)
215            ibbox = bbox_util.intersection(bbox, lbbox)
216
217            log.debug('bbox = %s' % (bbox,))
218            log.debug('lbbox = %s' % (lbbox,))
219            log.debug('ibbox = %s' % (ibbox,))
220
221            log.debug("width, height = %s, %s" % (width, height,))
222            img = slab.getImage(bbox, width, height)
223           
224            log.debug("img = %s format=%s, size=%s, mode=%s" % (img, img.format, img.size, img.mode))
225            log.debug("finalImg = %s format=%s, size=%s, mode=%s" % (finalImg, finalImg.format, finalImg.size, finalImg.mode))
226
227            finalImg = Image.composite(finalImg, img, finalImg)   
228
229           
230        # IE < 7 doesn't display the alpha layer right.  Here we sniff the
231        # user agent and remove the alpha layer if necessary.
232        try:
233            ua = request.headers['User-Agent']
234        except:
235            pass
236        else:
237            if 'MSIE' in ua and 'MSIE 7' not in ua:
238                finalImg = finalImg.convert('RGB')
239
240        buf = StringIO()
241        finalImg.save(buf, self._pilImageFormats[format])
242
243        response.headers['Content-Type'] = format
244        response.write(buf.getvalue())
245
246    def GetLegend(self):
247        """
248        Return an image of the legend.
249
250        """
251        # Parameters
252        layerName, layerObj = self._getLayerParamInfo()
253        format = self._getFormatParam()
254
255        # This hook alows extra arguments to be passed to the layer backend.  It
256        # is required for UKCP.
257#        renderOpts = dict(request_params=self._owsParams)
258     
259        renderingOptions = {}
260        for opt in RENDERING_OPTIONS:
261            if self.getOwsParam(opt, default=None) != None:
262                renderingOptions[opt] = self.getOwsParam(opt)
263       
264#        log.debug("renderingOptions = %s" % (renderingOptions,))
265
266        img = layerObj.getLegendImage(renderOpts=renderingOptions)
267
268        buf = StringIO()
269        img.save(buf, self._pilImageFormats[format])
270
271        response.headers['Content-Type'] = format
272        response.write(buf.getvalue())
273
Note: See TracBrowser for help on using the repository browser.