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

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

Configured a custom temporary directory for CSML extracts.

RevLine 
[2501]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
[2586]9
[2501]10"""
11from ows_server.lib.base import *
[2561]12from ows_server.lib.decorators import *
[2586]13from ows_server.lib import grid_util, render
[2588]14from ows_server.lib.csml_util import get_csml_doc, extract
[2578]15import ows_server.lib.validators as V
[2561]16
[2501]17from elementtree import ElementTree as ET
[2529]18
[2501]19from ows_common import exceptions as OWS_E
[2570]20from ows_common.wms import *
21from ows_common.common import BoundingBox
[2577]22from ows_common.domain import ValuesUnit, PossibleValues
[2529]23
[2586]24import cdms
[2588]25import os
[2586]26from cStringIO import StringIO
27import MA
[2501]28
29class CsmlWmsController(OwsController):
30
31    _ows_parameters = {
32        'Format': make_domain(['text/xml']),
33        'ExceptionFormat': make_domain(['text/xml']),
34        }
35
[2502]36    #_ows_constraints = {
[2501]37        # MaximumLayerLevels
38        # MaximumWidth
39        # MaximumWidth
[2502]40    #    }
[2529]41
42
[2586]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
[2577]59    def _loadFeatureDimensions(self, feature):
[2570]60        dims = {}
[2586]61        domain = feature.getDomain()
62        for axis_name in self._iterDimensions(feature):
63            axis = domain[axis_name]
[2578]64            dims[axis_name] = Dimension(possibleValues=PossibleValues.fromAllowedValues(axis),
[2586]65                                        #!TODO: see ticket:770 for how to populate this
[2578]66                                        valuesUnit=ValuesUnit(uoms=[''],
67                                                              referenceSystems=['']))
[2577]68        return dims
69
70    def _loadFeatureSummary(self, feature):
71        dims = self._loadFeatureDimensions(feature)
[2570]72       
73        return WmsDatasetSummary(identifier=feature.id,
74                                 titles=[feature.description.CONTENT],
75                                 boundingBoxes=[BoundingBox([-180,-90], [180,90],
76                                                            crs='CRS:84')],
[2577]77                                 dimensions=dims,               
[2570]78                                 )
79
[2577]80    def _loadCapabilities(self):
[2529]81        """
82        Overriding subclass to add layer capabilities
83
84        """
85        # Get default capabilities from superclass
[2577]86        sm = super(CsmlWmsController, self)._loadCapabilities()
[2529]87
[2549]88        # For WMS 1.3.0 compatibility we need a single root DatasetSummary
[2570]89        ds = WmsDatasetSummary(titles=['Root Dataset'], datasetSummaries=[],
90                               CRSs=['CRS:84'])
[2549]91        # Add a DatasetSummary for each feature       
[2529]92        for f_n in c.dataset.getFeatureList():
[2577]93            feature_ds = self._loadFeatureSummary(c.dataset.getFeature(f_n))
[2570]94            ds.datasetSummaries.append(feature_ds)
[2529]95
[2549]96        sm.contents = Contents(datasetSummaries=[ds])
[2529]97        return sm
98
[2501]99   
[2502]100    @operation
[2501]101    @parameter('Format', possibleValues=['text/xml'])
[2564]102    @parameter('Service', possibleValues=['WMS'], required=True)
[2570]103    @parameter('Version', possibleValues=['1.3.0'])
[2507]104    def GetCapabilities(self, file, service=None, version=None):
[2501]105        """
106        @note: format and updatesequence parameters are not supported
107            by this WMS.
108
109        """
110       
[2570]111        # Populate the context object with information required by the template
[2529]112        c.dataset = get_csml_doc(file)
113
[2577]114        return self._renderCapabilities('ows/wms_capabilities')
[2570]115
116
117    @operation
118    @parameter('Version', possibleValues=['1.3.0'], required=True)
[2578]119    @parameter('Layers', required=True, validator=V.single_layer)
[2570]120    @parameter('Styles', required=True)
121    @parameter('CRS', possibleValues=['CRS:84'], required=True)
[2578]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))
[2570]125    @parameter('Format', required=True)
[2578]126    @parameter('Transparent', validator=V.boolean('Transparent'))
[2570]127    @parameter('Bgcolor')
128    @parameter('Exceptions')
129    # Dimension parameters Time, Elevation, etc. are handled separately
[2578]130    def GetMap(self, file, version, layers, styles, crs, bbox, width, height, format,
131               transparent=False, bgcolor=None, exceptions=None):
[2577]132
[2586]133        # Retrieve dataset and selected feature
[2577]134        dataset = get_csml_doc(file)
[2586]135        feature = dataset.getFeature(layers)
136        if feature is None:
137            raise OWS_E.InvalidParameterValue('Layer not found', 'layers')
[2577]138
[2586]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)
[2588]152
153        # Extract via CSML.subsetToGridSeries()
154        var = extract(feature, sel)
[2577]155       
[2586]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.