source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/csml_wms.py @ 2592

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/csml_wms.py@2592
Revision 2592, 6.0 KB checked in by domlowe, 12 years ago (diff)

skeleton getCoverage request working, edits to csml_utils to create separate extractToVariable, extractToNetCDF functions

Line 
1# Copyright (C) 2007 STFC & NERC (Science and Technology Facilities Council).
2# This software may be distributed under the terms of the
3# Q Public License, version 1.0 or later.
4# http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5"""
6Example WMS controller driven by CSML.
7
8@author: Stephen Pascoe
9
10"""
11from ows_server.lib.base import *
12from ows_server.lib.decorators import *
13from ows_server.lib import grid_util, render
14from ows_server.lib.csml_util import get_csml_doc, extractToVariable
15import ows_server.lib.validators as V
16
17from elementtree import ElementTree as ET
18
19from ows_common import exceptions as OWS_E
20from ows_common.wms import *
21from ows_common.common import BoundingBox
22from ows_common.domain import ValuesUnit, PossibleValues
23
24import cdms
25import os
26from cStringIO import StringIO
27import MA
28
29class CsmlWmsController(OwsController):
30
31    _ows_parameters = {
32        'Format': make_domain(['text/xml']),
33        'ExceptionFormat': make_domain(['text/xml']),
34        }
35
36    #_ows_constraints = {
37        # MaximumLayerLevels
38        # MaximumWidth
39        # MaximumWidth
40    #    }
41
42
43    def _iterDimensions(self, feature):
44        """
45        Retrieve the non-geospatial dimensions of a feature.
46
47        @return: generator of dimension names
48
49        """
50        # Waiting for this feature to be implemented
51        #lat = feature.getLatitude()
52        #lon = feature.getLongitude()
53        lat = 'latitude'; lon = 'longitude'
54       
55        for axis_name in feature.getDomain():
56            if axis_name not in [lat, lon]:
57                yield axis_name
58
59    def _loadFeatureDimensions(self, feature):
60        dims = {}
61        domain = feature.getDomain()
62        for axis_name in self._iterDimensions(feature):
63            axis = domain[axis_name]
64            dims[axis_name] = Dimension(possibleValues=PossibleValues.fromAllowedValues(axis),
65                                        #!TODO: see ticket:770 for how to populate this
66                                        valuesUnit=ValuesUnit(uoms=[''],
67                                                              referenceSystems=['']))
68        return dims
69
70    def _loadFeatureSummary(self, feature):
71        dims = self._loadFeatureDimensions(feature)
72       
73        return WmsDatasetSummary(identifier=feature.id,
74                                 titles=[feature.description.CONTENT],
75                                 boundingBoxes=[BoundingBox([-180,-90], [180,90],
76                                                            crs='CRS:84')],
77                                 dimensions=dims,               
78                                 )
79
80    def _loadCapabilities(self):
81        """
82        Overriding subclass to add layer capabilities
83
84        """
85        # Get default capabilities from superclass
86        sm = super(CsmlWmsController, self)._loadCapabilities()
87
88        # For WMS 1.3.0 compatibility we need a single root DatasetSummary
89        ds = WmsDatasetSummary(titles=['Root Dataset'], datasetSummaries=[],
90                               CRSs=['CRS:84'])
91        # Add a DatasetSummary for each feature       
92        for f_n in c.dataset.getFeatureList():
93            feature_ds = self._loadFeatureSummary(c.dataset.getFeature(f_n))
94            ds.datasetSummaries.append(feature_ds)
95
96        sm.contents = Contents(datasetSummaries=[ds])
97        return sm
98
99   
100    @operation
101    @parameter('Format', possibleValues=['text/xml'])
102    @parameter('Service', possibleValues=['WMS'], required=True)
103    @parameter('Version', possibleValues=['1.3.0'])
104    def GetCapabilities(self, file, service=None, version=None):
105        """
106        @note: format and updatesequence parameters are not supported
107            by this WMS.
108
109        """
110       
111        # Populate the context object with information required by the template
112        c.dataset = get_csml_doc(file)
113
114        return self._renderCapabilities('ows/wms_capabilities')
115
116
117    @operation
118    @parameter('Version', possibleValues=['1.3.0'], required=True)
119    @parameter('Layers', required=True, validator=V.single_layer)
120    @parameter('Styles', required=True)
121    @parameter('CRS', possibleValues=['CRS:84'], required=True)
122    @parameter('Bbox', required=True, validator=V.bbox_2d)
123    @parameter('Width', required=True, validator=V.integer('Width', 0, 640))
124    @parameter('Height', required=True, validator=V.integer('Height', 0, 320))
125    @parameter('Format', required=True)
126    @parameter('Transparent', validator=V.boolean('Transparent'))
127    @parameter('Bgcolor')
128    @parameter('Exceptions')
129    # Dimension parameters Time, Elevation, etc. are handled separately
130    def GetMap(self, file, version, layers, styles, crs, bbox, width, height, format,
131               transparent=False, bgcolor=None, exceptions=None):
132
133        # Retrieve dataset and selected feature
134        dataset = get_csml_doc(file)
135        feature = dataset.getFeature(layers)
136        if feature is None:
137            raise OWS_E.InvalidParameterValue('Layer not found', 'layers')
138
139        # Define the extraction selector
140        sel = dict(latitude=(bbox[1], bbox[3]), longitude=(bbox[0], bbox[2]))
141
142        # Parse dimensions.
143        for dim in self._iterDimensions(feature):
144            # For the moment hard-code time in.  We don't support any other dimension yet.
145            if dim.lower() != 'time':
146                raise ValueError('Only lat, lon and time are supported domain axes')
147           
148            try:
149                sel[dim] = request.params[dim]
150            except KeyError:
151                raise OWS_E.MissingParameterValue('%s dimension not specified' % dim, dim)
152
153        # Extract via CSML.subsetToGridSeries()
154        var = extractToVariable(feature, sel)
155       
156        # Deduce min and max
157        varmin = MA.minimum(var, None)
158        varmax = MA.maximum(var, None)
159
160        # Render variable to a PIL image
161        img = render.render_variable(var, bbox, width, height, varmin, varmax)
162
163        # Serialise it to PNG
164        buf = StringIO()
165        img.save(buf, 'PNG')
166
167        return Response(content=buf.getvalue(), mimetype='image/png')
Note: See TracBrowser for help on using the repository browser.