source: cows/trunk/cows/pylons/wcs_controller.py @ 4769

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows/trunk/cows/pylons/wcs_controller.py@4769
Revision 4769, 8.4 KB checked in by domlowe, 11 years ago (diff)

adding gml:timepositions to describe coverage response

Line 
1"""
2WMS controller for OGC Web Services (OWS).
3
4@author: Stephen Pascoe
5"""
6
7import re
8import math
9from cStringIO import StringIO
10from sets import Set
11from matplotlib.cm import get_cmap
12from pylons import request, response, c
13import paste
14
15import logging
16log = logging.getLogger(__name__)
17
18import Image
19from genshi.template import TextTemplate
20
21from cows.model.wms import Dimension
22from cows.model.wcs import WcsDatasetSummary, CoverageDescription
23from cows.model import PossibleValues, WGS84BoundingBox, BoundingBox, Contents
24from cows.pylons import ows_controller
25from cows.exceptions import *
26from cows import bbox_util
27
28class WCSController(ows_controller.OWSController):
29    """
30    Subclass this controller in a pylons application and set the layerMapper
31    class attribute to implement a WCS.
32
33    @cvar layerMapper: an cows.service.wcs_iface.ILayerMapper object.
34
35    """
36    layerMapper = None
37    _layerSlabCache = {}
38
39    #-------------------------------------------------------------------------
40    # Attributes required by OWSController
41
42    service = 'WCS'
43    owsOperations = (ows_controller.OWSController.owsOperations +
44        ['GetCoverage', 'DescribeCoverage'])
45    validVersions = ['1.0.0']
46   
47
48    #-------------------------------------------------------------------------
49
50    def __before__(self, **kwargs):
51        """
52        This default implementation of __before__() will pass all routes
53        arguments to the layer mapper to retrieve a list of coverages for
54        this WCS.
55
56        It will be called automatically by pylons before each action method.
57
58        @todo: The layer mapper needs to come from somewhere.
59
60        """
61        log.debug("loading layers")
62        self.layers = self.layerMapper.map(**kwargs)
63
64    #-------------------------------------------------------------------------
65    # Methods implementing stubs in OWSController
66
67    def _renderCapabilities(self, version, format):
68        if version == '1.0.0':
69            t = ows_controller.templateLoader.load('wcs_capabilities_1_0_0.xml')
70        else:
71            # We should never get here!  The framework should raise an exception before now.
72            raise RuntimeError("Version %s not supported" % version)
73       
74        return t.generate(c=c).render()
75
76    def _loadCapabilities(self):
77        """
78        @note: Assumes self.layers has already been created by __before__().
79
80        """
81        ows_controller.addOperation('GetCoverage')
82        ows_controller.addOperation('DescribeCoverage') 
83        featureInfoFormats = Set()
84
85        log.debug('Loading capabilities contents')
86        c.capabilities.contents = Contents()
87       
88        #TODO, the bounding box may include a Z dimension in WCS.
89        for cvgName, coverage in self.layers.items():
90            log.debug('Loading coverage %s' % cvgName)
91
92            wgs84BBox = WGS84BoundingBox(coverage.wgs84BBox[:2],
93                                         coverage.wgs84BBox[2:])
94            # Get CRS/BBOX pairs
95            bboxObjs = []
96            for crs in coverage.crss:
97                bbox = coverage.getBBox(crs)
98                bboxObjs.append(BoundingBox(bbox[:2], bbox[2:], crs=crs))
99               
100            # Create the cows object
101            #From the ows_servers stack - allthese values should come from  the Coverage object.
102            #TODO, the bounding box may include a Z dimension in WCS.
103            ds = WcsDatasetSummary(identifier=coverage.id,
104                                 titles=coverage.title,
105                                 boundingBoxes=[BoundingBox([bbox[0],bbox[1]], [bbox[2],bbox[3]],
106                                 crs='CRS:84')], 
107                                 description=coverage.description,
108                                 abstracts=coverage.abstract,
109                                 formats=['application/cf-netcdf'],
110                                 supportedCRSs=coverage.crss, 
111                                 timelimits=coverage.timeLimits
112                                 )
113
114            c.capabilities.contents.datasetSummaries.append(ds)
115
116           
117    def _getLayerParam(self, paramName='coverage'):
118        """
119        Retrieve the layers parameter enforcing the rule of only
120        selecting one coverage for now.
121
122        @param paramName: Overrides the query string parameter name to
123            look for.  This is usefull for implementing GetFeatureInfo.
124
125        """
126        layerName = self.getOwsParam(paramName)
127
128        # Select the first layer if several are requested.
129        # This plays nicer with mapClient.
130        if ',' in layerName:
131            #layerName = layerName.split(',')[0]
132            raise InvalidParameterValue(
133                'Multi-coverage getCoverage requests are not supported', 'coverage')
134        try:
135            layerObj = self.layers[layerName]
136        except KeyError:
137            raise InvalidParameterValue('coverage %s not found' % layerName,
138                                        paramName)
139
140        return layerName, layerObj
141   
142   
143    #-------------------------------------------------------------------------
144    # OWS Operation methods: DescribeCoverage and GetCoverage
145   
146    def GetCoverage(self):
147        # Housekeeping
148        version = self.getOwsParam('version', default=self.validVersions[0])
149        if version not in self.validVersions:
150            raise InvalidParameterValue('Version %s not supported' % version,
151                                        'version')
152        # Layer handling
153        layerName, layerObj = self._getLayerParam()
154       
155        # Coordinate parameters
156        bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(','))
157
158        srs = self.getOwsParam('crs')
159
160        #if srs not in layerObj.crss:
161         #   raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs))
162
163        # Get format
164        format = self.getOwsParam('format')
165       
166        if srs not in layerObj.crss:
167            raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs))
168        times= self.getOwsParam('time')
169#               
170        filepath = layerObj.getCvg(bbox, time=times) #TODO, refactor so is more flexible (e.g. not just netcdf)
171        fileToReturn=open(filepath, 'r')
172        mType='application/cf-netcdf'
173        response.headers['Content-Type']=mType
174        response.headers['Content-Disposition'] = paste.httpheaders.CONTENT_DISPOSITION(attachment=True, filename='filename.nc')
175        return response.write(fileToReturn.read())
176           
177    def DescribeCoverage(self):
178        c.descriptions=[]
179        requestCvg=self.getOwsParam('coverage')
180#        super(WCSController, self).GetCapabilities()
181        #TODO, the bounding box may include a Z dimension in WCS.
182        log.debug(requestCvg)
183        for cvgName, coverage in self.layers.items():
184            log.debug(cvgName)
185            if cvgName == requestCvg:
186                log.debug('found match')
187                wgs84BBox = WGS84BoundingBox(coverage.wgs84BBox[:2],
188                                         coverage.wgs84BBox[2:])
189                # Get CRS/BBOX pairs
190                bboxObjs = []
191                for crs in coverage.crss:
192                    bbox = coverage.getBBox(crs)
193                    bboxObjs.append(BoundingBox(bbox[:2], bbox[2:], crs=crs))
194                   
195                # Create the enhanced Dataset summary for thic coverage
196                #TODO, the bounding box may include a Z dimension in WCS.
197                #TODO, what extra information does this require over the normal dataset summary               
198                ds = CoverageDescription(identifier=coverage.id,
199                                     titles=coverage.title,
200                                     boundingBoxes=[BoundingBox([bbox[0],bbox[1]], [bbox[2],bbox[3]],
201                                     crs='CRS:84')], 
202                                     description=coverage.description,
203                                     abstracts=coverage.abstract,
204                                     formats=['application/cf-netcdf'],
205                                     supportedCRSs=coverage.crss, 
206                                     timepositions=coverage.timePositions,
207                                     timelimits=coverage.timeLimits
208                                     )
209
210                c.descriptions.append(ds)
211        response.headers['content-type']='text/xml'
212        t = ows_controller.templateLoader.load('wcs_describecoverage_1_0_0.xml')
213        return t.generate(c=c).render()               
214
215
216
217
218           
Note: See TracBrowser for help on using the repository browser.