Dear list fellows,

I am writing an app focused in structural geology, using wxpython and
matplotlib. To be quite honest, I'm not sure if this question should
go here or in the wxpython list (so to avoid cross-posting, I'll try
here first).

The app uses matplotlib to plot data from orientation data as points
or lines (circles) in a stereonet (a circular plot using Lambert's
equal-area projection). So far, it is in it very early stages, I have
two panels (one for data display and the other for the plot itself), I
can open CSV files and I can even plot them! I must say I am surprised
to have achieved all this in about two week of work, with nearly no
experience in python (just some small scripts), and no experience at
all with wxpython/matplotilib.

My problem now is that I can plot the data in three different ways,
and the plots are overlaid on to the last one (I still don't know if
this kind of behaviour should be removed or not), but the thing is,
that depending on the order in which I plot the data, the graphic
changes its position in the window!

Just a brief explanation of the interface first: The option are in the
toolbar, the first button opens a data file, the second one creates
the stereonet, the third and fourfh plot data as points and the fifth
plot as lines.

Try this with the attached code: open the data (1st btn), create the
plot (2nd btn), then plot the data as points (3rd and 4th btns) and
then as lines (5th btn). OK, now clean the plot (2nd btn) and plot
first as lines (5th btn) and then as points (3rd or 4th btns), and you
will see that the plot moves to the left! At least for me (Ubuntu
Linux).

If you could give me any advice on why this is happening (and how to
prevent it), I will be very thankful.

PS. I know my code is not as good as it could. I'm new to
OO-programing, so I still need to understand properly how to work with
classes, etc, and I promisse I will improve the code in the near
future! (any advices here are also welcome!)

Many thanks for your help

Carlos




-- 
Carlos Henrique Grohmann - Geologist D.Sc.
a.k.a. Guano - Linux User #89721
ResearcherID: A-9030-2008
carlos dot grohmann at gmail dot com
http://www.igc.usp.br/pessoais/guano/
_________________
"Good morning, doctors. I have taken the liberty of removing Windows
95 from my hard drive."
--The winning entry in a "What were HAL's first words" contest judged
by 2001: A SPACE ODYSSEY creator Arthur C. Clarke

Can’t stop the signal.
145 23
136 40
140 47
155 15
160 63
150 65
148 48
160 55
172 34
180 10
160 15
160 50
170 15
160 35
120 89
150 12
155 35
167 43
156 32
170 42
200 33
120 30
160 50
348 69
330 50
187 66
180 78
180 80
160 71
156 56
210 75
180 80
#!/usr/bin/env python

"""
PyStereo - Open Source Stereonet App (someday...)

"""

import os, sys, csv
import wx


import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
#from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
#from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar

from matplotlib.patches import Circle
from matplotlib.lines import Line2D
from matplotlib.text import Text


import numpy as np
#from pylab import *

ID_PLOT_NETT = wx.NewId()
ID_PLOT_LINE = wx.NewId()
ID_PLOT_POLE = wx.NewId()
ID_PLOT_CIRCLE = wx.NewId()



#get data from file and create lists with values and column names
def GetData( filename ):
	csvfile = open(filename, 'r' )
	sample = csvfile.read( 2048 )
	csvfile.seek( 0 )

	# Check for file format with sniffer.
	dialect = csv.Sniffer().sniff(sample)
	csvfile = csv.reader( csvfile, dialect )

	# Grab a sample and see if there is a header.
	if csv.Sniffer().has_header( sample ): #if there is a header
		colnames = csvfile.next() # label columns from first line
		datalist = list( csvfile ) # append data to a list
	else: #if there is NO header
		datalist = list( csvfile ) # append data to a list
		colnames = ['col_%i' % i for i in range(len(datalist[0]))] # label columns as col_1, col_2, etc
	return colnames, datalist

#class for the first page of the notebook
class DataPanel(wx.Panel): 
	def __init__(self, parent):
		wx.Panel.__init__(self, parent)

		box1 = wx.BoxSizer(wx.VERTICAL)
		st1 = wx.StaticText(self, -1, 'Data')
		box1.Add(st1, 0, wx.RIGHT, 8)
		box3 = wx.BoxSizer(wx.VERTICAL)
		self.control1 = wx.TextCtrl(self, -1, style=wx.TE_MULTILINE)
		box3.Add(self.control1, 1, wx.EXPAND|wx.ALL, 2)
		box1.Add(box3,1, wx.EXPAND)
		self.SetSizer(box1)

