source: qesdi/geoplot/trunk/lib/geoplot/layer_drawer.py @ 5688

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/qesdi/geoplot/trunk/lib/geoplot/layer_drawer.py@5688
Revision 5688, 7.0 KB checked in by pnorton, 11 years ago (diff)

Improved the colour bar code so it now accepts the data array instead of just a minimum + maximum. It also now defaults to creating a Normalize instance with vmin=None and vmax=None instead of 0 and 1.

Also modified the layer_drawer objects to use the ColourBar? class instead of implementing it themselves.

Line 
1"""
2An object to draw just the layer (map + grid) from the plot,
3can draw to a file, a string or create an Image object.
4"""
5
6
7import logging
8import Image
9import StringIO
10import thread
11import time
12
13from matplotlib.figure import Figure
14
15from geoplot.grid_builder_lat_lon import GridBuilderLatLon
16from geoplot.grid_builder_national import GridBuilderNational
17from geoplot.grid_builder_rotated import GridBuilderRotated
18
19from geoplot.grid_factory import GridFactory
20from geoplot.map_factory import MapFactory
21
22import geoplot.utils as geoplot_utils
23
24from geoplot.colour_bar import ColourBar
25
26log = logging.getLogger(__name__)
27
28VALID_GRID_TYPES = ['latlon', 'national', 'rotated']
29
30VALID_PROJECTIONS = ['latlon', 'national']
31
32class LayerDrawerBase(object):
33    "Draws only the layer section of the plot to create a PIL image object"
34   
35    def __init__(self, 
36                 gridType='latlon', 
37                 transparent=False,
38                 projection='latlon',
39                 resolution=None,
40                 cmap=None, 
41                 cmapRange=(None,None), ):
42       
43        self._cb = ColourBar()
44        self.transparent = transparent
45        self.cmap = cmap
46        self.cmapRange = cmapRange
47       
48        self._gridFactory = GridFactory(dataType=gridType)
49        self._mapFactory = MapFactory(projection, drawCoast=True, drawRivers=False, resolution=resolution)
50       
51    def makeImage(self, xLimits=None, yLimits=None, width=800, height=600, dpi=100):
52        """
53        Creates a PIL image of the selected area of the layer.
54        """
55        st = time.time()
56        fig = self._getFigure(width, height, dpi)
57       
58        axes = self._addAxes(fig)
59       
60        self._drawToAxes(axes, xLimits, yLimits)
61       
62        self._resetAxes(axes, xLimits, yLimits)
63       
64        im = geoplot_utils.figureToImage(fig)
65       
66        log.debug("drawn layer in %s" % (time.time() -st ,))
67       
68        return im
69   
70   
71    def _drawToAxes(self, *args, **kwargs):
72        """
73        Draw the layer onto the axis, should be overidden by all subclasses.
74        """
75       
76        raise NotImplementedError()
77   
78    def _getFigure(self, width, height, dpi):
79        """
80        Returns a new figure object that is ready to be drawn on.
81        """
82
83        figsize=(width / float(dpi), height / float(dpi))
84
85        fig = Figure(figsize=figsize, dpi=dpi, facecolor='w', 
86                     frameon=(not self.transparent))
87       
88        return fig       
89   
90    def _addAxes(self, figure):
91        """
92        Adds an axis to the figure object provided. The axes has no border and takes
93        up all the area on the figure so that anything drawn on the axis will
94        completly cover the figure.
95       
96        The axis background is transparent, if self.transparency is set to false
97        then the Figure's frameon should be set to true not the axis.
98        """
99        axes = figure.add_axes([0.0, 0.0, 1.0, 1.0], 
100                               xticks=[], yticks=[], frameon=False)
101       
102        if self.transparent:
103            axes.set_alpha(0.0)
104            axes.patch.set_alpha(0.0)
105       
106        return axes
107   
108    def _buildGrid(self, cdmsVar, xLimits, yLimits):
109        """
110        Builds a new grid object using the data found in the cdmsVar.
111        """
112       
113        self._gridFactory.cdmsVar = cdmsVar
114       
115        grid = self._gridFactory.getGrid(xLimits, yLimits)
116       
117        return grid
118   
119    def _resetAxes(self, axes, xLimits=None, yLimits=None):
120        """
121        resets the axis to the original limis and aspect after they have
122        been drawn on, this is needed as some methods of drawing to the axis
123        (notably basemap) change these properties.
124        """
125       
126        axes.set_aspect('auto')
127       
128        axes.set_xticks([])
129        axes.set_yticks([])
130       
131        if self.projection == 'latlon':
132            xLimitsMapUnits, yLimitsMapUnits = xLimits, yLimits
133        else:
134            map = self._getMap(xLimits, yLimits)
135            xLimitsMapUnits, yLimitsMapUnits = map.basemap(xLimits, yLimits)
136       
137        #reset the limits after drawing the grid
138        if xLimits != None:
139            axes.set_xlim(float(xLimitsMapUnits[0]), float(xLimitsMapUnits[1]))
140       
141        if yLimits != None:
142            axes.set_ylim(float(yLimitsMapUnits[0]), float(yLimitsMapUnits[1]))   
143       
144    def _getMap(self, xLimits, yLimits, ):
145        """
146        Returns a map object that corresponds to the current projection,
147        map objects can be used for transformation or drawing data.
148        """
149       
150        self._mapFactory.xLimits = xLimits
151        self._mapFactory.yLimits = yLimits
152       
153        map = self._mapFactory.buildMap()
154           
155        return map       
156   
157    ### properties ###       
158   
159    def __set_gridType(self, value):
160        if value not in VALID_GRID_TYPES:
161           
162            raise Exception(\
163             "Invalid value of '%s' for LayerDrawer.gridType property, must be one of %s" 
164                % (value, VALID_GRID_TYPES,))
165           
166        self._gridFactory.dataType = value
167
168    def __get_gridType(self):
169        return self._gridFactory.dataType
170   
171    gridType = property(__get_gridType, __set_gridType, None, None)
172   
173    def __set_showGridLines(self, value):
174        self._gridDrawer.showGridLines = value
175   
176    def __get_showGridLines(self):
177        return self._gridDrawer.showGridLines
178   
179    showGridLines = property(__get_showGridLines, __set_showGridLines) 
180   
181    def __set_cmap(self, value):
182        self._gridDrawer.cmap = value
183       
184    def __get_cmap(self):
185        return self._gridDrawer.cmap
186   
187    cmap = property(__get_cmap, __set_cmap)
188   
189    def __set_cmapRange(self, value):
190        self._cmapRange = value
191       
192    def __get_cmapRange(self):
193        return self._cmapRange
194   
195    cmapRange = property(__get_cmapRange, __set_cmapRange)
196   
197    def __set_outline(self, value):
198        self._gridDrawer.outline = value
199       
200    def __get_outline(self):
201        return self._gridDrawer.outline
202   
203    outline = property(__get_outline, __set_outline)
204
205       
206    def __set_projection(self, value):
207        if value not in VALID_PROJECTIONS:
208           
209            raise Exception(\
210             "Invalid value of '%s' for projection property, must be one of %s" 
211                % (value, VALID_PROJECTIONS,))
212           
213        self._mapFactory.projection = value
214
215    def __get_projection(self):
216        return self._mapFactory.projection
217
218    def __set_cmap(self, value):
219        self._cb.cmap = value
220       
221    def __get_cmap(self):
222        return self._cb.cmap
223   
224    cmap = property(__get_cmap, __set_cmap)
225   
226    def __set_cmapRange(self, value):
227        self._cb.colourBarMin = value[0]
228        self._cb.colourBarMax = value[1]
229       
230    def __get_cmapRange(self):
231        return (self._cb.colourBarMin, self._cb.colourBarMax)
232   
233    cmapRange = property(__get_cmapRange, __set_cmapRange)
234   
235
236    projection = property(__get_projection, __set_projection, None, None)
237   
238       
239   
Note: See TracBrowser for help on using the repository browser.