source: cows/trunk/cows/service/imps/geoplot_wms_backend/geoplot_wms_layer.py @ 6520

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows/trunk/cows/service/imps/geoplot_wms_backend/geoplot_wms_layer.py@6520
Revision 6520, 10.2 KB checked in by pnorton, 10 years ago (diff)

Modified the geoplot layer legend size and added an additional contour rendering option.

Line 
1'''
2Created on 9 Jun 2009
3
4@author: pnorton
5'''
6
7import logging
8
9import time
10import os
11import numpy
12
13from cows.service.imps.csmlbackend.config import config
14from cows.service.wms_iface import IwmsLayer
15
16
17log = logging.getLogger(__name__)
18
19import geoplot.colour_bar
20
21from cows.model.wms import Style, LegendURL, FormattedURL, MetadataURL
22from cows.xml.iso19115_subset import OnlineResource
23
24from routes import url_for
25
26from cows.service.imps.csmlbackend.wms.wms_csmllayer import CSMLwmsLayer
27
28from cows.service.imps.geoplot_wms_backend.slabs.slab_contour import SlabContour
29from cows.service.imps.geoplot_wms_backend.slabs.slab_grid import SlabGrid
30from cows.service.imps.geoplot_wms_backend.slabs.slab_interval import SlabInterval
31from cows.service.imps.geoplot_wms_backend.slab_options_parser import SlabOptionsParser
32
33
34class GeoplotWmsLayer(CSMLwmsLayer):
35
36    slab_classes = [SlabGrid, SlabContour, SlabInterval]
37    default_slab_class = SlabGrid
38   
39    EnableDisplayOptions = False
40    EnableXMLAxisConfig = False
41   
42    def __init__(self, title, abstract, name=None, dimensions=None, 
43                       units=None, crss=None, boundingBox=None, 
44                       dataReader=None, childLayers=None):
45       
46        CSMLwmsLayer.__init__(self, title, abstract, name=name, dimensions=dimensions,
47                     units=units, crss=crss, boundingBox=boundingBox,
48                     dataReader=dataReader, childLayers=childLayers)
49         
50        self.legendSize=(630,120)
51       
52        if name is not None:
53            self.styles = self._buildStyles()
54            self.metadataURLs = self._buildMetadataURL()
55       
56    def getSlab(self, crs, style, dimValues, transparent, bgcolor, 
57                    additionalParams={}):
58        """
59        Creates a slab of the layer in a particular CRS and set of
60        dimensions.
61
62        @param crs: The coordinate reference system.
63        @param dimValues: A mapping of dimension names to dimension values
64            as specified in the IDimension.extent
65        @param renderOpts: A generic mapping object for passing rendering
66            options
67        @return: An object implementing ILayerSlab
68        #create netcdf for whole lat/lon for given dimValues, use to init slab
69        """
70       
71        #make the colour compatable with matplotlib
72        if bgcolor.find('0x') == 0:
73            bgcolor = '#' + bgcolor[2:]
74       
75        netcdfVar = self.dataReader.getNetcdfVar(self.title, dimValues)
76       
77        slabClass = self._getSlabClass(style)
78       
79        bbox=self.getBBox(crs)
80       
81        slab = slabClass(netcdfVar, self.title, crs, dimValues, transparent, bgcolor, bbox, additionalParams)
82               
83        return slab
84
85    def _getActualStyle(self, style=None):
86        actualStyle = None
87       
88        if style == 'default' or style == '' or style is None:
89            actualStyle = GeoplotWmsLayer.default_slab_class.style
90        else:
91            actualStyle = style
92       
93        if actualStyle not in [x.style for x in GeoplotWmsLayer.slab_classes]:
94            Exception("No slab class found for style = %s"  % (style,))
95             
96        return actualStyle
97   
98    def _getSlabClass(self, style):
99        slabClass = None
100       
101        s = self._getActualStyle(style)
102       
103        for klass in GeoplotWmsLayer.slab_classes:
104            if klass.style == s:
105                slabClass = klass
106                break
107       
108        if slabClass == None:
109            Exception("No slab class found for style = %s"  % (style,))
110       
111        return slabClass
112
113    def getFeatureInfo(self, format, crs, point, dimValues):
114        """
115        Return a response string descibing the feature at a given
116        point in a given CRS.
117
118        Currently only "html" is supported as output format
119
120        @param format: One of self.featureInfoFormats.  Defines which
121            format the response will be in.
122        @param crs: One of self.crss
123        @param point: a tuple (x, y) in the supplied crs of the point
124            being selected.
125        @param dimValues: A mapping of dimension names to dimension values.
126        @return: A string containing the response.
127
128        """
129        netcdf = self.dataReader.getNetcdfVar(self.title, dimValues)
130       
131        #Now grab the netCDF object for the point specified.
132        #The reason for the 'cob' option is so that if the grid the data
133        #is defined on does not have a grid point at the point specified,
134        #we should  still get the nearest location
135       
136        t_point = netcdf(latitude=(point[1], point[1], 'cob'), longitude=(point[0], point[0], 'cob'))
137        #now get the value recorded at this location
138        value = t_point.getValue().tolist()
139        log.debug(value)
140        log.debug(t_point.fill_value())
141        #and the fill_value too
142        fill_value = t_point.fill_value()
143        #value is actually embedded in a multi dimensional list,
144        #so we need to extract the actual value from the list
145        while type(value) is list:
146                value = value[0]
147
148        #now check if the value is actually the fill_value rather than
149        #a value recorded at the point specified
150        log.debug('%s %s' % (value, fill_value))
151        if (2*fill_value) == value:
152                value = "No value found at position: "+str(point[1])+", "+str(point[0])
153        else:
154                value = "Value found at position: "+str(point[1])+", "+str(point[0])+" is: "+str(value)
155               
156        # finally return the value
157        return value
158
159    def getLegendImage(self, dimValues, width=None, height=None, 
160                       orientation='horizontal', 
161                       renderOpts={}, 
162                       style=None
163                       ):
164        """
165        Create an image of the colourbar for this layer.
166        @param orientation: Either 'vertical' or 'horizontal'
167        @return: A PIL image with labels
168
169        """
170        if width == None:
171            width = self.legendSize[0]
172           
173        if height == None:
174            height = self.legendSize[1]
175               
176        variable = self.dataReader.getNetcdfVar(self.title, dimValues)
177       
178        klass = self._getSlabClass(style)
179       
180        return klass.makeColourBar(width , height, orientation, self.units, renderOpts, variable)
181   
182       
183        parser = SlabOptionsParser(klass.renderingOptions, renderOpts)
184       
185        log.debug("klass.style = %s" % (klass.style,))
186       
187        minval = parser.getOption('cmap_min')
188        if minval == None:
189            minval = variable.min()
190           
191        maxval = parser.getOption('cmap_max')
192        if maxval == None:
193            maxval = variable.max()
194           
195            # can't have a colourbar with an infinite maximum, take the highest
196            # non-inf value.
197            if maxval == numpy.inf:
198                maxval = numpy.ma.masked_equal(variable, numpy.inf).max()
199       
200        log.debug("parser.getOption('intervals') = %s" % (parser.getOption('intervals'),))
201        log.debug("parser.getOption('intervalNames') = %s" % (parser.getOption('intervalNames'),))
202       
203        im = geoplot.colour_bar.getColourBarImage(width, height, 
204                                             label='Units of measure: %s' % str(self.units),
205                                             cmap=parser.getOption('cmap'), 
206                                             colourBarMin=minval,
207                                             colourBarMax=maxval,
208                                             colourBarScale=parser.getOption('cmap_scale'),
209                                             numIntervals=parser.getOption('num_intervals'), 
210                                             orientation=orientation,
211                                             intervals=parser.getOption('intervals'),
212                                             intervalNames=parser.getOption('intervalNames'),
213                                             colourBarStyle=parser.getOption('cbar_style'),
214                                             )
215       
216        return im
217   
218    def _buildStyles(self):
219        onlineRes = OnlineResource(self._getIndexActionURL() + "?request=GetLegend&layers=%s" % self.name)
220       
221        legendURL = LegendURL(630, 80, format='img/png', onlineResource=onlineRes )
222       
223        styles = []
224        for klass in GeoplotWmsLayer.slab_classes:
225           
226            styleName = klass.style
227           
228            title = getattr(klass, 'title', None)
229           
230            if title is None:
231                title = styleName
232           
233            s = Style(styleName, title, legendURLs=[legendURL] )
234           
235            styles.append(s)
236       
237        return styles
238   
239    def getAxisConfigFile(self):
240        xmlFile = None
241       
242        if hasattr(self.dataReader, 'getConfigAxisXMLFile'):
243           
244            xmlFile =  self.dataReader.getConfigAxisXMLFile()
245       
246        return xmlFile
247   
248    def _buildMetadataURL(self):
249       
250        metadataURLs = []
251       
252        if GeoplotWmsLayer.EnableDisplayOptions == True:
253            onlineRes = OnlineResource(self._getIndexActionURL() +\
254                       "?request=GetDisplayOptions&layers=%s" % self.name)
255           
256            metadataURLs.append( MetadataURL(metadataType='display_options', 
257                                          format='application/json',
258                                          onlineResource=onlineRes) )
259           
260        if GeoplotWmsLayer.EnableXMLAxisConfig:
261           
262            xmlFile =  self.getAxisConfigFile()
263           
264            if xmlFile != None:
265               
266                onlineRes = OnlineResource(self._getIndexActionURL() +\
267                                "?request=GetAxisConfig&layers=%s" % self.name)
268           
269                metadataURLs.append( MetadataURL(metadataType='axis_config', 
270                                                 format='text/xml',
271                                                 onlineResource=onlineRes) )     
272       
273        return metadataURLs
274   
275    def _getIndexActionURL(self):
276        """
277        Uses the pylons config to build a url for the index action of this contoller.
278        """
279               
280        indexURL = url_for(qualified=True, action='index')
281        return indexURL
Note: See TracBrowser for help on using the repository browser.