source: cows/trunk/cows/service/imps/data_reader_geoplot_backend/geoplot_slabs/geoplot_slab_base.py @ 6102

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows/trunk/cows/service/imps/data_reader_geoplot_backend/geoplot_slabs/geoplot_slab_base.py@6102
Revision 6102, 6.0 KB checked in by pnorton, 11 years ago (diff)

Removed the old modis data reader class. Also modified COWS to pass the style parameter to the GetLegendImage? methods on the layer objects.

Line 
1import logging
2import time
3
4import numpy
5
6from geoplot.utils import isRangeInLimits
7
8from cows.service.wms_iface import IwmsLayerSlab
9from cows.service.imps.image_import import Image
10from cows.service.imps.data_reader_geoplot_backend.slab_options_parser import SlabOptionsParser
11from cows.service.imps.data_reader_geoplot_backend.rendering_option import RenderingOption
12   
13log = logging.getLogger(__name__)
14
15class GeoplotSlabBase(IwmsLayerSlab):
16    """
17    A layer slab that implements the IwmsLayerSlab interface and uses geoplot
18    to render the required images.
19   
20    This is an abstract base class and should not be used directly.
21    """
22
23    renderingOptions = [
24        RenderingOption('cmap', "Colour Scheme" ,str,'jet',["bone","jet", "copper", "gray", "winter"] ),
25       
26        RenderingOption('cmap_min', "Legend Min" ,float,None),
27        RenderingOption('cmap_max', "Legend Max" ,float,None),
28        RenderingOption('cmap_scale', "Colour Bar Scale" ,str ,'linear', ['linear','log']),
29    ]
30
31    """
32    contstructor
33   
34    @param netcdf: the netcdf variable that contains the data for this slab
35    @param title: the title of the variable that is to be used
36    @param crs: the coordinate refrence system the data is stored in
37    @param dimValues: the dimension values for this slab
38    @param transparent: indicates if the produced image should be transparent or
39        not.
40    @param bbox: the bounds of the data in lat/lon
41    @param renderOpts: the additional parameters recieved by the WMS, may include
42        some custom rendering options.
43    """
44    def __init__(self, variable, title, crs, dimValues, transparent, bgcolour, bbox, renderOpts):
45
46        self.title = title
47        self.renderOpts = renderOpts
48        self.bgcolour = bgcolour
49        self.transparent = transparent
50        self.variable = variable
51               
52        #log.debug("renderOpts = %s" % (renderOpts,))
53       
54        self.parser = SlabOptionsParser(self.renderingOptions, renderOpts)
55        self.ld = self._setupLayerDrawer()
56   
57    """
58    Creates the layer drawer object so that it can be used in getImage
59    """
60    def _setupLayerDrawer(self):
61        raise NotImplementedError()
62   
63    """
64    returns an image of the data constructed using the layer drawer
65   
66    @param bbox: the limits of the image requested
67    @param width: the width in px of the image
68    @param height: the height in px of the image
69    """
70    def getImage(self, bbox, width, height):
71        """
72        Create an image of a sub-bbox of a given size.
73
74        @ivar bbox: A bbox 4-tuple.
75        @ivar width: width in pixels.` 
76        @ivar height: height in pixels.
77        @return: A PIL Image object.
78
79        """
80        #log.debug("GetImage called with bbox=%s, width=%s, height = %s" % (bbox, width, height,))
81       
82        xLimits = (bbox[0], bbox[2])
83        yLimits = (bbox[1], bbox[3])
84       
85        if sorted(self.variable.getAxisIds()) == sorted(['latitude','longitude']):
86           
87            if not self._areBoundsInLimits(bbox, xLimits, yLimits):
88               
89                img = numpy.zeros((height,width,4), numpy.uint8)
90                pilImage = Image.fromarray(img, 'RGBA')
91               
92                log.debug("empty image used as no data found for id=%s (%sx%s), lon=%s, lat=%s " % \
93                  (self.variable.id, width, height, xLimits, yLimits))
94           
95                return pilImage
96                       
97        st = time.time()
98        im = self.ld.makeImage(xLimits, yLimits, width, height)
99       
100        log.debug("generated contour image id=%s (%sx%s, lon=%s, lat=%s in %.2fs" % \
101                  (self.variable.id, width, height, xLimits, yLimits,  time.time() - st,))
102       
103        return im
104
105    def _areBoundsInLimits(self, bbox, xLimits, yLimits):
106       
107        if self.variable.getAxisIds()[0] == 'longitude':
108            lonAx, latAx = self.variable.getAxisList()
109        else:
110            latAx, lonAx = self.variable.getAxisList()
111           
112        xRange = [ lonAx.getBounds().min(), lonAx.getBounds().max()]
113        yRange = [ latAx.getBounds().min(), latAx.getBounds().max()]
114        log.debug("xLimits = %s" % (xLimits,))
115        log.debug("yLimits = %s" % (yLimits,))
116        log.debug("xRange = %s" % (xRange,))
117        log.debug("yRange = %s" % (yRange,))
118       
119        xRange = self._fixLongitudeRange(xLimits, xRange)
120       
121        isInLimits = isRangeInLimits(xRange, xLimits) and \
122                     isRangeInLimits(yRange, yLimits)
123                             
124        log.debug("isInLimits = %s" % (isInLimits,))
125       
126        return isInLimits
127   
128    def _fixLongitudeRange(self, xLimits, xRange):
129        """
130        Attemts to match the upper and lower bounds of the longiude range
131        to that of the xLimits (either -180,180 or 0,360)
132        """
133       
134        returnRange = xRange
135       
136        range_180to0 = False
137        range180to360 = False 
138             
139        #assuming the xLimits are given in range -180 to 180
140        for i in [0,1]:
141            if -180.0 <= xLimits[i] < 0.0:
142                range_180to0 = True
143           
144            elif 180 < xLimits[i] <= 360:
145                range180to360 = True
146       
147#        log.debug("range180to360 = %s, range_180to0 = %s" % (range180to360, range_180to0,))
148        assert not (range_180to0 and range180to360), "confusing bounds found on longitude range %s " % (xLimits,)
149       
150        if range_180to0:
151            #if the xRange is 0-360 need to adjust it
152            for x in returnRange:
153               
154                if x > 180.0:
155                    returnRange = [x - 180 for x in returnRange]
156                    break
157                   
158        if range180to360:
159            #if the range is -180-0 need to adjust it
160            for x in returnRange:
161                if x < 0.0:
162                    returnRange =  [x + 180 for x in returnRange]
163                    break
164               
165#        log.debug("returnRange = %s" % (returnRange,))
166        return returnRange
167       
Note: See TracBrowser for help on using the repository browser.