Re: [Matplotlib-users] Basemap white space
2010/4/12 Filipe Pires Alvarenga Fernandes ocef...@gmail.com: Thanks for point TKinter to me. However, I'm stuck again. I've tried two approaches, one is following what you suggested: Tkinter import Tkinter as tk root = tk.Tk() from PIL import Image, ImageTk image = ImageTk.PhotoImage(Image.open('map.png')) # load saved image #image = ImageTk.PhotoImage(im) # load image from StringIO tk.Label(root, image=image).pack() The other is to convert the PIL image to array and show with imshow() PIL to array from matplotlib.image import pil_to_array rgba = pil_to_array(Image.open('map.png')) # load saved image #rgba = pil_to_array(im) # load image from StringIO rgba = rgba.astype(np.float32)/255. imshow(rgba) Both work fine for a saved image. However, they return strange errors when I tried to apply them to the image from StringIO, or even for a saved image in the same script used to generate them. I guess that something I import from matplotlib is causing a conflict here. Here are the error messages: Tkinter _tkinter.TclError: image pyimage9 doesn't exist PIL to array terminate called after throwing an instance of 'char const*' Hi, with the Tkinter PhotoImage, I think it's intended for use with Tkinter.Canvas, and not compatible with Label. For what I know, it works fine for me with Canvas (Windows). I guess what you end up with is not a real PhotoImage but something faky. Now, I cannot execute your script and dive in myself, because I switched to another laptop, where I have to compile everything ... So in some days, I will know more. With the pil_to_image issue, I really have no idea. It's really quite strange, isn't it? I mean, it should return a newly created numpy.ndarray, and shouldn't borrow any memory with the PIL Image? I really don't know at the moment, I'm sorry. For the Tkinter issue, from your script it seems that you simply want to display it, so give the Canvas a try. I used it in http://github.com/friedrichromstedt/diagram_cl/blob/master/panels/tk/diagram.py , start with update() and __init__(). hth for now, Friedrich -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Re: [Matplotlib-users] Basemap white space
Thanks for point TKinter to me. However, I'm stuck again. I've tried two approaches, one is following what you suggested: Tkinter import Tkinter as tk root = tk.Tk() from PIL import Image, ImageTk image = ImageTk.PhotoImage(Image.open('map.png')) # load saved image #image = ImageTk.PhotoImage(im) # load image from StringIO tk.Label(root, image=image).pack() The other is to convert the PIL image to array and show with imshow() PIL to array from matplotlib.image import pil_to_array rgba = pil_to_array(Image.open('map.png')) # load saved image #rgba = pil_to_array(im) # load image from StringIO rgba = rgba.astype(np.float32)/255. imshow(rgba) Both work fine for a saved image. However, they return strange errors when I tried to apply them to the image from StringIO, or even for a saved image in the same script used to generate them. I guess that something I import from matplotlib is causing a conflict here. Here are the error messages: Tkinter _tkinter.TclError: image pyimage9 doesn't exist PIL to array terminate called after throwing an instance of 'char const*' I'm attaching the script. Aborted # -*- coding: utf-8 -*- import matplotlib import numpy as np import matplotlib.pyplot as plt import StringIO, Image #matplotlib.use('Agg') matplotlib.use('TkAgg') from mpl_toolkits.basemap import Basemap lonmin = -87.5 lonmax = -22.5 latmin = -59.5 latmax = 14.5 m = Basemap( projection = 'merc', llcrnrlat = latmin, urcrnrlat = latmax, llcrnrlon = lonmin, urcrnrlon = lonmax, resolution = 'c' ) fig = plt.figure() ax = fig.add_subplot(111) m.ax = ax m.bluemarble() trim image imgdata = StringIO.StringIO() fig.savefig(imgdata, dpi=150, format='png') imgdata.seek(0) # rewind the data im = Image.open(imgdata) def trim(im, border): from PIL import ImageChops bg = Image.new(im.mode, im.size, border) diff = ImageChops.difference(im, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) else: # found no content raise ValueError(cannot trim; image was empty) im = trim(im,'white') PIL to array #from matplotlib.image import pil_to_array #rgba = pil_to_array(Image.open('mapa.png')) ##rgba = pil_to_array(im) #rgba = rgba.astype(np.float32)/255. #imshow(rgba) #show() error when used in the script: terminate called after throwing an instance of 'char const*' Aborted Tkinter import Tkinter as tk root = tk.Tk() from PIL import Image, ImageTk image = ImageTk.PhotoImage(Image.open('mapa.png')) #image = ImageTk.PhotoImage(im) tk.Label(root, image=image).pack() error when used in the script: _tkinter.TclError: image pyimage9 doesn't exist -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Re: [Matplotlib-users] Basemap white space
Sorry, my bad. I always hit reply without checking... it is not the first time did that, Here is the solution for the list sake: trim image import StringIO, Image imgdata = StringIO.StringIO() fig.savefig(imgdata, dpi=300, format='png') imgdata.seek(0) im = Image.open(imgdata) def trim(im, border): from PIL import ImageChops bg = Image.new(im.mode, im.size, border) diff = ImageChops.difference(im, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) else: # found no content raise ValueError(cannot trim; image was empty) im = trim(im,'white') im.show() The StringIO trick is a copy-and-paste from the matplotlib faq. And the trim function I got from here: http://mail.python.org/pipermail/image-sig/2008-July/005092.html Thanks for the discussion, I learned a lot abouth the Agg backend. BTW: What I meant by limitation is the fact that Agg has no GUI like the nice QT window I was using before. The users of this script have no experience with scripting languages and enjoyed choosing the format and filename using a GUI interface. In addition, PIL's show() use an external linux program xv. In the end I wanted to eliminate one external linux program (Imagemagik convert) but ended up with another one... Best, Filipe On 04/06/2010 05:01 PM, Friedrich Romstedt wrote: 2010/4/5 Filipe Fernandes ocef...@gmail.com: Thanks a lot. In the end the StringIO-solution worked fine. The only limitation is that this works only for the Agg backend. [...] I'm happy to hear this. As far as I know, using the Agg backend is not a limitation, because it provides fully anti-aliased output. Besides being available on all platforms (?). Let me make a small hint: The matplotlib-users mailing list is configured that by default replies go to the sender only, not to matplotlib-users, so maybe you want to let the list know about your solution? Anyway I'm happy for your Thanks, so thanks too, Friedrich -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Re: [Matplotlib-users] Basemap white space
2010/4/8 Filipe Fernandes ocef...@gmail.com: BTW: What I meant by limitation is the fact that Agg has no GUI like the nice QT window I was using before. The users of this script have no experience with scripting languages and enjoyed choosing the format and filename using a GUI interface. I'm quite convinced that you can have the figure in multiple Canvases at the same time. Or create the FigureCanvasAgg or the call to .savefig() only on save time. In every widget framework, it should be fairly easy to build a custom gui having a customised Save ... button, I guess? In addition, PIL's show() use an external linux program xv. In the end I wanted to eliminate one external linux program (Imagemagik convert) but ended up with another one... When using Tkinter, you can use ImageTk: im = {some PIL Image} # Some image to be shown canvas = {some Tkinter.Canvas} # For drawing graphics viewport = ImageTk.PhotoImage(im) canvas.create_image((0, 0), image = viewport, anchor = 'nw') # Put the image on the Tkinter.Canvas. Modify according your needs. # Now the PIL Image has been rendered on the canvas. # Maybe do canvas.update() or call the master's .update(), # or call some .mainloop() entry function. For instance, use the # Tkinter.Tk instance's method .mainloop(). When renewing the graphics, don't forget to canvas.delete({tag}) using the {tag} returned by canvas.create_image(), otherwise you will probably loose perfomance. There are examples on matplotlib.sourceforge.net how to use Tkinter with matplotlib. hth, Friedrich -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Re: [Matplotlib-users] Basemap white space
Thanks Friedrich, However, my knowledge of python is very limited, even though I think I understood what you suggested I do not know how to get the shape (of the figure?) for this part: fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) error is: Traceback (most recent call last): File blueearth-map.py, line 108, in module fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) TypeError: 'function' object is unsubscriptable It seems that it ended up calling a function shape instead of a variable shape. I'm sending attached the script if you are interested in looking at it. Thanks again. Filipe. On Sun, Mar 28, 2010 at 3:35 PM, Friedrich Romstedt friedrichromst...@gmail.com wrote: 2010/3/28 Filipe Pires Alvarenga Fernandes ocef...@gmail.com: Hello list I've trying for a while a python only solution to remove white spaces that Basemap generate to keep the aspect ratio. I found these two threads that explain the issue better: I think maybe you can make use of the Agg Backend to achieve a Python-only solution to obtain a PIL Image from a figure without bypassing over the HDD: Furthemore, if this doesn't work, maybe you can use a StringIO as file, then seek() the StringIO and reread with PIL from the file-like StringIO, or something like that? # # Render the Figure to a PIL Image ... # # Prepare figure to be of pixel extent *shape* ... dpi = figure.dpi figure.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) # Create the rendering Canvas ... # # We also convert the picture to an RGB string. canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(figure) canvas.draw() image_string = canvas.tostring_rgb() # Create a PIL Image from RGB string ... image = Image.fromstring(RGB, shape, image_string) # Now do whatever you want with the Image. Friedrich #!/usr/bin/env python # -*- coding: utf-8 -*- # blueearth-map.py # update brazillian states database, this one is too old import sys import os import basemap and pylab try: from mpl_toolkits.basemap import Basemap except ImportError: print Basemap not found. try: import matplotlib matplotlib.use('Agg') from pylab import * except ImportError: print Matplotlib not found. # parse args (ugly!) if len(sys.argv) == 6: lonmin = float(sys.argv[2]) lonmax = float(sys.argv[3]) latmin = float(sys.argv[4]) latmax = float(sys.argv[5]) lonlat = np.loadtxt(sys.argv[1]) lonpt = lonlat[:,0] latpt = lonlat[:,1] elif len(sys.argv) == 5: lonmin = float(sys.argv[1]) lonmax = float(sys.argv[2]) latmin = float(sys.argv[3]) latmax = float(sys.argv[4]) else: sys.exit(\nMust provide at least 4 arguments!!! A 2 column file with longitue and latitute of the points (optional) and the lon lat limits for the map. e.g.: blueearth-map lonlat.dat -87.5 -22.5 -59.5 14.5\n) m = Basemap( projection = 'merc', llcrnrlat = latmin, urcrnrlat = latmax, llcrnrlon = lonmin, urcrnrlon = lonmax, resolution = 'c' ) # crude coastlines resolution create figure and associate axes with Basemap fig = figure() ax = fig.add_subplot(111) m.ax = ax m.drawstates() m.drawcountries(linewidth=1.2) m.bluemarble() add a non bluearth alternative #m.drawcoastlines() #m.drawlsmask(land_color='grey',ocean_color='None', lakes=True) plot points try: lonpt xc,yc = m(lonpt,latpt) #m.plot(xc,yc,'ro', alpha = 0.5, markersize=2) m.plot(xc,yc,'ro', markersize=2) if lonpt.min() lonmin: print \n some points are out of bounds (min longitude) \n if lonpt.max() lonmax: print \n some points are out of bounds (max longitude) \n if latpt.min() latmin: print \n some points are out of bounds (min latitude) \n if latpt.max() latmax: print \n some points are out of bounds (max latitude) \n except: print \n No lon/lat file to plot \n savefig('blueearthmap.png', dpi=300) trim method 1 from PIL import Image im = Image.open(blueearthmap.png) def trim(im, border): from PIL import ImageChops bg = Image.new(im.mode, im.size, border) diff = ImageChops.difference(im, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) else: # found no content raise ValueError(cannot trim; image was empty) im2=trim(im,'white') show() # allow user to save to a different filename and format, but it won't be cropped! im2.save('blueearthmap.png',format='png') #- trim method 2 #os.system('convert -trim blueearthmap.png blueearthmap.png') #show() #- trim method 3 #Render the Figure to a PIL Image # Prepare figure to be of pixel extent *shape* dpi = fig.dpi fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) # Create the rendering Canvas. We also convert the picture to an RGB
Re: [Matplotlib-users] Basemap white space
2010/3/30 Filipe Pires Alvarenga Fernandes ocef...@gmail.com: However, my knowledge of python is very limited, even though I think I understood what you suggested I do not know how to get the shape (of the figure?) for this part: fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) error is: Traceback (most recent call last): File blueearth-map.py, line 108, in module fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) TypeError: 'function' object is unsubscriptable It seems that it ended up calling a function shape instead of a variable shape. You're completely right, I assumed that you fill in some 2-element vector in *shape*, it was intended as an /argument/. The function attemted to be indexed is imported from numpy by matplotlib.pyplot: There is a code line from numpy import *. So, simply put some line somewhere like: shape = [500, 500] . You have to set or have to calculate the figure's shape in pixels somewhere, because you need it to convert the rgb string back into a PIL image. It's not that nice, I know, for your problem? Friedrich -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Re: [Matplotlib-users] Basemap white space
2010/3/28 Filipe Pires Alvarenga Fernandes ocef...@gmail.com: Hello list I've trying for a while a python only solution to remove white spaces that Basemap generate to keep the aspect ratio. I found these two threads that explain the issue better: I think maybe you can make use of the Agg Backend to achieve a Python-only solution to obtain a PIL Image from a figure without bypassing over the HDD: Furthemore, if this doesn't work, maybe you can use a StringIO as file, then seek() the StringIO and reread with PIL from the file-like StringIO, or something like that? # # Render the Figure to a PIL Image ... # # Prepare figure to be of pixel extent *shape* ... dpi = figure.dpi figure.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi) # Create the rendering Canvas ... # # We also convert the picture to an RGB string. canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(figure) canvas.draw() image_string = canvas.tostring_rgb() # Create a PIL Image from RGB string ... image = Image.fromstring(RGB, shape, image_string) # Now do whatever you want with the Image. Friedrich -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev ___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users
[Matplotlib-users] Basemap white space
Hello list I've trying for a while a python only solution to remove white spaces that Basemap generate to keep the aspect ratio. I found these two threads that explain the issue better: http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg14430.html http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg14262.html In the past I relied on ImageMagick's convert command with the -trim white option for the job. However, just recently I came across with this other list and a PIL solution: http://mail.python.org/pipermail/image-sig/2008-July/005092.html Here is how I'm doing: savefig('mapa.png', dpi=300) from PIL import Image im = Image.open(mapa.png) def trim(im, border): from PIL import ImageChops bg = Image.new(im.mode, im.size, border) diff = ImageChops.difference(im, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) else: # found no content raise ValueError(cannot trim; image was empty) im2=trim(im,'white') im2.show() This works and the aspect ratio is preserved, but as you can see, it is not a very smart implementation. I save and then reload it again... any suggestions to improve this are welcome. Also, I have not tried this on figures with labels and annotations. Thanks for any input. * Filipe Pires Alvarenga Fernandes University of Massachusetts Dartmouth 200 Mill Road - Fairhaven, MA Tel: (508) 910-6381 Email: falvarengafernan...@umassd.edu ocef...@yahoo.com.br ocef...@gmail.com http://ocefpaf.tiddlyspot.com/ * -- Download Intel#174; Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev___ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users