Dear ALL,

Enclosed is an sample application I put together (partially using
wxGlade) that is a first attempt at providing a working example of a
GUI frontend with wxPython and Matplotlib/Basemap.

The application consists of two panels, separated by a splitter. The
left panel has a notebook with two pages, which have, respectively, a
listbox and a read-only multine text control. The right panel has a
figure object created at runtime, to which a basemap object is
attached.

The application reads comma-delimited data files of geographic
coordinates (in decimal format) selected by the user, appending them
to the listbox. When a file is selected on the list, the points are
plotted on the basemap displayed in the panel to the right.

Well, at least it should! It turns out that the map is correctly
displayed, but it then fills almost the whole parent window,
overlapping the left panel where the notebook with the listbox and the
text control should appear! This illustrates one of the worst (in my
opinion) things about wxPython, that is the handling of "sizers" to
correctly place the widgets on an application window.

I have commented the parts of the code where the map is created, so
that one can see clearly what happens with and without the map plot.
Just uncomment these parts to see the map displayed (with a toolbar
properly placed, at least under Linux).

If someone can help me with this, this sample application could
provide a useful skeleton to build programs which integrate
Matplotlib/Basemap with wxPython (incidentally, this sample
application bears a very slight resemblance to Google Earth... :)). I
am, of course, donating it to the community.

Thanks in advance!

With best regards,

-- 
Dr. Mauro J. Cavalcanti
Ecoinformatics Studio
P.O. Box 46521, CEP 20551-970
Rio de Janeiro, RJ, BRASIL
E-mail: [EMAIL PROTECTED]
Web: http://studio.infobio.net
Linux Registered User #473524 * Ubuntu User #22717
"Life is complex. It consists of real and imaginary parts."
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Thu Nov 20 17:06:15 2008

# This sample program shows how to read
# geographic coordinates stored in comma-delimited files
# and plot them in a Matplotlib Basemap class object.
# Data files should be formatted as below:

# cities,latitude,longitude
# "Boulder, CO",40.02,-105.16
# "San Diego, CA",32.73,-117.16
# "Washington, DC",38.55,-77.00
# "Whitefish, MT",48.25,-114.21
# "Belize City, Belize",17.29,-88.10

import os
import csv
import wx

from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
from mpl_toolkits.basemap import Basemap

fields = {'cities':0,
		'latitude':1,
		'longitude':2}

# begin wxGlade: extracode
# end wxGlade

