source: qesdi/geoplot/trunk/lib/geoplot/plot_writer.py @ 5876

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/qesdi/geoplot/trunk/lib/geoplot/plot_writer.py@5876
Revision 5876, 9.3 KB checked in by pnorton, 10 years ago (diff)

Added a faster layer drawer for the grid, a new style of colour bar and colour schemes which now hold the normalisation and colour map instances.

Line 
1"""
2plot_writer.py
3==============
4Contains a class responsible for writing a completed plot to an image file.
5"""
6import os
7
8import StringIO
9import logging
10
11from matplotlib.backends.backend_agg import FigureCanvasAgg
12from matplotlib.backends.backend_ps import FigureCanvasPS
13from matplotlib.backends.backend_pdf import FigureCanvasPdf
14from matplotlib.backends.backend_svg import FigureCanvasSVG
15
16
17import image_utils.convert as convert
18#import image_utils.merge_bitmap_logo as merge_bitmap_logo
19import image_utils.merge_eps_logo as merge_eps_logo
20#import image_utils.cmyk_conversion.cmykify_ps as cmykify_ps
21
22#import resources
23from geoplot.image_import import Image
24
25import geoplot.config as geoplot_config
26config = geoplot_config.getConfig()
27
28log = logging.getLogger(__name__)
29
30PLOT_SECTION = 'PlotProperties'
31POSITION_LOGO_IN_CENTER = True
32
33class PlotWriter(object):
34    """
35    A class that takes a plotarea after the plot has been done and writes it
36    to an image file on the local disk.
37    """
38
39    def __init__(self, format, outputCMYK):
40        """
41        Constructs a PlotWriter object
42
43        @keyword format:the format of the output file
44        @type format: a string , one of ('jpg','pdf','ps','png')
45        """
46
47        self.format = format
48        self.outputCMYK = outputCMYK
49
50    def writeFile(self, figure, filename, drawLogo, logoAx=None):
51        """
52        Writes the current plot to the specified filename
53
54        Because mapplotlib cant write to jpg directly first a temporary
55        png file is written then this file is converted into a jpg.
56
57        @param filename: the name of the file (including path) to write the plot to
58        @type filename: string
59        """
60
61        self.checkFileExtension(filename)
62
63        log.info("Writing File :" + filename)
64        log.debug("self.format = %s" % (self.format,))
65        if self.format in ['png', 'jpg']:
66            initialFormat = 'png'
67        elif self.format in ['ps', 'pdf']:
68            initialFormat = 'ps'
69        elif self.format in ['svg']:
70            initialFormat = self.format
71        else:
72            raise Exception("Unknown format %s" % (self.format,))
73           
74        if initialFormat != self.format:
75            initialFileName = self._getTempFilename(filename, initialFormat)
76        else:
77            initialFileName = filename
78
79        log.debug("initialFormat = %s" % (initialFormat,))
80
81
82        if drawLogo and initialFormat == 'png':
83                self._addLogo(figure, logoAx)
84
85        self._printFigure(initialFileName, figure, initialFormat)
86       
87        #convert to cmyk (if postscript)
88        if self.outputCMYK and initialFormat == 'ps':
89            pass
90            #self._convertEPSToCMYK(initialFileName)
91       
92        # add the logo
93        if drawLogo and initialFormat == 'ps':
94                if self.outputCMYK:
95                    self._addLogoToPlot(initialFileName, version='CMYK')
96                else:
97                    self._addLogoToPlot(initialFileName, version='RGB')               
98
99       
100        if self.format == 'pdf':
101            pass
102            #convert the .ps to a .pdf
103            convert.epsToPdf(initialFileName, outputFile=filename)
104            os.remove(initialFileName) # remove the old ps file
105                   
106        elif self.format == 'jpg':
107            convert.pngToJpg(initialFileName, filename)
108            os.remove(initialFileName)           
109 
110
111
112    def checkFileExtension(self, filename):
113        """
114        Checks the extenstion of the filename matches the self.Format value
115
116        @param filename:the name of the file to check the format of
117        @type filename:string
118        """
119
120        froot, ext = os.path.splitext(filename)
121        if ext[1:] != self.format :
122            raise Exception("File extension [%s] must match format [%s]!" \
123                             % (ext[1:], self.format))
124
125
126    def _addLogo(self, figure, logoAxes):
127        logo = Image.open(config[PLOT_SECTION]['logoPath'])
128        logo = logo.transpose(Image.FLIP_TOP_BOTTOM)
129        logoAxes.imshow(logo)
130
131    def _addBitmapLogo(self, figure, filename):
132        """
133        Adds a bitmap logo to a .png file. The logo is added in the logoRegion, read from config.ini
134
135        if POSITION_LOGO_IN_CENTER is True then the logo will be centered in the region, otherwise it
136        will be drawn in the top left corner. The figure is needed to caculate the absolute size of the
137        resulting image.
138
139        @param figure: the figure representing the plot
140        @type  figure: a matplotlib.figure instance
141        @param filename: the name of the file to join the logo to
142        @type  filename: string
143        """
144        logoRegion = config['PlotRegions']['logoRegion']
145
146        size = figure.get_size_inches() # get the size in inches
147        size = (size[0] * figure.get_dpi(), size[1] * figure.get_dpi()) #inches * dpi = pixels
148        pxLeft = size[0] * logoRegion[0]
149        # need to transform as logoRegion[1] is distance from bottom not top
150        pxDown = size[1] * (1 - logoRegion[1] - logoRegion[3])
151        maxWidth = size[0] * logoRegion[2]
152        maxHeight = size[1] * logoRegion[3]
153
154        merge_bitmap_logo.stampBitmapLogo(filename, pxLeft, pxDown, maxWidth, maxHeight,
155                                          centerImage=POSITION_LOGO_IN_CENTER,
156                                          printMessages=False)
157
158    def _getTempFilename(self, filename, extension):
159        """
160        Writes the output from a plotArea object to a temporary image file.
161
162        @param  plotArea: the plot area object used to generate the image
163        @type   plotArea: a PlotArea object
164        @param  filename: the filename for the final output file, the name of the
165            temporary file will be based on this name.
166        @type   filename: string
167        @param extension: The image format of the tempoarary file (note this may not
168            be the same as the final output image)
169        @type  extension: string, one of ('jpg', 'pdf,' 'ps', 'png')
170        @return         : the filename of the temporary file that was written
171        @rtype          : string
172        """
173
174        froot, ext = os.path.splitext(filename)
175        tempFileName = froot + "_tmp" + "." + extension
176#        log.debug("temp file name:" + tempFileName)
177        return tempFileName
178
179
180    def _addLogoToPlot(self, filename, version='RGB'):
181
182        if version == 'RGB':
183            logoPath = config[PLOT_SECTION]['EPSLogoPathRGB']
184#            logoFilename = pkg_resources.resource_filename('geoplot',
185#                            config[PLOT_SECTION]['EPSLogoPathRGB'])
186        elif version == 'CMYK':
187            logoPath = config[PLOT_SECTION]['EPSLogoPathCMYK']
188#            logoFilename = pkg_resources.resource_filename('geoplot',
189#                            config[PLOT_SECTION]['EPSLogoPathCMYK'])
190        else:
191            raise Exception("Unknown logo version :" + str(version))
192
193#        logoFilename = resources.getPath(logoPath)
194        logoRegion = config['PlotRegions']['logoRegion']
195
196        log.debug("logoPath = %s" % (logoPath,))
197
198        froot, ext = os.path.splitext(filename)
199
200        outputFile = froot + '_with_logo' + ext
201
202        #join the temporary file with the logo postscript file to produce the ouput file
203        merge_eps_logo.addLogoToFile(filename, outputFile, logoPath, logoRegion)
204
205        log.debug("Removing the old file %s" % (filename, ))
206       
207        #remove the old file
208        os.remove(filename)
209
210        log.debug("Renaming %s to %s" % (outputFile, filename,))
211        #rename the new file to the old one
212        os.rename(outputFile, filename)
213
214    def _convertEPSToCMYK(self, filename):
215
216        froot, ext = os.path.splitext(filename)
217        outputFile = froot + '_cmyk' + ext
218
219        cmykify_ps.cmykifyPostscript(filename, outputFile)
220
221        #remove the old file
222        os.remove(filename)
223
224        #rename the new file to the old one
225        os.rename(outputFile, filename)
226
227    def printFigureToBuffer(self, figure):
228        """
229        Plots the figure directly to StringIO buffer
230        """
231       
232        buffer = StringIO.StringIO()
233        self._printFigure(buffer, figure)
234        buffer.seek(0)
235       
236        return buffer     
237
238    def _printFigure(self, filename, figure, format=None):
239        """
240        Instantiate a canvas class and call its print_figure method.
241
242        This is a convenience function that hides a little object assembly.
243
244        @param filename: The output filename
245            (first argument passed to canvas.print_figure())
246        @param CanvasClass: A backend-specific subclass of FigureCanvasBase
247        @param kwargs: Arguments passed to canvas.print_figure()
248
249        """
250
251        if format == None:
252            format = self.format
253       
254        if format == 'ps':
255            CanvasClass=FigureCanvasPS
256        elif format == 'png':
257            CanvasClass=FigureCanvasAgg
258        elif format == 'pdf':
259            CanvasClass=FigureCanvasPdf
260        elif format == 'svg':
261            CanvasClass = FigureCanvasSVG
262        else:
263            raise Exception("Unknown format to write to , " + self.format)
264
265        canvas = CanvasClass(figure)
266
267        return canvas.print_figure(filename, 
268                                   dpi=figure.get_dpi(),
269                                   facecolor=figure.get_facecolor(), 
270                                   edgecolor=figure.get_edgecolor())
271   
272   
273   
Note: See TracBrowser for help on using the repository browser.