class ExposureView(wx.Panel): def __init__(self, *args, **kwargs): wx.Panel.__init__(self, *args, **kwargs) vbox = wx.BoxSizer(wx.VERTICAL) self.image_view = ImageView(self, ID_EXPOSURE_VIEW, size=(487, 195), style=wx.BORDER_SUNKEN) vbox.Add(self.image_view, 1, wx.EXPAND) self.figure = Figure() self.plot = FigureCanvas(self, wx.ID_ANY, self.figure) self.plot.SetSize((487, 195)) self.plot.SetWindowStyle(wx.BORDER_SUNKEN) vbox.Add(self.plot, 1, wx.EXPAND) self.plot.Hide() self.toolbar = NavigationToolbar2WxAgg(self.plot) vbox.Add(self.toolbar, 0, wx.EXPAND) self.plot.Hide() self.SetSizerAndFit(vbox) def SetViewMode(self, mode): if mode == VIEW_MODE_SPECTRUM: self.image_view.Hide() self.plot.Show() self.toolbar.Show() else: self.image_view.Show() self.plot.Hide() self.toolbar.Hide() self.Layout()
class PlotPanel(wx.Panel): def __init__(self, parent, choices, *args, **kwargs): wx.Panel.__init__(self, parent=parent, *args, **kwargs) self.initPieMenu(choices) self.initFeatureCanvas() self.initLayout() def initPieMenu(self, choices): self.pieMenu = widgets.PieMenu( self, choices=choices, rotation=np.pi / len(choices) + np.pi / 2.0, #colors=('red', (50,220,50), 'yellow', 'blue')) colors=('turquoise', 'red', 'blue violet', 'orange', 'blue', 'yellow')) def initFeatureCanvas(self): self.featureFig = plt.Figure() ##self.featureFig.subplots_adjust(hspace=0.32, wspace=0.02, ## left=0.065, right=0.95, top=0.97, bottom=0.18) self.featureAx = self.featureFig.add_subplot(1, 1, 1) self.featureCanvas = FigureCanvas(parent=self, id=wx.ID_ANY, figure=self.featureFig) def initLayout(self): plotSizer = wx.BoxSizer(orient=wx.VERTICAL) plotSizer.Add(self.pieMenu, proportion=1, flag=wx.EXPAND | wx.ALL) plotSizer.Add(self.featureCanvas, proportion=1, flag=wx.EXPAND | wx.ALL) self.SetSizer(plotSizer) self.featureCanvas.Hide() self.Layout() def showPieMenu(self): self.featureCanvas.Hide() self.pieMenu.Show() self.Layout() def showFeatureCanvas(self): self.featureCanvas.Show() self.pieMenu.Hide() self.Layout() def plotFeatures(self, trainData, freqs, choices, chanNames): self.featureAx.cla() meanFeat = [np.mean(cls, axis=0) for cls in trainData] for cls, choice in zip(meanFeat, choices): self.featureAx.plot(cls, label=choice, marker='o', linewidth=2) self.featureAx.set_xlabel(r'Frequency ($Hz$)') self.featureAx.set_ylabel( r'Mean Log$_{10}$ Power $(uV^2 / Hz)^{\frac{1}{2}}$') self.featureAx.legend() nFreq = len(freqs) mn = np.min(np.concatenate(meanFeat)) mx = np.max(np.concatenate(meanFeat)) for i, cn in enumerate(chanNames): if i > 0: self.featureAx.vlines(i * float(nFreq), mn, mx, linestyle='--') self.featureAx.text((i + 0.25) * float(nFreq), mx - 0.1 * (mx - mn), cn, fontsize=14) tickStride = int(np.ceil(nFreq / 3.0)) tickFreqs = freqs[::tickStride] tickPlaces = np.arange(nFreq)[::tickStride] tickLocs = np.concatenate( [tickPlaces + nFreq * i for i, c in enumerate(chanNames)]) tickLabels = np.round(np.tile(tickFreqs, len(chanNames))).astype(np.int) self.featureAx.set_xticks(tickLocs) self.featureAx.set_xticklabels(tickLabels) self.featureAx.autoscale(tight=True) self.featureFig.tight_layout() self.showFeatureCanvas()
class MainWindow(wx.Frame): # Constructor def __init__(self): wx.Frame.__init__(self, parent = None, title = "PyStrEmbed-1") self.SetBackgroundColour('white') ### MENU BAR menuBar = wx.MenuBar() fileMenu = wx.Menu() menuBar.Append(fileMenu, "&File") fileOpen = fileMenu.Append(wx.ID_OPEN, "&Open", "Open file") fileSave = fileMenu.Append(wx.ID_SAVE, "&Save", "Save file") fileSaveAs = fileMenu.Append(wx.ID_SAVEAS, "&Save as", "Save file as") fileClose = fileMenu.Append(wx.ID_CLOSE, "&Close", "Close file") fileExit = fileMenu.Append(wx.ID_EXIT, "&Exit", "Exit program") partMenu = wx.Menu() menuBar.Append(partMenu, "&Parts") geomMenu = wx.Menu() menuBar.Append(geomMenu, "&Geometry") lattMenu = wx.Menu() menuBar.Append(lattMenu, "&Lattice") abtMenu = wx.Menu() menuBar.Append(abtMenu, "&About") menuAbout = abtMenu.Append(wx.ID_ABOUT,"&About", "About PyStrEmbed-1") self.SetMenuBar(menuBar) # Bindings for menu items self.Bind(wx.EVT_MENU, self.OnFileOpen, fileOpen) self.Bind(wx.EVT_MENU, self.DoNothingDialog, fileSave) self.Bind(wx.EVT_MENU, self.DoNothingDialog, fileSaveAs) self.Bind(wx.EVT_MENU, self.OnExit, fileClose) self.Bind(wx.EVT_MENU, self.OnExit, fileExit) self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) ### TOOLBAR # Main window toolbar with assembly operations self.tb = wx.ToolBar(self, style = wx.TB_NODIVIDER | wx.TB_FLAT) self.SetToolBar(self.tb) self.tb.SetToolBitmapSize((40,40)) self.tb.SetBackgroundColour('white') # File tools self.fileOpenTool = self.tb.AddTool(wx.ID_ANY, 'Open', wx.Bitmap("Images/fileopen.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'File open', longHelp = 'File open') self.exitTool = self.tb.AddTool(wx.ID_ANY, 'Exit', wx.Bitmap("Images/fileclose.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'Exit', longHelp = 'Exit') self.tb.AddSeparator() # Assembly tools self.insertLeftTool = self.tb.AddTool(wx.ID_ANY, 'Insert node to left', wx.Bitmap("Images/insertleft1.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'Insert left', longHelp = 'Insert left') self.insertRightTool = self.tb.AddTool(wx.ID_ANY, 'Insert node to right', wx.Bitmap("Images/insertright1.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'Insert right', longHelp = 'Insert right') self.adoptTool = self.tb.AddTool(wx.ID_ANY, 'Adopt node', wx.Bitmap("Images/adopt1.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'Adopt', longHelp = 'Adopt') self.aggregateTool = self.tb.AddTool(wx.ID_ANY, 'Aggregate nodes', wx.Bitmap("Images/aggregate1.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'Aggregate', longHelp = 'Aggregate') self.disaggregateTool = self.tb.AddTool(wx.ID_ANY, 'Disaggregate nodes', wx.Bitmap("Images/disaggregate1.bmp"), bmpDisabled = wx.NullBitmap, shortHelp = 'Disaggregate', longHelp = 'Disaggregate') self.tb.Realize() # Bind toolbar tools to actions self.Bind(wx.EVT_TOOL, self.OnFileOpen, self.fileOpenTool) self.Bind(wx.EVT_TOOL, self.OnExit, self.exitTool) self.Bind(wx.EVT_TOOL, self.DoNothingDialog, self.insertLeftTool) self.Bind(wx.EVT_TOOL, self.DoNothingDialog, self.insertRightTool) self.Bind(wx.EVT_TOOL, self.DoNothingDialog, self.adoptTool) self.Bind(wx.EVT_TOOL, self.DoNothingDialog, self.aggregateTool) self.Bind(wx.EVT_TOOL, self.DoNothingDialog, self.disaggregateTool) ### STATUS BAR # Status bar self.statbar = self.CreateStatusBar() self.statbar.SetBackgroundColour('white') # Update status bar with window size on (a) first showing and (b) resizing self.Bind(wx.EVT_SIZE, self.OnResize, self) # Create main panel self.InitMainPanel() def InitMainPanel(self): ### MAIN PANEL # # Create main panel to contain everything self.panel = wx.Panel(self) self.box = wx.BoxSizer(wx.VERTICAL) # Create FlexGridSizer to have 3 panes # 2nd and 3rd arguments are hgap and vgap b/t panes (cosmetic) self.grid = wx.FlexGridSizer(cols = 3, rows = 2, hgap = 10, vgap = 10) self.part_header = wx.StaticText(self.panel, label = "Parts view") self.geom_header = wx.StaticText(self.panel, label = "Geometry view") self.latt_header = wx.StaticText(self.panel, label = "Lattice view") self.panel_style = wx.SIMPLE_BORDER self.part_panel = wx.Panel(self.panel, style = self.panel_style) self.geom_panel = wx.Panel(self.panel, style = self.panel_style) self.latt_panel = wx.Panel(self.panel, style = self.panel_style) self.part_sizer = wx.BoxSizer(wx.VERTICAL) self.latt_sizer = wx.BoxSizer(wx.VERTICAL) # Some special setup for geometry sizer (grid) self.image_cols = 2 self.geom_sizer = wx.GridSizer(cols = self.image_cols, rows = 0, hgap = 5, vgap = 5) # Defines tightness of images in grid (i.e. produces blank border) self.geom_tight = 0.7 # PARTS VIEW SETUP # Custom tree ctrl implementation self.treeStyle = (ctc.TR_MULTIPLE | ctc.TR_EDIT_LABELS | ctc.TR_HAS_BUTTONS) self.partTree_ctc = ctc.CustomTreeCtrl(self.part_panel, agwStyle = self.treeStyle) self.partTree_ctc.SetBackgroundColour('white') self.part_sizer.Add(self.partTree_ctc, 1, wx.EXPAND) # GEOMETRY VIEW SETUP # Set up image-view grid, where "rows = 0" means the sizer updates dynamically # according to the number of elements it holds # self.geom_sizer.Add(self.image_grid, 1, wx.EXPAND) # Binding for toggling of part/assembly images # though toggle buttons not yet realised self.Bind(wx.EVT_TOGGLEBUTTON, self.ImageToggled) self.no_image_ass = 'Images/noimage_ass.png' self.no_image_part = 'Images/noimage_part.png' # LATTICE VIEW SETUP # Set up matplotlib FigureCanvas with toolbar for zooming and movement self.latt_figure = mpl.figure.Figure() self.latt_canvas = FigureCanvas(self.latt_panel, -1, self.latt_figure) self.latt_axes = self.latt_figure.add_subplot(111) self.latt_canvas.Hide() # Realize but hide, to be shown later when file loaded/data updated self.latt_tb = NavigationToolbar(self.latt_canvas) # self.latt_tb.Realize() self.latt_tb.Hide() self.latt_sizer.Add(self.latt_canvas, 1, wx.EXPAND | wx.ALIGN_BOTTOM | wx.ALL, border = 5) self.latt_sizer.Add(self.latt_tb, 0, wx.EXPAND) self.selected_colour = 'blue' # OVERALL SIZERS SETUP self.part_panel.SetSizer(self.part_sizer) self.geom_panel.SetSizer(self.geom_sizer) self.latt_panel.SetSizer(self.latt_sizer) self.grid.AddMany([(self.part_header), (self.geom_header), (self.latt_header), (self.part_panel, 1, wx.EXPAND), (self.geom_panel, 1, wx.EXPAND), (self.latt_panel, 1, wx.EXPAND)]) # Set all grid elements to "growable" upon resizing # Flags (second argument is proportional size) self.grid.AddGrowableRow(1,0) self.grid.AddGrowableCol(0,3) self.grid.AddGrowableCol(1,2) self.grid.AddGrowableCol(2,3) # Set sizer for/update main panel self.box.Add(self.grid, 1, wx.ALL | wx.EXPAND, 5) self.panel.SetSizer(self.box) def GetFilename(self, dialog_text = "Open file", starter = None, ender = None): ### General file-open method; takes list of file extensions as argument ### and can be used for specific file names ("starter", string) ### or types ("ender", string or list) # Convert "ender" to list if only one element if isinstance(ender, str): ender = [ender] # Check that only one kwarg is present # Create text for file dialog if starter is not None and ender is None: file_open_text = starter.upper() + " files (" + starter.lower() + "*)|" + starter.lower() + "*" elif starter is None and ender is not None: file_open_text = [el.upper() + " files (*." + el.lower() + ")|*." + el.lower() for el in ender] file_open_text = "|".join(file_open_text) else: raise ValueError("Requires starter or ender only") # Create file dialog fileDialog = wx.FileDialog(self, dialog_text, "", "", file_open_text, wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) fileDialog.ShowModal() filename = fileDialog.GetPath() fileDialog.Destroy() # Return file name, ignoring rest of path return filename def DisplayPartsList(self): # Create root node... root_id = self.assembly.tree.root root_tag = self.assembly.tree.get_node(root_id).tag # Exception handler if file loaded previously try: self.partTree_ctc.DeleteAllItems() except: pass ctc_root_item = self.partTree_ctc.AddRoot(text = root_tag, ct_type = 1) self.ctc_dict[root_id] = ctc_root_item self.ctc_dict_inv[ctc_root_item] = root_id # ...then all others # Assumes treelib ordering ensures parents are defined before children for el in self.assembly.tree_dict: if el != root_id: parent_id = self.assembly.tree.parent(el).identifier ctc_parent = self.ctc_dict[parent_id] ctc_text = self.assembly.part_dict[self.assembly.tree_dict[el]] ctc_item = self.partTree_ctc.AppendItem(ctc_parent, text = ctc_text, ct_type = 1) self.ctc_dict[el] = ctc_item self.ctc_dict_inv[ctc_item] = el # Binding for checking of list items self.Bind(ctc.EVT_TREE_ITEM_CHECKED, self.TreeItemChecked) self.Bind(ctc.EVT_TREE_SEL_CHANGED, self.TreeItemSelected) self.partTree_ctc.ExpandAll() def TreeItemChecked(self, event): def ScaleImage(img): # Resize image to geometry panel # NEEDS IMPROVEMENT TO BE MORE GENERAL (IN TERMS OF ASPECT RATIO) p_w, p_h = self.geom_panel.GetSize() h = img.GetHeight() w = img.GetWidth() w_new = p_w*self.geom_tight/self.image_cols h_new = w_new*h/w img = img.Scale(w_new, h_new) return img # Get checked item and search for corresponding image # item = event.GetItem() id_ = self.ctc_dict_inv[item] self.selected_items = self.partTree_ctc.GetSelections() if item.IsChecked(): # Get image if id_ in self.assembly.leaf_ids: img = self.assembly.tree_dict[id_] img = os.path.join('Images', img + '.png') if os.path.isfile(img): img = wx.Image(img, wx.BITMAP_TYPE_ANY) else: img = wx.Image(self.no_image_part, wx.BITMAP_TYPE_ANY) else: img = wx.Image(self.no_image_ass, wx.BITMAP_TYPE_ANY) # Create/add button in geom_panel # # Includes rescaling to panel img = ScaleImage(img) button = wx.BitmapToggleButton(self.geom_panel, id_, wx.Bitmap(img)) button.SetBackgroundColour('white') self.geom_sizer.Add(button, 0, wx.EXPAND) # Update global list and dict # # Data is list, i.e. same format as "selected_items" # but ctc lacks "get selections" method for checked items self.checked_items.append(item) self.button_dict[id_] = button self.button_dict_inv[button] = id_ # Toggle if already selected elsewhere if self.ctc_dict[id_] in self.selected_items: button.SetValue(True) else: pass else: # Remove button from geom_panel obj = self.button_dict[id_] obj.Destroy() # Update global list and dict self.checked_items.remove(item) self.button_dict.pop(id_) self.button_dict_inv.pop(obj) # Update image sizer self.geom_sizer.Layout() def TreeItemSelected(self, event): # Get selected item and update global list of items # # Using GetSelection rather than maintaining list of items # as with checked items b/c releasing ctrl key during multiple # selection means not all selections are tracked easily self.selected_items = self.partTree_ctc.GetSelections() self.UpdateToggledImages() self.UpdateLatticeSelections() def ImageToggled(self, event): id_ = event.GetId() self.UpdateListSelections(id_) self.UpdateLatticeSelections() def UpdateListSelections(self, id_): # Select/deselect parts list item item = self.ctc_dict[id_] if item in self.selected_items: self.selected_items.remove(item) else: self.selected_items.append(item) # With "select = True", SelectItem toggles state if multiple selections enabled self.partTree_ctc.SelectItem(self.ctc_dict[id_], select = True) def UpdateLatticeSelections(self): # Update colour of selected items # # Set all back to default colour first for node in self.assembly.g.nodes(): self.assembly.g.nodes[node]['colour'] = self.assembly.default_colour # Then selected nodes for item in self.selected_items: id_ = self.ctc_dict_inv[item] self.assembly.g.nodes[id_]['colour'] = self.selected_colour # Redraw lattice self.DisplayLattice() def UpdateToggledImages(self): for id_, button in self.button_dict.items(): button.SetValue(False) for item in self.selected_items: id_ = self.ctc_dict_inv[item] if id_ in self.button_dict: button = self.button_dict[id_] button.SetValue(True) else: pass def DisplayLattice(self): # Get node positions, colour map, labels pos = nx.get_node_attributes(self.assembly.g, 'pos') colour_map = [self.assembly.g.nodes[el]['colour'] for el in self.assembly.g.nodes] # node_labels = nx.get_node_attributes(self.assembly.g, 'label') # Draw to lattice panel figure try: self.latt_axes.clear() except: pass nx.draw(self.assembly.g, pos, node_color = colour_map, with_labels = True, ax = self.latt_axes) # nx.draw_networkx_labels(self.assembly.g, pos, labels = node_labels, ax = self.latt_axes) # Minimise white space around plot in panel self.latt_figure.subplots_adjust(left = 0.01, bottom = 0.01, right = 0.99, top = 0.99) # Show lattice figure self.latt_canvas.draw() self.latt_canvas.Show() self.latt_tb.Show() # Update lattice panel layout self.latt_panel.Layout() def DoNothingDialog(self, event): nowt = wx.MessageDialog(self, "Functionality to be added", "Do nothing dialog", wx.OK) # Create modal dialogue that stops process nowt.ShowModal() nowt.Destroy() def OnFileOpen(self, event): # # Delete if exists from previous file load # # TO BE COMPLETED FOR VERSION 1-2 # try: # del self.assembly # except AttributeError: # pass # Get STEP filename self.open_filename = self.GetFilename(ender = ["stp", "step"]).split("\\")[-1] # Load data, create nodes and edges, etc. self.assembly = StepParse() self.assembly.load_step(self.open_filename) self.assembly.create_tree() # Checked and selected items lists, shared b/t all views self.checked_items = [] self.selected_items = [] # Toggle buttons self.button_dict = {} self.button_dict_inv = {} # Write interactive parts list using WX customtreectrl, from treelib nodes self.ctc_dict = {} self.ctc_dict_inv = {} # Show parts list and lattice self.DisplayPartsList() # Clear geometry window if necessary try: self.geom_sizer.Clear(True) except: pass # Clear lattice plot if necessary try: self.latt_axes.clear() except: pass # Display lattice self.DisplayLattice() def OnInsertLeft(self, event): pass def OnInsertRight(self, event): pass def OnAdopt(self, event): pass def OnAggregate(self, event): pass def OnDisaggregate(self, event): pass def OnAbout(self, event): # Show program info abt_text = """StrEmbed-5-1: A user interface for manipulation of design configurations\n Copyright (C) 2019 Hugh Patrick Rice\n This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.""" abt = wx.MessageDialog(self, abt_text, 'About StrEmbed-5-1', wx.OK) abt.ShowModal() # Shows dialogue that stops process (modal) abt.Destroy() def OnExit(self, event): self.Close(True) # Close program def OnResize(self, event): # Display window size in status bar self.statbar.SetStatusText("Window size = " + format(self.GetSize())) event.Skip()
class Spectrogram(StandardMonitorPage): """Main class for a page that generates real-time spectrogram plots of EEG. """ def __init__(self, *args, **kwargs): """Construct a new Spectrogram page. Args: *args, **kwargs: Arguments to pass to the Page base class. """ self.initConfig() # initialize Page base class StandardMonitorPage.__init__(self, name='Spectrogram', configPanelClass=ConfigPanel, *args, **kwargs) self.initCanvas() self.initLayout() def initConfig(self): self.filter = True # use raw or filtered signal self.chanIndex = 0 # index of channel to show self.width = 5.0 # width of window to use for computing PSD self.decimationFactor = 1 # decimation factor, e.g., 2 will decimate to half sampRate self.interpolation = 'none' self.normScale = 'log' self.scale = -2 self.method = 'Wavelet' self.setRefreshDelay(200) self.waveletConfig = util.Holder(nFreq=100, span=10) self.fourierConfig = util.Holder() def initCanvas(self): """Initialize a new matplotlib canvas, figure and axis. """ self.plotPanel = wx.Panel(self) self.plotPanel.SetBackgroundColour('white') plotSizer = wx.BoxSizer(orient=wx.VERTICAL) self.plotPanel.SetSizer(plotSizer) self.fig = plt.Figure(facecolor='white') #self.canvas = FigureCanvas(parent=self, id=wx.ID_ANY, figure=self.fig) self.canvas = FigureCanvas(parent=self.plotPanel, id=wx.ID_ANY, figure=self.fig) self.ax = self.fig.add_subplot(1, 1, 1) self.ax.set_xlabel('Time (s)') self.ax.set_ylabel('Frequency (Hz)') self.cbAx = self.fig.add_axes([0.91, 0.05, 0.03, 0.93]) #self.fig.subplots_adjust(hspace=0.0, wspace=0.0, # left=0.035, right=0.92, top=0.98, bottom=0.05) self.adjustMargins() self.firstPlot() self.lastSize = (0, 0) self.needsResizePlot = True self.canvas.Bind(wx.EVT_SIZE, self.resizePlot) self.canvas.Bind(wx.EVT_IDLE, self.idleResizePlot) ##self.plotToolbar = widgets.PyPlotNavbar(self.canvas) ##plotSizer.Add(self.plotToolbar, proportion=0, flag=wx.EXPAND) plotSizer.Add(self.canvas, proportion=1, flag=wx.EXPAND) #self.plotToolbar.Hide() def initLayout(self): self.initStandardLayout() plotPaneAuiInfo = aui.AuiPaneInfo().Name('canvas').Caption( 'Spectrogram').CenterPane() #self.auiManager.AddPane(self.canvas, plotPaneAuiInfo) self.auiManager.AddPane(self.plotPanel, plotPaneAuiInfo) self.auiManager.Update() self.canvas.Hide() def afterUpdateSource(self): self.configPanel.updateChannels() def afterStart(self): # make sure canvas is visible self.canvas.Show() self.plotPanel.Layout() # trigger initial plot update self.needsFirstPlot = True def getCap(self): cap = self.src.getEEGSecs(self.width, filter=self.filter, copy=False) if self.decimationFactor > 1: cap.decimate(self.decimationFactor) return cap def getSpectrum(self, cap): # configurable XXX - idfah data = cap.data[:, self.chanIndex] * sig.windows.tukey( cap.data.shape[0]) # tukey or hann? XXX - idfah freqs, powers, phases = self.cwt.apply(data) # configurable XXX - idfah powers = np.clip(powers, 1.0e-10, np.inf) return freqs, powers def firstPlot(self, event=None): cap = self.getCap() self.cwt = sig.CWT(sampRate=cap.getSampRate(), freqs=self.waveletConfig.nFreq, span=self.waveletConfig.span) if self.isRunning(): freqs, powers = self.getSpectrum(cap) else: freqs = np.arange(1, self.src.getSampRate() // 2 + 1) powers = np.zeros((128, 10, 1)) powers[0, 0, 0] = 1.0 self.ax.cla() self.cbAx.cla() self.ax.set_xlabel('Time (s)') self.ax.set_ylabel('Frequency (Hz)') self.wimg = self.ax.imshow(powers[:, :, 0].T, interpolation=self.interpolation, origin='lower', aspect='auto', norm=self.getNorm(), extent=self.getExtent(cap, freqs), cmap=plt.cm.get_cmap('jet'), animated=True) self.cbar = self.fig.colorbar(self.wimg, cax=self.cbAx) self.cbar.set_label(r'Power Density ($V^2 / Hz$)') #self.updateNorm(powers) self.canvas.draw() #self.background = self.canvas.copy_from_bbox(self.fig.bbox) self.background = self.canvas.copy_from_bbox(self.ax.bbox) self.needsFirstPlot = False def adjustMargins(self): self.fig.subplots_adjust(hspace=0.0, wspace=0.0, left=0.045, right=0.90, top=0.98, bottom=0.07) def resizePlot(self, event): # prevents handling extra resize events, hack XXX - idfah size = self.canvas.GetSize() if self.lastSize == size: return else: self.lastSize = size # this is all a hack to do resizing on idle when page is not running # should this be a custom FigureCanvas derived widget? XXX - idfah if self.isRunning(): # when running, just do event.Skip() this will # call canvas._onSize since it is second handler self.needsResizePlot = False event.Skip() else: # flag to resize on next idle event self.needsResizePlot = True def idleResizePlot(self, event): # if not running and flagged for resize if not self.isRunning() and self.needsResizePlot: ##self.adjustMargins() self.needsResizePlot = False # call canvas resize method manually # hack alert, we just pass None as event # since it's not used anyway self.canvas._onSize(None) def getExtent(self, cap, freqs): return (0.0, cap.getNObs() / float(cap.getSampRate()), np.min(freqs), np.max(freqs)) def getNorm(self): mx = 10**self.scale if self.normScale == 'linear': mn = 0.0 norm = pltLinNorm(mn, mx) elif self.normScale == 'log': mn = 1e-10 norm = pltLogNorm(mn, mx) else: raise RuntimeError('Invalid norm %s.' % norm) return norm def updatePlot(self, event=None): """Draw the spectrogram plot. """ if self.needsFirstPlot: self.firstPlot() else: cap = self.getCap() freqs, powers = self.getSpectrum(cap) #self.updateNorm(powers) self.canvas.restore_region(self.background) self.wimg.set_array(powers[:, :, 0].T) self.wimg.set_extent(self.getExtent(cap, freqs)) self.ax.draw_artist(self.wimg) ##self.cbAx.draw_artist(self.cbar.patch) ##self.cbAx.draw_artist(self.cbar.solids) #self.cbar.draw_all() #self.canvas.blit(self.cbAx.bbox) #self.canvas.blit(self.fig.bbox) self.canvas.blit(self.ax.bbox) # for debugging, redraws everything ##self.canvas.draw() def captureImage(self, event=None): ## Parts borrowed from backends_wx.py from matplotlib # Fetch the required filename and file type. filetypes, exts, filter_index = self.canvas._get_imagesave_wildcards() default_file = self.canvas.get_default_filename() dlg = wx.FileDialog(self, "Save to file", "", default_file, filetypes, wx.SAVE | wx.OVERWRITE_PROMPT) dlg.SetFilterIndex(filter_index) if dlg.ShowModal() == wx.ID_OK: dirname = dlg.GetDirectory() filename = dlg.GetFilename() format = exts[dlg.GetFilterIndex()] basename, ext = os.path.splitext(filename) if ext.startswith('.'): ext = ext[1:] if ext in ('svg', 'pdf', 'ps', 'eps', 'png') and format != ext: #looks like they forgot to set the image type drop #down, going with the extension. format = ext self.canvas.print_figure(os.path.join(dirname, filename), format=format)
class PlotPanel(wx.Panel): def __init__(self, parent, pg, *args, **kwargs): wx.Panel.__init__(self, parent=parent, *args, **kwargs) self.pg = pg # various initialization routines self.initPieMenu() self.initERPCanvas() self.initLayout() def initPieMenu(self): self.pieMenu = widgets.PieMenu(self, choices=self.pg.choices, rotation=4.0*np.pi/len(self.pg.choices), colors=('turquoise', 'red', 'blue violet', 'orange', 'blue', 'yellow')) #colors=('turquoise', 'red', 'blue', 'green', # 'yellow', 'blue violet')) def initERPCanvas(self): #self.erpFig = plt.Figure() #self.erpAx = self.erpFig.add_subplot(1,1,1) #self.erpCanvas = FigureCanvas(parent=self, id=wx.ID_ANY, figure=self.erpFig) self.erpFig = plt.Figure() self.erpFig.subplots_adjust(hspace=0.32, wspace=0.02, left=0.065, right=0.95, top=0.97, bottom=0.18) gs = pltgs.GridSpec(2,4) self.erpAx = self.erpFig.add_subplot(gs[0,:]) self.h1Ax = self.erpFig.add_subplot(gs[1,0]) self.h2Ax = self.erpFig.add_subplot(gs[1,1]) self.h3Ax = self.erpFig.add_subplot(gs[1,2]) self.h4Ax = self.erpFig.add_subplot(gs[1,3]) self.cbAx = self.erpFig.add_axes([0.05, 0.08, 0.9, 0.05]) self.erpCanvas = FigureCanvas(parent=self, id=wx.ID_ANY, figure=self.erpFig) def initLayout(self): plotSizer = wx.BoxSizer(orient=wx.VERTICAL) plotSizer.Add(self.pieMenu, proportion=1, flag=wx.EXPAND) plotSizer.Add(self.erpCanvas, proportion=1, flag=wx.EXPAND) self.SetSizer(plotSizer) self.erpCanvas.Hide() self.Layout() def showPieMenu(self): self.erpCanvas.Hide() self.pieMenu.Show() self.Layout() def showERPCanvas(self): self.erpCanvas.Show() #self.erpCanvas.draw() self.pieMenu.Hide() self.Layout() def plotERP(self, cap): chanIndex = cap.getChanIndices(('cz',))[0] if chanIndex is None: chans = (0,) chanIndex = 0 wx.LogWarning('Could not find channel Cz. Using first channel instead.') else: chans = ('Cz',) cap = cap.copy().bandpass(0.5, np.inf, order=3) seg = cap.segment(start=-0.2, end=0.75) targ = seg.select(matchFunc=lambda mark: self.pg.markToStim(mark) == self.pg.targStr) nonTarg = seg.select(matchFunc=lambda mark: self.pg.markToStim(mark) == self.pg.nonTargStr) for ax in (self.erpAx, self.h1Ax, self.h2Ax, self.h3Ax, self.h4Ax): ax.cla() targPlot = targ.plotAvg(chans=chans, ax=self.erpAx, linewidth=2, color='blue') targPlot['lines'][0].set_label(self.pg.targStr + ' ERP') nonTargPlot = nonTarg.plotAvg(chans=chans, ax=self.erpAx, linewidth=2, color='green') nonTargPlot['lines'][0].set_label(self.pg.nonTargStr + ' ERP') erp = np.mean(targ.data, axis=0) mn = np.min(erp[:,chanIndex]) mx = np.max(erp[:,chanIndex]) self.erpAx.hlines(0.0, 0.0, 0.8, linestyle='--', linewidth=2, color='grey') self.erpAx.vlines(0.0, mn, mx, linestyle='--', linewidth=2, color='grey') self.erpAx.vlines((200, 300, 400, 500), mn, mx, linestyle='--', linewidth=1, color='red') self.erpAx.legend() self.erpAx.set_xlabel('Time (s)') self.erpAx.set_ylabel(r'Signal ($\mu V$)') sampRate = targ.getSampRate() erp1 = erp[int((0.2+0.2)*sampRate),:] erp2 = erp[int((0.2+0.3)*sampRate),:] erp3 = erp[int((0.2+0.4)*sampRate),:] erp4 = erp[int((0.2+0.5)*sampRate),:] erpAll = np.concatenate((erp1, erp2, erp3, erp4)) mn = np.min(erpAll) mx = np.max(erpAll) interpMethod = 'multiquadric' coord = '3d' h1 = eeg.plotHeadInterp(erp1, chanNames=targ.getChanNames(), method=interpMethod, coord=coord, mn=mn, mx=mx, ax=self.h1Ax) self.h1Ax.set_title('200ms') h2 = eeg.plotHeadInterp(erp2, chanNames=targ.getChanNames(), method=interpMethod, coord=coord, mn=mn, mx=mx, ax=self.h2Ax) self.h2Ax.set_title('300ms') h3 = eeg.plotHeadInterp(erp3, chanNames=targ.getChanNames(), method=interpMethod, coord=coord, mn=mn, mx=mx, ax=self.h3Ax) self.h3Ax.set_title('400ms') h4 = eeg.plotHeadInterp(erp4, chanNames=targ.getChanNames(), method=interpMethod, coord=coord, mn=mn, mx=mx, ax=self.h4Ax) self.h4Ax.set_title('500ms') cbar = plt.colorbar(h1['im'], ax=self.erpAx, orientation='horizontal', cax=self.cbAx) cbar.set_label(r'Target ERP ($\mu V$)') self.showERPCanvas()
class mainFrame(wx.Frame): Data = None def __init__(self, parent): wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=u"Обработка данных детектора", pos=wx.DefaultPosition, size=wx.Size(737, 425), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL) self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize) bSizer1 = wx.BoxSizer(wx.VERTICAL) self.m_panel2 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) self.m_panel2.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)) self.m_panel2.SetBackgroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT)) bSizer61 = wx.BoxSizer(wx.VERTICAL) gSizer21 = wx.GridSizer(0, 2, 0, 0) bSizer6 = wx.BoxSizer(wx.VERTICAL) self.graphPanel1 = wx.Panel(self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) bSizer14 = wx.BoxSizer(wx.VERTICAL) self.graphPanel1.SetSizer(bSizer14) self.graphPanel1.Layout() bSizer14.Fit(self.graphPanel1) bSizer6.Add(self.graphPanel1, 1, wx.EXPAND | wx.ALL, 5) ########### self.figure1 = Figure() #self.axes1 = self.figure.add_subplot(111) self.canvas1 = FigureCanvas(self, wx.ID_ANY, self.figure1) bSizer14.Add(self.canvas1, 1, wx.LEFT | wx.TOP | wx.EXPAND) self.toolbar1 = NavigationToolbar2Wx(self.canvas1) self.toolbar1.Realize() bSizer14.Add(self.toolbar1, 0, wx.LEFT | wx.EXPAND) self.toolbar1.Show() self.Fit() ################ gSizer21.Add(bSizer14, 2, wx.EXPAND, 5) bSizer7 = wx.BoxSizer(wx.VERTICAL) self.m_staticText4 = wx.StaticText(self.m_panel2, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0) self.m_staticText4.Wrap(-1) self.m_staticText4.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT)) bSizer7.Add(self.m_staticText4, 0, wx.ALL, 5) self.m_staticText5 = wx.StaticText(self.m_panel2, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0) self.m_staticText5.Wrap(-1) self.m_staticText5.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT)) bSizer7.Add(self.m_staticText5, 0, wx.ALL, 5) self.m_staticText6 = wx.StaticText(self.m_panel2, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0) self.m_staticText6.Wrap(-1) self.m_staticText6.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT)) bSizer7.Add(self.m_staticText6, 0, wx.ALL, 5) gSizer21.Add(bSizer7, 0, wx.EXPAND, 5) bSizer61.Add(gSizer21, 1, wx.EXPAND, 5) gSizer3 = wx.GridSizer(0, 2, 0, 0) bSizer62 = wx.BoxSizer(wx.VERTICAL) gSizer3.Add(bSizer62, 1, wx.EXPAND, 5) bSizer71 = wx.BoxSizer(wx.VERTICAL) self.m_staticText41 = wx.StaticText(self.m_panel2, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0) self.m_staticText41.Wrap(-1) self.m_staticText41.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT)) bSizer71.Add(self.m_staticText41, 0, wx.ALL, 5) self.m_staticText51 = wx.StaticText(self.m_panel2, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0) self.m_staticText51.Wrap(-1) self.m_staticText51.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT)) bSizer71.Add(self.m_staticText51, 0, wx.ALL, 5) self.m_staticText61 = wx.StaticText(self.m_panel2, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0) self.m_staticText61.Wrap(-1) self.m_staticText61.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT)) bSizer71.Add(self.m_staticText61, 0, wx.ALL, 5) gSizer3.Add(bSizer71, 1, wx.EXPAND, 5) bSizer61.Add(gSizer3, 1, wx.EXPAND, 5) self.m_panel2.SetSizer(bSizer61) self.m_panel2.Layout() bSizer61.Fit(self.m_panel2) bSizer1.Add(self.m_panel2, 1, wx.EXPAND, 5) self.SetSizer(bSizer1) self.Layout() self.m_menubar1 = wx.MenuBar(0) self.m_menu1 = wx.Menu() self.m_menuItem1 = wx.MenuItem(self.m_menu1, wx.ID_ANY, u"Открыть...", wx.EmptyString, wx.ITEM_NORMAL) self.m_menu1.AppendItem(self.m_menuItem1) self.m_menu1.AppendSeparator() self.m_menuItem2 = wx.MenuItem(self.m_menu1, wx.ID_ANY, u"Выход", wx.EmptyString, wx.ITEM_NORMAL) self.m_menu1.AppendItem(self.m_menuItem2) self.m_menubar1.Append(self.m_menu1, u"Файл") self.m_menu2 = wx.Menu() self.m_menuItem3 = wx.MenuItem(self.m_menu2, wx.ID_ANY, u"График 1", wx.EmptyString, wx.ITEM_CHECK) self.m_menu2.AppendItem(self.m_menuItem3) self.m_menuItem3.Check(True) self.m_menuItem4 = wx.MenuItem(self.m_menu2, wx.ID_ANY, u"График 2", wx.EmptyString, wx.ITEM_CHECK) self.m_menu2.AppendItem(self.m_menuItem4) self.m_menuItem4.Check(True) self.m_menubar1.Append(self.m_menu2, u"Показать") self.SetMenuBar(self.m_menubar1) self.Centre(wx.BOTH) # COnnect events self.Bind(wx.EVT_MENU, self.openFile, id=self.m_menuItem1.GetId()) self.Bind(wx.EVT_MENU, self.showGraph1, id=self.m_menuItem3.GetId()) def showGraph1(self, event): if self.m_menuItem3.IsChecked() == False: self.graphPanel1.Hide() self.canvas1.Hide() self.toolbar1.Hide() else: self.graphPanel1.Show() self.canvas1.Show() self.toolbar1.Show() def __del__(self): pass def openFile(self, event): with wx.FileDialog(self, "Открыть файл данных детектора", wildcard="DAT файлы (*.dat)|*.dat", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: if fileDialog.ShowModal() == wx.ID_CANCEL: return # the user changed their mind # Proceed loading the file chosen by the user pathname = fileDialog.GetPath() try: self.Data = DetectorData(pathname) self.axes1 = self.figure1.add_subplot(111) self.axes1.plot(self.Data.datTim, self.Data.inten) self.axes1.set_xlabel("Время хуемя") self.axes1.set_ylabel("Интенсивность") self.axes2 = self.figure1.add_subplot(111) self.axes2.plot(self.Data.datTim, self.Data.press) self.axes2.set_ylabel("Давление") except IOError: wx.LogError("Не удалось открыть файл '%s'." % newfile)