source: qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/controllers/coastwms.py @ 5647

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

Removed the ddc layer/slab/layermapper as these are now included in cows as the csml_geoplot implementation.

Added the GetFigure? method that uses geoplot to generate a simple figure output.

Line 
1import logging
2import Image
3import thread
4import re
5import simplejson as json
6
7from StringIO import StringIO
8from sets import Set
9from matplotlib.cm import get_cmap
10from pylons import request, response, c
11from routes import url_for
12from routes.util import GenerationException
13from genshi.template import NewTextTemplate
14from cows.pylons.wms_controller import WMSController
15from cows.model.wms import WmsDatasetSummary, Dimension, DataURL
16from cows.model import PossibleValues, WGS84BoundingBox, BoundingBox, Contents
17from cows.pylons import ows_controller
18from cows.exceptions import *
19from cows import bbox_util
20import time
21
22from geoplot.layer_drawer_coastline import LayerDrawerCoastlines
23
24from cows.model.wms import Style, LegendURL, FormattedURL, MetadataURL
25from cows.xml.iso19115_subset import OnlineResource
26
27log = logging.getLogger(__name__)
28
29class CoastwmsController(ows_controller.OWSController):
30
31    #layers = {}   
32    _pilImageFormats = {
33        'image/png': 'PNG',
34        'image/jpg': 'JPEG',
35        'image/gif': 'GIF',
36        'image/tiff': 'TIFF'
37        }
38   
39    _layerSlabCache = {}
40
41    #-------------------------------------------------------------------------
42    # Attributes required by OWSController
43
44    service = 'WMS'
45    owsOperations = (ows_controller.OWSController.owsOperations +
46        ['GetMap', 'GetContext', 'GetLegend', 'GetFeatureInfo', 'GetInfo', 'GetDisplayOptions'])
47   
48    validVersions = ['1.1.1', '1.3.0']
49
50
51
52    def _renderCapabilities(self, version, format):
53        if format == 'application/json':
54            t = ows_controller.templateLoader.load('wms_capabilities_json.txt',
55                                                   cls=NewTextTemplate)
56        elif version == '1.1.1':
57            t = ows_controller.templateLoader.load('wms_capabilities_1_1_1.xml')
58        elif version == '1.3.0':
59            t = ows_controller.templateLoader.load('wms_capabilities_1_3_0.xml')
60        else:
61            # We should never get here!  The framework should raise an exception before now.
62            raise RuntimeError("Version %s not supported" % version)
63       
64        return t.generate(c=c).render()
65
66    def _loadCapabilities(self):
67        """
68        @note: Assumes self.layers has already been created by __before__().
69
70        """
71        #!TODO: Add json format to GetCapabilities operation
72
73        ows_controller.addOperation('GetMap', formats=self._pilImageFormats.keys())
74        ows_controller.addOperation('GetContext', formats=['text/xml', 'application/json'])
75
76       
77        featureInfoFormats = Set()
78
79        log.debug('Loading capabilities contents')
80        c.capabilities.contents = Contents()
81       
82       
83        layers = ( ('c', 'coarse', 'coarse detail'), 
84                   ('l', 'low', 'low detail'), 
85                   ('i', 'intermediate', 'intermediate detail'),
86                   ('h', 'high', 'high detail'),
87                   ('f', 'full', 'full detail'),)
88       
89       
90        for layerName, title,  abstract in layers:
91            log.debug('LayerName: %s' % layerName)
92            log.debug('Loading layer %s' % layerName)
93
94            wgs84BBox = WGS84BoundingBox((-180,-90), (180,90))
95
96            # Get CRS/BBOX pairs
97            bboxObjs = []
98            for crs in ('EPSG:4326', 'CRS:84', 'WGS84'):
99                bbox = [-180,-90,180,90]
100                bboxObjs.append(BoundingBox(bbox[:2], bbox[2:], crs=crs))
101               
102
103               
104            #URL to WCS - uses named route 'wcsroute'
105            #TODO: Allow for a WCS blacklist to opt out of providing dataurls for certain datasets?
106            #TODO: How to make this more configurable - what if WCS is not coupled with WMS?
107#            try:
108#                version='1.0.0' #wcs version
109#                wcsbaseurl=url_for('wcsroute', fileoruri=c.fileoruri,qualified=True)+'?'
110#                dataURLs=[DataURL(format='WCS:CoverageDescription', onlineResource='%sService=WCS&Request=DescribeCoverage&Coverage=%s&Version=%s'%(wcsbaseurl, layerName, version))]
111#            except GenerationException:
112#                log.info("dataURLs not populated: could not generate WCS url with url_for('wcsroute', filedoruri=%s,qualified=True)"%c.fileoruri)
113#                dataURLs=[]
114           
115            onlineRes = OnlineResource(url_for(qualified=True, action='index') +\
116                                    "?request=GetDisplayOptions&layers=%s" % layerName)
117            metadataURL = MetadataURL(metadataType='display_options', format='application/json', onlineResource=onlineRes)
118       
119            # Create the cows object
120            ds = WmsDatasetSummary(identifier=layerName,
121                                   titles=[title],
122                                   CRSs=('EPSG:4326', 'CRS:84', 'WGS84'),
123                                   wgs84BoundingBoxes=[wgs84BBox],
124                                   boundingBoxes=bboxObjs,
125                                   abstracts=[abstract],
126                                   dimensions={},
127                                   queryable=False,
128                                   dataURLs=[],
129                                   styles=[],
130                                   metadataURLs=[metadataURL])
131
132            # Stuff that should go in the capabilities tree eventually
133            ds.legendSize = (630,80)
134            ds.legendFormats = ['image/png']
135
136            c.capabilities.contents.datasetSummaries.append(ds)
137
138        # Add this operation here after we have found all formats
139        ows_controller.addOperation('GetFeatureInfo',
140                                    formats = list(featureInfoFormats))
141
142
143    _escapedDimNames = ['width', 'height', 'version', 'request',
144                        'layers', 'styles', 'crs', 'srs', 'bbox',
145                        'format', 'transparent', 'bgcolor',
146                        'exceptions']
147
148
149    def _mapDimToParam(self, dimName):
150        """
151        Dimension names might clash with WMS parameter names, making
152        them inaccessible in WMS requests.  This method maps a
153        dimension name to a parameter name that appears in the
154        capabilities document and WMS requests.
155
156        """
157        if dimName.lower() in self._escapedDimNames:
158            return dimName+'_dim'
159        else:
160            return dimName
161       
162   
163    def GetMap(self):       
164        st = time.time()
165
166       
167        # Housekeeping
168        version = self.getOwsParam('version', default=self.validVersions[0])
169        if version not in self.validVersions:
170            raise InvalidParameterValue('Version %s not supported' % version,
171                                        'version')
172        styles = self.getOwsParam('styles', default='')
173        transparent = self.getOwsParam('transparent', default='FALSE')
174        bgcolor = self.getOwsParam('bgcolor', default='0xFFFFFF')
175
176        # Layer handling
177        layerName = self.getOwsParam('layers')
178       
179        transparent = self.getOwsParam('transparent').lower() == 'true'
180       
181       
182        # Coordinate parameters
183        bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(','))
184        width = int(self.getOwsParam('width'))
185        height = int(self.getOwsParam('height'))
186
187        if version == '1.1.1':
188            srs = self.getOwsParam('srs')
189        else:
190            srs = self.getOwsParam('crs')
191
192       # Get format
193        format = self.getOwsParam('format')
194        if format not in self._pilImageFormats:
195            raise InvalidParameterValue(
196                'Format %s not supported' % format, 'format')
197
198        if layerName == 'auto':
199            layerName = None
200       
201        ldg = LayerDrawerCoastlines(transparent=transparent,
202                                    resolution=layerName)
203
204        xLimits = (bbox[0], bbox[2])
205        yLimits = (bbox[1], bbox[3])       
206        finalImg = ldg.makeImage(xLimits, yLimits, width, height)     
207
208       
209        # IE < 7 doesn't display the alpha layer right.  Here we sniff the
210        # user agent and remove the alpha layer if necessary.
211        try:
212            ua = request.headers['User-Agent']
213        except:
214            pass
215        else:
216            if 'MSIE' in ua and 'MSIE 7' not in ua:
217                finalImg = finalImg.convert('RGB')
218
219        buf = StringIO()
220        finalImg.save(buf, self._pilImageFormats[format])
221
222        response.headers['Content-Type'] = format
223        response.write(buf.getvalue())
224
225       
226        log.debug("got coastline in %s" % (time.time() - st,))
227
228    def GetContext(self):
229        """
230        Return a WebMap Context document for a given set of layers.
231
232        """
233        # Parameters
234        layers = self.getOwsParam('layers', default=None)
235        format = self.getOwsParam('format', default='text/xml')
236
237        # Filter self.layers for selected layers
238        if layers is not None:
239            newLayerMap = {}
240            for layerName in layers.split(','):
241                try:
242                    newLayerMap[layerName] = self.layers[layerName]
243                except KeyError:
244                    raise InvalidParameterValue('Layer %s not found' % layerName,
245                                                'layers')
246                   
247            self.layers = newLayerMap
248
249        # Automatically select the first bbox/crs for the first layer
250        aLayer = self.layers.values()[0]
251        crs = aLayer.crss[0]
252        bb = aLayer.getBBox(crs)
253        c.bbox = BoundingBox(bb[:2], bb[2:], crs)
254
255        # Initialise as if doing GetCapabilities
256        ows_controller.initCapabilities()
257        self._loadCapabilities()
258
259        if format == 'text/xml':
260           
261            response.headers['Content-Type'] = format
262            t = ows_controller.templateLoader.load('wms_context_1_1_1.xml')
263            return t.generate(c=c).render()
264       
265        elif format == 'application/json':
266           
267            response.headers['Content-Type'] = format
268            t = ows_controller.templateLoader.load('wms_context_json.txt',
269                                                   cls=NewTextTemplate)
270            return t.generate(c=c).render()
271       
272        else:
273            raise InvalidParameterValue('Format %s not supported' % format)
274
275
276    def GetDisplayOptions(self):
277           
278        displayOptions = {
279#          "common": [
280#                        {
281#                            "type":"select",
282#                            "name":"cmap",
283#                            "options":["bone","jet", "copper", "gray", "winter"],
284#                            "title":"Colour Scheme",
285#                            "defaultVal":"jet",
286#                        },
287#                        {
288#                            "type":"value",
289#                            "name":"cmap_min",
290#                            "title":"Legend Min",
291#                            "defaultVal":None,
292#                        },
293#                        {
294#                            "type":"value",
295#                            "name":"cmap_max",
296#                            "title":"Legend Max",
297#                            "defaultVal":None,
298#                        },         
299#                     ],
300#          "grid": [
301#                        {
302#                            "type":"bool",
303#                            "name":"show_grid_lines",
304#                            "title":"Draw Grid Boxes",
305#                            "defaultVal":"False",
306#                        },   
307#                  ],
308#          "contour":[
309#                        {
310#                            "type":"value",
311#                            "name":"num_contour_lines",
312#                            "title":"Number of Contour Lines",
313#                            "defaultVal":10,
314#                        },
315#                        {
316#                            "type":"select",
317#                            "name":"contour_font_size",
318#                            "title":"Contour Label Size",
319#                            "options":["small","medium", "large",],
320#                            "defaultVal":"medium",
321#                        },   
322#                        {
323#                            "type":"value",
324#                            "name":"contour_label_interval",
325#                            "title":"Interval Between Labels",
326#                            "defaultVal":1,
327#                        },             
328#                    ],
329        }
330       
331       
332        request.headers['Content-Type'] = 'application/json'
333        response.write( json.dumps(displayOptions) )
334
Note: See TracBrowser for help on using the repository browser.