#class for the second page of the notebook
class PlotPanel(wx.Panel):
	def __init__(self, parent):
		wx.Panel.__init__(self, parent)

		box1 = wx.BoxSizer(wx.VERTICAL)
		st1 = wx.StaticText(self, -1, 'Plot')
		box1.Add(st1, 0, wx.RIGHT)
		box3 = wx.BoxSizer(wx.HORIZONTAL)

		self.figure = Figure(figsize=(6,6))#
		self.canvas = FigureCanvas(self, -1, self.figure)

		box3.Add(self.canvas, 4, wx.LEFT|wx.TOP|wx.EXPAND)
		box1.Add(box3,1, wx.EXPAND|wx.ALL, 2)
		self.SetSizer(box1)



class MyFrame(wx.Frame):
	def __init__(self, parent, ID, title, size):
		wx.Frame.__init__(self, parent, ID, title,(-1,-1),size)
		self.CreateStatusBar()

		self.dirname=os.getcwd() #not sure why we need this

#create the file menu
		filemenu=wx.Menu()
		filemenu.Append(wx.ID_OPEN, '&Open', 'Open data file')
		filemenu.Append(wx.ID_EXIT, 'E&xit', 'Exit the program')

#create the menubar for the frame and add the menu to it
		menuBar=wx.MenuBar()
		menuBar.Append(filemenu, '&File')
		self.SetMenuBar(menuBar)

#set up menu events
		wx.EVT_MENU(self, wx.ID_OPEN, self.OnOpenData)
		wx.EVT_MENU(self, wx.ID_EXIT, self.Exit)

		wx.EVT_MENU(self, ID_PLOT_NETT, self.PlotStereonett)

		wx.EVT_MENU(self, ID_PLOT_POLE, self.PlotPoles)
		wx.EVT_MENU(self, ID_PLOT_LINE, self.PlotLines)
		wx.EVT_MENU(self, ID_PLOT_CIRCLE, self.PlotCircles)


#create the toolbar for the frame
		toolbar = self.CreateToolBar()
		toolbar.SetToolBitmapSize((16,16))  # sets icon size
		openTool = toolbar.AddLabelTool(wx.ID_OPEN, 'Open', wx.Bitmap('images/silk/application.png'), wx.NullBitmap, wx.ITEM_NORMAL, "Open File", "")
        
		toolbar.AddSeparator()
		plotNetTool = toolbar.AddLabelTool(ID_PLOT_NETT, 'Plot', wx.Bitmap('images/silk/chart_line.png'), wx.NullBitmap, wx.ITEM_NORMAL, "Draw/clear the stereonet", "")

		toolbar.AddSeparator()

		plotPoleTool = toolbar.AddLabelTool(ID_PLOT_POLE, 'Plot', wx.Bitmap('images/silk/chart_line.png'), wx.NullBitmap, wx.ITEM_NORMAL, "Plot poles of planes", "")

		plotLineTool = toolbar.AddLabelTool(ID_PLOT_LINE, 'Plot', wx.Bitmap('images/silk/chart_line.png'), wx.NullBitmap, wx.ITEM_NORMAL, "Plot poles of lines or planes as lines", "")

		plotCircleTool = toolbar.AddLabelTool(ID_PLOT_CIRCLE, 'Plot', wx.Bitmap('images/silk/chart_line.png'), wx.NullBitmap, wx.ITEM_NORMAL, "Plot great circles of planes", "")

		toolbar.Realize()


# Here we split the frame in two

		box = wx.BoxSizer(wx.VERTICAL) # sizer
		splitter = wx.SplitterWindow(self, -1) 
		splitter.SetMinimumPaneSize(100) # cannot shrink panel to less than 100 px
		leftsizer = wx.BoxSizer(wx.VERTICAL) # box for left pabel
		self.left_panel = DataPanel(splitter) # left panel, where the datafile shows
		rightsizer = wx.BoxSizer(wx.HORIZONTAL) #box for right panel
		self.right_panel = PlotPanel(splitter) # right panel, where stats are shown
		splitter.SplitVertically(self.left_panel,self.right_panel,150) 
		box.Add(splitter,1, wx.EXPAND|wx.ALL, 5) # the panels are inside this sizer with 5px border
		self.SetSizer(box)


		self.Show(True)
		return

#Open the file 

	def OnOpenData(self, event):
		dlg=wx.FileDialog(self, 'Choose a file',
		self.dirname, '','TXT files (*.txt)|*.txt|CSV files (*.csv)|*.csv|All files(*.*)|*.*',wx.OPEN)
		if dlg.ShowModal() == wx.ID_OK:
			self.filename=dlg.GetFilename()
			self.dirname=dlg.GetDirectory()

            # Open the file, read the contents and set them into the text edit window
			filehandle=open(os.path.join(self.dirname, self.filename),'r')
			showdata = self.left_panel.control1 #the txtCtrl in DataPanel (left panel)
			showdata.SetValue(filehandle.read()) # show the data file
			filehandle.close()

			self.colnames, self.datalist = GetData(dlg.GetFilename()) # get values from file (colnames, datalist)


            # Report on name of latest file read
		self.SetTitle("PyStereo v0.001- Data: "+self.filename)

