From 5ebb1d7e034e843ab8ca78fa4fe6e9d86309b4a6 Mon Sep 17 00:00:00 2001 From: Cosmin SAVEANU <cosmin.saveanu@pasteur.fr> Date: Tue, 15 Mar 2022 13:48:57 +0100 Subject: [PATCH] Upload New File --- PolysomeRider/PolysomeRider_04uv2.pyw | 710 ++++++++++++++++++++++++++ 1 file changed, 710 insertions(+) create mode 100644 PolysomeRider/PolysomeRider_04uv2.pyw diff --git a/PolysomeRider/PolysomeRider_04uv2.pyw b/PolysomeRider/PolysomeRider_04uv2.pyw new file mode 100644 index 0000000..9c25235 --- /dev/null +++ b/PolysomeRider/PolysomeRider_04uv2.pyw @@ -0,0 +1,710 @@ +""" +Polysome Rider version 0.2 + +A visualisation and data acquisition +program linked to a PCI NIDAQ card +and the Pharmacia monitor UV-2 + +Written using wxPython, ctypes, numarray +et al., in Python, August 2004, Cosmin + +Modified to be used with the Pharmacia +Dual Path monitor UV-2, 10 mV output +January 2005 + +Alain Jacquier's laboratory, IP + +INSTRUCTIONS: + +Operation is simple. Press Ctrl+G to start data +collection and Ctrl+H (Halt) to stop acquisition. +Save your data by pressing Ctrl+S. + +If you're not acquiring data, you can +zoom in the drawing panel with the mouse; +unzoom by right click or by two left clicks. + +Pay attention to the settings in the Abs range +menu, it must correspond to the absorbance range +on the UV monitor. + +Printing has been disabled because it gene- +rated too many erors. However you can print +your image by saving it in a bitmap format (PNG +is the best) and printing with an image viewer +application. + +DO NOT FORGET TO SAVE YOUR DATA AT THE END OF +DATA COLLECTION! If you forget, the data will +be lost. Traces of data might be found in the +<temp_data> file, where the program saves inter- +mediate data. + +24/08/2004 +- added a menu to change the size +of the window (200 points, 400 points, 800 points) +- when the user stops acquisition a mandatory +save file dialog is called. + +04/02/2005 +- added a moving average routine to smooth +data, very noisy from the UV monitor. Why it +is so noisy? To investigate... +""" +import wx +import os, string +from shutil import copyfile +from wx.lib.plot import * +from numarray import * +from pydaqminimal import * +from random import random + +[ID_OPEN, +ID_CLOSE, +ID_SAVEP, +ID_SAVEDATA, +ID_EXIT, +ID_ABOUT, +ID_TSTART, +ID_TSTOP, +ID_256, +ID_128, +ID_064, +ID_PSETUP, +ID_PPRINT, +ID_PPREVIEW, +ID_ENGRID, +ID_AUTOSCALE, +ID_WIN200, +ID_WIN400, +ID_WIN800, +ID_SMOOTH +] = map(lambda init_ctrls: wx.NewId(), range(20)) + +def combine_array(array1, array2): + """ + combines two arrays by concatenating them + where x are identical; used at the end when saving + data + """ + lastlineindex = array1[-1, 0] + counter = 0 + for line2 in array2: + counter+=1 + if lastlineindex==line2[0]: + #from here we have to get the data into the other array + break + newarray2 = array2[counter:] + #print "counter", counter + #print newarray2 + return concatenate((array1, newarray2)) + +def ReadFromFileOld(filename, skip=0): + """ + Obtain data from a tab delimited file into a list + + Needs the import string statement + The <skip> parameter indicate the number of lines not + read. + + """ + data = [] + f=open(filename, 'r') + for i in range(skip): + f.readline() + while (1): + line = f.readline() + if line == "": break + if (line[-1] == '\n' or line[-1] == '\r'): + line = line[:-1] #strip the last character (the newline usually) + data.append(string.split(line, '\t')) + f.close() + return data + #the returned data will be in string format + +def ReadFromFileArray(filename, skip=0): + """ + Obtain floats from a tab delimited file into a numarray array + + The <skip> parameter indicate the number of lines not + read. + + """ + data = [] + err = 0 + errmsg = "" + f=open(filename, 'r') + for i in range(skip): + f.readline() + #simple test to see if the file looks like a float coercible text file + try: + for line in f: + data.append(map(float, line.strip().split("\t"))) + data_array = array(data) + except ValueError: + data = [[1, 1]] + data_array = array(data) + err = 1 + errmsg = "The file you are trying to open does not look like a tab delimited one" + + f.close() + return (data_array, err, errmsg) + #the returned data is a tuple with an array of floats, error and errmsg + +def ListToArray(inlist): + """ + Transform the elements of a list in floats + Transform this list to a numeric array + """ + fl_list = [] + for pair in inlist: + first = float(pair[0]) + second = float(pair[1]) + fl_list.append([first, second]) + return array(fl_list) + +def WriteArrayToFile(outfilename, outarray): + """ + Write an numarray array to a file, tab delimited + The array may have many columns and lines but + only two dimensions. + """ + fout = open(outfilename, "w") + for line in outarray: + for column in line: + fout.write(str(column)+'\t') + fout.write('\n') + fout.close() + +class MainFrame(wx.Frame): + + def __init__(self, parent, id, title): + wx.Frame.__init__(self, parent, id, title, + wx.DefaultPosition, (600, 600)) + + self.timerexists = 0 + #used to shut off the timer if still running when the app exits + self.timerinterval = 500 + #used to establish the frequency of readings (500 ms by default) + self.MAX_ACQPOINTS = 5000 + #We won't acquire more than 5000 points. If got there, + #just send a stop signal to the timer. + self.displayrange = 800 + #the number of displayed points + self.temp_outfile = "temp_data" + #the data saved during every acquisition + #goes to a temporary file in the current directory + self.in_recorded = 0 + #test if data was already transferred to recorded_arr + #recorded_arr contains the cummulated readings + #it is written to disk once the acquisition timer stops + self.absrange = 1 #default absorbance range + self.defaultdirname = "c:\\users\\" + #default directory for saving, will be modified after first save + self.maxy = self.absrange + + #put the icon on the frame (small icon top left) + if wx.Platform == '__WXMSW__': + self.icon = wx.Icon('pyviewnidaq.ico', wx.BITMAP_TYPE_ICO ) + self.SetIcon(self.icon) + + + # Create the menu bar and items + self.menubar = wx.MenuBar() + + filemenu = wx.Menu() + filemenu.Append(ID_OPEN, '&Open\tCtrl+O', 'Open tab delimited file for plotting') + filemenu.Append(ID_CLOSE, '&Close\tCtrl+W', 'Close file') + filemenu.Append(ID_SAVEP, '&Save image', 'Save image in a bmp, png or jpg format') + filemenu.AppendSeparator() + filemenu.Append(ID_SAVEDATA, '&Save data as...\tCtrl+S', 'Save data to a tab delimited text file') + filemenu.AppendSeparator() + filemenu.Append(ID_SMOOTH, '&Filter file...\tCtrl+F', 'Apply a moving average filter to a previously opened file') + filemenu.AppendSeparator() + #filemenu.Append(ID_PSETUP, '&Page setup...', 'Change the format of the page for printing') + #filemenu.Append(ID_PPRINT, '&Print image\tCtrl+P', 'Prints image to a printer') + #filemenu.Append(ID_PPREVIEW, '&Page preview\tCtrl+V', 'Previews the image for printing') + #filemenu.AppendSeparator() + filemenu.Append(ID_EXIT, '&Quit\tCtrl+Q', 'Exit program') + + timermenu = wx.Menu() + timermenu.Append(ID_TSTART, '&Start\tCtrl+G', 'Start acquisition from card. Unsaved data will be deleted!') + timermenu.Append(ID_TSTOP, '&Stop!(Halt)\tCtrl+H', 'Stop acquisition from card') + + lkbmenu = wx.Menu() + lkbmenu.Append(ID_256,'&Abs 2' ,'Range of UV-2 absorbance' ,wx.ITEM_RADIO) + lkbmenu.Append(ID_128,'&Abs 1' ,'Range of UV-2 absorbance' ,wx.ITEM_RADIO) + lkbmenu.Append(ID_064,'&Abs 0.5' ,'Range of UV-2 absorbance' ,wx.ITEM_RADIO) + + viewmenu = wx.Menu() + viewmenu.Append(ID_WIN800, '&6 minutes/view' ,'How many points are viewed at once when acquiring' ,wx.ITEM_RADIO) + viewmenu.Append(ID_WIN400, '&3 minutes/view' ,'How many points are viewed at once when acquiring' ,wx.ITEM_RADIO) + viewmenu.Append(ID_WIN200, '&1.5 minutes/view' ,'How many points are viewed at once when acquiring' ,wx.ITEM_RADIO) + viewmenu.AppendSeparator() + viewmenu.Append(ID_ENGRID, 'Grid &enabled', 'Enable or disable grid when drawing', wx.ITEM_CHECK) + viewmenu.Append(ID_AUTOSCALE, '&Autoscale', 'Enable or disable autoscaling. When autoscale is off, the ABS range is used', wx.ITEM_CHECK) + + helpmenu = wx.Menu() + helpmenu.Append(ID_ABOUT, 'About...\tCtrl+H', 'About this program') + + # Bind the events to methods + wx.EVT_MENU(self, ID_OPEN, self.OnFileOpen) + wx.EVT_MENU(self, ID_CLOSE, self.OnFileClose) + wx.EVT_MENU(self, ID_SAVEP, self.OnSaveImage) + wx.EVT_MENU(self, ID_SAVEDATA, self.OnSaveData) + wx.EVT_MENU(self, ID_SMOOTH, self.OnSmoothFile) + #wx.EVT_MENU(self, ID_PSETUP, self.OnFilePageSetup) + #wx.EVT_MENU(self, ID_PPRINT, self.OnFilePrint) + #wx.EVT_MENU(self, ID_PPREVIEW, self.OnFilePrintPreview) + wx.EVT_MENU(self, ID_EXIT, self.OnFileExit) + wx.EVT_MENU(self, ID_TSTART, self.OnTimerStart) + wx.EVT_MENU(self, ID_TSTOP, self.OnTimerStop) + wx.EVT_MENU(self, ID_ENGRID, self.OnEnableGrid) + wx.EVT_MENU(self, ID_AUTOSCALE, self.OnAutoScale) + wx.EVT_MENU(self, ID_256, self.OnRange256) + wx.EVT_MENU(self, ID_128, self.OnRange128) + wx.EVT_MENU(self, ID_064, self.OnRange064) + wx.EVT_MENU(self, ID_WIN200, self.OnViewLimits200) + wx.EVT_MENU(self, ID_WIN400, self.OnViewLimits400) + wx.EVT_MENU(self, ID_WIN800, self.OnViewLimits800) + wx.EVT_MENU(self, ID_ABOUT, self.OnHelpAbout) + + # Bind all EVT_TIMER events to self.OnTimerEvent + # TimerEvent is the function called + self.Bind(wx.EVT_TIMER, self.OnTimerEvent) + + # Attach menus to the menubar + self.menubar.Append(filemenu, '&File') + self.menubar.Append(timermenu, '&Data collection') + self.menubar.Append(lkbmenu, '&Abs. range') + self.menubar.Append(viewmenu, '&Options') + self.menubar.Append(helpmenu, '&Help') + + self.SetMenuBar(self.menubar) + + #Disable by default the STOP and Save data as menus + self.menubar.Enable(ID_TSTOP, 0) + self.menubar.Enable(ID_SAVEDATA, 0) + self.menubar.Enable(ID_SMOOTH, 0) + self.menubar.Check(ID_AUTOSCALE, 0) + self.menubar.Check(ID_128, 1) + self.autoscale = 1 + + # A status bar to tell people what's happening + self.CreateStatusBar(1) + + self.plotcanvas = PlotCanvas(self) + # Create mouse event for showing cursor coords in status bar + self.plotcanvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown) + self.plotcanvas.SetEnableZoom(1) #to ensure zoom by default + self.Show(True) + + def InitializeArray(self): + """ + Sets up an array containing displayrange points + with zero values. A 0 line is thus displayed. + """ + self.gl_array = zeros((self.displayrange, 2), Float) + #initial 0 array for a blank line drawing + self.arraycounter = 0 + for line in self.gl_array: + line[0] = self.arraycounter + self.arraycounter+=1 + + def OnAutoScale(self, event): + """ + links autoscale to the menu event + """ + self.autoscale = event.IsChecked() + self.AutoScale() + + def AutoScale(self): + """ + redefines the self.autoscale constant + to see if Autoscale should be used, or use another + scale (coming from Absorbance range) + """ + #self.autoscale = event.IsChecked() + if self.autoscale: + self.maxy = 0 + else: + self.maxy = self.absrange + + def OnSmoothFile(self, event): + """ + Filters a file using a moving average + linear filter with a fixed window of 20 + (change it if you like). It is activated + only after a File_Open menud command + """ + wsize = 20 #window size, even number only + INTTRANSFORM = 1000 + #self.array contains data from the previous FileOpen + data = [] + outflst = os.path.splitext(self.filename) + for lst in self.array: + data.append([int(float(lst[0])), int(INTTRANSFORM*float(lst[1]))]) + + self.menubar.Enable(ID_SAVEDATA, 0) + #disable the save data menu item + + filtdata = [] + sum = 0 + prevsum = 0 + for i in range(int(wsize/2)): + filtdata.append([data[i][0], data[i][1]/float(INTTRANSFORM)]) + #prevsum=prevsum+data[i][1] + + for i in range(int(wsize)): + prevsum = prevsum+data[i][1] + + for i in range(int(wsize/2),len(data)-wsize/2-1): + sum = prevsum - data[i-wsize/2 -1][1] + data[i + wsize/2][1] + prevsum = sum + filtdata.append([data[i][0], sum/float(wsize)/float(INTTRANSFORM)]) + + for i in range(len(data)-wsize/2-1, len(data)): + filtdata.append([data[i][0], data[i][1]/float(INTTRANSFORM)]) + + wildcard = "Tab delimited text file (*.txt)|*.txt|"\ + "All files (*.*)|*.*" + dlg = wx.FileDialog( + self, message="Save smoothed data to ...", defaultDir = self.defaultdirname, + defaultFile=outflst[0]+"flt.txt", wildcard=wildcard, style=wx.SAVE + ) + dlg.SetFilterIndex(0) + if dlg.ShowModal() == wx.ID_OK: + self.dirname=dlg.GetDirectory() + self.defaultdirname = self.dirname + path = dlg.GetPath() + try: + fout = open(path, "w") + for line in filtdata: + fout.write('%d\t%.3f\n'%(line[0], line[1])) + fout.close() + + self.SetStatusText("Smoothed data saved to file %s"%path) + readed = ReadFromFileArray(path) + self.array = readed[0] + + if readed[1] == 1: #error + dlg = wx.MessageDialog(self, readed[2], 'Problem opening file', + wx.OK | wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + + self.PlotArray(self.array, "brown") + + except IOError: + dlg = wx.MessageDialog(self, "Error. Maybe the output file is in use...", 'Problem saving data', + wx.OK | wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + dlg.Destroy() + self.menubar.Enable(ID_SMOOTH, 0) + + def OnFileOpen(self, event): + """ + Opens and plots a tab delimited text file + If not a recognized file, a message is displayed + """ + self.resetDefaults() + wildcard = "Tab delimited text file (*.txt)|*.txt|"\ + "All files (*.*)|*.*" + dlg = wx.FileDialog(self, "Choose a tab delimited text file", + self.defaultdirname, "", wildcard, wx.OPEN) + if dlg.ShowModal() == wx.ID_OK: + self.filename=dlg.GetFilename() + self.dirname=dlg.GetDirectory() + self.defaultdirname = self.dirname + fname = os.path.join(self.dirname, self.filename) + readed = ReadFromFileArray(fname) + self.array = readed[0] + dlg.Destroy() + self.menubar.Enable(ID_SAVEDATA, 0) + #disable the save data menu item + self.menubar.Enable(ID_SMOOTH, 1) + #enable the Filter file menu for smoothing + if readed[1] == 1: #error + dlg = wx.MessageDialog(self, readed[2], 'Problem opening file', + wx.OK | wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + + #self.line1 = PolyLine(self.array, colour = "dark green", width = 2) + self.PlotArray(self.array, "dark green") + #self.plotcanvas.Draw(PlotGraphics([self.line1,], self.filename, "", "")) + + + + def OnSaveData(self, event): + """ + Saves the data by moving the temp.txt file + to a user specified location. Uses shutil.copyfile + """ + #log.WriteText("CWD: %s\n" % os.getcwd()) + wildcard = "Tab delimited text file (*.txt)|*.txt|"\ + "All files (*.*)|*.*" + #might be os.getcwd() + dlg = wx.FileDialog( + self, message="Save data to a file as ...", defaultDir = self.defaultdirname, + defaultFile="", wildcard=wildcard, style=wx.SAVE + ) + dlg.SetFilterIndex(0) + if dlg.ShowModal() == wx.ID_OK: + self.dirname=dlg.GetDirectory() + self.defaultdirname = self.dirname + path = dlg.GetPath() + #print "You selected", path + try: + copyfile("temp_data", path) + except IOError: + dlg = wx.MessageDialog(self, "Error. Maybe the output file is in use...", 'Problem saving data', + wx.OK | wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + dlg.Destroy() + + + + + def PlotArray(self, data_array, color): + """ + Used to plot on the plotcanvas the points of a data_array + Default is autoscale, otherwise give ymax a value + """ + self.line = PolyLine(data_array, colour = color) + if self.maxy == 0: + self.plotcanvas.Draw(PlotGraphics([self.line, ], + "Absorbance", "time (half seconds)", "")) + else: + self.plotcanvas.Draw(PlotGraphics([self.line, ], + "Absorbance", "time (half seconds)", ""), yAxis = (-0.1,self.maxy)) + #self.plotcanvas.Redraw() + + def AdvanceAPoint(self, newpointarr, prevarray): + """ + Serves the DrawStripChart function, allowing the removal + of the first pair of data from the array that is plotted. Next + a new data pair is concatenated to the end of the array + + Additionally, the function verifies if the recorded_arr has already + been filled up or not and takes care to fill it up every time the + arraycounter reaches a value that is the multiple of the displayrange + constant. + """ + new_arr = prevarray[1:] + #remove the first pair of values + self.arraycounter+=1 + #increment the global counter + #this counter serves also to stop acquisition after + #MAX_ACQPOINTS points + test_accumul = divmod(self.arraycounter, self.displayrange) + if test_accumul[1] == 0: + if self.in_recorded == 0: + self.recorded_arr = prevarray[1:] + self.in_recorded = 1 + #print "recorded array", self.recorded_arr + else: + self.recorded_arr = concatenate((self.recorded_arr, prevarray)) + self.in_recorded = 1 + + return concatenate((new_arr, newpointarr)) + + def GeneratePointRandom(self): + """ + Used for testing, replaced by a more useful + function that gets data from the NIDAQ card + """ + newpoint = [[self.arraycounter, random()]] + return array(newpoint) + + def GeneratePoint(self, absrange): + """ + Reads a normalized, mean value from pydaq + returns a simple array to be used by AdvanceAPoint + """ + reading = 0 + for i in range(400): + reading+= self.ReadV(absrange) + reading_mean = reading/400 + #getting the mean reduces a lot the noise to acceptable levels + newpoint = [[self.arraycounter, reading_mean]] + return array(newpoint) + + + + def GenerateNullArr(self, length): + """ + Fabricate the display array + """ + return zeros((length, 2), Float) + + def DrawStripChart(self): + """ + The function called every time a timed event + occurs. Calls the AdvanceAPoint function. Stops + the whole process if the MAX_ACQPOINTS number + of points have been acquired in the actual timer session. + """ + newpnt = self.GeneratePoint(self.absrange) + self.gl_array = self.AdvanceAPoint(newpnt, self.gl_array) + self.PlotArray(self.gl_array, "red") + if self.arraycounter > self.MAX_ACQPOINTS + self.displayrange: + self.TimerStop() + + def OnFileClose(self, event): + self.plotcanvas.Clear() + + def OnTimerStart(self, event): + self.InitializeArray() + self.t1 = wx.Timer(self) + self.t1.Start(self.timerinterval) + self.SetStatusText("Data Acquisition Started...") + #print "EVT_TIMER timer started\n" + self.menubar.Enable(ID_TSTART, 0) + self.menubar.Enable(ID_TSTOP, 1) + self.menubar.Enable(ID_OPEN, 0) + self.menubar.Enable(ID_CLOSE, 0) + self.menubar.Enable(ID_SAVEP, 0) + self.menubar.Enable(ID_SAVEDATA, 0) + self.menubar.Enable(ID_WIN200, 0) + self.menubar.Enable(ID_WIN400, 0) + self.menubar.Enable(ID_WIN800, 0) + self.menubar.Enable(ID_SMOOTH, 0) + self.SetStatusText("You can stop acquisition with Ctrl+H (Halt).") + timerexists = 1 + self.in_recorded = 0 + self.InitializeNIDAQ(1) + + def OnTimerEvent(self, event): + #print "An event" + self.DrawStripChart() + + def OnTimerStop(self, event): + self.TimerStop() + + def TimerStop(self): + self.t1.Stop() + #print "EVT_TIMER timer stoped\n" + self.SetStatusText("Data Acquisition Stopped.") + del self.t1 + self.menubar.Enable(ID_TSTART, 1) + self.menubar.Enable(ID_TSTOP, 0) + self.menubar.Enable(ID_OPEN, 1) + self.menubar.Enable(ID_CLOSE, 1) + self.menubar.Enable(ID_SAVEP, 1) + self.menubar.Enable(ID_SAVEDATA, 1) + self.menubar.Enable(ID_WIN200, 1) + self.menubar.Enable(ID_WIN400, 1) + self.menubar.Enable(ID_WIN800, 1) + timerexists = 0 + #and write data to a temporary file + if self.in_recorded == 1: + written_arr = combine_array(self.recorded_arr, self.gl_array) + else: + written_arr = self.gl_array + WriteArrayToFile(self.temp_outfile, written_arr) + self.PlotArray(written_arr, "blue") + self.OnSaveData(100) + + def OnRange256(self, event): + self.absrange = 2.0 + self.AutoScale() + def OnRange128(self, event): + self.absrange = 1.0 + self.AutoScale() + def OnRange064(self, event): + self.absrange = 0.5 + self.AutoScale() + def OnViewLimits200(self, event): + self.displayrange = 200 + def OnViewLimits400(self, event): + self.displayrange = 400 + def OnViewLimits800(self, event): + self.displayrange = 800 + + def InitializeNIDAQ(self, channo=1): + """ + Initialize the device and channel to listen to + """ + self.pd=pydaq() + self.chan = c_int(channo) + self.volt = pointer(c_double(0.01)) + self.deviceNo=c_int(1) + #usually the deviceNo is 1 + self.pd.DAQ_Clear(self.pd.deviceNumber) + + def ReadV(self, absrange): + readtuple = self.pd.AI_VRead(chan = self.chan, gain=c_int(10), pvoltage = self.volt) + #print readtuple[1], "volts" + return readtuple[1]/0.01*absrange #2.0 is the scale on the spectro + #print readtuple[1], "volts" + + def ClearNIDAQ(self): + self.pd.DAQ_Clear(self.pd.deviceNumber) + + def OnMouseLeftDown(self,event): + s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.plotcanvas.GetXY(event) + self.SetStatusText(s) + event.Skip() + + def OnSaveImage(self, event): + self.plotcanvas.SaveFile() + + def OnFileExit(self, event): + if self.timerexists: + self.t1.Stop() + del self.t1 + print 'Timer stopped and destroyed' + self.Close() + + def OnFilePageSetup(self, event): + self.plotcanvas.PageSetup() + + def OnFilePrintPreview(self, event): + self.plotcanvas.PrintPreview() + + def OnFilePrint(self, event): + self.plotcanvas.Printout() + + def OnPlotRedraw(self,event): + self.plotcanvas.Redraw() + + def OnPlotClear(self,event): + self.plotcanvas.Clear() + + def OnPlotScale(self, event): + if self.plotcanvas.last_draw != None: + graphics, xAxis, yAxis= self.plotcanvas.last_draw + self.plotcanvas.Draw(graphics,(1,3.05),(0,1)) + + def OnEnableZoom(self, event): + self.plotcanvas.SetEnableZoom(event.IsChecked()) + + def OnEnableGrid(self, event): + self.plotcanvas.SetEnableGrid(event.IsChecked()) + + def OnEnableLegend(self, event): + self.plotcanvas.SetEnableLegend(event.IsChecked()) + def OnReset(self,event): + self.plotcanvas.Reset() + + def OnHelpAbout(self, event): + from wx.lib.dialogs import ScrolledMessageDialog + about = ScrolledMessageDialog(self, __doc__, "About...") + about.ShowModal() + + def resetDefaults(self): + """Just to reset the fonts back to the PlotCanvas defaults""" + self.plotcanvas.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL)) + self.plotcanvas.SetFontSizeAxis(10) + self.plotcanvas.SetFontSizeLegend(7) + self.plotcanvas.SetXSpec('auto') + self.plotcanvas.SetYSpec('auto') + self.plotcanvas.SetEnableZoom(1) + self.plotcanvas.SetEnableGrid(0) +app = wx.PySimpleApp() +frame = MainFrame(None, -1, "Polysome Rider v. 0.4") +app.SetTopWindow(frame) +app.MainLoop() -- GitLab