class PlotFrame(wx.Frame): help_msg = """ Menus for Save export figure (png,eps,bmp) to file Copy copy bitmap of figure to the system clipboard Print Setup setup size of figure for printing Print Preview preview printer page Print send figure to a system printer Exit end application where 'figure' means an image of the matplotlib canvas In addition, "Ctrl-C" is bound to copy-figure-to-clipboard """ start_msg = """ Use Menus to test printing or Ctrl-C to copy plot image to clipboard """ about_msg = """ printing_in_wx version 0.1 12-Nov-2004 Matt Newville <*****@*****.**>""" def __init__(self): wx.Frame.__init__(self, None, -1, "Test Printing with WX Backend") self.fig = Figure((5.0, 3.0), 100) self.canvas = FigCanvas(self, -1, self.fig) self.axes = self.fig.add_axes([0.15, 0.15, 0.75, 0.75]) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) sizer.Add(wx.StaticText(self, -1, self.start_msg), 0, wx.ALIGN_LEFT | wx.TOP) self.canvas.Bind(wx.EVT_KEY_DOWN, self.onKeyEvent) self.SetSizer(sizer) self.Fit() self.Build_Menus() self.Plot_Data() def Build_Menus(self): """ build menus """ MENU_EXIT = wx.NewId() MENU_SAVE = wx.NewId() MENU_PRINT = wx.NewId() MENU_PSETUP = wx.NewId() MENU_PREVIEW = wx.NewId() MENU_CLIPB = wx.NewId() MENU_HELP = wx.NewId() menuBar = wx.MenuBar() f0 = wx.Menu() f0.Append(MENU_SAVE, "&Export", "Save Image of Plot") f0.AppendSeparator() f0.Append(MENU_PSETUP, "Page Setup...", "Printer Setup") f0.Append(MENU_PREVIEW, "Print Preview...", "Print Preview") f0.Append(MENU_PRINT, "&Print", "Print Plot") f0.AppendSeparator() f0.Append(MENU_EXIT, "E&xit", "Exit") menuBar.Append(f0, "&File") f1 = wx.Menu() f1.Append(MENU_HELP, "Quick Reference", "Quick Reference") menuBar.Append(f1, "&Help") self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU, self.onPrint, id=MENU_PRINT) self.Bind(wx.EVT_MENU, self.onPrinterSetup, id=MENU_PSETUP) self.Bind(wx.EVT_MENU, self.onPrinterPreview, id=MENU_PREVIEW) self.Bind(wx.EVT_MENU, self.onClipboard, id=MENU_CLIPB) self.Bind(wx.EVT_MENU, self.onExport, id=MENU_SAVE) self.Bind(wx.EVT_MENU, self.onExit, id=MENU_EXIT) self.Bind(wx.EVT_MENU, self.onHelp, id=MENU_HELP) # the printer / clipboard methods are implemented # in backend_wx, and so are very simple to use. def onPrinterSetup(self, event=None): self.canvas.Printer_Setup(event=event) def onPrinterPreview(self, event=None): self.canvas.Printer_Preview(event=event) def onPrint(self, event=None): self.canvas.Printer_Print(event=event) def onClipboard(self, event=None): self.canvas.Copy_to_Clipboard(event=event) def onKeyEvent(self, event=None): """ capture , act upon keystroke events""" if event == None: return key = event.KeyCode() if (key < wx.WXK_SPACE or key > 255): return if (event.ControlDown() and chr(key) == 'C'): # Ctrl-C self.onClipboard(event=event) def onHelp(self, event=None): dlg = wx.MessageDialog(self, self.help_msg, "Quick Reference", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onExport(self, event=None): """ save figure image to file""" file_choices = "PNG (*.png)|*.png|" \ "PS (*.ps)|*.ps|" \ "EPS (*.eps)|*.eps|" \ "BMP (*.bmp)|*.bmp" thisdir = os.getcwd() dlg = wx.FileDialog(self, message='Save Plot Figure as...', defaultDir=thisdir, defaultFile='plot.png', wildcard=file_choices, style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.canvas.print_figure(path, dpi=300) if (path.find(thisdir) == 0): path = path[len(thisdir) + 1:] print 'Saved plot to %s' % path def onExit(self, event=None): self.Destroy() def Plot_Data(self): t = numpy.arange(0.0, 5.0, 0.01) s = numpy.sin(2.0 * numpy.pi * t) c = numpy.cos(0.4 * numpy.pi * t) self.axes.plot(t, s) self.axes.plot(t, c)
class PlotFrame(wx.Frame): help_msg=""" Menus for Import...import project settings file Export...export figure (png, jpg) to file Print Setup...setup size of figure for printing Print Preview...preview printer page Print...send figure to a system printer Exit...end application Basic-2D...View basic 2D representation of data Advanced-2D...View 2D representation (with span selection control) Advanced-3D...View 3D representation of data View-Grid...Toggle grid View-Legend...Toggle legend View-Fill...Toggle fill representation of data (only for 2D) where 'figure' means an image of the matplotlib canvas In addition, "Ctrl-C" is bound to copy-figure-to-clipboard """ about_msg=""" Option_price_visualisation v0.1 29-Aug-2013 Nathan Floor, [email protected] """ def __init__(self): wx.Frame.__init__(self, None, -1, "Visualise Option Prices and Greeks", size=(300, 500)) self.Bind(wx.EVT_KEY_DOWN, self.onKeyEvent) # intialise variables when start program self.viewLegend = False self.viewGrid = True self.viewFill = False self.reInitialiseData() # build interface self.Build_Menus() self.Build_Panel() self.statusbar = self.CreateStatusBar() self.Plot_Data() self.SetSize(size=(900, 550)) def reInitialiseData(self): self.fileReader = csvReader.Reader() self.current_view = 0 self.time = numpy.arange(0, 31, 1) self.indmin = 0 self.indmax = 31 self.strike_price = 0 # initialise data arrays self.option_price = [] self.stock_price = [] self.delta = [] self.gamma = [] self.vega = [] self.theta = [] self.rho = [] self.risidual = [] # initialise secondary data sets self.option_price_fill = [] self.time_span_fill = [] self.delta_fill = [] self.gamma_fill = [] self.vega_fill = [] self.theta_fill = [] self.rho_fill = [] # initialise bump values self.stock_bump = 0 self.time_bump = 0 self.rate_bump = 0 self.volitile_bump = 0 # on span-selection of graph def onselect(self, xmin, xmax): # initialise data sets option_price = [] delta = [] gamma = [] theta = [] rho = [] vega = [] maxYLimlist = [] minYLimlist = [] # identify the indices of new data set based on selection self.indmin = int(xmin) #self.indmax = numpy.searchsorted(t, (xmin, xmax)) self.indmax = min(len(self.time)-1, int(xmax)+1) self.time_span_fill = self.time[self.indmin:self.indmax] if len(self.option_price) > 0: option_price = numpy.array(map(float, self.option_price[self.stock_bump])) self.option_price_fill = option_price[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.option_price_fill)) minYLimlist.append(min(self.option_price_fill)) if not self.viewFill: self.line1.set_data(self.time_span_fill, self.option_price_fill) if len(self.delta) > 0: delta = numpy.array(map(float, self.delta[self.stock_bump])) self.delta_fill = delta[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.delta_fill)) minYLimlist.append(min(self.delta_fill)) if not self.viewFill: self.line2.set_data(self.time_span_fill, self.delta_fill) if len(self.gamma) > 0: gamma = numpy.array(map(float, self.gamma[self.stock_bump])) self.gamma_fill = gamma[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.gamma_fill)) minYLimlist.append(min(self.gamma_fill)) if not self.viewFill: self.line3.set_data(self.time_span_fill, self.gamma_fill) if len(self.theta) > 0: theta = numpy.array(map(float, self.theta[self.time_bump])) self.theta_fill = theta[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.theta_fill)) minYLimlist.append(min(self.theta_fill)) if not self.viewFill: self.line4.set_data(self.time_span_fill, self.theta_fill) if len(self.rho) > 0: rho = numpy.array(map(float, self.rho[self.rate_bump])) self.rho_fill = rho[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.rho_fill)) minYLimlist.append(min(self.rho_fill)) if not self.viewFill: self.line5.set_data(self.time_span_fill, self.rho_fill) if len(self.vega) > 0: vega = numpy.array(map(float, self.vega[self.volitile_bump])) self.vega_fill = vega[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.vega_fill)) minYLimlist.append(min(self.vega_fill)) if not self.viewFill: self.line6.set_data(self.time_span_fill, self.vega_fill) if len(self.risidual) > 0: risidual = numpy.array(map(float, self.risidual[self.stock_bump])) self.risidual_fill = risidual[self.indmin:self.indmax] # append to lists for axes limits maxYLimlist.append(max(self.risidual_fill)) minYLimlist.append(min(self.risidual_fill)) if not self.viewFill: self.line7.set_data(self.time_span_fill, self.risidual_fill) if len(maxYLimlist) > 0: maxYLim = max(maxYLimlist) else: maxYLim = 1 if len(minYLimlist) > 0: minYLim = min(minYLimlist) else: minYLim = 0 self.axes2.set_xlim(self.time_span_fill[0]-1, self.time_span_fill[-1]+1) self.axes2.set_ylim(minYLim, maxYLim) if not self.viewFill: self.canvas.draw() else: self.Plot_Data() def Build_Panel(self): self.panel = wx.Panel(self) # Create Figure and canvas objects self.fig = Figure((6.0, 4.0)) self.canvas = FigCanvas(self.panel, -1, self.fig) self.axes = self.fig.add_subplot(111) # setup slider-widgets for controlling GUI self.sliderPanel = wx.Panel(self.panel) self.stockSlider_label = wx.StaticText(self.sliderPanel, -1, "Stock Price: ") self.stockSlider = wx.Slider(self.sliderPanel, value=5, minValue=1, maxValue=9, pos=(20, 20), size=(100,-1), style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS) # self.stockSlider.SetTickFreq(9, 1) self.rateSlider_label = wx.StaticText(self.sliderPanel, -1, "Interest Rate: ") self.rateSlider = wx.Slider(self.sliderPanel, value=5, minValue=1, maxValue=9, pos=(20, 20), size=(100,-1), style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS) self.rateSlider.SetTickFreq(1, 1) self.timeStepSlider_label = wx.StaticText(self.sliderPanel, -1, "Time Step: ") self.timeStepSlider = wx.Slider(self.sliderPanel, value=5, minValue=1, maxValue=9, pos=(20, 20), size=(100,-1), style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS) self.timeStepSlider.SetTickFreq(1, 1) self.Bind(wx.EVT_SLIDER, self.onStockSlider, self.stockSlider) self.Bind(wx.EVT_SLIDER, self.onRateSlider, self.rateSlider) self.Bind(wx.EVT_SLIDER, self.ontimeStepSlider, self.timeStepSlider) # setup options-widgets for controlling graphs self.callRadio = wx.RadioButton(self.panel, label="Call options", pos=(10, 10)) self.putRadio = wx.RadioButton(self.panel, label="Put options", pos=(10, 30)) self.callRadio.SetValue(True) self.spaceKeeper = wx.StaticText(self.panel, -1, '') self.optionPriceCheck = wx.CheckBox(self.panel, label="view Option Price", pos=(20, 20)) self.deltaCheck = wx.CheckBox(self.panel, label="show Delta", pos=(20, 20)) self.gammaCheck = wx.CheckBox(self.panel, label="show Gamma", pos=(20, 20)) self.rhoCheck = wx.CheckBox(self.panel, label="show Rho", pos=(20, 20)) self.thetaCheck = wx.CheckBox(self.panel, label="show Theta", pos=(20, 20)) self.fillCheck = wx.CheckBox(self.panel, label="show fill feature", pos=(20, 20)) self.risidualCheck = wx.CheckBox(self.panel, label="Show Residual", pos=(20, 20)) self.differenceCheck = wx.CheckBox(self.panel, label="Show Difference", pos=(20, 20)) self.effectCheck = wx.CheckBox(self.panel, label="Show Greek's effect on option price", pos=(20, 20)) self.effectCheck.SetValue(True) self.Bind(wx.EVT_RADIOBUTTON, self.onCallRadio, self.callRadio) self.Bind(wx.EVT_RADIOBUTTON, self.onPutRadio, self.putRadio) self.Bind(wx.EVT_CHECKBOX, self.onOptionPrice, self.optionPriceCheck) self.Bind(wx.EVT_CHECKBOX, self.onDelta, self.deltaCheck) self.Bind(wx.EVT_CHECKBOX, self.onGamma, self.gammaCheck) self.Bind(wx.EVT_CHECKBOX, self.onRho, self.rhoCheck) self.Bind(wx.EVT_CHECKBOX, self.onTheta, self.thetaCheck) self.Bind(wx.EVT_CHECKBOX, self.onRisidual, self.risidualCheck) self.Bind(wx.EVT_CHECKBOX, self.onDifferenceCheck, self.differenceCheck) self.Bind(wx.EVT_CHECKBOX, self.onShowEffects, self.effectCheck) self.Bind(wx.EVT_CHECKBOX, self.onShowFillEffect, self.fillCheck) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas) #################### # Layout with sizers #################### flags = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL self.sizer = wx.BoxSizer(wx.VERTICAL) self.hboxMainBlock = wx.BoxSizer(wx.HORIZONTAL) self.vboxOptions = wx.BoxSizer(wx.VERTICAL) self.hboxSliders = wx.BoxSizer(wx.HORIZONTAL) self.flexiGridSizer = wx.FlexGridSizer(4, 2, 3, 10) # adds border around sliders to group related widgets self.vboxOptions.AddSpacer(10) self.sliderStaticBox = wx.StaticBox(self.sliderPanel, -1, 'Bump Sliders') self.sliderBorder = wx.StaticBoxSizer(self.sliderStaticBox, orient=wx.VERTICAL) self.flexiGridSizer.AddMany([(self.stockSlider_label), (self.stockSlider, 1, wx.ALL), (self.rateSlider_label), (self.rateSlider, 1, wx.EXPAND), (self.timeStepSlider_label), (self.timeStepSlider, 1, wx.EXPAND)]) self.sliderBorder.Add(self.flexiGridSizer, 1, wx.ALL, 5) self.sliderPanel.SetSizer(self.sliderBorder) self.vboxOptions.Add(self.sliderPanel, 0, flag=wx.ALIGN_LEFT|wx.ALL) # add border for type of option price self.optionsBorder = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, 'Option Price Type'), orient=wx.VERTICAL) self.flexiOptions = wx.FlexGridSizer(3, 1, 3, 10) self.flexiOptions.AddMany([(self.callRadio, 1, wx.EXPAND), (self.putRadio, 1, wx.EXPAND), (self.optionPriceCheck, 1, wx.EXPAND)]) self.optionsBorder.Add(self.flexiOptions, 1, wx.ALL, 5) self.vboxOptions.Add(self.optionsBorder, 0, flag=wx.ALIGN_LEFT|wx.ALL|wx.GROW) # add border for greeks self.greekOptionsBorder = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, 'Greek effect Options'), orient=wx.VERTICAL) self.flexiOptions2 = wx.FlexGridSizer(6, 1, 3, 10) self.flexiOptions2.AddMany([(self.deltaCheck, 1, wx.EXPAND), (self.gammaCheck, 1, wx.EXPAND), (self.rhoCheck, 1, wx.EXPAND), (self.thetaCheck, 1, wx.EXPAND), (self.risidualCheck, 1, wx.EXPAND)]) self.greekOptionsBorder.Add(self.flexiOptions2, 1, wx.ALL, 5) self.vboxOptions.Add(self.greekOptionsBorder, 1, flag=wx.ALIGN_LEFT|wx.ALL|wx.GROW) #self.vboxOptions.AddSpacer(5) # add border for other checkable options self.otherOptionsBorder = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, 'Extra Options'), orient=wx.VERTICAL) self.flexiOptions3 = wx.FlexGridSizer(3, 1, 3, 10) self.flexiOptions3.AddMany([(self.fillCheck, 1, wx.EXPAND), (self.differenceCheck, 1, wx.EXPAND), (self.effectCheck, 1, wx.EXPAND)]) self.otherOptionsBorder.Add(self.flexiOptions3, 1, wx.ALL, 5) self.vboxOptions.Add(self.otherOptionsBorder, 0, flag=wx.ALIGN_LEFT|wx.ALL|wx.GROW) self.vboxOptions.AddSpacer(5) self.hboxMainBlock.Add(self.vboxOptions, 0, flag=flags) self.hboxMainBlock.Add(self.canvas, 1, flag=wx.ALIGN_RIGHT|wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) self.sizer.Add(self.hboxMainBlock, 1, wx.ALL|wx.EXPAND) self.sizer.Add(self.toolbar, 0, wx.ALL|wx.ALIGN_RIGHT) self.sizer.AddSpacer(1) self.canvas.Bind(wx.EVT_KEY_DOWN, self.onKeyEvent) self.Bind(wx.EVT_CLOSE, self.onExit) self.panel.SetSizer(self.sizer) self.sizer.Fit(self) self.Center() def Build_Menus(self): """ build menus """ MENU_EXIT = wx.NewId() MENU_OPEN = wx.NewId() MENU_SAVE = wx.NewId() MENU_PRINT = wx.NewId() MENU_PSETUP = wx.NewId() MENU_PREVIEW =wx.NewId() MENU_CLIPB =wx.NewId() MENU_VIEW_GRID = wx.NewId() MENU_HELP =wx.NewId() MENU_BASIC = wx.NewId() MENU_ADVANCE = wx.NewId() MENU_LEGEND = wx.NewId() MENU_3D = wx.NewId() MENU_ABOUT = wx.NewId() menuBar = wx.MenuBar() f0 = wx.Menu() importItem = wx.MenuItem(f0, MENU_OPEN, "&Import\tCtrl+I") f0.AppendItem(importItem) f0.Append(MENU_SAVE, "&Export", "Save Image of Plot") f0.AppendSeparator() printMenu = wx.Menu() printMenu.Append(MENU_PSETUP, "Page Setup...", "Printer Setup") printMenu.Append(MENU_PREVIEW,"Print Preview...", "Print Preview") printItem = wx.MenuItem(printMenu, MENU_PRINT, "Print\tCtrl+P") printMenu.AppendItem(printItem) f0.AppendMenu(-1, '&Print', printMenu) f0.AppendSeparator() exitItem = wx.MenuItem(f0, MENU_EXIT, 'E&xit\tCtrl+Q') f0.AppendItem(exitItem) menuBar.Append(f0, "&File") f1 = wx.Menu() f1.Append(MENU_BASIC, '&Basic', "Basic View(2D)") f1.Append(MENU_ADVANCE, '&Advanced-2D', "Advanced View(2D)") f1.Append(MENU_3D, 'A&dvanced-3D', "Advanced View(3D)") optionsMenu = wx.Menu() viewGridItem = wx.MenuItem(optionsMenu, MENU_VIEW_GRID, 'View &Grid\tCtrl+G') optionsMenu.AppendItem(viewGridItem) viewLegendItem = wx.MenuItem(optionsMenu, MENU_LEGEND, 'View &Legend\tCtrl+L') optionsMenu.AppendItem(viewLegendItem) f1.AppendMenu(-1, "&Options", optionsMenu) menuBar.Append(f1, "&View") f2 = wx.Menu() f2.Append(MENU_HELP, "Quick &Reference", "Quick Reference") f2.Append(MENU_ABOUT, "&About", "About this interface") menuBar.Append(f2, "&Help") self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU, self.onImport, id=MENU_OPEN) self.Bind(wx.EVT_MENU, self.onPrint, id=MENU_PRINT) self.Bind(wx.EVT_MENU, self.onPrinterSetup, id=MENU_PSETUP) self.Bind(wx.EVT_MENU, self.onPrinterPreview, id=MENU_PREVIEW) self.Bind(wx.EVT_MENU, self.onClipboard, id=MENU_CLIPB) self.Bind(wx.EVT_MENU, self.onExport, id=MENU_SAVE) self.Bind(wx.EVT_MENU, self.onExit , id=MENU_EXIT) self.Bind(wx.EVT_MENU, self.onViewGrid, id=MENU_VIEW_GRID) self.Bind(wx.EVT_MENU, self.onViewLegend, id=MENU_LEGEND) self.Bind(wx.EVT_MENU, self.onHelp, id=MENU_HELP) self.Bind(wx.EVT_MENU, self.onAbout, id=MENU_ABOUT) self.Bind(wx.EVT_MENU, self.onBasicView, id=MENU_BASIC) self.Bind(wx.EVT_MENU, self.onAdvancedView, id=MENU_ADVANCE) self.Bind(wx.EVT_MENU, self.onAdvanced3DView, id=MENU_3D) """ Menu event methods """ def onViewLegend(self, event=None): if self.viewLegend: self.viewLegend = False self.Plot_Data() else: self.viewLegend = True # use proxy artist plot_op = Line2D([], [], linewidth=3, color="black") plot_delta = Line2D([], [], linewidth=3, color="royalblue") plot_gamma = Line2D([], [], linewidth=3, color="cyan") plot_theta = Line2D([], [], linewidth=3, color="green") plot_rho = Line2D([], [], linewidth=3, color="darkorange") plot_risidual = Line2D([], [], linewidth=3, color="purple") # Shink current axis by 15% box = self.axes.get_position() self.axes.set_position([box.x0, box.y0, box.width * 0.88, box.height]) # Put a legend to the right of the current axis self.axes.legend([plot_op, plot_delta, plot_gamma, plot_theta, plot_rho, plot_risidual], ['Option Price', 'Delta', 'Gamma', 'Theta', 'Rho', 'Residual'], loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8}) if self.current_view == 1: box = self.axes2.get_position() self.axes2.set_position([box.x0, box.y0, box.width * 0.88, box.height]) # Put a legend to the right of the current axis self.axes2.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8}) self.canvas.draw() def onBasicView(self, event=None): self.current_view = 0 # show sliders panel self.sliderPanel.Enable() self.toolbar.Enable() self.fillCheck.Enable() self.panel.Layout() self.Plot_Data() def onAdvancedView(self, event=None): self.current_view = 1 # show sliders panel self.sliderPanel.Enable() self.toolbar.Enable() self.fillCheck.Enable() self.panel.Layout() self.Plot_Data() def onAdvanced3DView(self, event=None): self.current_view = 2 # hide slider panel since will not be used self.sliderPanel.Disable() self.toolbar.Disable() self.fillCheck.Disable() self.panel.Layout() self.Plot_Data() def onPrinterSetup(self,event=None): self.canvas.Printer_Setup(event=event) def onPrinterPreview(self,event=None): self.canvas.Printer_Preview(event=event) def onPrint(self,event=None): self.canvas.Printer_Print(event=event) def onClipboard(self,event=None): self.canvas.Copy_to_Clipboard(event=event) def onKeyEvent(self,event=None): """ capture and act upon keystroke events """ if event == None: return key = event.GetKeyCode() if (key < wx.WXK_SPACE or key > 255): return if (event.ControlDown() and chr(key)=='C'): # Ctrl-C self.onClipboard(event=event) if (event.ControlDown() and chr(key)=='P'): # Ctrl-P self.onPrinterPreview(event=event) def onHelp(self, event=None): dlg = wx.MessageDialog(self, self.help_msg, "Quick Reference", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onAbout(self, event=None): dlg = wx.MessageDialog(self, self.about_msg, "About", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onViewGrid(self, event=None): if self.viewGrid: self.viewGrid = False else: self.viewGrid = True for a in self.fig.axes: a.grid(self.viewGrid) self.canvas.draw() def onExport(self,event=None): """ save figure image to file""" file_choices = "PNG (*.png)|*.png|" \ "JPEG (*.jpg)|*.jpg|" \ "BMP (*.bmp)|*.bmp" thisdir = os.getcwd() dlg = wx.FileDialog(self, message='Save Plot Figure as...', defaultDir = thisdir, defaultFile='plot.png', wildcard=file_choices, style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.canvas.print_figure(path,dpi=300) if (path.find(thisdir) == 0): path = path[len(thisdir)+1:] print('Saved plot to %s' % path) def onImport(self, event=None): """ Import csv file of option prices and greeks """ file_choices = "SETTINGS (*.settings)|*.settings" thisdir = ''.join(os.getcwd()+'/data') # import output file dlg = wx.FileDialog(self, message='Import option prices and greeks (Outputs)', defaultDir = thisdir, defaultFile='data.settings', wildcard=file_choices, style=wx.OPEN) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() projectDir = path.rsplit('/', 1)[0] #projectDir = path.rsplit('\\', 1)[0] self.reInitialiseData() # this also involves reading in all the data self.number_bumps = self.fileReader.loadSettingsFile(path, projectDir, self.statusbar) print('Opened settings file at %s' % path) else: dlg = wx.MessageDialog(self, "Failed to import the correct settings file.", "Complication", wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return # populate data self.strike_price = self.fileReader.getStrikePrice() self.stock_price = self.fileReader.getStockPrice() self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), self.optionPriceCheck.IsChecked()) self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked()) self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked()) # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), self.vegaCheck.IsChecked()) self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked()) self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked()) self.onBasicView() def onExit(self,event=None): dlg = wx.MessageDialog(None, 'Are you sure to exit?', 'Confirm', wx.YES_NO|wx.NO_DEFAULT|wx.ICON_QUESTION) ret = dlg.ShowModal() if ret == wx.ID_YES: self.Destroy() """ GUI event methods """ def onShowFillEffect(self, event=None): if self.fillCheck.IsChecked(): if self.differenceCheck.IsChecked(): self.differenceCheck.SetValue(False) # reload and replot data self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), # self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.viewFill = True else: self.viewFill = False self.Plot_Data() def onCallRadio(self, event=None): self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), self.optionPriceCheck.IsChecked()) self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), # self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onPutRadio(self, event=None): self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), self.optionPriceCheck.IsChecked()) self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), # self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onOptionPrice(self, event=None): self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), self.optionPriceCheck.IsChecked()) self.Plot_Data() def onDelta(self, event=None): self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onGamma(self, event=None): self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onRho(self, event=None): self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onTheta(self, event=None): self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onVega(self, event=None): self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onRisidual(self, event=None): self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) # print(self.risidual) self.Plot_Data() def onShowEffects(self, event=None): if not self.effectCheck.IsChecked(): warning_msg = """ This setting will plot the value of the greeks, but not terms of the option price. This means that the greek graphs will no-longer be comparable. You will still be able to plot the greeks against each other though. Do you want to continue? """ dlg = wx.MessageDialog(self, warning_msg, "Take Note", wx.YES_NO | wx.ICON_INFORMATION) ret = dlg.ShowModal() if ret == wx.ID_NO: dlg.Destroy() self.effectCheck.SetValue(True) return dlg.Destroy() self.differenceCheck.Disable() self.fillCheck.Disable() self.optionPriceCheck.SetValue(False) self.onOptionPrice() self.optionPriceCheck.Disable() else: self.differenceCheck.Enable() self.optionPriceCheck.Enable() if self.current_view != 2: self.fillCheck.Enable() # reload and replot data self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), # self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onDifferenceCheck(self, event=None): if self.fillCheck.IsChecked(): self.fillCheck.SetValue(False) self.viewFill = False # reload and replot data self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), # self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked()) self.Plot_Data() def onStockSlider(self, event=None): self.statusbar.SetStatusText("Stock price bump: "+str(self.stockSlider.GetValue())) self.stock_bump = self.stockSlider.GetValue()-1 self.Plot_Data() def onRateSlider(self, event=None): self.statusbar.SetStatusText("Interest Rate bump: "+str(self.rateSlider.GetValue())) self.rate_bump = self.rateSlider.GetValue()-1 self.Plot_Data() def onVolatilSlider(self, event=None): self.statusbar.SetStatusText("Volatility bump: "+str(self.volatilSlider.GetValue())) self.volitile_bump = self.volatilSlider.GetValue()-1 self.Plot_Data() def ontimeStepSlider(self, event=None): self.statusbar.SetStatusText("Time step bump: "+str(self.timeStepSlider.GetValue())) self.time_bump = self.timeStepSlider.GetValue()-1 self.Plot_Data() self.Plot_Data() """ Graph plotting methods """ def clearPlots(self): """ Clear all graphs and plots for next draw """ for a in self.fig.axes: self.fig.delaxes(a) def Plotter_2D_general(self, axes): # plot option price graph temp_option_price = [] if len(self.option_price) > 0: temp_option_price = numpy.array(map(float, self.option_price[self.stock_bump])) if len(self.option_price) > 0: axes.plot(self.time, self.option_price[self.stock_bump], color='black') # stagger plot effects of greeks temp_delta = [] temp_gamma = [] temp_theta = [] temp_rho = [] temp_risidual = [] if len(self.delta) > 0: temp_delta = numpy.array(self.delta[self.stock_bump]) if len(self.gamma) > 0: temp_gamma = numpy.array(self.gamma[self.stock_bump]) if len(self.rho) > 0: temp_rho = numpy.array(self.rho[self.rate_bump]) if len(self.theta) > 0: temp_theta = numpy.array(self.theta[self.time_bump]) if len(self.risidual) > 0: temp_risidual = numpy.array(self.risidual[self.stock_bump]) if not self.differenceCheck.IsChecked() and len(temp_option_price) > 0: for t in self.time: greeks_below = [] greeks_above = [] # above/below option price if t < 30: # sort arrays if len(temp_delta) > 0: if temp_delta[t+1] > temp_option_price[t+1]: greeks_above.append([temp_delta[t:t+2], 'delta']) else: greeks_below.append([temp_delta[t:t+2], 'delta']) if len(temp_gamma) > 0: if temp_gamma[t+1] > temp_option_price[t+1]: greeks_above.append([temp_gamma[t:t+2], 'gamma']) else: greeks_below.append([temp_gamma[t:t+2], 'gamma']) if len(temp_theta) > 0: if temp_theta[t+1] > temp_option_price[t+1]: greeks_above.append([temp_theta[t:t+2], 'theta']) else: greeks_below.append([temp_theta[t:t+2], 'theta']) if len(temp_rho) > 0: if temp_rho[t+1] > temp_option_price[t+1]: greeks_above.append([temp_rho[t:t+2], 'rho']) else: greeks_below.append([temp_rho[t:t+2], 'rho']) if len(temp_risidual) > 0: if temp_risidual[t+1] > temp_option_price[t+1]: greeks_above.append([temp_risidual[t:t+2], 'risidual']) else: greeks_below.append([temp_risidual[t:t+2], 'risidual']) temp_time = numpy.arange(t, t+2, 1) greeks_above = sorted(greeks_above, key=lambda tup: tup[0][1]) greeks_below = sorted(greeks_below, key=lambda tup: tup[0][1], reverse=True) # PLOT stagger greek effects temp_time = numpy.arange(t, t+2, 1) temp1 = numpy.array(temp_option_price[t:t+2]) # print(t, greeks_below, greeks_above) for g in greeks_above: # print(t) temp2 = numpy.array([temp_option_price[t], g[0][1]]) if self.viewFill and len(self.option_price) > 0: if g[1] == 'delta': axes.fill_between(temp_time, temp2, temp1, color='blue') if g[1] == 'gamma': axes.fill_between(temp_time, temp2, temp1, color='cyan') if g[1] == 'theta': axes.fill_between(temp_time, temp2, temp1, color='green') if g[1] == 'rho': axes.fill_between(temp_time, temp2, temp1, color='darkorange') if g[1] == 'risidual': axes.fill_between(temp_time, temp2, temp1, color='purple') if g[1] == 'delta': axes.plot(temp_time, temp2, label="Delta", color='blue') if g[1] == 'gamma': axes.plot(temp_time, temp2, label="Gamma", color='cyan') if g[1] == 'theta': axes.plot(temp_time, temp2, label="Theta", color='green') if g[1] == 'rho': axes.plot(temp_time, temp2, label="Rho", color='darkorange') if g[1] == 'risidual': axes.plot(temp_time, temp2, label="risidual", color='purple') temp1 = temp2 temp1 = numpy.array(temp_option_price[t:t+2]) for g in greeks_below: temp2 = numpy.array([temp_option_price[t], g[0][1]]) if self.viewFill and len(self.option_price) > 0: if g[1] == 'delta': axes.fill_between(temp_time, temp2, temp1, color='blue') if g[1] == 'gamma': axes.fill_between(temp_time, temp2, temp1, color='cyan') if g[1] == 'theta': axes.fill_between(temp_time, temp2, temp1, color='green') if g[1] == 'rho': axes.fill_between(temp_time, temp2, temp1, color='darkorange') if g[1] == 'risidual': axes.fill_between(temp_time, temp2, temp1, color='purple') if g[1] == 'delta': axes.plot(temp_time, temp2, label="Delta", color='blue') if g[1] == 'gamma': axes.plot(temp_time, temp2, label="Gamma", color='cyan') if g[1] == 'theta': axes.plot(temp_time, temp2, label="Theta", color='green') if g[1] == 'rho': axes.plot(temp_time, temp2, label="Rho", color='darkorange') if g[1] == 'risidual': axes.plot(temp_time, temp2, label="risidual", color='purple') temp1 = temp2 else: # plot difference between greeks and option price if len(self.delta) > 0: axes.plot(self.delta[self.stock_bump], color='blue') if len(self.gamma) > 0: axes.plot(self.gamma[self.stock_bump], color='cyan') # if len(self.vega) > 0: # axes.plot(self.vega[self.volitile_bump], label="Vega", color='yellow') if len(self.theta) > 0: axes.plot(self.time, self.theta[self.time_bump], color='green') if len(self.rho) > 0: axes.plot(self.time, self.rho[self.rate_bump], color='darkorange') if len(self.risidual) > 0: axes.plot(self.time, self.risidual[self.stock_bump], color='purple') if self.viewLegend: # use proxy artist plot_op = Line2D([], [], linewidth=3, color="black") plot_delta = Line2D([], [], linewidth=3, color="royalblue") plot_gamma = Line2D([], [], linewidth=3, color="cyan") plot_theta = Line2D([], [], linewidth=3, color="green") plot_rho = Line2D([], [], linewidth=3, color="darkorange") plot_risidual = Line2D([], [], linewidth=3, color="purple") # Shink current axis by 15% box = axes.get_position() axes.set_position([box.x0, box.y0, box.width * 0.88, box.height]) # Put a legend to the right of the current axis axes.legend([plot_op, plot_delta, plot_gamma, plot_theta, plot_rho, plot_risidual], ['Option Price', 'Delta', 'Gamma', 'Theta', 'Rho', 'Residual'], loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8}) def Plot_Data(self): if self.current_view == 1: self.Plot_Data_advanced() elif self.current_view == 2: self.Plot_Data_3D() elif self.current_view == 0: """ Basic 2D graph plotter """ self.clearPlots() self.axes = self.fig.add_subplot(111) # can use add_axes, but then nav-toolbar would not work self.axes.set_xlim(0, 30) self.axes.grid(self.viewGrid) self.Plotter_2D_general(self.axes) # set caption and axes labels self.axes.set_xlabel('Time (Daily)') if self.effectCheck.IsChecked(): self.axes.set_ylabel('Price (Rands)') if hasattr(self, 'title'): self.title.set_text('Option Prices and breakdown of the effects of Greeks') else: self.title = self.fig.suptitle('Option Prices and breakdown of the effects of Greeks') else: self.axes.set_ylabel('Greek Value') if hasattr(self, 'title'): self.title.set_text('Raw Greek values not in terms of option price') else: self.title = self.fig.suptitle('Greek values not in terms of option price') self.canvas.draw() def Plot_Data_advanced(self): """ Advanced 2D plotter """ self.clearPlots() self.axes2 = self.fig.add_subplot(212) self.axes = self.fig.add_subplot(211, sharex=self.axes2) self.axes.set_xlim(0, 30) self.axes.grid(self.viewGrid) self.axes2.grid(self.viewGrid) self.Plotter_2D_general(self.axes) # plot strike price and stock price curve if self.strike_price > 0: self.axes2.plot([0, 30], [self.strike_price, self.strike_price], label="Strike Price", color='red') # plot stock price curve temp_stock_price = numpy.array(self.stock_price) if len(temp_stock_price) > 0: self.axes2.plot(self.time, temp_stock_price, label="Stock Price", color='blue') # set limits for x and y axes # self.axes2.set_xlim(self.time_span_fill[0], self.time_span_fill[-1]) # self.axes2.set_ylim(min(p, key=float), max(p, key=float)) # set caption and axes labels self.axes2.set_xlabel('Time (Daily)') self.axes2.set_ylabel('Price (Rands)') if self.effectCheck.IsChecked(): self.axes.set_ylabel('Price (Rands)') if hasattr(self, 'title'): self.title.set_text('Option Prices and breakdown of the effects of Greeks') else: self.title = self.fig.suptitle('Option Prices and breakdown of the effects of Greeks') else: self.axes.set_ylabel('Greek Value') if hasattr(self, 'title'): self.title.set_text('Raw Greek values not in terms of option price') else: self.title = self.fig.suptitle('Greek values not in terms of option price') # set useblit True on gtkagg for enhanced performance # self.span = SpanSelector(self.axes, self.onselect, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='red')) if self.viewLegend: # Shink current axis by 15% box = self.axes2.get_position() self.axes2.set_position([box.x0, box.y0, box.width * 0.88, box.height]) # Put a legend to the right of the current axis self.axes2.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8}) self.canvas.draw() def Plot_Data_3D(self): """ Advanced 3D plotter """ # plot graphs self.clearPlots() self.axes = self.fig.add_subplot(111, projection='3d') # can use add_axes, but then nav-toolbar would not work self.axes.grid(self.viewGrid) b = numpy.arange(0, 9, 1) X2D, Y2D = numpy.meshgrid(self.time, b) Z2D = None # plot option price surface if len(self.option_price) > 0: Z2D = [[float(string) for string in inner] for inner in self.option_price] surf = self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, antialiased=False, alpha=0.75, cmap=cm.afmhot, zorder=0.5) #cm.coolwarm, cm.winter, cm.autumn cbar = self.fig.colorbar(surf, shrink=0.5, aspect=5) cbar.set_label('Option Price', rotation=90) ### TODO - mayavi ### # X2D, Y2D = numpy.mgrid[self.time, b] # print(X2D) # s = mlab.surf(Z2D) # mlab.show() # plot greek surfaces if len(self.delta) > 0: Z2D = [[float(string) for string in inner] for inner in self.delta] self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, antialiased=False, alpha=0.75, color='blue') if len(self.gamma) > 0: Z2D = [[float(string) for string in inner] for inner in self.gamma] self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, antialiased=False, alpha=0.75, color='cyan') if len(self.theta) > 0: Z2D = [[float(string) for string in inner] for inner in self.theta] self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, antialiased=False, alpha=0.75, color='green') if len(self.rho) > 0: Z2D = [[float(string) for string in inner] for inner in self.rho] self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, antialiased=False, alpha=0.75, color='orange') # if len(self.vega) > 0: # Z2D = [[float(string) for string in inner] for inner in self.vega] # self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, # antialiased=False, alpha=0.75, color='aqua') if len(self.risidual) > 0: Z2D = [[float(string) for string in inner] for inner in self.risidual] self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1, antialiased=False, alpha=0.75, color='rosybrown') if Z2D != None: # cset1 = self.axes.contourf(X2D, Y2D, Z2D, zdir='z', offset=300, cmap=cm.afmhot) self.axes.contourf(X2D, Y2D, Z2D, zdir='x', offset=0, cmap=cm.coolwarm) self.axes.contour(X2D, Y2D, Z2D, zdir='y', offset=-0.3, cmap=cm.winter) # cset = self.axes.contour(X2D, Y2D, Z2D, zdir='y', offset=10, cmap=cm.afmhot) # cbar = self.fig.colorbar(cset1, shrink=0.7, aspect=3) # cbar = self.fig.colorbar(cset2, shrink=0.7, aspect=3) # cbar = self.fig.colorbar(cset3, shrink=0.5, aspect=5) # cbar.set_label('Option Proce', rotation=90) # set captions and axis labels self.axes.set_xlabel('Time (Days)') self.axes.set_xlim(0, 35) self.axes.set_ylabel('Bump Size') #~ self.axes.set_ylim(-3, 8) # self.axes.set_zlabel('Price (Rands)') # ~ self.axes.set_zlim(-100, 100) if self.effectCheck.IsChecked(): if self.differenceCheck.IsChecked(): self.axes.set_zlabel('Greek Value') else: self.axes.set_zlabel('Price (Rands)') if hasattr(self, 'title'): self.title.set_text('Option Prices and breakdown of the effects of Greeks') else: self.title = self.fig.suptitle('Option Prices and breakdown of the effects of Greeks') else: self.axes.set_zlabel('Greek Value') if hasattr(self, 'title'): self.title.set_text('Raw Greek values not in terms of option price') else: self.title = self.fig.suptitle('Greek values not in terms of option price') self.canvas.draw()
class PanelGraph(wx.Panel): def __init__(self, parent, figure=None): wx.Panel.__init__(self, parent, id=-1, style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL) self.figure = figure self.figure.set_size_inches(90, 90) self.canvas = Canvas(self, -1, figure) self.SetColor( (255,255,255) ) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas,1,wx.EXPAND|wx.ALL, 0) self.SetSizer(sizer) 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 Save_image(self): """ save figure image to file""" file_choices = "PNG (*.png)|*.png|" \ "PS (*.ps)|*.ps|" \ "EPS (*.eps)|*.eps|" \ "BMP (*.bmp)|*.bmp" standardPath = wx.StandardPaths.Get() save_destination = standardPath.GetDocumentsDir() dlg = wx.FileDialog(self, message=_(u"Enregistrer le graphe sous..."), defaultDir = save_destination, defaultFile="graphe.png", wildcard=file_choices, style=wx.FD_SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.canvas.print_figure(path, dpi=300) message = _(u"Le graphe a été sauvegardé avec succès") dlg = wx.MessageDialog(self, message, _(u"Sauvegarde"), wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def Clipboard_image(self): self.canvas.Copy_to_Clipboard() message = _(u"Le graphe a été envoyé dans le presse-papiers.") dlg = wx.MessageDialog(self, message, _(u"Presse-papiers"), wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def Imprimer_image(self): # Enregistrement de l'image dans repertoire Temp self.canvas.print_figure(UTILS_Fichiers.GetRepTemp(fichier="grapheTemp.png"), dpi=300) # Création du PDF from reportlab.pdfgen import canvas as canvasPDF from reportlab.lib.pagesizes import A4 hauteur, largeur = A4 cheminFichier = UTILS_Fichiers.GetRepTemp(fichier="grapheTemp.pdf") if sys.platform.startswith("win") : cheminFichier = cheminFichier.replace("/", "\\") c = canvasPDF.Canvas(cheminFichier, pagesize=(largeur, hauteur), pageCompression = 1) img = c.drawImage(UTILS_Fichiers.GetRepTemp(fichier="grapheTemp.png"), 0, 0, width=largeur, height=hauteur, preserveAspectRatio=True) c.save() FonctionsPerso.LanceFichierExterne(cheminFichier)
class BarChartGraphic(wx.Panel): """ This module accepts data, creates a BarChart from it, and places that BarChart in the CLipboard. """ def __init__(self, parent, pos=(10, 10)): """ Initialize a panel for drawing the BarChart. This panel can be hidden. """ # Initialize a Panel wx.Panel.__init__(self, parent, pos=pos) # Create a PyPlot figure self.figure = plt.figure(figsize=(7, 9)) # Create a MatPlotLib FigureCanvas based on the Panel and the Figure self.canvas = FigureCanvas(self, -1, self.figure) def plot(self, title, data, dataLabels): """ Create a BarChart. title Title for the BarChart data List of data values for the BarChart dataLabels Matching list of data labels for the BarChart This module limits the BarChart to 15 bars max. """ # Clear the Figure (in case we use the same BarChartGraphic to create multiple BarCharts) self.figure.clf() # The length of data is the number of bars we need numBars = len(data) # Define the colors to be used in the BarChart # If we're running stand-alone ... if __name__ == '__main__': # ... use generic colors colors = [ '#FF0000', '#00FF00', '#0000FF', '#666600', '#FF00FF', '#00FFFF', '#440000', '#004400', '#000044' ] # colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (0.5, 0.5, 0), (1, 0, 1), (0, 1, 1)] # There are no Colors for Keywords when running stand-alone colorsForKeywords = {} # If we're running inside Transana ... else: # ... import Transana's Global Values ... import TransanaGlobal # ... and use Transana's defined color scheme colorList = TransanaGlobal.getColorDefs( TransanaGlobal.configData.colorConfigFilename)[:-1] # Initialize the Colors list colors = [] # Populate the colors list. for colorName, colorDef in colorList: # MatPlotLib uses a 0 .. 1 scale rather than a 0 .. 255 scale for RGB colors! colors.append((colorDef[0] / 255.0, colorDef[1] / 255.0, colorDef[2] / 255.0)) # Get the color definitions for all keywords in Transana colorsForKeywords = DBInterface.dict_of_keyword_colors() # If we have more data points that will fit, we should truncate the number of bars maxBars = 30 if numBars > maxBars: # Reduce data to the first 15 points data = data[:maxBars] # Reduce the data labels to the first 15 labels dataLabels = dataLabels[:maxBars] # Reduce the number of bars to be displayed to maxBars numBars = maxBars # X values for the bars are simple integers for bar number xValues = range(numBars) # Set the bar width to allow space between bars width = .85 # Create a MatPlotLib SubPlot ax = self.figure.add_subplot(111) # Define the BarChart Bars in the figure rects1 = ax.bar(xValues, data, width) # Add the Chart Title ax.set_title(title) # If we're running stand-alone ... if __name__ == '__main__': # Add the Y axis label ax.set_ylabel('Frequency') else: # Add the Y axis label ax.set_ylabel(_('Frequency')) # Set X axis tick marks for each bar ax.set_xticks(xValues) # Add the bar labels lbls = ax.set_xticklabels(dataLabels, rotation=90) # 35 65 # Initialize the color list position indicator colorIndx = 0 # For each bar ... for x in range(numBars): # If there's a color defined for the Keyword ... if dataLabels[x] in colorsForKeywords.keys(): # ... use that color color = colorsForKeywords[dataLabels[x]]['colorDef'] # If there's no color defined ... else: # ... use the next color from the color list color = colors[colorIndx] # Increment or reset the color index if colorIndx >= len(colors) - 1: colorIndx = 0 else: colorIndx += 1 # ... define the bar color rects1[x].set_color(color) # ... make the label color match the bar color lbls[x].set_color(color) # Give the graph small inside margins plt.margins(0.05) # Adjust the bottom margin to make room for bar labels plt.subplots_adjust(bottom=0.5) # 0.2 0.4 # Draw the BarChart self.canvas.draw() # Copy the BarChart to the Clipboard self.canvas.Copy_to_Clipboard()
class t_C_MatPlot(My_Control_Class): def __init__(self, *args, **kwargs): My_Control_Class.__init__(self, *args, **kwargs) # ************************************************************* # Create the panel with the plot controls # ************************************************************* self.Panel = wx.Panel(self.Dock) self.CB_Grid = wx.CheckBox(self.Panel, -1, "Grid", pos=(0, 5)) self.CP_Grid = wx.ColourPickerCtrl(self.Panel, -1, pos=(40, 1)) wx.StaticText(self.Panel, -1, "BackGround-", pos=(70, 5)) self.CP_BG = wx.ColourPickerCtrl(self.Panel, -1, pos=(130, 1)) self.CB_Axis = wx.CheckBox(self.Panel, -1, "Axis", pos=(160, 5)) self.CB_Legend = wx.CheckBox(self.Panel, -1, "Legend", pos=(210, 5)) self.CB_Polar = wx.CheckBox(self.Panel, -1, "Low Res", pos=(275, 5)) self.CB_FFT = wx.CheckBox(self.Panel, -1, "FFT", pos=(335, 5)) bmp = wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_BUTTON, (16, 16)) self.Button_ClipBoard = wx.BitmapButton(self.Panel, -1, bmp, pos=(375, 0)) self.Button_ClipBoard.SetToolTipString('Copy to ClipBoard') bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_BUTTON, (16, 16)) self.Button_Image = wx.BitmapButton(self.Panel, -1, bmp, pos=(405, 0)) self.Button_Image.SetToolTipString('Save as PNG-image') if self.Test: self.Spin = wx.SpinCtrl(self.Panel, wx.ID_ANY, min=1, max=5, pos=(435, 2), size=(40, 20)) self.Spin.SetToolTipString('Select Demo') # background color of the not used part of the button bar self.Dock.SetBackgroundColour(self.Panel.GetBackgroundColour()) # ************************************************************* # ************************************************************* # ************************************************************* # These parameters must be set before the figure is created # EASIER to set these parameters from rcParams, than from rc, # because you can use deep nested properties #rc ('figure.subplot', 'left' = 0.5) ## not accepted rcParams['figure.subplot.top'] = 0.95 rcParams['figure.subplot.bottom'] = 0.05 rcParams['figure.subplot.left'] = 0.1 rcParams['figure.subplot.right'] = 0.97 self.figure = Figure() self.Canvas = FigureCanvas(self.Dock, -1, self.figure) self.axes = self.figure.add_subplot(111) self.axes_2 = None self.lx = None # ************************************************************* # ************************************************************* # Try to reload the settings, otherwise set defaults # ************************************************************* self.Legends = ('signal 1', 'signal 2') self.SignalsX = [] self.SignalsY = [] self.Pseudo_Color = False if self.Test and self.Ini: print('piep1') self.Ini.Section = 'MatPlot' #line = self.Ini.Read ( 'Pars', '' ) self.Load_Settings(self.Ini) if self.Test: self.MatPlot_Example(self.Spin.GetValue()) else: self.MatPlot_Redraw() # ************************************************************* # ************************************************************* # ************************************************************* Sizer = wx.BoxSizer(wx.VERTICAL) Sizer.Add(self.Canvas, 1, wx.EXPAND) Sizer.Add(self.Panel, 0) self.Dock.SetSizer(Sizer) #Dock.Fit() # We need this for Ubuntu, and even then it works limited self.Dock.Bind(wx.EVT_SIZE, self._OnSize) # ************************************************************* # ************************************************************* # ************************************************************* self.Dock.Bind(wx.EVT_COLOURPICKER_CHANGED, self.MatPlot_OnPolar, self.CP_Grid) self.Dock.Bind(wx.EVT_COLOURPICKER_CHANGED, self.MatPlot_OnSet_CBs, self.CP_BG) self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnSet_CBs, self.CB_Grid) self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnSet_CBs, self.CB_Axis) self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnSet_CBs, self.CB_Legend) self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnPolar, self.CB_Polar) self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnFFT, self.CB_FFT) self.Button_Image.Bind(wx.EVT_BUTTON, self.MatPlot_OnSaveImage, self.Button_Image) self.Button_ClipBoard.Bind(wx.EVT_BUTTON, self.MatPlot_OnCopyClipBoard, self.Button_ClipBoard) if self.Test: self.Spin.Bind(wx.EVT_SPINCTRL, self.MatPlot_OnSpinEvent, self.Spin) self.Dock.Bind(wx.EVT_CLOSE, self.MatPlot_OnClose) #if not ( self.connect ) : self.Dock.connect = self.Canvas.mpl_connect('motion_notify_event', self.MatPlot_OnMotion) # ************************************************************* # ************************************************************* # We need this for Ubuntu, and even then it works limited # ************************************************************* def _OnSize(self, event): event.Skip() wx.CallAfter(self.MatPlot_Redraw) # ************************************************************* # ************************************************************* def Calculate(self): # input might be one of the following: # 1: <array> # 2: list = [ <array>, [ <signal name>, <signal color>, <linewidth> ] ] # # array might be one of the following: # A: a 1-dimensional array ==> y(x), x=equidistant # B: a 2-dimensional array, with second dimension = 2 ==> y = f(x) # C: a 2-dimensional array, with second dimension >> 6 ==> z = f(x,y) # we can either use signal, which is the input channel that has changed # or use the Bricks input channels, so we can use all of them at once self.SignalsX = [] self.SignalsY = [] self.Legends = [] # for test purposes, we don't have a brick but Test_Inputs try: Inputs = self.Brick.In except: Inputs = self.Test_Inputs for s, IVV in enumerate(Inputs[1:]): if IVV != None: #print 'MatPlot',s,len(IVV) if not ( operator.isSequenceType ( IVV ) ) or \ isinstance ( IVV, ndarray ): IVV = eval('[IVV]') #print 'no sequence' # determine the number of arrays # if exactly 2, special case: x,y pairs NA = 0 for IV in IVV: if isinstance(IV, ndarray): NA += 1 else: break #print 'NA',NA,IVV[0].shape # process all signals self.Pseudo_Color = False if IVV[0].ndim == 2: self.Pseudo_Color = True self.SignalsX.append(IVV[0]) elif NA == 1: L = len(IVV[0]) self.SignalsX.append(linspace(0, L - 1, L)) self.SignalsY.append(IVV[0]) elif NA == 2: self.SignalsX.append(IVV[0]) self.SignalsY.append(IVV[1]) else: self.SignalsX.append(IVV[0]) for i, IV in enumerate(IVV[1:NA]): self.SignalsY.append(IV) # add legends if NA == 1: if (len(IVV) > NA) and (len(IVV[NA]) > 0): self.Legends.append(IVV[NA][0]) else: self.Legends.append('Signal 1') for i, IV in enumerate(IVV[1:NA]): if (len(IVV) > NA) and (len(IVV[NA]) > i): self.Legends.append(IVV[NA][i]) else: self.Legends.append('Signal ' + str(i + 1)) #print 'Legends',self.Legends self.MatPlot_ReCreate_Plot() #print 'MatPlot recreated' # ************************************************************* # ************************************************************* def MatPlot_ReCreate_Plot(self): # BUG, "hold" doesn't work in polar, therefore create a new figure # helps sometimes .... for polar plot ## LUKT NIET MEER rcParams [ 'grid.color' ] = self.Color_2_MatPlot ( self.CP_Grid.GetColour () ) self.figure.clear() self.lx = None if not (self.Pseudo_Color): self.CB_Polar.SetLabel('-Polar') if self.CB_FFT.GetValue(): config = 212 else: config = 111 self.axes = self.figure.add_subplot(config, polar=self.CB_Polar.GetValue()) for i, SX in enumerate(self.SignalsY): self.axes.plot( self.SignalsX[0], self.SignalsY[i], ) if self.CB_FFT.GetValue(): self.axes_2 = self.figure.add_subplot( 211, polar=self.CB_Polar.GetValue()) for i, SX in enumerate(self.SignalsY): self.axes_2.psd( self.SignalsY[i], 512, 1, #detrend = mlab.detrend_linear, #doesn't work #detrend = mlab.detrend_mean, #doesn't work detrend=mlab.detrend_none, #window = mlab.window_none ) #weird scaling window=mlab.window_hanning) # doesn't work: # self.axes_2.xlabel = 'aap' # self.axes_2.axis ( 0, 0, 50, -50) else: self.axes_2 = None else: # Pseudo color self.CB_FFT.Hide() self.CB_Polar.SetLabel('-Low Res') self.axes = self.figure.add_subplot(111) if self.CB_Polar.GetValue(): cmap = cm.get_cmap('jet', 10) # 10 discrete colors else: cmap = cm.jet #cmap = cm.gray # IMPORTANT, setting the size explictly, # prevents rescaling which sometimes occurs when crosshair is drawn s = self.SignalsX[0].shape try: # SignalsX might not be available yet im = self.axes.imshow(self.SignalsX[0], cmap=cmap, extent=(0, s[0], 0, s[1])) #im.set_interpolation ( 'nearest' ) # and there are a lot more !! #im.set_interpolation ( 'bicubic' ) im.set_interpolation('bilinear') self.figure.colorbar(im) except: pass self.axes.hold(True) # needed for measurement cursor if self.axes_2: self.axes_2.hold(True) self.MatPlot_Redraw() # ************************************************************* # ************************************************************* def MatPlot_Redraw(self): color = self.CP_BG.GetColour() color = self.Color_2_MatPlot(color) self.axes.set_axis_bgcolor(color) if self.axes_2: self.axes_2.set_axis_bgcolor(color) self.figure.set_facecolor(color) self.figure.set_edgecolor(color) if self.CB_Axis.GetValue(): self.axes.set_axis_on() if self.axes_2: self.axes_2.set_axis_on() else: self.axes.set_axis_off() if self.axes_2: self.axes_2.set_axis_off() color = self.CP_Grid.GetColour() color = self.Color_2_MatPlot(color) self.axes.grid(self.CB_Grid.GetValue()) if self.axes_2: self.axes_2.grid(self.CB_Grid.GetValue()) # setting the grid color sometimes generates an exception # this seems to happen completely random ???? try: if self.CB_Grid.GetValue(): self.axes.grid(color=color) if self.axes_2: self.axes_2.grid(color=color) except: pass # Polar doesn't support legend (use figlegend) if self.Pseudo_Color or not (self.CB_Polar.GetValue()): if self.CB_Legend.GetValue(): self.axes.legend(self.Legends) else: self.axes.legend_ = None # FFT plot: no legend if self.axes_2: self.axes_2.legend_ = None self.Canvas.draw() # ************************************************************* # create an example image # ************************************************************* def MatPlot_Example(self, Example): self.Test_Inputs = [None] if Example == 1: # Sine x = arange(0.0, 3.0, 0.01) y = sin(2 * pi * x) elif Example == 2: # SPIRAL t = arange(0, 10 * pi, 0.1) x = t * sin(t) y = t * cos(t) elif Example == 3: # CARDIOID t = arange(0, 2 * pi, 0.1) x = (1 + cos(t)) * cos(t) y = (1 + cos(t)) * sin(t) elif Example == 4: # SPIROGRAPH phi = linspace(0, 4, 100) #r=sin(phi*pi) # r = sin(cos(tan(phi))) x = phi y = 20 * r elif Example == 5: # Pseudo Color def _func(x, y): return (1 - x / 2 + x**5 + y**3) * exp(-x**2 - y**2) dx, dy = 0.05, 0.05 x = arange(-3.0, 3.0, dx) y = arange(-3.0, 3.0, dy) X, Y = meshgrid(x, y) self.Test_Inputs.append(_func(X, Y)) if len(self.Test_Inputs) == 1: temp = [] temp.append(x) temp.append(y) self.Test_Inputs.append(temp) self.Calculate() # ************************************************************* # ************************************************************* def MatPlot_OnMotion(self, event): if self.CB_Polar.GetValue() and not (self.Pseudo_Color): return x, y = event.x, event.y # check if within an "axes" but not in a "bar-axes" if event.inaxes and isinstance(event.inaxes, matplotlib.axes.Subplot): x, y = event.xdata, event.ydata if not (self.lx): self.minx, self.maxx = event.inaxes.get_xlim() self.miny, self.maxy = event.inaxes.get_ylim() """ self.lx, = self.axes.plot ( ( self.minx, self.maxx ), ( y, y ), 'k-' ) # the horiz line self.ly, = self.axes.plot ( ( x, x ), ( self.miny, self.maxy ), 'k-' ) # the vert line self.meas_txt = self.axes.text ( 0.02, 0.02, 'x=%1.2f, y=%1.2f'% ( x, y ), transform = self.axes.transAxes ) """ self.lx, = event.inaxes.plot((self.minx, self.maxx), (y, y), 'k-') # the horiz line self.ly, = event.inaxes.plot((x, x), (self.miny, self.maxy), 'k-') # the vert line self.meas_txt = event.inaxes.text( 0.02, 0.02, 'x=%1.2f, y=%1.2f' % (x, y), transform=event.inaxes.transAxes) else: # update the crosshair positions self.lx.set_data((self.minx, self.maxx), (y, y)) self.ly.set_data((x, x), (self.miny, self.maxy)) self.meas_txt.set_text('x=%1.2f, y=%1.2f' % (x, y)) else: # Hide the cross hair if self.lx: self.lx.set_data((x, x), (y, y)) self.ly.set_data((x, x), (y, y)) self.meas_txt.set_text('') self.lx = None self.Canvas.draw() # ************************************************************* # ************************************************************* def MatPlot_OnSet_CBs(self, event): self.MatPlot_Redraw() # ************************************************************* # ************************************************************* def MatPlot_OnPolar(self, event): if self.CB_Polar.GetValue(): self.CB_FFT.Hide() else: self.CB_FFT.Show() self.MatPlot_ReCreate_Plot() # ************************************************************* # ************************************************************* def MatPlot_OnFFT(self, event): if self.CB_FFT.GetValue(): self.CB_Polar.Hide() else: self.CB_Polar.Show() self.MatPlot_ReCreate_Plot() # ************************************************************* # ************************************************************* def MatPlot_OnSpinEvent(self, event): Example = event.GetInt() self.MatPlot_Example(Example) # ************************************************************* # ************************************************************* def MatPlot_OnCopyClipBoard(self, event): #canvas = FigureCanvasWxAgg(...) self.Canvas.Copy_to_Clipboard(event=event) # ************************************************************* # ************************************************************* def MatPlot_OnSaveImage(self, event): file = Ask_File_For_Save(os.getcwd(), FileTypes='*.png', Title='Save Plot as PNG-image') if file: self.figure.savefig(file) # ************************************************************* # Set Grid color of all backgrounds # Doing this gives huges problems, # therefor we accept that in the polar # ************************************************************* """ def OnGridColor ( self, event ) : rcParams [ 'grid.color' ] = self.Color_2_MatPlot ( self.CP_Grid.GetColour () ) # Because we need to reload the resources, # we force it by recreating to the total plot self.Sizer.Remove ( self.Canvas ) self.figure = Figure () self.Canvas = FigureCanvas ( self.Dock, -1, self.figure ) self.lx = None self.Sizer.Prepend ( self.Canvas, 1, wx.EXPAND ) self.Sizer.Layout () self.MatPlot_Example ( self.Spin.GetValue () ) """ # ************************************************************* # MatPlot accepts RGB colors in relative range 0..1, # alpha blend is also not accepted # ************************************************************* def Color_2_MatPlot(self, color): # if already in MatPlot format, just return the same value if isinstance(color, float) or isinstance(color[0], float): return color # else limit to 3 elements in the range 0.0 ... 1.0 kleur = [] for c in color[:3]: kleur.append(c / 255.0) return kleur # ************************************************************* # MatPlot accepts RGB colors in relative range 0..1, # alpha blend is also not accepted # ************************************************************* def MatPlot_2_Color(self, color): # if already in normal format, just return the same value if isinstance(color, wx.Color): return color if isinstance(color, basestring): try: color = float(color) except: return color # named color probably if isinstance(color, float): i = int(color * 255) kleur = [i, i, i] else: kleur = [] if isinstance(color[0], float): for c in color[:3]: kleur.append(int(255 * c)) else: kleur = color[:3] kleur = wx.Color(*kleur) return kleur # ************************************************************* # ************************************************************* def MatPlot_OnClose(self, event): if self.Ini and self.Test: self.Ini.Section = 'MatPlot' self.Ini.Write('Pos', self.Dock.GetPosition()) self.Ini.Write('Size', self.Dock.GetSize()) self.Save_Settings(self.Ini) event.Skip() # ************************************************************* # ************************************************************* def Save_Settings(self, ini, key=None): if ini: line = [] line.append(tuple(self.CP_BG.GetColour())) line.append(tuple(self.CP_Grid.GetColour())) line.append(self.CB_Grid.GetValue()) line.append(self.CB_Axis.GetValue()) line.append(self.CB_Legend.GetValue()) line.append(self.CB_Polar.GetValue()) line.append(self.CB_FFT.GetValue()) if self.Test: line.append(self.Spin.GetValue()) if not (key): key = 'CS_' v3print('MatPlot SAVE', key, '=', line) line = ini.Write(key, line) # ************************************************************* # ************************************************************* def Load_Settings(self, ini, key=None): #print 'llkwp',line if not (key): key = 'CS_' line = ini.Read(key, '') if line: self.CP_BG.SetColour(line[0]) self.CP_Grid.SetColour(line[1]) self.CB_Grid.SetValue(line[2]) self.CB_Axis.SetValue(line[3]) self.CB_Legend.SetValue(line[4]) self.CB_Polar.SetValue(line[5]) self.CB_FFT.SetValue(line[6]) if self.Test: self.Spin.SetValue(line[7]) self.MatPlot_ReCreate_Plot()
class PlotPanel(wx.Panel): ''' Base class for the plotting in GenX - all the basic functionallity should be implemented in this class. The plots should be derived from this class. These classes should implement an update method to update the plots. ''' def __init__(self, parent, id = -1, color = None, dpi = None , style = wx.NO_FULL_REPAINT_ON_RESIZE|wx.EXPAND|wx.ALL , config = None, config_name = '', **kwargs): wx.Panel.__init__(self,parent, id = id, style = style, **kwargs) self.parent = parent self.callback_window = self self.config = config self.config_name = config_name self.figure = Figure(None,dpi) self.canvas = FigureCanvasWxAgg(self, -1, self.figure) self.canvas.SetExtraStyle(wx.EXPAND) self.SetColor(color) self.Bind(wx.EVT_IDLE, self._onIdle) self.Bind(wx.EVT_SIZE, self._onSize) self._resizeflag = True self.print_size = (15./2.54, 12./2.54) #self._SetSize() # Flags and bindings for zooming self.zoom = False self.zooming = False self.scale = 'linear' self.autoscale = True self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnLeftMouseButtonDown) self.canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftMouseButtonUp) self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMove) self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick) self.canvas.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu) cursor = wx.StockCursor(wx.CURSOR_CROSS) self.canvas.SetCursor(cursor) self.old_scale_state = True self.ax = None # Init printout stuff self.fig_printer = FigurePrinter(self) # Create the drawing bitmap self.bitmap =wx.EmptyBitmap(1, 1) # DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w,h), 2, self) self._isDrawn = False def SetColor(self, rgbtuple=None): ''' Set the figure and canvas color to be the same ''' if not rgbtuple: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() col = [c/255. for c in rgbtuple] self.figure.set_facecolor(col) self.figure.set_edgecolor(col) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) def _onSize(self, evt): self._resizeflag = True self._SetSize() #self.canvas.draw(repaint = False) def _onIdle(self, evt): if self._resizeflag: self._resizeflag = False self._SetSize() #self.canvas.gui_repaint(drawDC = wx.PaintDC(self)) def _SetSize(self, pixels = None): ''' This method can be called to force the Plot to be a desired size which defaults to the ClientSize of the Panel. ''' if not pixels: pixels = self.GetClientSize() self.canvas.SetSize(pixels) #self.figure.set_size_inches(pixels[0]/self.figure.get_dpi() #, pixels[1]/self.figure.get_dpi()) def ReadConfig(self): '''ReadConfig(self) --> None Reads in the config file ''' bool_items = ['zoom', 'autoscale'] bool_func = [self.SetZoom, self.SetAutoScale] if not self.config: return vals = [] for index in range(len(bool_items)): try: val = self.config.get_boolean(self.config_name,\ bool_items[index]) except io.OptionError as e: print('Could not locate option %s.%s'\ %(self.config_name, bool_items[index])) vals.append(None) else: vals.append(val) try: scale = self.config.get(self.config_name, 'y scale') string_sucess = True except io.OptionError as e: string_sucess = False print('Could not locate option %s.%s'\ %(self.config_name, 'scale')) else: self.SetYScale(scale) # This is done due to that the zoom and autoscale has to read # before any commands are issued in order not to overwrite # the config [bool_func[i](vals[i]) for i in range(len(vals)) if vals[i]] def WriteConfig(self): '''WriteConfig(self) --> None Writes the current settings to the config file ''' if self.config: self.config.set(self.config_name, 'zoom', self.GetZoom()) self.config.set(self.config_name, 'autoscale', self.GetAutoScale()) self.config.set(self.config_name, 'y scale', self.GetYScale()) def SetZoom(self, active = False): ''' set the zoomstate ''' #if not self.zoom_sel: #self.zoom_sel = RectangleSelector(self.ax,\ # self.box_select_callback, drawtype='box',useblit=False) #print help(self.zoom_sel.ignore) if active: #self.zoom_sel.ignore = lambda x: False self.zoom = True cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER) self.canvas.SetCursor(cursor) if self.callback_window: evt = state_changed(zoomstate = True,\ yscale = self.GetYScale(), autoscale = self.autoscale) wx.PostEvent(self.callback_window, evt) if self.ax: #self.ax.set_autoscale_on(False) self.old_scale_state = self.GetAutoScale() self.SetAutoScale(False) else: #self.zoom_sel.ignore = lambda x: True self.zoom = False cursor = wx.StockCursor(wx.CURSOR_CROSS) self.canvas.SetCursor(cursor) if self.callback_window: evt = state_changed(zoomstate = False,\ yscale = self.GetYScale(), autoscale = self.autoscale) wx.PostEvent(self.callback_window, evt) if self.ax: #self.ax.set_autoscale_on(self.autoscale) self.SetAutoScale(self.old_scale_state) self.WriteConfig() def GetZoom(self): '''GetZoom(self) --> state [bool] Returns the zoom state of the plot panel. True = zoom active False = zoom inactive ''' return self.zoom def SetAutoScale(self, state): '''SetAutoScale(self, state) --> None Sets autoscale of the main axes wheter or not it should autoscale when plotting ''' #self.ax.set_autoscale_on(state) self.autoscale = state self.WriteConfig() evt = state_changed(zoomstate = self.GetZoom(),\ yscale = self.GetYScale(), autoscale = self.autoscale) wx.PostEvent(self.callback_window, evt) def GetAutoScale(self): '''GetAutoScale(self) --> state [bool] Returns the autoscale state, true if the plots is automatically scaled for each plot command. ''' return self.autoscale def AutoScale(self, force = False): '''AutoScale(self) --> None A log safe way to autoscale the plots - the ordinary axis tight does not work for negative log data. This works! ''' if not (self.autoscale or force): return # If nothing is plotted no autoscale use defaults... if sum([len(line.get_ydata()) > 0 for line in self.ax.lines]) == 0: self.ax.set_xlim(0, 1) self.ax.set_ylim(1e-3, 1.0) return if self.scale == 'log': #print 'log scaling' # Find the lowest possible value of all the y-values that are #greater than zero. check so that y data contain data before min # is applied tmp = [line.get_ydata().compress(line.get_ydata() > 0.0).min()\ for line in self.ax.lines if array(line.get_ydata() > 0.0).sum() > 0] if len(tmp) > 0: ymin = min(tmp) else: ymin = 1e-3 tmp = [line.get_ydata().compress(line.get_ydata() > 0.0).max()\ for line in self.ax.lines if array(line.get_ydata() > 0.0).sum() > 0] if len(tmp) > 0: ymax = max(tmp) else: ymax = 1 else: ymin = min([array(line.get_ydata()).min()\ for line in self.ax.lines if len(line.get_ydata()) > 0]) ymax = max([array(line.get_ydata()).max()\ for line in self.ax.lines if len(line.get_ydata()) > 0]) tmp = [array(line.get_xdata()).min()\ for line in self.ax.lines if len(line.get_ydata()) > 0] if len(tmp) > 0: xmin = min(tmp) else: xmin = 0 tmp = [array(line.get_xdata()).max()\ for line in self.ax.lines if len(line.get_ydata()) > 0] if len(tmp) > 0: xmax = max(tmp) else: xmax = 1 # Set the limits #print 'Autoscaling to: ', ymin, ymax self.ax.set_xlim(xmin, xmax) self.ax.set_ylim(ymin*(1-sign(ymin)*0.05), ymax*(1+sign(ymax)*0.05)) #self.ax.set_yscale(self.scale) self.flush_plot() def SetYScale(self, scalestring): ''' SetYScale(self, scalestring) --> None Sets the y-scale of the main plotting axes. Currently accepts 'log' or 'lin'. ''' if self.ax: if scalestring == 'log': self.scale = 'log' self.AutoScale(force = True) try: self.ax.set_yscale('log') except OverflowError: self.AutoScale(force = True) elif scalestring == 'linear' or scalestring == 'lin': self.scale = 'linear' self.ax.set_yscale('linear') self.AutoScale(force = True) else: raise ValueError('Not allowed scaling') self.flush_plot() evt = state_changed(zoomstate = self.GetZoom(),\ yscale = self.GetYScale(), autoscale = self.autoscale) wx.PostEvent(self.callback_window, evt) self.WriteConfig() def GetYScale(self): '''GetYScale(self) --> String Returns the current y-scale in use. Currently the string 'log' or 'linear'. If the axes does not exist it returns None. ''' if self.ax: return self.ax.get_yscale() else: return None def CopyToClipboard(self, event = None): '''CopyToClipboard(self, event) --> None Copy the plot to the clipboard. ''' self.canvas.Copy_to_Clipboard(event = event) def PrintSetup(self, event = None): '''PrintSetup(self) --> None Sets up the printer. Creates a dialog box ''' self.fig_printer.pageSetup() def PrintPreview(self, event = None): '''PrintPreview(self) --> None Prints a preview on screen. ''' self.fig_printer.previewFigure(self.figure) def Print(self, event= None): '''Print(self) --> None Print the figure. ''' self.fig_printer.printFigure(self.figure) def SetCallbackWindow(self, window): '''SetCallbackWindow(self, window) --> None Sets the callback window that should recieve the events from picking. ''' self.callback_window = window def OnLeftDblClick(self, event): if self.ax and self.zoom: tmp = self.GetAutoScale() self.SetAutoScale(True) self.AutoScale() self.SetAutoScale(tmp) #self.AutoScale() #self.flush_plot() #self.ax.set_autoscale_on(False) def OnLeftMouseButtonDown(self, event): self.start_pos = event.GetPosition() #print 'Left Mouse button pressed ', self.ax.transData.inverse_xy_tup(self.start_pos) class Point: pass p = Point() p.x, p.y = self.start_pos size = self.canvas.GetClientSize() p.y = (size.height - p.y) if self.zoom and self.ax: if mat_ver > zoom_ver: in_axes = self.ax.in_axes(p) else: in_axes = self.ax.in_axes(*self.start_pos) if in_axes: self.zooming = True self.cur_rect = None self.canvas.CaptureMouse() else: self.zooming = False elif self.ax: size = self.canvas.GetClientSize() if mat_ver > zoom_ver: xy = self.ax.transData.inverted().transform(\ array([self.start_pos[0], size.height-self.start_pos[1]])\ [newaxis,:]) x, y = xy[0,0], xy[0,1] else: x, y = self.ax.transData.inverse_xy_tup(\ (self.start_pos[0], size.height - self.start_pos[1])) if self.callback_window: evt = plot_position(text = '(%.3e, %.3e)'%(x, y)) wx.PostEvent(self.callback_window, evt) #print x,y def OnMouseMove(self, event): if self.zooming and event.Dragging() and event.LeftIsDown(): self.cur_pos = event.GetPosition() #print 'Mouse Move ', self.ax.transData.inverse_xy_tup(self.cur_pos) class Point: pass p = Point() p.x, p.y = self.cur_pos size = self.canvas.GetClientSize() p.y = (size.height - p.y) if mat_ver > zoom_ver: in_axes = self.ax.in_axes(p) else: in_axes = self.ax.in_axes(*self.start_pos) if in_axes: new_rect = (min(self.start_pos[0], self.cur_pos[0]), min(self.start_pos[1], self.cur_pos[1]), abs(self.cur_pos[0] - self.start_pos[0]), abs(self.cur_pos[1] - self.start_pos[1])) self._DrawAndErase(new_rect, self.cur_rect) self.cur_rect = new_rect #event.Skip() def OnLeftMouseButtonUp(self, event): if self.canvas.HasCapture(): #print 'Left Mouse button up' self.canvas.ReleaseMouse() if self.zooming and self.cur_rect: # Note: The coordinte system for matplotlib have a different # direction of the y-axis and a different origin! size = self.canvas.GetClientSize() if mat_ver > zoom_ver: start = self.ax.transData.inverted().transform(\ array([self.start_pos[0], size.height-self.start_pos[1]])[newaxis,:]) end = self.ax.transData.inverted().transform(\ array([self.cur_pos[0], size.height-self.cur_pos[1]])[newaxis, :]) xend, yend = end[0,0], end[0,1] xstart, ystart = start[0,0], start[0,1] else: xstart, ystart = self.ax.transData.inverse_xy_tup(\ (self.start_pos[0], size.height-self.start_pos[1])) xend, yend = self.ax.transData.inverse_xy_tup(\ (self.cur_pos[0], size.height-self.cur_pos[1])) #print xstart, xend #print ystart, yend self.ax.set_xlim(min(xstart,xend), max(xstart,xend)) self.ax.set_ylim(min(ystart,yend), max(ystart,yend)) self.flush_plot() self.zooming = False def _DrawAndErase(self, box_to_draw, box_to_erase = None): '''_DrawAndErase(self, box_to_draw, box_to_erase = None) --> None ''' dc = wx.ClientDC(self.canvas) # dc.BeginDrawing() dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT)) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetLogicalFunction(wx.XOR) if box_to_erase: dc.DrawRectangle(*box_to_erase) dc.DrawRectangle(*box_to_draw) # dc.EndDrawing() def OnContextMenu(self, event): '''OnContextMenu(self, event) --> None Callback to show the popmenu for the plot which allows various settings to be made. ''' menu = wx.Menu() zoomID = wx.NewId() menu.AppendCheckItem(zoomID, "Zoom") menu.Check(zoomID, self.GetZoom()) def OnZoom(event): self.SetZoom(not self.GetZoom()) self.Bind(wx.EVT_MENU, OnZoom, id = zoomID) zoomallID = wx.NewId() menu.Append(zoomallID, 'Zoom All') def zoomall(event): tmp = self.GetAutoScale() self.SetAutoScale(True) self.AutoScale() self.SetAutoScale(tmp) #self.flush_plot() self.Bind(wx.EVT_MENU, zoomall, id = zoomallID) copyID = wx.NewId() menu.Append(copyID, "Copy") def copy(event): self.CopyToClipboard() self.Bind(wx.EVT_MENU, copy, id = copyID) yscalemenu = wx.Menu() logID = wx.NewId() linID = wx.NewId() yscalemenu.AppendRadioItem(logID, "log") yscalemenu.AppendRadioItem(linID, "linear") menu.AppendMenu(-1, "y-scale", yscalemenu) if self.GetYScale() == 'log': yscalemenu.Check(logID, True) else: yscalemenu.Check(linID, True) def yscale_log(event): if self.ax: self.SetYScale('log') self.AutoScale() self.flush_plot() def yscale_lin(event): if self.ax: self.SetYScale('lin') self.AutoScale() self.flush_plot() self.Bind(wx.EVT_MENU, yscale_log, id = logID) self.Bind(wx.EVT_MENU, yscale_lin, id = linID) autoscaleID = wx.NewId() menu.AppendCheckItem(autoscaleID, "Autoscale") menu.Check(autoscaleID, self.GetAutoScale()) def OnAutoScale(event): self.SetAutoScale(not self.GetAutoScale()) self.Bind(wx.EVT_MENU, OnAutoScale, id = autoscaleID) # Time to show the menu self.PopupMenu(menu) menu.Destroy() def flush_plot(self): #self._SetSize() #self.canvas.gui_repaint(drawDC = wx.PaintDC(self)) #self.ax.set_yscale(self.scale) self.canvas.draw() def update(self, data): pass