#		dlg.Destroy()

#plot main stereonett
	def PlotStereonett(self, event): 

		axes = self.right_panel.figure.add_axes([0.05, 0.05, 0.9, 0.9])
		axes.cla()
		axes.set_axis_off()
		axes.set_xlim(-1.05,1.05)
		axes.set_ylim(-1.05,1.05)
		axes.set_aspect(aspect='equal', adjustable=None, anchor='C')
		cir = Circle( (0,0), radius=1, edgecolor='black', facecolor='white')
		axes.add_patch(cir)
		x_cross = [0,1,0,-1,0]
		y_cross = [0,0,1,0,-1]
		axes.plot(x_cross,y_cross,'k+',markersize=6)
		axes.text(0,1.02,'N',family='sans-serif',size='small',horizontalalignment='center' )

		self.right_panel.canvas.draw()



#plot poles to planes in stereonet (radius = 1)
	def PlotPoles(self, event): 

		axes = self.right_panel.figure.add_axes([0.05, 0.05, 0.9, 0.9])

		azim=[int(az[0]) for az in self.datalist]
		dip=[int(dp[1]) for dp in self.datalist]

		azim_rad_pi = [np.radians(i) + np.pi for i in azim] #convert azimuth to radians and adds pi
		dip_rad_half = [np.radians(i)/2 for i in dip] #converts dip to radians and divide by 2

		rad_circ = [1 * np.sqrt(2) * np.sin(i) for i in dip_rad_half] # calculates radii on stereonett

		x_pole = []
		y_pole = []

		for i in range(len(azim)):
			x_pole.append(rad_circ[i] * np.sin(azim_rad_pi[i]))
			y_pole.append(rad_circ[i] * np.cos(azim_rad_pi[i]))



		axes.plot(x_pole,y_pole, 'o')
		self.right_panel.canvas.draw()

#plot poles of line or planes as lines in stereonet (radius = 1)
	def PlotLines(self, event):

		axes = self.right_panel.figure.add_axes([0.05, 0.05, 0.9, 0.9])

		azim=[int(az[0]) for az in self.datalist]
		dip=[int(dp[1]) for dp in self.datalist]

		azim_rad = [np.radians(i) for i in azim] #convert azimuth to radians
		dip_rad_half = [np.radians(i)/2 for i in dip] #converts dip to radians and divide by 2

		rad_circ = [1 * np.sqrt(2) * np.sin(np.pi/4 - i) for i in dip_rad_half] # calculates radii on stereonett

		x_line = []
		y_line = []

		for i in range(len(azim)):
			x_line.append(rad_circ[i] * np.sin(azim_rad[i]))
			y_line.append(rad_circ[i] * np.cos(azim_rad[i]))



		axes.plot(x_line,y_line, 'o')
		self.right_panel.canvas.draw()



#plot great circles of planes in stereonet (radius = 1)
	def PlotCircles(self, event):

		axes = self.right_panel.figure.add_axes([0.05, 0.05, 0.9, 0.9])

		azim=[int(az[0]) for az in self.datalist]
		dip=[int(dp[1]) for dp in self.datalist]

		for i in range(len(azim)):

			x = []
			y = []

			x.append(0 - 1 * np.sin(np.radians(azim[i]) - np.pi / 2))
			y.append(0 - 1 * np.cos(np.radians(azim[i]) - np.pi / 2))

			for j in np.arange(0,3.15,np.pi/100):
				gap = np.arctan(np.tan(np.radians(dip[i])) * np.sin(j))
				rad_circ = 1 * np.sqrt(2) * np.sin((np.pi / 2 - gap) / 2 )
				x_gc = -rad_circ * np.sin(np.radians(azim[i]) - j - np.pi / 2 )
				y_gc = -rad_circ * np.cos(np.radians(azim[i]) - j - np.pi / 2 )
	
				x.append(x_gc)
				y.append(y_gc)

			g_circle = Line2D(x,y)

			axes.add_line(g_circle)

		self.right_panel.canvas.draw()



	def Exit(self, event):
		if getattr(self, 'file',0):
			self.file.close()
		self.Close(True)

class pystereo(wx.App):
	def OnInit(self):
		self.frame=MyFrame(None, -1, 'PyStereo', size=(900,600))
		self.SetTopWindow(self.frame)
		return True

if __name__ == '__main__':
	app=pystereo()
	app.MainLoop()



<<attachment: application.png>>

<<attachment: chart_line.png>>

------------------------------------------------------------------------------
Stay on top of everything new and different, both inside and 
around Java (TM) technology - register by April 22, and save
$200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
300 plus technical and hands-on sessions. Register today. 
Use priority code J9JMT32. http://p.sf.net/sfu/p
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to