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