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

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

Attempted to fix the problems with anti-aliasing and transparent backgrounds.

I found that the agg backend was using a white background to do the antialiasing rather than using the alpha layer so I moved to the cairo backend.

This required modifying the filtered_basemap.py to get it to work.

I've also removed the log.setLevel(logging.DEBUG) statements as they were affecting pasters handling of the loggers.

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