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

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

Fixed a problem with imshow drawing a grid when there was no data to draw. Also fixed some of the tests.

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