class TMainForm(wx.Frame):
	def __init__(self, *args, **kwds):
		# begin wxGlade: TMainForm.__init__
		kwds["style"] = wx.DEFAULT_FRAME_STYLE
		wx.Frame.__init__(self, *args, **kwds)
		self.Splitter = wx.SplitterWindow(self, -1, style=wx.SP_3D|wx.SP_BORDER)
		self.PlotPanel = wx.Panel(self.Splitter, -1)
		self.FilePanel = wx.Panel(self.Splitter, -1)
		self.Notebook = wx.Notebook(self.FilePanel, -1, style=0)
		self.ReportPage = wx.Panel(self.Notebook, -1)
		self.FilePage = wx.Panel(self.Notebook, -1)
		
		# Menu Bar
		self.MainMenu = wx.MenuBar()
		self.FileMenu = wx.Menu()
		self.FileOpenItem = wx.MenuItem(self.FileMenu, 102, "&Open...\tCtrl+O", "Open an existing file", wx.ITEM_NORMAL)
		self.FileMenu.AppendItem(self.FileOpenItem)
		self.FileMenu.AppendSeparator()
		self.FileQuitItem = wx.MenuItem(self.FileMenu, wx.ID_EXIT, "&Quit\tCtrl+Q", "Quit the program", wx.ITEM_NORMAL)
		self.FileMenu.AppendItem(self.FileQuitItem)
		self.MainMenu.Append(self.FileMenu, "&File")
		self.HelpMenu = wx.Menu()
		self.HelpAboutItem = wx.MenuItem(self.HelpMenu, 201, "&About...", "Display general information about the program", wx.ITEM_NORMAL)
		self.HelpMenu.AppendItem(self.HelpAboutItem)
		self.MainMenu.Append(self.HelpMenu, "&Help")
		self.SetMenuBar(self.MainMenu)
		# Menu Bar end
		self.StatusBar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
		self.FileList = wx.ListBox(self.FilePage, -1, choices=[])
		self.ReportText = wx.TextCtrl(self.ReportPage, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY)

		self.__set_properties()
		self.__do_layout()

		self.Bind(wx.EVT_MENU, self.OnFileOpen, self.FileOpenItem)
		self.Bind(wx.EVT_MENU, self.OnFileQuit, self.FileQuitItem)
		self.Bind(wx.EVT_MENU, self.OnHelpAbout, self.HelpAboutItem)
		self.Bind(wx.EVT_LISTBOX, self.OnSelect, self.FileList)
		# end wxGlade

	def __set_properties(self):
		# begin wxGlade: TMainForm.__set_properties
		self.SetTitle("Gaia")
		self.SetSize((800, 600))
		self.SetFocus()
		self.StatusBar.SetStatusWidths([-1, -1])
		# statusbar fields
		StatusBar_fields = ["Ready", ""]
		for i in range(len(StatusBar_fields)):
		    self.StatusBar.SetStatusText(StatusBar_fields[i], i)
		self.FileList.SetMinSize((680, 545))
		self.ReportText.SetMinSize((680, 545))
		# end wxGlade
		
		# ----- UNCOMMENT THE LINES BELOW TO DRAW THE MAP
		#self.figure = Figure(figsize=(10,5))
		#self.canvas = FigureCanvas(self, -1, self.figure)
		#self.ax = self.figure.add_axes([0,0,1,1])
		#self.SetColor( (255,255,255) )

	def __do_layout(self):
		# begin wxGlade: TMainForm.__do_layout
		sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
		sizer_7 = wx.BoxSizer(wx.VERTICAL)
		sizer_6 = wx.BoxSizer(wx.VERTICAL)
		sizer_8 = wx.BoxSizer(wx.HORIZONTAL)
		sizer_9 = wx.BoxSizer(wx.HORIZONTAL)
		sizer_9.Add(self.FileList, 0, wx.EXPAND, 0)
		self.FilePage.SetSizer(sizer_9)
		sizer_8.Add(self.ReportText, 0, wx.EXPAND, 0)
		self.ReportPage.SetSizer(sizer_8)
		self.Notebook.AddPage(self.FilePage, "Files")
		self.Notebook.AddPage(self.ReportPage, "Report")
		sizer_6.Add(self.Notebook, 1, wx.EXPAND, 0)
		self.FilePanel.SetSizer(sizer_6)
		self.PlotPanel.SetSizer(sizer_7)
		self.Splitter.SplitVertically(self.FilePanel, self.PlotPanel, 240)
		sizer_5.Add(self.Splitter, 1, wx.EXPAND|wx.FIXED_MINSIZE, 0)
		self.SetSizer(sizer_5)
		self.Layout()
		self.Centre()
		# end wxGlade
		
		self.Splitter.SetMinimumPaneSize(200)
		
		# ----- UNCOMMENT THE LINES BELOW TO SHOW THE MAP WITH THE TOOLBARS
		#sizer_7.Add(self.canvas, 1, wx.EXPAND|wx.RIGHT, 0)
		#self.SetSizer(sizer_7)
		#self.toolbar = NavigationToolbar2Wx(self.canvas)
		#self.toolbar.Realize()
		#tw, th = self.toolbar.GetSizeTuple()
		#fw, fh = self.canvas.GetSizeTuple()
		#self.toolbar.SetSize(wx.Size(fw, th))
		#sizer_7.Add(self.toolbar, 0)
		#self.toolbar.update()
		#self.PlotMap()

	def OnFileOpen(self, event): # wxGlade: TMainForm.<event_handler>
		dlg = wx.FileDialog(self, "Open", os.getcwd(), "", "Comma-Separated Values files (*.csv)|*.csv", wx.OPEN)
		if dlg.ShowModal() == wx.ID_OK:
			fileName = dlg.GetFilename()
			dirName = dlg.GetDirectory()
			self.SetTitle("Gaia" + " - [" + fileName + "]")
			self.FileList.Append(fileName)
		dlg.Destroy()

	def OnFileQuit(self, event): # wxGlade: TMainForm.<event_handler>
		self.Close()
		
	def OnHelpAbout(self, event): # wxGlade: TMainForm.<event_handler>
		dlg = wx.MessageDialog(self, "This sample program shows how to read\n"
				"geographic coordinates stored in comma-delimited files\n"
				"and plot them in a Matplotlib Basemap class object,",
				"About Gaia", wx.OK|wx.ICON_INFORMATION)
		dlg.ShowModal()
		dlg.Destroy()

	def OnSelect(self, event): # wxGlade: TMainForm.<event_handler>
		dataFile = open(self.FileList.GetStringSelection(), "r")
		try:
			reader = csv.reader(dataFile, delimiter = ',', quoting=csv.QUOTE_ALL)
			longs = []
			lats = []
			reader.next() # Skip header line
			i = 0
			for row in reader:
				locality = row[fields['cities']]
				longitude = float(row[fields['longitude']])
				latitude  = float(row[fields['latitude']])
				longs.append(longitude)
				lats.append(latitude)
				i = i + 1
		finally:
			dataFile.close()
		self.StatusBar.SetStatusText(str(i) + " record(s) processed", 1)
		
		# ----- UNCOMMENT THE LINES BELOW TO PLOT THE POINTS ON THE MAP
		#x,y = map(longs,lats)
		#self.map.plot(x,y,'ro')
		
	def SetColor(self, rgbtuple=None):
		"""Set figure and canvas colours to be the same."""
		if rgbtuple is None:
			rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
		clr = [c/255. for c in rgbtuple]
		self.figure.set_facecolor(clr)
		self.figure.set_edgecolor(clr)
		self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
	
	def PlotMap(self):
		"""Plot basemap."""
		self.map = Basemap(ax=self.ax)
		self.map.drawcoastlines()
		self.map.drawcountries()
		self.map.drawmapboundary()
		self.map.fillcontinents(color='lime', lake_color='aqua')
		self.map.drawmapboundary(fill_color='aqua')
		self.figure.canvas.draw()
	
# end of class TMainForm


class TApplication(wx.App):
	def OnInit(self):
		wx.InitAllImageHandlers()
		MainForm = TMainForm(None, -1, "")
		self.SetTopWindow(MainForm)
		MainForm.Show()
		return 1

# end of class TApplication

if __name__ == "__main__":
	Application = TApplication(0)
	Application.MainLoop()
cities,latitude,longitude
"Boulder, CO",40.02,-105.16
"San Diego, CA",32.73,-117.16
"Washington, DC",38.55,-77.00
"Whitefish, MT",48.25,-114.21
"Belize City, Belize",17.29,-88.10
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to