def __init__(self, parent, dstack=None, do=None, xvals=None, xlabel='', ylabel=''): if (dstack is None and do is None): dstack = np.zeros((10, 10)) if do is None: self.do = DisplayOpts(dstack) self.do.Optimise() else: self.do = do self.do.WantChangeNotification.append(self.draw) if xvals is None: xvals = np.arange(self.do.ds.shape[0]) self.xvals = xvals self.xlabel = xlabel fastGraph.FastGraphPanel.__init__(self, parent, -1, self.xvals, self.do.ds[:, :])
def __init__(self, parent, dstack=None, do=None, xvals=None, xlabel='', ylabel=''): wx.Panel.__init__(self, parent) if (dstack is None and do is None): dstack = np.zeros((10, 10)) if do is None: self.do = DisplayOpts(dstack) self.do.Optimise() else: self.do = do self.do.WantChangeNotification.append(self.draw) self.xvals = xvals self.xlabel = xlabel self.ylabel = ylabel sizer1 = wx.BoxSizer(wx.VERTICAL) self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) sizer1.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) #self.toolbar = NavigationToolbar2WxAgg(self.canvas) #self.toolbar = MyNavigationToolbar(self.canvas, self) #self.toolbar.Realize() # if wx.Platform == '__WXMAC__': # # Mac platform (OSX 10.3, MacPython) does not seem to cope with # # having a toolbar in a sizer. This work-around gets the buttons # # back, but at the expense of having the toolbar at the top # self.SetToolBar(self.toolbar) # else: # # On Windows platform, default window size is incorrect, so set # # toolbar width to figure width. # tw, th = self.toolbar.GetSizeTuple() # fw, fh = self.canvas.GetSizeTuple() # # By adding toolbar in sizer, we are able to put it at the bottom # # of the frame - so appearance is closer to GTK version. # # As noted above, doesn't work for Mac. # self.toolbar.SetSize(wx.Size(fw, th)) # # sizer1.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.Bind(wx.EVT_SIZE, self._onSize) #self.toolbar.update() self.SetSizer(sizer1) self.draw()
class GraphViewPanel(fastGraph.FastGraphPanel): def __init__(self, parent, dstack=None, do=None, xvals=None, xlabel=''): if (dstack == None and do == None): dstack = np.zeros((10, 10)) if do == None: self.do = DisplayOpts(dstack) self.do.Optimise() else: self.do = do self.do.WantChangeNotification.append(self.draw) if xvals == None: xvals = np.arange(self.do.ds.shape[0]) self.xvals = xvals self.xlabel = xlabel fastGraph.FastGraphPanel.__init__(self, parent, -1, self.xvals, self.do.ds[:, :]) #self.draw() def draw(self, event=None): self.SetData(self.xvals, self.do.ds[:, :])
class GraphViewPanel(wx.Panel): def __init__(self, parent, dstack=None, do=None, xvals=None, xlabel=''): wx.Panel.__init__(self, parent) if (dstack == None and do == None): dstack = scipy.zeros((10, 10)) if do == None: self.do = DisplayOpts(dstack) self.do.Optimise() else: self.do = do self.do.WantChangeNotification.append(self.draw) self.xvals = xvals self.xlabel = xlabel sizer1 = wx.BoxSizer(wx.VERTICAL) self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) sizer1.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) #self.toolbar = NavigationToolbar2WxAgg(self.canvas) #self.toolbar = MyNavigationToolbar(self.canvas, self) #self.toolbar.Realize() # if wx.Platform == '__WXMAC__': # # Mac platform (OSX 10.3, MacPython) does not seem to cope with # # having a toolbar in a sizer. This work-around gets the buttons # # back, but at the expense of having the toolbar at the top # self.SetToolBar(self.toolbar) # else: # # On Windows platform, default window size is incorrect, so set # # toolbar width to figure width. # tw, th = self.toolbar.GetSizeTuple() # fw, fh = self.canvas.GetSizeTuple() # # By adding toolbar in sizer, we are able to put it at the bottom # # of the frame - so appearance is closer to GTK version. # # As noted above, doesn't work for Mac. # self.toolbar.SetSize(wx.Size(fw, th)) # # sizer1.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.Bind(wx.EVT_SIZE, self._onSize) #self.toolbar.update() self.SetSizer(sizer1) self.draw() def draw(self, event=None): self.axes.cla() if self.xvals == None: xvals = np.arange(self.do.ds.shape[0]) else: xvals = self.xvals for i in range(self.do.ds.shape[3]): self.axes.plot(xvals, self.do.ds[:, self.do.yp, self.do.zp, i].squeeze(), label=self.do.names[i]) if self.do.ds.shape[3] > 1: self.axes.legend() self.axes.set_xlabel(self.xlabel) self.canvas.draw() def _onSize(self, event): #self._resizeflag = True self._SetSize() def _SetSize(self): pixels = tuple(self.GetClientSize()) self.SetSize(pixels) self.canvas.SetSize(pixels) self.figure.set_size_inches( float(pixels[0]) / self.figure.get_dpi(), float(pixels[1]) / self.figure.get_dpi())
def __init__(self, image, parent=None, title='', mode='LM', size = (800,700), glCanvas=None): AUIFrame.__init__(self,parent, -1, title,size=size, pos=wx.DefaultPosition) self.mode = mode self.glCanvas = glCanvas self.updateHooks = [] self.statusHooks = [] self.installedModules = [] # will store weakrefs to things that modules previously injected into our namespace #self._module_injections = weakref.WeakValueDictionary() self.dataChangeHooks = [] self.updating = False if glCanvas: self.glCanvas.wantViewChangeNotification.add(self) self.timer = mytimer() self.timer.Start(10000) self.image = image #self.image = ImageStack(data = dstack, mdh = mdh, filename = filename, queueURI = queueURI, events = None) if not self.image.filename is None and title == '': self.SetTitle(self.image.filename) self.do = DisplayOpts(self.image.data) if self.image.data.shape[1] == 1: self.do.slice = self.do.SLICE_XZ self.do.Optimise() if self.image.mdh and 'ChannelNames' in self.image.mdh.getEntryNames(): chan_names = self.image.mdh.getEntry('ChannelNames') if len(chan_names) == self.image.data.shape[3]: self.do.names = chan_names #self.vp = ArraySettingsAndViewPanel(self, self.image.data, wantUpdates=[self.update], mdh=self.image.mdh) #self.view = ArrayViewPanel(self, do=self.do) #self.AddPage(self.view, True, 'Data') #self._mgr.AddPane(self.vp, aui.AuiPaneInfo(). # Name("Data").Caption("Data").Centre().CloseButton(False).CaptionVisible(False)) self.mainFrame = weakref.ref(self) #self.do = self.vp.do tmp_menu = wx.Menu() tmp_menu.Append(wx.ID_OPEN, '&Open', "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVE, "&Save As", "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVEAS, "&Export Cropped", "", wx.ITEM_NORMAL) #a submenu for modules to hook and install saving functions into self.save_menu = wx.Menu() self._menus['Save'] = self.save_menu tmp_menu.AppendMenu(-1, 'Save &Results', self.save_menu) #tmp_menu.AppendSeparator() #tmp_menu.Append(wx.ID_CLOSE, "Close", "", wx.ITEM_NORMAL) self.menubar.Append(tmp_menu, "File") self._menus['File'] = tmp_menu self.view_menu = wx.Menu() self.menubar.Append(self.view_menu, "&View") self._menus['View'] = self.view_menu #'extras' menu for modules to install stuff into self.mProcessing = wx.Menu() self.menubar.Append(self.mProcessing, "&Processing") self._menus['Processing'] = self.mProcessing # Menu Bar end self.Bind(wx.EVT_MENU, self.OnOpen, id=wx.ID_OPEN) self.Bind(wx.EVT_MENU, self.OnSave, id=wx.ID_SAVE) self.Bind(wx.EVT_MENU, self.OnExport, id=wx.ID_SAVEAS) #self.Bind(wx.EVT_MENU, lambda e: self.Close(), id=wx.ID_CLOSE) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.statusbar = self.CreateStatusBar(1, wx.STB_SIZEGRIP) self.panesToMinimise = [] modules.loadMode(self.mode, self) self.CreateModuleMenu() self.add_common_menu_items() self.optionspanel = OptionsPanel(self, self.do, thresholdControls=True) self.optionspanel.SetSize(self.optionspanel.GetBestSize()) pinfo = aui.AuiPaneInfo().Name("optionsPanel").Right().Caption('Display Settings').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.optionspanel, pinfo) self.panesToMinimise.append(pinfo) self._mgr.AddPane(self.optionspanel.CreateToolBar(self), aui.AuiPaneInfo().Name("ViewTools").Caption("View Tools").CloseButton(False). ToolbarPane().Right().GripperTop()) if self.do.ds.shape[2] > 1: from PYME.DSView.modules import playback self.playbackpanel = playback.PlayPanel(self, self) self.playbackpanel.SetSize(self.playbackpanel.GetBestSize()) pinfo1 = aui.AuiPaneInfo().Name("playbackPanel").Bottom().Caption('Playback').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.playbackpanel, pinfo1) self.do.WantChangeNotification.append(self.playbackpanel.update) #self.mWindows = wx.Menu() #self.menubar.append(self.mWindows, '&Composite With') self.do.WantChangeNotification.append(self.update) self.CreateFoldPanel() for pn in self.panesToMinimise: self._mgr.MinimizePane(pn) #self._mgr.MinimizePane(pinfo2) self.Layout() if 'view' in dir(self): sc = np.floor(np.log2(1.0*self.view.Size[0]/self.do.ds.shape[0])) #print self.view.Size[0], self.do.ds.shape[0], sc self.do.SetScale(sc) self.view.Refresh() self.update() self.drop = dt() self.SetDropTarget(self.drop) self.AddMenuItem('Save', 'To Cluster', self.OnSaveToCluster) openViewers[self.image.filename] = self
class DSViewFrame(AUIFrame): def __init__(self, image, parent=None, title='', mode='LM', size = (800,700), glCanvas=None): AUIFrame.__init__(self,parent, -1, title,size=size, pos=wx.DefaultPosition) self.mode = mode self.glCanvas = glCanvas self.updateHooks = [] self.statusHooks = [] self.installedModules = [] # will store weakrefs to things that modules previously injected into our namespace #self._module_injections = weakref.WeakValueDictionary() self.dataChangeHooks = [] self.updating = False if glCanvas: self.glCanvas.wantViewChangeNotification.add(self) self.timer = mytimer() self.timer.Start(10000) self.image = image #self.image = ImageStack(data = dstack, mdh = mdh, filename = filename, queueURI = queueURI, events = None) if not self.image.filename is None and title == '': self.SetTitle(self.image.filename) self.do = DisplayOpts(self.image.data) if self.image.data.shape[1] == 1: self.do.slice = self.do.SLICE_XZ self.do.Optimise() if self.image.mdh and 'ChannelNames' in self.image.mdh.getEntryNames(): chan_names = self.image.mdh.getEntry('ChannelNames') if len(chan_names) == self.image.data.shape[3]: self.do.names = chan_names #self.vp = ArraySettingsAndViewPanel(self, self.image.data, wantUpdates=[self.update], mdh=self.image.mdh) #self.view = ArrayViewPanel(self, do=self.do) #self.AddPage(self.view, True, 'Data') #self._mgr.AddPane(self.vp, aui.AuiPaneInfo(). # Name("Data").Caption("Data").Centre().CloseButton(False).CaptionVisible(False)) self.mainFrame = weakref.ref(self) #self.do = self.vp.do tmp_menu = wx.Menu() tmp_menu.Append(wx.ID_OPEN, '&Open', "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVE, "&Save As", "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVEAS, "&Export Cropped", "", wx.ITEM_NORMAL) #a submenu for modules to hook and install saving functions into self.save_menu = wx.Menu() self._menus['Save'] = self.save_menu tmp_menu.AppendMenu(-1, 'Save &Results', self.save_menu) #tmp_menu.AppendSeparator() #tmp_menu.Append(wx.ID_CLOSE, "Close", "", wx.ITEM_NORMAL) self.menubar.Append(tmp_menu, "File") self._menus['File'] = tmp_menu self.view_menu = wx.Menu() self.menubar.Append(self.view_menu, "&View") self._menus['View'] = self.view_menu #'extras' menu for modules to install stuff into self.mProcessing = wx.Menu() self.menubar.Append(self.mProcessing, "&Processing") self._menus['Processing'] = self.mProcessing # Menu Bar end self.Bind(wx.EVT_MENU, self.OnOpen, id=wx.ID_OPEN) self.Bind(wx.EVT_MENU, self.OnSave, id=wx.ID_SAVE) self.Bind(wx.EVT_MENU, self.OnExport, id=wx.ID_SAVEAS) #self.Bind(wx.EVT_MENU, lambda e: self.Close(), id=wx.ID_CLOSE) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.statusbar = self.CreateStatusBar(1, wx.STB_SIZEGRIP) self.panesToMinimise = [] modules.loadMode(self.mode, self) self.CreateModuleMenu() self.add_common_menu_items() self.optionspanel = OptionsPanel(self, self.do, thresholdControls=True) self.optionspanel.SetSize(self.optionspanel.GetBestSize()) pinfo = aui.AuiPaneInfo().Name("optionsPanel").Right().Caption('Display Settings').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.optionspanel, pinfo) self.panesToMinimise.append(pinfo) self._mgr.AddPane(self.optionspanel.CreateToolBar(self), aui.AuiPaneInfo().Name("ViewTools").Caption("View Tools").CloseButton(False). ToolbarPane().Right().GripperTop()) if self.do.ds.shape[2] > 1: from PYME.DSView.modules import playback self.playbackpanel = playback.PlayPanel(self, self) self.playbackpanel.SetSize(self.playbackpanel.GetBestSize()) pinfo1 = aui.AuiPaneInfo().Name("playbackPanel").Bottom().Caption('Playback').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.playbackpanel, pinfo1) self.do.WantChangeNotification.append(self.playbackpanel.update) #self.mWindows = wx.Menu() #self.menubar.append(self.mWindows, '&Composite With') self.do.WantChangeNotification.append(self.update) self.CreateFoldPanel() for pn in self.panesToMinimise: self._mgr.MinimizePane(pn) #self._mgr.MinimizePane(pinfo2) self.Layout() if 'view' in dir(self): sc = np.floor(np.log2(1.0*self.view.Size[0]/self.do.ds.shape[0])) #print self.view.Size[0], self.do.ds.shape[0], sc self.do.SetScale(sc) self.view.Refresh() self.update() self.drop = dt() self.SetDropTarget(self.drop) self.AddMenuItem('Save', 'To Cluster', self.OnSaveToCluster) openViewers[self.image.filename] = self def CreateModuleMenu(self): #self.modMenuIds = {} self.moduleNameByID = {} self.moduleMenuIDByName = {} self.mModules = wx.Menu() for mn in modules.allmodules(): id = wx.NewId() self.mModules.AppendCheckItem(id, mn) self.moduleNameByID[id] = mn self.moduleMenuIDByName[mn] = id if mn in self.installedModules: self.mModules.Check(id, True) self.mModules.Enable(id, False) self.Bind(wx.EVT_MENU, self.OnToggleModule, id=id) self.menubar.Append(self.mModules, "&Modules") self._menus["&Modules"] = self.mModules def OnToggleModule(self, event): id = event.GetId() mn = self.moduleNameByID[id] #if self.mModules.IsChecked(id): self.LoadModule(mn) def LoadModule(self, moduleName): """Load a module with the given name and update GUI """ modules.loadModule(moduleName, self) if moduleName in self.installedModules: id = self.moduleMenuIDByName[moduleName] self.mModules.Check(id, True) self.mModules.Enable(id, False) self.CreateFoldPanel() self._mgr.Update() def GetSelectedPage(self): nbs = self._mgr.GetNotebooks() currPage = nbs[0].GetCurrentPage() return currPage def create_overlay_panel(self): from PYME.DSView.OverlaysPanel import OverlayPanel if not 'overlaypanel' in dir(self): self.overlaypanel = OverlayPanel(self, self.view, self.image.mdh) self.overlaypanel.SetSize(self.overlaypanel.GetBestSize()) pinfo2 = aui.AuiPaneInfo().Name("overlayPanel").Right().Caption('Overlays').CloseButton( False).MinimizeButton(True).MinimizeMode( aui.AUI_MINIMIZE_CAPT_SMART | aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.overlaypanel, pinfo2) self.panesToMinimise.append(pinfo2) def update(self): if not self.updating: self.updating = True #if 'view' in dir(self): # self.view.Refresh() statusText = 'Slice No: (%d/%d) x: %d y: %d' % (self.do.zp, self.do.ds.shape[2], self.do.xp, self.do.yp) #grab status from modules which supply it for sCallback in self.statusHooks: statusText += '\t' + sCallback() #'Frames Analysed: %d Events detected: %d' % (self.vp.do.zp, self.vp.do.ds.shape[2], self.vp.do.xp, self.vp.do.yp, self.LMAnalyser.numAnalysed, self.LMAnalyser.numEvents) self.statusbar.SetStatusText(statusText) #if 'playbackpanel' in dir(self): # self.playbackpanel.update() #update any modules which require it for uCallback in self.updateHooks: #print uCallback uCallback(self) self.updating = False #def Redraw(self): # self.v def DataChanged(self): for uCallback in self.dataChangeHooks: uCallback(self) def OnOpen(self, event=None): ViewIm3D(ImageStack()) def OnSave(self, event=None): self.image.Save() self.SetTitle(self.image.filename) def OnSaveToCluster(self, event=None): from PYME.IO import clusterExport seriesName = clusterExport.suggest_cluster_filename(self.image) ted = wx.TextEntryDialog(None, 'Cluster filename:', 'Save file to cluster', seriesName) if ted.ShowModal() == wx.ID_OK: #pd = wx.ProgressDialog() clusterExport.ExportImageToCluster(self.image, ted.GetValue()) ted.Destroy() def OnExport(self, event=None): bx = min(self.do.selection_begin_x, self.do.selection_end_x) ex = max(self.do.selection_begin_x, self.do.selection_end_x) by = min(self.do.selection_begin_y, self.do.selection_end_y) ey = max(self.do.selection_begin_y, self.do.selection_end_y) roi = [[bx, ex + 1],[by, ey + 1], [0, self.image.data.shape[2]]] self.image.Save(crop = True, roi=roi) def OnCrop(self): pass #View3D(self.image.data[]) def OnCloseWindow(self, event): plt.close('all') if (not self.image.saved): dialog = wx.MessageDialog(self, "Save data stack?", "PYME", wx.YES_NO|wx.CANCEL) ans = dialog.ShowModal() if(ans == wx.ID_YES): self.OnSave() self._cleanup() elif (ans == wx.ID_NO): self._cleanup() else: #wxID_CANCEL: if (not event.CanVeto()): self._cleanup() else: event.Veto() else: self._cleanup() def _cleanup(self): self.timer.Stop() del(self.image) AUIFrame._cleanup(self) def dsRefresh(self): #zp = self.vp.do.zp #save z -position self.do.SetDataStack(self.image.dataSource) #self.vp.do.zp = zp #restore z position self.elv.SetEventSource(self.image.dataSource.getEvents()) self.elv.SetRange([0, self.image.dataSource.getNumSlices()]) if b'ProtocolFocus' in self.elv.evKeyNames: self.zm = piecewiseMapping.GeneratePMFromEventList(self.elv.eventSource, self.mdh.getEntry('Camera.CycleTime'), self.mdh.getEntry('StartTime'), self.mdh.getEntry('Protocol.PiezoStartPos')) self.elv.SetCharts([('Focus [um]', self.zm, b'ProtocolFocus'),]) self.update()
def __init__(self, parent, dstack=None, aspect=1, do=None, voxelsize=[1, 1, 1]): if (dstack is None and do is None): dstack = scipy.zeros((10, 10)) if do is None: self.do = DisplayOpts(dstack, aspect=aspect) self.do.Optimise() else: self.do = do self.voxelsize = voxelsize scrolledImagePanel.ScrolledImagePanel.__init__(self, parent, self.DoPaint, style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL) self.do.WantChangeNotification.append(self.GetOpts) #self.do.WantChangeNotification.append(self.Refresh) self.SetVirtualSize(wx.Size(self.do.ds.shape[0], self.do.ds.shape[1])) #self.imagepanel.SetSize(wx.Size(self.do.ds.shape[0],self.do.ds.shape[1])) self.points = [] self.pointsR = [] self.showPoints = True self.showTracks = True self.showContours = True self.showScaleBar = True self.scaleBarLength = 2000 self.pointMode = 'confoc' self.pointTolNFoc = { 'confoc': (5, 5, 5), 'lm': (2, 5, 5), 'splitter': (2, 5, 5) } self.showAdjacentPoints = False self.pointSize = 11 self.layerMode = 'Add' self.psfROIs = [] self.psfROISize = [30, 30, 30] self.lastUpdateTime = 0 self.lastFrameTime = 2e-3 #self.do.scale = 0 self.crosshairs = True #self.showSelection = True self.selecting = False self.aspect = 1. self._slice = None self._sc = None self.overlays = [] self._oldIm = None self._oldImSig = None self.CenteringHandlers = [] self.selectHandlers = [] self.labelPens = [ wx.Pen( wx.Colour(*[ int(c) for c in matplotlib.cm.hsv(v, alpha=.5, bytes=True) ]), 2) for v in numpy.linspace(0, 1, 16) ] # if not aspect is None: # if scipy.isscalar(aspect): # self.do.aspects[2] = aspect # elif len(aspect) == 3: # self.do.aspects = aspect #self.SetOpts() #self.optionspanel.RefreshHists() self.updating = 0 self.showOptsPanel = 1 self.refrTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnRefrTimer) self.imagepanel.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel) self.imagepanel.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress) #wx.EVT_KEY_DOWN(self.Parent(), self.OnKeyPress) self.imagepanel.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.imagepanel.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.imagepanel.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown) self.imagepanel.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp) self.imagepanel.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) self.imagepanel.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) self.imagepanel.Bind(wx.EVT_MIDDLE_DCLICK, self.OnMiddleDClick) self.imagepanel.Bind(wx.EVT_MOTION, self.OnMotion) # self.imagepanel.Bind(wx.EVT_ERASE_BACKGROUND, self.DoNix) self.Bind(wx.EVT_ERASE_BACKGROUND, self.DoNix)
class ArrayViewPanel(scrolledImagePanel.ScrolledImagePanel): def __init__(self, parent, dstack=None, aspect=1, do=None, voxelsize=[1, 1, 1]): if (dstack is None and do is None): dstack = scipy.zeros((10, 10)) if do is None: self.do = DisplayOpts(dstack, aspect=aspect) self.do.Optimise() else: self.do = do self.voxelsize = voxelsize scrolledImagePanel.ScrolledImagePanel.__init__(self, parent, self.DoPaint, style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL) self.do.WantChangeNotification.append(self.GetOpts) #self.do.WantChangeNotification.append(self.Refresh) self.SetVirtualSize(wx.Size(self.do.ds.shape[0], self.do.ds.shape[1])) #self.imagepanel.SetSize(wx.Size(self.do.ds.shape[0],self.do.ds.shape[1])) self.points = [] self.pointsR = [] self.showPoints = True self.showTracks = True self.showContours = True self.showScaleBar = True self.scaleBarLength = 2000 self.pointMode = 'confoc' self.pointTolNFoc = { 'confoc': (5, 5, 5), 'lm': (2, 5, 5), 'splitter': (2, 5, 5) } self.showAdjacentPoints = False self.pointSize = 11 self.layerMode = 'Add' self.psfROIs = [] self.psfROISize = [30, 30, 30] self.lastUpdateTime = 0 self.lastFrameTime = 2e-3 #self.do.scale = 0 self.crosshairs = True #self.showSelection = True self.selecting = False self.aspect = 1. self._slice = None self._sc = None self.overlays = [] self._oldIm = None self._oldImSig = None self.CenteringHandlers = [] self.selectHandlers = [] self.labelPens = [ wx.Pen( wx.Colour(*[ int(c) for c in matplotlib.cm.hsv(v, alpha=.5, bytes=True) ]), 2) for v in numpy.linspace(0, 1, 16) ] # if not aspect is None: # if scipy.isscalar(aspect): # self.do.aspects[2] = aspect # elif len(aspect) == 3: # self.do.aspects = aspect #self.SetOpts() #self.optionspanel.RefreshHists() self.updating = 0 self.showOptsPanel = 1 self.refrTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnRefrTimer) self.imagepanel.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel) self.imagepanel.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress) #wx.EVT_KEY_DOWN(self.Parent(), self.OnKeyPress) self.imagepanel.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.imagepanel.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.imagepanel.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown) self.imagepanel.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp) self.imagepanel.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) self.imagepanel.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) self.imagepanel.Bind(wx.EVT_MIDDLE_DCLICK, self.OnMiddleDClick) self.imagepanel.Bind(wx.EVT_MOTION, self.OnMotion) # self.imagepanel.Bind(wx.EVT_ERASE_BACKGROUND, self.DoNix) self.Bind(wx.EVT_ERASE_BACKGROUND, self.DoNix) def OnRefrTimer(self, event): self.Refresh() self.Update() def SetDataStack(self, ds): self.do.SetDataStack(ds) self.SetVirtualSize(wx.Size(self.do.ds.shape[0], self.do.ds.shape[1])) self.do.xp = 0 self.do.yp = 0 self.do.zp = 0 self.do.Optimise() self.do.ResetSelection() self.Layout() # self.Refresh() def ResetDataStack(self, ds): self.do.SetDataStack(ds) def _ScreenToAbsCoordinates(self, x, y): xp, yp = self.CalcUnscrolledPosition(x, y) #xp = self.centreX + self.glCanvas.pixelsize*(x - self.Size[0]/2) #yp = self.centreY - self.glCanvas.pixelsize*(y - self.Size[1]/2) if self.do.orientation == self.do.UPRIGHT: return xp, yp else: return yp, xp def _ScreenToPixelCoordinates(self, x, y): #sc = pow(2.0,(self.do.scale-2)) xp, yp = self._ScreenToAbsCoordinates(x, y) return xp / self.scale, yp / (self.scale * self.aspect) def _AbsToScreenCoordinates(self, x, y): x0, y0 = self.CalcUnscrolledPosition(0, 0) if self.do.orientation == self.do.UPRIGHT: return x - x0, y - y0 else: return y - x0, x - y0 def _PixelToScreenCoordinates(self, x, y): #sc = pow(2.0,(self.do.scale-2)) #print self.scale, self.aspect return self._AbsToScreenCoordinates(x * self.scale, y * self.scale * self.aspect) def _PixelToScreenCoordinates3D(self, x, y, z): #sc = pow(2.0,(self.do.scale-2)) if (self.do.slice == self.do.SLICE_XY): xs, ys = self._PixelToScreenCoordinates(x, y) elif (self.do.slice == self.do.SLICE_XZ): xs, ys = self._PixelToScreenCoordinates(x, z) elif (self.do.slice == self.do.SLICE_YZ): xs, ys = self._PixelToScreenCoordinates(y, z) return xs, ys def _drawBoxPixelCoords(self, dc, x, y, z, w, h, d): """Draws a box in screen space given 3D co-ordinates""" if (self.do.slice == self.do.SLICE_XY): xs, ys = self._PixelToScreenCoordinates(x, y) ws, hs = (w * self.scale, h * self.scale * self.aspect) elif (self.do.slice == self.do.SLICE_XZ): xs, ys = self._PixelToScreenCoordinates(x, z) ws, hs = (w * self.scale, d * self.scale * self.aspect) elif (self.do.slice == self.do.SLICE_YZ): xs, ys = self._PixelToScreenCoordinates(y, z) ws, hs = (h * self.scale, d * self.scale * self.aspect) dc.DrawRectangle(xs - 0.5 * ws, ys - 0.5 * hs, ws, hs) @property def scale(self): return pow(2.0, (self.do.scale)) def DrawCrosshairs(self, view, dc): if self.crosshairs: sX, sY = view.imagepanel.Size dc.SetPen(wx.Pen(wx.CYAN, 1)) if (view.do.slice == view.do.SLICE_XY): lx = view.do.xp ly = view.do.yp elif (view.do.slice == view.do.SLICE_XZ): lx = view.do.xp ly = view.do.zp elif (view.do.slice == view.do.SLICE_YZ): lx = view.do.yp ly = view.do.zp xc, yc = view._PixelToScreenCoordinates(lx, ly) dc.DrawLine(0, yc, sX, yc) dc.DrawLine(xc, 0, xc, sY) dc.SetPen(wx.NullPen) def DrawSelection(self, view, dc): if self.do.showSelection: col = wx.TheColourDatabase.FindColour('YELLOW') #col.Set(col.red, col.green, col.blue, 125) dc.SetPen(wx.Pen(col, 1)) dc.SetBrush(wx.TRANSPARENT_BRUSH) lx, ly, hx, hy = self.do.GetSliceSelection() lx, ly = self._PixelToScreenCoordinates(lx, ly) hx, hy = self._PixelToScreenCoordinates(hx, hy) if self.do.selectionMode == DisplayOpts.SELECTION_RECTANGLE: dc.DrawRectangle(lx, ly, (hx - lx), (hy - ly)) elif self.do.selectionMode == DisplayOpts.SELECTION_SQUIGGLE: if len(self.do.selection_trace) > 2: x, y = numpy.array(self.do.selection_trace).T pts = numpy.vstack(self._PixelToScreenCoordinates(x, y)).T dc.DrawSpline(pts) elif self.do.selectionWidth == 1: dc.DrawLine(lx, ly, hx, hy) else: lx, ly, hx, hy = self.do.GetSliceSelection() dx = hx - lx dy = hy - ly if dx == 0 and dy == 0: #special case - profile is orthogonal to current plane d_x = 0.5 * self.do.selectionWidth d_y = 0.5 * self.do.selectionWidth else: d_x = 0.5 * self.do.selectionWidth * dy / numpy.sqrt( (dx**2 + dy**2)) d_y = 0.5 * self.do.selectionWidth * dx / numpy.sqrt( (dx**2 + dy**2)) x_0, y_0 = self._PixelToScreenCoordinates(lx + d_x, ly - d_y) x_1, y_1 = self._PixelToScreenCoordinates(lx - d_x, ly + d_y) x_2, y_2 = self._PixelToScreenCoordinates(hx - d_x, hy + d_y) x_3, y_3 = self._PixelToScreenCoordinates(hx + d_x, hy - d_y) lx, ly = self._PixelToScreenCoordinates(lx, ly) hx, hy = self._PixelToScreenCoordinates(hx, hy) dc.DrawLine(lx, ly, hx, hy) dc.DrawPolygon([(x_0, y_0), (x_1, y_1), (x_2, y_2), (x_3, y_3)]) dc.SetPen(wx.NullPen) dc.SetBrush(wx.NullBrush) def DrawTracks(self, view, dc): if self.showTracks and 'filter' in dir( self) and 'clumpIndex' in self.filter.keys(): t = self.filter['t'] #prob safe as int x = self.filter['x'] / self.voxelsize[0] y = self.filter['y'] / self.voxelsize[1] xb, yb, zb = self._calcVisibleBounds() IFoc = (x >= xb[0]) * (y >= yb[0]) * (t >= zb[0]) * (x < xb[1]) * ( y < yb[1]) * (t < zb[1]) tFoc = list(set(self.filter['clumpIndex'][IFoc])) dc.SetBrush(wx.TRANSPARENT_BRUSH) for tN in tFoc: IFoc = (self.filter['clumpIndex'] == tN) if IFoc.sum() < 2: return pFoc = numpy.vstack( self._PixelToScreenCoordinates3D(x[IFoc], y[IFoc], t[IFoc])).T #print pFoc.shape dc.SetPen(self.labelPens[tN % 16]) dc.DrawLines(pFoc) def DrawScaleBar(self, view, dc): if self.showScaleBar: pGreen = wx.Pen(wx.TheColourDatabase.FindColour('WHITE'), 10) pGreen.SetCap(wx.CAP_BUTT) dc.SetPen(pGreen) sX, sY = view.imagepanel.Size sbLen = self.scaleBarLength * view.scale / view.voxelsize[0] y1 = 20 x1 = 20 + sbLen x0 = x1 - sbLen dc.DrawLine(x0, y1, x1, y1) dc.SetTextForeground(wx.TheColourDatabase.FindColour('WHITE')) if self.scaleBarLength > 1000: s = u'%1.1f \u00B5m' % (self.scaleBarLength / 1000.) else: s = u'%d nm' % int(self.scaleBarLength) w, h = dc.GetTextExtent(s) dc.DrawText(s, x0 + (sbLen - w) / 2, y1 + 7) def DrawContours(self, view, dc): if self.showContours and 'filter' in dir( self) and 'contour' in self.filter.keys( ) and self.do.slice == self.do.SLICE_XY: t = self.filter['t'] # prob safe as int x = self.filter['x'] / self.voxelsize[0] y = self.filter['y'] / self.voxelsize[1] xb, yb, zb = self._calcVisibleBounds() IFoc = (x >= xb[0]) * (y >= yb[0]) * (t >= zb[0]) * (x < xb[1]) * ( y < yb[1]) * (t < zb[1]) dc.SetBrush(wx.TRANSPARENT_BRUSH) pGreen = wx.Pen(wx.TheColourDatabase.FindColour('RED'), 1) #pRed = wx.Pen(wx.TheColourDatabase.FindColour('RED'),1) dc.SetPen(pGreen) contours = self.filter['contour'][IFoc] if 'clumpIndex' in self.filter.keys(): colInds = self.filter['clumpIndex'][IFoc] % len(self.labelPens) else: colInds = numpy.zeros(len(contours), 'i') #%len(self.labelPens) for c, colI in zip(contours, colInds): xc, yc = c.T dc.SetPen(self.labelPens[int(colI)]) dc.DrawSpline( numpy.vstack(self._PixelToScreenCoordinates(xc, yc)).T) def DrawPoints(self, view, dc): dx = 0 dy = 0 aN = SLICE_AXIS_LUT[self.do.slice] tolN = TOL_AXIS_LUT[self.do.slice] pos = [self.do.xp, self.do.yp, self.do.zp] if self.showPoints and ('filter' in dir(self) or len(self.points) > 0): if 'filter' in dir(self): t = self.filter['t'] #prob safe as int x = self.filter['x'] / self.voxelsize[0] y = self.filter['y'] / self.voxelsize[1] xb, yb, zb = self._calcVisibleBounds() IFoc = (x >= xb[0]) * (y >= yb[0]) * (t >= zb[0]) * ( x < xb[1]) * (y < yb[1]) * (t < zb[1]) pFoc = numpy.vstack((x[IFoc], y[IFoc], t[IFoc])).T if self.pointMode == 'splitter': pCol = self.filter['gFrac'][IFoc] > .5 pNFoc = [] #intrinsic points elif len(self.points) > 0: pointTol = self.pointTolNFoc[self.pointMode] IFoc = abs(self.points[:, aN] - pos[aN]) < 1 INFoc = abs(self.points[:, aN] - pos[aN]) < pointTol[tolN] pFoc = self.points[IFoc] pNFoc = self.points[INFoc] if self.pointMode == 'splitter': pCol = self.pointColours[IFoc] if self.pointMode == 'splitter': if 'chroma' in dir(self): dx = self.chroma.dx.ev( pFoc[:, 0] * 1e3 * self.voxelsize[0], pFoc[:, 1] * 1e3 * self.voxelsize[1]) / (1e3 * self.voxelsize[0]) dy = self.chroma.dy.ev( pFoc[:, 0] * 1e3 * self.voxelsize[0], pFoc[:, 1] * 1e3 * self.voxelsize[1]) / (1e3 * self.voxelsize[1]) else: dx = 0 * pFoc[:, 0] dy = 0 * pFoc[:, 0] if 'chroma' in dir(self): dxn = self.chroma.dx.ev( pNFoc[:, 0] * 1e3 * self.voxelsize[0], pNFoc[:, 1] * 1e3 * self.voxelsize[1]) / (1e3 * self.voxelsize[0]) dyn = self.chroma.dy.ev( pNFoc[:, 0] * 1e3 * self.voxelsize[0], pNFoc[:, 1] * 1e3 * self.voxelsize[1]) / (1e3 * self.voxelsize[1]) else: dxn = 0 * pNFoc[:, 0] dyn = 0 * pNFoc[:, 0] dc.SetBrush(wx.TRANSPARENT_BRUSH) ps = self.pointSize if self.showAdjacentPoints: dc.SetPen(wx.Pen(wx.TheColourDatabase.FindColour('BLUE'), 1)) if self.pointMode == 'splitter': for p, dxi, dyi in zip(pNFoc, dxn, dyn): self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) self._drawBoxPixelCoords( dc, p[0] - dxi, 0.5 * self.do.ds.shape[1] + p[1] - dyi, p[2], ps, ps, ps) else: for p in pNFoc: self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) pGreen = wx.Pen(wx.TheColourDatabase.FindColour('GREEN'), 1) pRed = wx.Pen(wx.TheColourDatabase.FindColour('RED'), 1) dc.SetPen(pGreen) if self.pointMode == 'splitter': for p, c, dxi, dyi in zip(pFoc, pCol, dx, dy): if c: dc.SetPen(pGreen) else: dc.SetPen(pRed) self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) self._drawBoxPixelCoords( dc, p[0] - dxi, 0.5 * self.do.ds.shape[1] + p[1] - dyi, p[2], ps, ps, ps) else: for p in pFoc: self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) dc.SetPen(wx.NullPen) dc.SetBrush(wx.NullBrush) def _calcVisibleBounds(self): sc = pow(2.0, (self.do.scale)) x0, y0 = self.CalcUnscrolledPosition(0, 0) sX, sY = self.imagepanel.Size if self.do.slice == self.do.SLICE_XY: bnds = [(x0 / sc, (x0 + sX) / sc), (y0 / sc, (y0 + sY) / sc), (self.do.zp - .5, self.do.zp + .5)] elif self.do.slice == self.do.SLICE_XZ: bnds = [(x0 / sc, (x0 + sX) / sc), (self.do.yp - .5, self.do.yp + .5), (y0 / sc, (y0 + sY) / sc)] elif self.do.slice == self.do.SLICE_YZ: bnds = [(self.do.xp - .5, self.do.xp + .5), (x0 / sc, (x0 + sX) / sc), (y0 / sc, (y0 + sY) / sc)] return bnds def DoPaint(self, dc, fullImage=False): #print 'p' dc.Clear() im = self.Render(fullImage) sc = pow(2.0, (self.do.scale)) sc2 = sc if sc >= 1: step = 1 else: step = 2**(-numpy.ceil(numpy.log2(sc))) sc2 = sc * step im2 = wx.BitmapFromImage(im) dc.DrawBitmap(im2, -sc2 / 2, -sc2 / 2) #sX, sY = im.GetWidth(), im.GetHeight() self.DrawCrosshairs(self, dc) self.DrawSelection(self, dc) self.DrawScaleBar(self, dc) #self.DrawTracks(self, dc) self.DrawPoints(self, dc) self.DrawContours(self, dc) dc.SetPen(wx.NullPen) dc.SetBrush(wx.NullBrush) for ovl in self.do.overlays: ovl(self, dc) def GrabImage(self, fullImage=True): #TODO - get suitable image dependent viewport xs, ys = self._unscrolled_view_size() if fullImage: if (xs > 2e3 or ys > 2e3) and wx.MessageBox( 'Captured image will be very large, continue?', 'Warning', style=wx.OK | wx.CANCEL) != wx.OK: return else: s = self.GetClientSize() xs = min(s.GetWidth(), xs) ys = min(s.GetHeight(), ys) MemBitmap = wx.EmptyBitmap(xs, ys) MemDC = wx.MemoryDC() OldBitmap = MemDC.SelectObject(MemBitmap) self.DoPaint(MemDC, fullImage) return MemBitmap def GrabPNG(self, filename, fullImage=True): MemBitmap = self.GrabImage(fullImage) img = MemBitmap.ConvertToImage() img.SaveFile(filename, wx.BITMAP_TYPE_PNG) def GrabPNGToBuffer(self, fullImage=True): '''Get PNG data in a buffer (rather than writing directly to file)''' from io import BytesIO img = self.GrabImage(fullImage) out = BytesIO() # NB - using wx functionality rather than pillow here as wxImage.GetData() returns a BytesArray object rather # than a buffer on py3. This underlying problem may need to be revisited. img.ConvertToImage().SaveFile(out, wx.BITMAP_TYPE_PNG) return out.getvalue() def CopyImage(self, fullImage=True): """ Copies the currently displayed image to the clipboard""" bmp = self.GrabImage(fullImage) try: wx.TheClipboard.Open() bmpDataObject = wx.BitmapDataObject(bmp) wx.TheClipboard.SetData(bmpDataObject) finally: wx.TheClipboard.Close() def OnWheel(self, event): rot = event.GetWheelRotation() if rot < 0: if event.RightIsDown(): self.do.yp = max(self.do.yp - 1, 0) elif event.MiddleIsDown(): self.do.xp = max(self.do.xp - 1, 0) elif event.ShiftDown(): self.do.SetScale(self.do.scale - 1) else: self.do.zp = max(self.do.zp - 1, 0) if rot > 0: if event.RightIsDown(): self.do.yp = min(self.do.yp + 1, self.do.ds.shape[1] - 1) elif event.MiddleIsDown(): self.do.xp = min(self.do.xp + 1, self.do.ds.shape[0] - 1) elif event.ShiftDown(): self.do.SetScale(self.do.scale + 1) else: self.do.zp = min(self.do.zp + 1, self.do.ds.shape[2] - 1) if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() #self.update() def OnKeyPress(self, event): if event.GetKeyCode() == wx.WXK_PAGEUP: self.do.zp = max(0, self.do.zp - 1) #self.optionspanel.RefreshHists() if ('update' in dir(self.GetParent())): self.GetParent().update() else: #if not self.painting: self.imagepanel.Refresh() #else: # if not self.refrTimer.IsRunning(): # self.refrTimer.Start(.2, True) elif event.GetKeyCode() == wx.WXK_PAGEDOWN: self.do.zp = min(self.do.zp + 1, self.do.ds.shape[2] - 1) #self.optionspanel.RefreshHists() if ('update' in dir(self.GetParent())): self.GetParent().update() #print 'upd' else: #if not self.painting: self.imagepanel.Refresh() #else: # if not self.refrTimer.IsRunning(): #print 'upt' # self.refrTimer.Start(.2, True) elif event.GetKeyCode() == 74: #J self.do.xp = (self.do.xp - 1) if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 76: #L self.do.xp += 1 if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 73: #I self.do.yp -= 1 if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 75: #K self.do.yp += 1 if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 77: #M #print 'o' self.do.Optimise() elif event.GetKeyCode() == ord('C'): if event.GetModifiers() == wx.MOD_CMD: self.CopyImage() elif event.GetModifiers() == wx.MOD_CMD | wx.MOD_SHIFT: self.CopyImage(False) else: event.Skip() else: event.Skip() def GetOpts(self, event=None): if (self.updating == 0): sc = pow(2.0, (self.do.scale)) s = self.CalcImSize() self.SetVirtualSize(wx.Size(s[0] * sc, s[1] * sc)) if (self._slice != self.do.slice) or (self._sc != sc): #print('recentering') #if the slice has changed, change our aspect and do some self._slice = self.do.slice self._sc = sc #if not event is None and event.GetId() in [self.cbSlice.GetId(), self.cbScale.GetId()]: #recenter the view if (self.do.slice == self.do.SLICE_XY): lx = self.do.xp ly = self.do.yp self.aspect = self.do.aspect[1] / self.do.aspect[0] elif (self.do.slice == self.do.SLICE_XZ): lx = self.do.xp ly = self.do.zp self.aspect = self.do.aspect[2] / self.do.aspect[0] elif (self.do.slice == self.do.SLICE_YZ): lx = self.do.yp ly = self.do.zp self.aspect = self.do.aspect[2] / self.do.aspect[1] sx, sy = self.imagepanel.GetClientSize() ppux, ppuy = self.GetScrollPixelsPerUnit() self.Scroll( max(0, lx * sc - sx / 2) / ppux, max(0, ly * sc * self.aspect - sy / 2) / ppuy) #self.imagepanel.Refresh() self.Refresh() self.Update() def Optim(self, event=None): self.do.Optimise(self.do.ds, int(self.do.zp)) self.updating = 1 #self.SetOpts() #self.optionspanel.RefreshHists() self.Refresh() self.Update() self.updating = 0 def CalcImSize(self): if (self.do.slice == self.do.SLICE_XY): if (self.do.orientation == self.do.UPRIGHT): return (self.do.ds.shape[0], self.do.ds.shape[1]) else: return (self.do.ds.shape[1], self.do.ds.shape[0]) elif (self.do.slice == self.do.SLICE_XZ): return (self.do.ds.shape[0], self.do.ds.shape[2]) else: return (self.do.ds.shape[1], self.do.ds.shape[2]) def DoNix(self, event): pass def OnLeftDown(self, event): if self.do.leftButtonAction == self.do.ACTION_SELECTION: self.StartSelection(event) event.Skip() def OnLeftUp(self, event): if self.do.leftButtonAction == self.do.ACTION_SELECTION: self.ProgressSelection(event) self.EndSelection() else: self.OnSetPosition(event) event.Skip() def OnMiddleDown(self, event): dc = wx.ClientDC(self.imagepanel) # self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) self.middleDownPos = self.CalcUnscrolledPosition(*pos) event.Skip() def OnMiddleUp(self, event): dc = wx.ClientDC(self.imagepanel) # self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) dx = pos[0] - self.middleDownPos[0] dy = pos[1] - self.middleDownPos[1] sc = pow(2.0, (self.do.scale)) if (abs(dx) > 5) or (abs(dy) > 5): for h in self.CenteringHandlers: h(-dx / sc, -dy / sc) event.Skip() def OnMiddleDClick(self, event): dc = wx.ClientDC(self.imagepanel) # self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print pos sc = pow(2.0, (self.do.scale)) if (self.do.slice == self.do.SLICE_XY): x = (pos[0] / sc) - 0.5 * self.do.ds.shape[0] y = (pos[1] / (sc * self.aspect)) - 0.5 * self.do.ds.shape[1] for h in self.CenteringHandlers: h(x, y) event.Skip() def _unscrolled_view_size(self): sc = pow(2.0, (self.do.scale)) shp = self.do.ds.shape if (self.do.slice == self.do.SLICE_XY): xs = int(shp[0] * sc) ys = int(shp[1] * sc * self.aspect) elif (self.do.slice == self.do.SLICE_XZ): xs = int(shp[0] * sc) ys = int(shp[2] * sc * self.aspect) elif (self.do.slice == self.do.SLICE_YZ): xs = int(shp[1] * sc) ys = int(shp[2] * sc * self.aspect) return xs, ys def OnSetPosition(self, event): dc = wx.ClientDC(self.imagepanel) #self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print(pos) self.do.inOnChange = True try: sc = pow(2.0, (self.do.scale)) #print(sc) if (self.do.slice == self.do.SLICE_XY): self.do.xp = int(pos[0] / sc) self.do.yp = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_XZ): self.do.xp = int(pos[0] / sc) self.do.zp = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.yp = int(pos[0] / sc) self.do.zp = int(pos[1] / (sc * self.aspect)) finally: self.do.inOnChange = False self.do.OnChange() for cb in self.selectHandlers: cb(self) #if ('update' in dir(self.GetParent())): # self.GetParent().update() #else: # self.imagepanel.Refresh() def PointsHitTest(self): if len(self.points) > 0: iCand = numpy.where((abs(self.points[:, 2] - self.do.zp) < 1) * (abs(self.points[:, 0] - self.do.xp) < 3) * (abs(self.points[:, 1] - self.do.yp) < 3))[0] if len(iCand) == 0: return None elif len(iCand) == 1: return iCand[0] else: pCand = self.points[iCand, :] iNearest = numpy.argmin((pCand[:, 0] - self.do.xp)**2 + (pCand[:, 1] - self.do.yp)**2) return iCand[iNearest] else: return None def OnRightDown(self, event): self.StartSelection(event) def StartSelection(self, event): self.selecting = True dc = wx.ClientDC(self.imagepanel) #self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print pos sc = pow(2.0, (self.do.scale)) if (self.do.slice == self.do.SLICE_XY): self.do.selection_begin_x = int(pos[0] / sc) self.do.selection_begin_y = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_XZ): self.do.selection_begin_x = int(pos[0] / sc) self.do.selection_begin_z = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.selection_begin_y = int(pos[0] / sc) self.do.selection_begin_z = int(pos[1] / (sc * self.aspect)) self.do.selection_trace = [] self.do.selection_trace.append( ((pos[0] / sc), (pos[1] / (sc * self.aspect)))) def OnRightUp(self, event): self.ProgressSelection(event) self.EndSelection() def OnMotion(self, event): if event.Dragging() and self.selecting: self.ProgressSelection(event) def ProgressSelection(self, event): dc = wx.ClientDC(self.imagepanel) #self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print pos sc = pow(2.0, (self.do.scale)) if not event.ShiftDown(): if (self.do.slice == self.do.SLICE_XY): self.do.selection_end_x = int(pos[0] / sc) self.do.selection_end_y = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_XZ): self.do.selection_end_x = int(pos[0] / sc) self.do.selection_end_z = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.selection_end_y = int(pos[0] / sc) self.do.selection_end_z = int(pos[1] / (sc * self.aspect)) else: #lock if (self.do.slice == self.do.SLICE_XY): self.do.selection_end_x = int(pos[0] / sc) self.do.selection_end_y = int(pos[1] / (sc * self.aspect)) dx = abs(self.do.selection_end_x - self.do.selection_begin_x) dy = abs(self.do.selection_end_y - self.do.selection_begin_y) if dx > 1.5 * dy: #horizontal self.do.selection_end_y = self.do.selection_begin_y elif dy > 1.5 * dx: #vertical self.do.selection_end_x = self.do.selection_begin_x else: #diagonal self.do.selection_end_y = self.do.selection_begin_y + dx * numpy.sign( self.do.selection_end_y - self.do.selection_begin_y) elif (self.do.slice == self.do.SLICE_XZ): self.do.selection_end_x = int(pos[0] / sc) self.do.selection_end_z = int(pos[1] / (sc * self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.selection_end_y = int(pos[0] / sc) self.do.selection_end_z = int(pos[1] / (sc * self.aspect)) self.do.selection_trace.append( ((pos[0] / sc), (pos[1] / (sc * self.aspect)))) self.Refresh() self.Update() def EndSelection(self): self.selecting = False self.do.EndSelection() def _gensig(self, x0, y0, sX, sY, do): sig = [ x0, y0, sX, sY, do.scale, do.slice, do.GetActiveChans(), do.ds.shape ] if do.slice == DisplayOpts.SLICE_XY: sig += [do.zp, do.maximumProjection] if do.slice == DisplayOpts.SLICE_XZ: sig += [do.yp] if do.slice == DisplayOpts.SLICE_YZ: sig += [do.xp] return sig def Redraw(self, sender=None, **kwargs): self._oldImSig = None self.Refresh() self.Update() def _map_colour(self, seg, gain, offset, cmap, ima): lut = getLUT(cmap) if cmap == labeled: # special case for labelled colourmap - use slow matplotlib lookup and rely on matplotlib roll-around to # cycle colour map TODO - check if recent matplotlibs actually roll around or not. ima[:] = numpy.minimum( ima[:] + (255 * cmap(gain * (seg - offset))[:, :, :3])[:], 255) elif numpy.iscomplexobj(seg): if self.do.colourMax or (self.do.complexMode == 'imag coloured'): applyLUT(numpy.imag(seg), self.do.cmax_scale / self.do.ds.shape[2], self.do.cmax_offset, lut, ima) ima[:] = (ima * numpy.clip((numpy.real(seg) - offset) * gain, 0, 1)[:, :, None]).astype('uint8') elif self.do.complexMode == 'real': applyLUT(seg.real, gain, offset, lut, ima) elif self.do.complexMode == 'imag': applyLUT(seg.imag, gain, offset, lut, ima) elif self.do.complexMode == 'abs': applyLUT(numpy.abs(seg), gain, offset, lut, ima) elif self.do.complexMode == 'angle': applyLUT(numpy.angle(seg), gain, offset, lut, ima) else: applyLUT(numpy.angle(seg), self.do.cmax_scale / self.do.ds.shape[2], self.do.cmax_offset, lut, ima) ima[:] = (ima * numpy.clip((numpy.abs(seg) - offset) * gain, 0, 1)[:, :, None]).astype('uint8') else: #print seg.shape applyLUT(seg, gain, offset, lut, ima) def Render(self, fullImage=False): #print 'rend' if fullImage: x0, y0 = 0, 0 sX, sY = self._unscrolled_view_size() else: x0, y0 = self.CalcUnscrolledPosition(0, 0) sX, sY = self.imagepanel.Size sig = self._gensig(x0, y0, sX, sY, self.do) if sig == self._oldImSig: # and not self._oldIm is None: #if nothing has changed, don't re-render return self._oldIm sc = pow(2.0, self.do.scale) sc2 = sc if sc >= 1: step = 1 else: step = 2**(-numpy.ceil(numpy.log2(sc))) sc2 = sc * step sX_ = int(sX / (sc)) sY_ = int(sY / (sc * self.aspect)) x0_ = int(x0 / sc) y0_ = int(y0 / (sc * self.aspect)) fstep = float(step) step = int(step) if (step > 1) and hasattr(self.do.ds, 'levels'): # we have a pyramidal data source level = -self.do.scale #if (level > len(self.do.ds.levels)): level = int(min(level, len(self.do.ds.levels))) step = int(2**(-numpy.ceil(numpy.log2(sc)) - level)) _s = 1.0 / (2**level) x0_, y0_, sX_, sY_ = [ int(numpy.ceil(v * _s)) for v in [x0_, y0_, sX_, sY_] ] # x0_ = int(numpy.ceil(x0_*_s)) # y0_ = int(y0_*_s) # sX_ = int(sX_*_s) # sY_ = int(sY_*_s) ds = self.do.ds.levels[level] else: ds = self.do.ds _s = 1 #XY if self.do.slice == DisplayOpts.SLICE_XY: dmy, dmx = self.do.ds.shape[1], self.do.ds.shape[0] slice_key = (slice(x0_, (x0_ + sX_), step), slice(y0_, (y0_ + sY_), step), int(self.do.zp * _s), int(self.do.tp * _s)) proj_axis = 2 #XZ elif self.do.slice == DisplayOpts.SLICE_XZ: dmy, dmx = self.do.ds.shape[2], self.do.ds.shape[0] slice_key = (slice(x0_, (x0_ + sX_), step), int(self.do.yp * _s), slice(y0_, (y0_ + sY_), step), int(self.do.tp * _s)) proj_axis = 1 #YZ elif self.do.slice == DisplayOpts.SLICE_YZ: dmy, dmx = self.do.ds.shape[2], self.do.ds.shape[1] slice_key = (int(self.do.xp * _s), slice(x0_, (x0_ + sX_), step), slice(y0_, (y0_ + sY_), step), int(self.do.tp * _s)) proj_axis = 0 if ds.ndim < 5: # for old-style data, drop the time dimension slice_key = slice_key[:3] #ima = numpy.zeros((int(numpy.ceil(min(sY_/_s, dmy)/fstep)), int(numpy.ceil(min(sX_/_s, dmx)/fstep)), 3), 'uint8') segs = [] for chan, offset, gain, cmap in self.do.GetActiveChans(): if self.do.maximumProjection and (self.do.slice == DisplayOpts.SLICE_XY): # special case for max projection - fixme - remove after we get colour coded projections in the projection module seg = self.do.ds[slice_key[:2] + (slice(None), chan)].max(2).squeeze().T if self.do.colourMax: seg = seg + 1j * self.do.ds[slice_key[:2] + (slice(None), chan)].argmax(2).squeeze().T else: seg = ds[slice_key + (chan, )].squeeze().T segs.append((seg, chan, offset, gain, cmap)) if len(segs) > 0: ima = numpy.zeros(segs[0][0].shape[:2] + (3, ), 'uint8') else: ima = numpy.zeros((int(numpy.ceil(min(sY_ / _s, dmy) / fstep)), int(numpy.ceil(min(sX_ / _s, dmx) / fstep)), 3), 'uint8') for seg, chan, offset, gain, cmap in segs: #'slice_key:', slice_key) #print('seg.shape, ima.shape:', seg.shape, ima.shape) self._map_colour(seg, gain, offset, cmap, ima) # img = wx.ImageFromData(ima.shape[1], ima.shape[0], ima.ravel()) img.Rescale(img.GetWidth() * sc2, img.GetHeight() * sc2 * self.aspect) self._oldIm = img self._oldImSig = sig return img
class ArrayViewPanel(scrolledImagePanel.ScrolledImagePanel): def __init__(self, parent, dstack = None, aspect=1, do = None, voxelsize=[1,1,1]): if (dstack == None and do == None): dstack = scipy.zeros((10,10)) if do == None: self.do = DisplayOpts(dstack, aspect=aspect) self.do.Optimise() else: self.do = do self.voxelsize = voxelsize scrolledImagePanel.ScrolledImagePanel.__init__(self, parent, self.DoPaint, style=wx.SUNKEN_BORDER|wx.TAB_TRAVERSAL) self.do.WantChangeNotification.append(self.GetOpts) #self.do.WantChangeNotification.append(self.Refresh) self.SetVirtualSize(wx.Size(self.do.ds.shape[0],self.do.ds.shape[1])) #self.imagepanel.SetSize(wx.Size(self.do.ds.shape[0],self.do.ds.shape[1])) self.points =[] self.pointsR = [] self.showPoints = True self.showTracks = True self.showContours = True self.showScaleBar = True self.scaleBarLength = 2000 self.pointMode = 'confoc' self.pointTolNFoc = {'confoc' : (5,5,5), 'lm' : (2, 5, 5), 'splitter' : (2,5,5)} self.showAdjacentPoints = False self.pointSize = 11 self.layerMode = 'Add' self.psfROIs = [] self.psfROISize=[30,30,30] self.lastUpdateTime = 0 self.lastFrameTime = 2e-3 #self.do.scale = 0 self.crosshairs = True #self.showSelection = True self.selecting = False self.aspect = 1. self.slice = None self.overlays = [] self._oldIm = None self._oldImSig = None self.CenteringHandlers = [] self.labelPens = [wx.Pen(wx.Colour(*pylab.cm.hsv(v, bytes=True)), 2) for v in numpy.linspace(0, 1, 16)] # if not aspect == None: # if scipy.isscalar(aspect): # self.do.aspects[2] = aspect # elif len(aspect) == 3: # self.do.aspects = aspect #self.SetOpts() #self.optionspanel.RefreshHists() self.updating = 0 self.showOptsPanel = 1 self.refrTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnRefrTimer) wx.EVT_MOUSEWHEEL(self.imagepanel, self.OnWheel) wx.EVT_KEY_DOWN(self.imagepanel, self.OnKeyPress) #wx.EVT_KEY_DOWN(self.Parent(), self.OnKeyPress) wx.EVT_LEFT_DOWN(self.imagepanel, self.OnLeftDown) wx.EVT_LEFT_UP(self.imagepanel, self.OnLeftUp) wx.EVT_MIDDLE_DOWN(self.imagepanel, self.OnMiddleDown) wx.EVT_MIDDLE_UP(self.imagepanel, self.OnMiddleUp) wx.EVT_RIGHT_DOWN(self.imagepanel, self.OnRightDown) wx.EVT_RIGHT_UP(self.imagepanel, self.OnRightUp) wx.EVT_MIDDLE_DCLICK(self.imagepanel, self.OnMiddleDClick) wx.EVT_MOTION(self.imagepanel, self.OnMotion) # wx.EVT_ERASE_BACKGROUND(self.imagepanel, self.DoNix) wx.EVT_ERASE_BACKGROUND(self, self.DoNix) def OnRefrTimer(self, event): self.Refresh() self.Update() def SetDataStack(self, ds): self.do.SetDataStack(ds) self.SetVirtualSize(wx.Size(self.do.ds.shape[0],self.do.ds.shape[1])) self.do.xp=0 self.do.yp=0 self.do.zp=0 self.do.Optimise() self.do.ResetSelection() self.Layout() # self.Refresh() def ResetDataStack(self, ds): self.do.SetDataStack(ds) def _ScreenToAbsCoordinates(self, x, y): xp,yp = self.CalcUnscrolledPosition(x,y) #xp = self.centreX + self.glCanvas.pixelsize*(x - self.Size[0]/2) #yp = self.centreY - self.glCanvas.pixelsize*(y - self.Size[1]/2) if self.do.orientation == self.do.UPRIGHT: return xp, yp else: return yp, xp def _ScreenToPixelCoordinates(self, x, y): #sc = pow(2.0,(self.do.scale-2)) xp, yp = self._ScreenToAbsCoordinates(x, y) return xp/self.scale, yp/(self.scale*self.aspect) def _AbsToScreenCoordinates(self, x, y): x0,y0 = self.CalcUnscrolledPosition(0,0) if self.do.orientation == self.do.UPRIGHT: return x - x0, y - y0 else: return y - x0, x - y0 def _PixelToScreenCoordinates(self, x, y): #sc = pow(2.0,(self.do.scale-2)) return self._AbsToScreenCoordinates(x*self.scale, y*self.scale*self.aspect) def _PixelToScreenCoordinates3D(self, x, y, z): #sc = pow(2.0,(self.do.scale-2)) if (self.do.slice == self.do.SLICE_XY): xs, ys = self._PixelToScreenCoordinates(x,y) elif (self.do.slice == self.do.SLICE_XZ): xs, ys = self._PixelToScreenCoordinates(x,z) elif (self.do.slice == self.do.SLICE_YZ): xs, ys = self._PixelToScreenCoordinates(y,z) return xs, ys def _drawBoxPixelCoords(self, dc, x, y, z, w, h, d): '''Draws a box in screen space given 3D co-ordinates''' if (self.do.slice == self.do.SLICE_XY): xs, ys = self._PixelToScreenCoordinates(x,y) ws, hs = (w*self.scale, h*self.scale*self.aspect) elif (self.do.slice == self.do.SLICE_XZ): xs, ys = self._PixelToScreenCoordinates(x,z) ws, hs = (w*self.scale, d*self.scale*self.aspect) elif (self.do.slice == self.do.SLICE_YZ): xs, ys = self._PixelToScreenCoordinates(y,z) ws, hs = (h*self.scale, d*self.scale*self.aspect) dc.DrawRectangle(xs - 0.5*ws, ys - 0.5*hs, ws,hs) @property def scale(self): return pow(2.0,(self.do.scale)) def DrawCrosshairs(self, view, dc): if self.crosshairs: sX, sY = view.imagepanel.Size dc.SetPen(wx.Pen(wx.CYAN,1)) if(view.do.slice == view.do.SLICE_XY): lx = view.do.xp ly = view.do.yp elif(view.do.slice == view.do.SLICE_XZ): lx = view.do.xp ly = view.do.zp elif(view.do.slice == view.do.SLICE_YZ): lx = view.do.yp ly = view.do.zp xc, yc = view._PixelToScreenCoordinates(lx, ly) dc.DrawLine(0, yc, sX, yc) dc.DrawLine(xc, 0, xc, sY) dc.SetPen(wx.NullPen) def DrawSelection(self, view, dc): if self.do.showSelection: col = wx.TheColourDatabase.FindColour('YELLOW') #col.Set(col.red, col.green, col.blue, 125) dc.SetPen(wx.Pen(col,1)) dc.SetBrush(wx.TRANSPARENT_BRUSH) lx, ly, hx, hy = self.do.GetSliceSelection() lx, ly = self._PixelToScreenCoordinates(lx, ly) hx, hy = self._PixelToScreenCoordinates(hx, hy) if self.do.selectionMode == DisplayOpts.SELECTION_RECTANGLE: dc.DrawRectangle(lx,ly, (hx-lx),(hy-ly)) elif self.do.selectionMode == DisplayOpts.SELECTION_SQUIGLE: if len(self.do.selection_trace) > 2: x, y = numpy.array(self.do.selection_trace).T pts = numpy.vstack(self._PixelToScreenCoordinates(x, y)).T dc.DrawSpline(pts) elif self.do.selectionWidth == 1: dc.DrawLine(lx,ly, hx,hy) else: lx, ly, hx, hy = self.do.GetSliceSelection() dx = hx - lx dy = hy - ly if dx == 0 and dy == 0: #special case - profile is orthogonal to current plane d_x = 0.5*self.do.selectionWidth d_y = 0.5*self.do.selectionWidth else: d_x = 0.5*self.do.selectionWidth*dy/numpy.sqrt((dx**2 + dy**2)) d_y = 0.5*self.do.selectionWidth*dx/numpy.sqrt((dx**2 + dy**2)) x_0, y_0 = self._PixelToScreenCoordinates(lx + d_x, ly - d_y) x_1, y_1 = self._PixelToScreenCoordinates(lx - d_x, ly + d_y) x_2, y_2 = self._PixelToScreenCoordinates(hx - d_x, hy + d_y) x_3, y_3 = self._PixelToScreenCoordinates(hx + d_x, hy - d_y) lx, ly = self._PixelToScreenCoordinates(lx, ly) hx, hy = self._PixelToScreenCoordinates(hx, hy) dc.DrawLine(lx, ly, hx, hy) dc.DrawPolygon([(x_0, y_0), (x_1, y_1), (x_2, y_2), (x_3, y_3)]) dc.SetPen(wx.NullPen) dc.SetBrush(wx.NullBrush) def DrawTracks(self, view, dc): if self.showTracks and 'filter' in dir(self) and 'clumpIndex' in self.filter.keys(): t = self.filter['t'] x = self.filter['x']/self.voxelsize[0] y = self.filter['y']/self.voxelsize[1] xb, yb, zb = self._calcVisibleBounds() IFoc = (x >= xb[0])*(y >= yb[0])*(t >= zb[0])*(x < xb[1])*(y < yb[1])*(t < zb[1]) tFoc = list(set(self.filter['clumpIndex'][IFoc])) dc.SetBrush(wx.TRANSPARENT_BRUSH) #pGreen = wx.Pen(wx.TheColourDatabase.FindColour('RED'),1) #pRed = wx.Pen(wx.TheColourDatabase.FindColour('RED'),1) #dc.SetPen(pGreen) for tN in tFoc: IFoc = (self.filter['clumpIndex'] == tN) if IFoc.sum() < 2: return pFoc = numpy.vstack(self._PixelToScreenCoordinates3D(x[IFoc], y[IFoc], t[IFoc])).T #print pFoc.shape dc.SetPen(self.labelPens[tN%16]) dc.DrawLines(pFoc) def DrawScaleBar(self, view, dc): if self.showScaleBar: pGreen = wx.Pen(wx.TheColourDatabase.FindColour('WHITE'),10) pGreen.SetCap(wx.CAP_BUTT) dc.SetPen(pGreen) sX, sY = view.imagepanel.Size sbLen = self.scaleBarLength*view.scale/view.voxelsize[0] y1 = 20 x1 = 20 + sbLen x0 = x1 - sbLen dc.DrawLine(x0, y1, x1, y1) dc.SetTextForeground(wx.TheColourDatabase.FindColour('WHITE')) if self.scaleBarLength > 1000: s = u'%1.1f \u03BCm' % (self.scaleBarLength/1000.) else: s = u'%d mm' % int(self.scaleBarLength) w, h = dc.GetTextExtent(s) dc.DrawText(s, x0 + (sbLen - w)/2, y1 + 7) def DrawContours(self, view, dc): if self.showContours and 'filter' in dir(self) and 'contour' in self.filter.keys() and self.do.slice ==self.do.SLICE_XY: t = self.filter['t'] x = self.filter['x']/self.voxelsize[0] y = self.filter['y']/self.voxelsize[1] xb, yb, zb = self._calcVisibleBounds() IFoc = (x >= xb[0])*(y >= yb[0])*(t >= zb[0])*(x < xb[1])*(y < yb[1])*(t < zb[1]) dc.SetBrush(wx.TRANSPARENT_BRUSH) pGreen = wx.Pen(wx.TheColourDatabase.FindColour('RED'),1) #pRed = wx.Pen(wx.TheColourDatabase.FindColour('RED'),1) dc.SetPen(pGreen) contours = self.filter['contour'][IFoc] if 'clumpIndex' in self.filter.keys(): colInds = self.filter['clumpIndex'][IFoc] %len(self.labelPens) else: colInds = numpy.zeros(len(contours), 'i') for c, colI in zip(contours, colInds): xc, yc = c.T dc.SetPen(self.labelPens[int(colI)]) dc.DrawSpline(numpy.vstack(self._PixelToScreenCoordinates(xc, yc)).T) def DrawPoints(self, view, dc): dx = 0 dy = 0 aN = SLICE_AXIS_LUT[self.do.slice] tolN = TOL_AXIS_LUT[self.do.slice] pos = [self.do.xp, self.do.yp, self.do.zp] if self.showPoints and ('filter' in dir(self) or len(self.points) > 0): if 'filter' in dir(self): t = self.filter['t'] x = self.filter['x']/self.voxelsize[0] y = self.filter['y']/self.voxelsize[1] xb, yb, zb = self._calcVisibleBounds() IFoc = (x >= xb[0])*(y >= yb[0])*(t >= zb[0])*(x < xb[1])*(y < yb[1])*(t < zb[1]) pFoc = numpy.vstack((x[IFoc], y[IFoc], t[IFoc])).T if self.pointMode == 'splitter': pCol = self.filter['gFrac'][IFoc] > .5 pNFoc = [] #intrinsic points elif len(self.points) > 0: pointTol = self.pointTolNFoc[self.pointMode] IFoc = abs(self.points[:,aN] - pos[aN]) < 1 INFoc = abs(self.points[:,aN] - pos[aN]) < pointTol[tolN] pFoc = self.points[IFoc] pNFoc = self.points[INFoc] if self.pointMode == 'splitter': pCol = self.pointColours[IFoc] if self.pointMode == 'splitter': if 'chroma' in dir(self): dx = self.chroma.dx.ev(pFoc[:,0]*1e3*self.voxelsize[0], pFoc[:,1]*1e3*self.voxelsize[1])/(1e3*self.voxelsize[0]) dy = self.chroma.dy.ev(pFoc[:,0]*1e3*self.voxelsize[0], pFoc[:,1]*1e3*self.voxelsize[1])/(1e3*self.voxelsize[1]) else: dx = 0*pFoc[:,0] dy = 0*pFoc[:,0] if 'chroma' in dir(self): dxn = self.chroma.dx.ev(pNFoc[:,0]*1e3*self.voxelsize[0], pNFoc[:,1]*1e3*self.voxelsize[1])/(1e3*self.voxelsize[0]) dyn = self.chroma.dy.ev(pNFoc[:,0]*1e3*self.voxelsize[0], pNFoc[:,1]*1e3*self.voxelsize[1])/(1e3*self.voxelsize[1]) else: dxn = 0*pFoc[:,0] dyn = 0*pFoc[:,0] dc.SetBrush(wx.TRANSPARENT_BRUSH) ps = self.pointSize if self.showAdjacentPoints: dc.SetPen(wx.Pen(wx.TheColourDatabase.FindColour('BLUE'),1)) if self.pointMode == 'splitter': for p, dxi, dyi in zip(pNFoc, dxn, dyn): self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) self._drawBoxPixelCoords(dc, p[0]-dxi, 0.5*self.do.ds.shape[1] + p[1]-dyi, p[2], ps, ps, ps) else: for p in pNFoc: self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) pGreen = wx.Pen(wx.TheColourDatabase.FindColour('GREEN'),1) pRed = wx.Pen(wx.TheColourDatabase.FindColour('RED'),1) dc.SetPen(pGreen) if self.pointMode == 'splitter': for p, c, dxi, dyi in zip(pFoc, pCol, dx, dy): if c: dc.SetPen(pGreen) else: dc.SetPen(pRed) self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) self._drawBoxPixelCoords(dc, p[0]-dxi, 0.5*self.do.ds.shape[1] + p[1]-dyi, p[2], ps, ps, ps) else: for p in pFoc: self._drawBoxPixelCoords(dc, p[0], p[1], p[2], ps, ps, ps) dc.SetPen(wx.NullPen) dc.SetBrush(wx.NullBrush) def _calcVisibleBounds(self): sc = pow(2.0,(self.do.scale)) x0,y0 = self.CalcUnscrolledPosition(0,0) sX, sY = self.imagepanel.Size if self.do.slice == self.do.SLICE_XY: bnds = [(x0/sc, (x0+sX)/sc), (y0/sc, (y0+sY)/sc), (self.do.zp-.5, self.do.zp+.5)] elif self.do.slice == self.do.SLICE_XZ: bnds = [(x0/sc, (x0+sX)/sc), (self.do.yp-.5, self.do.yp+.5), (y0/sc, (y0+sY)/sc)] elif self.do.slice == self.do.SLICE_YZ: bnds = [(self.do.xp-.5, self.do.xp+.5),(x0/sc, (x0+sX)/sc), (y0/sc, (y0+sY)/sc)] return bnds def DoPaint(self, dc): #print 'p' dc.Clear() im = self.Render() sc = pow(2.0,(self.do.scale)) sc2 = sc if sc >= 1: step = 1 else: step = 2**(-numpy.ceil(numpy.log2(sc))) sc2 = sc*step #sX, sY = view.imagepanel.Size #im.Rescale(im.GetWidth()*sc2,im.GetHeight()*sc2*self.aspect) im2 = wx.BitmapFromImage(im) dc.DrawBitmap(im2,-sc2/2,-sc2/2) #sX, sY = im.GetWidth(), im.GetHeight() self.DrawCrosshairs(self, dc) self.DrawSelection(self, dc) self.DrawScaleBar(self, dc) #self.DrawTracks(self, dc) self.DrawPoints(self, dc) self.DrawContours(self, dc) dc.SetPen(wx.NullPen) dc.SetBrush(wx.NullBrush) for ovl in self.do.overlays: ovl(self, dc) # def OnPaint(self,event): # self.painting = True # DC = wx.PaintDC(self.imagepanel) # if not time.time() > (self.lastUpdateTime + 2*self.lastFrameTime): #avoid paint floods # if not self.refrTimer.IsRunning(): # self.refrTimer.Start(.2, True) #make sure we do get a refresh after disposing of flood # return # # frameStartTime = time.time() # self.imagepanel.impanel.PrepareDC(DC) # # x0,y0 = self.imagepanel.CalcUnscrolledPosition(0,0) # # #s = self.imagepanel.GetVirtualSize() # s = self.imagepanel.impanel.GetClientSize() # MemBitmap = wx.EmptyBitmap(s.GetWidth(), s.GetHeight()) # #del DC # MemDC = wx.MemoryDC() # OldBitmap = MemDC.SelectObject(MemBitmap) # try: # DC.BeginDrawing() # #DC.Clear() # #Perform(WM_ERASEBKGND, MemDC, MemDC); # #Message.DC := MemDC; # self.DoPaint(MemDC); # #Message.DC := 0; # #DC.BlitXY(0, 0, s.GetWidth(), s.GetHeight(), MemDC, 0, 0) # DC.Blit(x0, y0, s.GetWidth(), s.GetHeight(), MemDC, 0, 0) # DC.EndDrawing() # finally: # #MemDC.SelectObject(OldBitmap) # del MemDC # del MemBitmap # # self.lastUpdateTime = time.time() # self.lastFrameTime = self.lastUpdateTime - frameStartTime # # self.painting = False # #print self.lastFrameTime def OnWheel(self, event): rot = event.GetWheelRotation() if rot < 0: if event.RightIsDown(): self.do.yp = max(self.do.yp - 1, 0) elif event.MiddleIsDown(): self.do.xp = max(self.do.xp - 1, 0) elif event.ShiftDown(): self.do.SetScale(self.do.scale - 1) else: self.do.zp = max(self.do.zp - 1, 0) if rot > 0: if event.RightIsDown(): self.do.yp = min(self.do.yp + 1, self.do.ds.shape[1] -1) elif event.MiddleIsDown(): self.do.xp = min(self.do.xp + 1, self.do.ds.shape[0] -1) elif event.ShiftDown(): self.do.SetScale(self.do.scale + 1) else: self.do.zp = min(self.do.zp + 1, self.do.ds.shape[2] -1) if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() #self.update() def OnKeyPress(self, event): if event.GetKeyCode() == wx.WXK_PRIOR: self.do.zp = max(0, self.do.zp - 1) #self.optionspanel.RefreshHists() if ('update' in dir(self.GetParent())): self.GetParent().update() else: #if not self.painting: self.imagepanel.Refresh() #else: # if not self.refrTimer.IsRunning(): # self.refrTimer.Start(.2, True) elif event.GetKeyCode() == wx.WXK_NEXT: self.do.zp = min(self.do.zp + 1, self.do.ds.shape[2] - 1) #self.optionspanel.RefreshHists() if ('update' in dir(self.GetParent())): self.GetParent().update() #print 'upd' else: #if not self.painting: self.imagepanel.Refresh() #else: # if not self.refrTimer.IsRunning(): #print 'upt' # self.refrTimer.Start(.2, True) elif event.GetKeyCode() == 74: #J self.do.xp = (self.do.xp - 1) if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 76: #L self.do.xp +=1 if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 73: #I self.do.yp += 1 if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 75: #L self.do.yp -= 1 if ('update' in dir(self.GetParent())): self.GetParent().update() else: self.imagepanel.Refresh() elif event.GetKeyCode() == 77: #M #print 'o' self.do.Optimise() else: event.Skip() def GetOpts(self,event=None): if (self.updating == 0): sc = pow(2.0,(self.do.scale)) s = self.CalcImSize() self.SetVirtualSize(wx.Size(s[0]*sc,s[1]*sc)) if not self.slice == self.do.slice: #if the slice has changed, change our aspect and do some self.slice = self.do.slice #if not event == None and event.GetId() in [self.cbSlice.GetId(), self.cbScale.GetId()]: #recenter the view if(self.do.slice == self.do.SLICE_XY): lx = self.do.xp ly = self.do.yp self.aspect = self.do.aspect[1]/self.do.aspect[0] elif(self.do.slice == self.do.SLICE_XZ): lx = self.do.xp ly = self.do.zp self.aspect = self.do.aspect[2]/self.do.aspect[0] elif(self.do.slice == self.do.SLICE_YZ): lx = self.do.yp ly = self.do.zp self.aspect = self.do.aspect[2]/self.do.aspect[1] sx,sy =self.imagepanel.GetClientSize() #self.imagepanel.SetScrollbars(20,20,s[0]*sc/20,s[1]*sc/20,min(0, lx*sc - sx/2)/20, min(0,ly*sc - sy/2)/20) ppux, ppuy = self.GetScrollPixelsPerUnit() #self.imagepanel.SetScrollPos(wx.HORIZONTAL, max(0, lx*sc - sx/2)/ppux) #self.imagepanel.SetScrollPos(wx.VERTICAL, max(0, ly*sc - sy/2)/ppuy) self.Scroll(max(0, lx*sc - sx/2)/ppux, max(0, ly*sc*self.aspect - sy/2)/ppuy) #self.imagepanel.Refresh() self.Refresh() self.Update() def Optim(self, event = None): self.do.Optimise(self.do.ds, int(self.do.zp)) self.updating=1 #self.SetOpts() #self.optionspanel.RefreshHists() self.Refresh() self.Update() self.updating=0 def CalcImSize(self): if (self.do.slice == self.do.SLICE_XY): if (self.do.orientation == self.do.UPRIGHT): return (self.do.ds.shape[0],self.do.ds.shape[1]) else: return (self.do.ds.shape[1],self.do.ds.shape[0]) elif (self.do.slice == self.do.SLICE_XZ): return (self.do.ds.shape[0],self.do.ds.shape[2]) else: return(self.do.ds.shape[1],self.do.ds.shape[2] ) def DoNix(self, event): pass def OnLeftDown(self,event): if self.do.leftButtonAction == self.do.ACTION_SELECTION: self.StartSelection(event) event.Skip() def OnLeftUp(self,event): if self.do.leftButtonAction == self.do.ACTION_SELECTION: self.ProgressSelection(event) self.EndSelection() else: self.OnSetPosition(event) event.Skip() def OnMiddleDown(self,event): dc = wx.ClientDC(self.imagepanel) self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) self.middleDownPos = self.CalcUnscrolledPosition(*pos) event.Skip() def OnMiddleUp(self,event): dc = wx.ClientDC(self.imagepanel) self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) dx = pos[0] - self.middleDownPos[0] dy = pos[1] - self.middleDownPos[1] sc = pow(2.0,(self.do.scale)) if (abs(dx) > 5) or (abs(dy) > 5): for h in self.CenteringHandlers: h(-dx/sc,-dy/sc) event.Skip() def OnMiddleDClick(self,event): dc = wx.ClientDC(self.imagepanel) self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print pos sc = pow(2.0,(self.do.scale)) if (self.do.slice == self.do.SLICE_XY): x = (pos[0]/sc) - 0.5*self.do.ds.shape[0] y = (pos[1]/(sc*self.aspect)) - 0.5*self.do.ds.shape[1] for h in self.CenteringHandlers: h(x,y) event.Skip() def OnSetPosition(self,event): dc = wx.ClientDC(self.imagepanel) #self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) print(pos) self.do.inOnChange = True sc = pow(2.0,(self.do.scale)) print(sc) if (self.do.slice == self.do.SLICE_XY): self.do.xp =int(pos[0]/sc) self.do.yp = int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_XZ): self.do.xp =int(pos[0]/sc) self.do.zp =int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.yp =int(pos[0]/sc) self.do.zp =int(pos[1]/(sc*self.aspect)) self.do.inOnChange = False self.do.OnChange() #if ('update' in dir(self.GetParent())): # self.GetParent().update() #else: # self.imagepanel.Refresh() def PointsHitTest(self): if len(self.points) > 0: iCand = numpy.where((abs(self.points[:,2] - self.do.zp) < 1)*(abs(self.points[:,0] - self.do.xp) < 3)*(abs(self.points[:,1] - self.do.yp) < 3))[0] if len(iCand) == 0: return None elif len(iCand) == 1: return iCand[0] else: pCand = self.points[iCand, :] iNearest = numpy.argmin((pCand[:,0] - self.do.xp)**2 + (pCand[:,1] - self.do.yp)**2) return iCand[iNearest] else: return None def OnRightDown(self, event): self.StartSelection(event) def StartSelection(self,event): self.selecting = True dc = wx.ClientDC(self.imagepanel) #self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print pos sc = pow(2.0,(self.do.scale)) if (self.do.slice == self.do.SLICE_XY): self.do.selection_begin_x = int(pos[0]/sc) self.do.selection_begin_y = int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_XZ): self.do.selection_begin_x = int(pos[0]/sc) self.do.selection_begin_z = int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.selection_begin_y = int(pos[0]/sc) self.do.selection_begin_z = int(pos[1]/(sc*self.aspect)) self.do.selection_trace = [] self.do.selection_trace.append(((pos[0]/sc), (pos[1]/(sc*self.aspect)))) def OnRightUp(self,event): self.ProgressSelection(event) self.EndSelection() def OnMotion(self, event): if event.Dragging() and self.selecting: self.ProgressSelection(event) def ProgressSelection(self,event): dc = wx.ClientDC(self.imagepanel) #self.imagepanel.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos = self.CalcUnscrolledPosition(*pos) #print pos sc = pow(2.0,(self.do.scale)) if not event.ShiftDown(): if (self.do.slice == self.do.SLICE_XY): self.do.selection_end_x = int(pos[0]/sc) self.do.selection_end_y = int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_XZ): self.do.selection_end_x = int(pos[0]/sc) self.do.selection_end_z = int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.selection_end_y = int(pos[0]/sc) self.do.selection_end_z = int(pos[1]/(sc*self.aspect)) else: #lock if (self.do.slice == self.do.SLICE_XY): self.do.selection_end_x = int(pos[0]/sc) self.do.selection_end_y = int(pos[1]/(sc*self.aspect)) dx = abs(self.do.selection_end_x - self.do.selection_begin_x) dy = abs(self.do.selection_end_y - self.do.selection_begin_y) if dx > 1.5*dy: #horizontal self.do.selection_end_y = self.do.selection_begin_y elif dy > 1.5*dx: #vertical self.do.selection_end_x = self.do.selection_begin_x else: #diagonal self.do.selection_end_y = self.do.selection_begin_y + dx*numpy.sign(self.do.selection_end_y - self.do.selection_begin_y) elif (self.do.slice == self.do.SLICE_XZ): self.do.selection_end_x = int(pos[0]/sc) self.do.selection_end_z = int(pos[1]/(sc*self.aspect)) elif (self.do.slice == self.do.SLICE_YZ): self.do.selection_end_y = int(pos[0]/sc) self.do.selection_end_z = int(pos[1]/(sc*self.aspect)) self.do.selection_trace.append(((pos[0]/sc), (pos[1]/(sc*self.aspect)))) #if ('update' in dir(self.GetParent())): # self.GetParent().update() #self.update() #else: self.Refresh() self.Update() def EndSelection(self): self.selecting = False def _gensig(self, x0, y0, sX,sY, do): sig = [x0, y0, sX, sY, do.scale, do.slice, do.GetActiveChans(), do.ds.shape] if do.slice == DisplayOpts.SLICE_XY: sig += [do.zp, do.maximumProjection] if do.slice == DisplayOpts.SLICE_XZ: sig += [do.yp] if do.slice == DisplayOpts.SLICE_YZ: sig += [do.xp] return sig def Redraw(self, caller=None): self._oldImSig = None self.Refresh() self.Update() ################################################################# def Render(self): #print 'rend' x0,y0 = self.CalcUnscrolledPosition(0,0) sX, sY = self.imagepanel.Size sig = self._gensig(x0, y0, sX, sY, self.do) if sig == self._oldImSig:# and not self._oldIm == None: #if nothing has changed, don't re-render return self._oldIm aspect = {} sc = pow(2.0,self.do.scale) sc2 = sc if sc >= 1: step = 1 else: step = 2**(-numpy.ceil(numpy.log2(sc))) sc2 = sc*step sX_ = int(sX/(sc)) sY_ = int(sY/(sc*self.aspect)) x0_ = int(x0/sc) y0_ = int(y0/(sc*self.aspect)) #sc = pow(2.0,(self.do.scale-2)) #print sX, sX_, self.do.ds.shape[0], step, x0_, y0_ #sc = sc*step fstep = float(step) #XY if self.do.slice == DisplayOpts.SLICE_XY: ima = numpy.zeros( (numpy.ceil(min(sY_, self.do.ds.shape[1])/fstep), numpy.ceil(min(sX_, self.do.ds.shape[0])/fstep), 3), 'uint8' ) #print ima.shape for chan, offset, gain, cmap in self.do.GetActiveChans():#zip(self.do.Chans, self.do.Offs, self.do.Gains, self.do.cmaps, self.do.show): #ima[:] = numpy.minimum(ima[:] + (255*cmap(gain*(self.do.ds[x0_:(x0_+sX_),y0_:(y0_+sY_),int(self.do.zp), chan].squeeze().T - offset))[:,:,:3])[:], 255) #cmap = #print lut.shape #if show: if not cmap == labeled: #seg = self.do.ds[x0_:(x0_+sX_),y0_:(y0_+sY_),int(self.do.zp), chan].squeeze().T #seg = seg.astype('f4') #g = numpy.float32(255.*gain) #o = numpy.float32(offset) #seg = (g*(seg - o)) #print seg.dtype #seg = seg.astype('uint8') #seg = (g*(self.do.ds[x0_:(x0_+sX_),y0_:(y0_+sY_),int(self.do.zp), chan].squeeze().T - o)).astype('uint8') #seg = lut[seg] #print seg.shape #ima[:] = seg #ima[:,:,0] = seg #ima[:,:,1] = seg #ima[:,:,2] = seg lut = getLUT(cmap) if self.do.maximumProjection: seg = self.do.ds[x0_:(x0_+sX_):step,y0_:(y0_+sY_):step,:, chan].max(2).squeeze().T if self.do.colourMax: aseg = self.do.ds[x0_:(x0_+sX_):step,y0_:(y0_+sY_):step,:, chan].argmax(2).squeeze().T applyLUT(aseg, self.do.cmax_scale/self.do.ds.shape[2], self.do.cmax_offset, lut, ima) ima[:] = (ima*numpy.clip((seg - offset)*gain, 0,1)[:,:,None]).astype('uint8') else: applyLUT(seg, gain, offset, lut, ima) else: seg = self.do.ds[x0_:(x0_+sX_):step,y0_:(y0_+sY_):step,int(self.do.zp), chan].squeeze().T if numpy.iscomplexobj(seg): if self.do.complexMode == 'real': applyLUT(seg.real, gain, offset, lut, ima) elif self.do.complexMode == 'imag': applyLUT(seg.imag, gain, offset, lut, ima) elif self.do.complexMode == 'abs': applyLUT(numpy.abs(seg), gain, offset, lut, ima) elif self.do.complexMode == 'angle': applyLUT(numpy.angle(seg), gain, offset, lut, ima) else: applyLUT(numpy.angle(seg), self.do.cmax_scale/self.do.ds.shape[2], self.do.cmax_offset, lut, ima) ima[:] = (ima*numpy.clip((numpy.abs(seg) - offset)*gain, 0,1)[:,:,None]).astype('uint8') else: #print seg.shape applyLUT(seg, gain, offset, lut, ima) else: if self.layerMode == 'mult': ima[:] = numpy.minimum(ima[:]*(cmap(gain*(self.do.ds[x0_:(x0_+sX_):step,y0_:(y0_+sY_):step,int(self.do.zp), chan].squeeze().T - offset))[:,:,:3])[:], 255) else: ima[:] = numpy.minimum(ima[:] + (255*cmap(gain*(self.do.ds[x0_:(x0_+sX_):step,y0_:(y0_+sY_):step,int(self.do.zp), chan].squeeze().T - offset))[:,:,:3])[:], 255) #XZ elif self.do.slice == DisplayOpts.SLICE_XZ: ima = numpy.zeros((numpy.ceil(min(sY_, self.do.ds.shape[2])/fstep), numpy.ceil(min(sX_, self.do.ds.shape[0])/fstep), 3), 'uint8') for chan, offset, gain, cmap in self.do.GetActiveChans():#in zip(self.do.Chans, self.do.Offs, self.do.Gains, self.do.cmaps): if not cmap == labeled: lut = getLUT(cmap) seg = self.do.ds[x0_:(x0_+sX_):step,int(self.do.yp),y0_:(y0_+sY_):step, chan].squeeze().T applyLUT(seg, gain, offset, lut, ima) else: ima[:] = ima[:] + 255*cmap(gain*(self.do.ds[x0_:(x0_+sX_):step,int(self.do.yp),y0_:(y0_+sY_):step, chan].squeeze().T - offset))[:,:,:3][:] #YZ elif self.do.slice == DisplayOpts.SLICE_YZ: ima = numpy.zeros((numpy.ceil(min(sY_, self.do.ds.shape[2])/fstep), numpy.ceil(min(sX_, self.do.ds.shape[1])/fstep), 3), 'uint8') for chan, offset, gain, cmap in self.do.GetActiveChans():#zip(self.do.Chans, self.do.Offs, self.do.Gains, self.do.cmaps): if not cmap == labeled: lut = getLUT(cmap) seg = self.do.ds[int(self.do.xp),x0_:(x0_+sX_):step,y0_:(y0_+sY_):step, chan].squeeze().T applyLUT(seg, gain, offset, lut, ima) else: ima[:] = ima[:] + 255*cmap(gain*(self.do.ds[int(self.do.xp),x0_:(x0_+sX_):step,y0_:(y0_+sY_):step, chan].squeeze().T - offset))[:,:,:3][:] # ###################################### #import matplotlib.pyplot as plt #print '> ready to show' #plt.imshow(ima) #plt.show() ###################################### img = wx.ImageFromData(ima.shape[1], ima.shape[0], ima.ravel()) img.Rescale(img.GetWidth()*sc2,img.GetHeight()*sc2*self.aspect) self._oldIm = img self._oldImSig = sig return img
def __init__(self, image, parent=None, title='', mode='LM', size = (800,700), glCanvas=None): wx.Frame.__init__(self,parent, -1, title,size=size, pos=(1100, 300)) self.SetAutoLayout(True) self.mode = mode self.glCanvas = glCanvas self.paneHooks = [] self.updateHooks = [] self.statusHooks = [] self.installedModules = [] self.dataChangeHooks = [] self.updating = False if glCanvas: self.glCanvas.wantViewChangeNotification.add(self) self.pane0 = None self.timer = mytimer() self.timer.Start(10000) self.image = image #self.image = ImageStack(data = dstack, mdh = mdh, filename = filename, queueURI = queueURI, events = None) if not self.image.filename == None and title == '': self.SetTitle(self.image.filename) self._mgr = aui.AuiManager(agwFlags = aui.AUI_MGR_DEFAULT | aui.AUI_MGR_AUTONB_NO_CAPTION) atabstyle = self._mgr.GetAutoNotebookStyle() self._mgr.SetAutoNotebookStyle((atabstyle ^ aui.AUI_NB_BOTTOM) | aui.AUI_NB_TOP) # tell AuiManager to manage this frame self._mgr.SetManagedWindow(self) self.do = DisplayOpts(self.image.data) if self.image.data.shape[1] == 1: self.do.slice = self.do.SLICE_XZ self.do.Optimise() if self.image.mdh and 'ChannelNames' in self.image.mdh.getEntryNames(): self.do.names = self.image.mdh.getEntry('ChannelNames') #self.vp = ArraySettingsAndViewPanel(self, self.image.data, wantUpdates=[self.update], mdh=self.image.mdh) #self.view = ArrayViewPanel(self, do=self.do) #self.AddPage(self.view, True, 'Data') #self._mgr.AddPane(self.vp, aui.AuiPaneInfo(). # Name("Data").Caption("Data").Centre().CloseButton(False).CaptionVisible(False)) self.mainFrame = weakref.ref(self) #self.do = self.vp.do self._menus = {} # Menu Bar self.menubar = wx.MenuBar() self.SetMenuBar(self.menubar) tmp_menu = wx.Menu() tmp_menu.Append(wx.ID_OPEN, '&Open', "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVE, "&Save As", "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVEAS, "&Export Cropped", "", wx.ITEM_NORMAL) #a submenu for modules to hook and install saving functions into self.save_menu = wx.Menu() self._menus['Save'] = self.save_menu tmp_menu.AppendMenu(-1, 'Save &Results', self.save_menu) tmp_menu.AppendSeparator() tmp_menu.Append(wx.ID_CLOSE, "Close", "", wx.ITEM_NORMAL) self.menubar.Append(tmp_menu, "File") self.view_menu = wx.Menu() self.menubar.Append(self.view_menu, "&View") self._menus['View'] = self.view_menu #'extras' menu for modules to install stuff into self.mProcessing = wx.Menu() self.menubar.Append(self.mProcessing, "&Processing") self._menus['Processing'] = self.mProcessing # Menu Bar end wx.EVT_MENU(self, wx.ID_OPEN, self.OnOpen) wx.EVT_MENU(self, wx.ID_SAVE, self.OnSave) wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnExport) wx.EVT_CLOSE(self, self.OnCloseWindow) wx.EVT_SIZE(self, self.OnSize) self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP) self.panesToMinimise = [] modules.loadMode(self.mode, self) self.CreateModuleMenu() self.optionspanel = OptionsPanel(self, self.do, thresholdControls=True) self.optionspanel.SetSize(self.optionspanel.GetBestSize()) pinfo = aui.AuiPaneInfo().Name("optionsPanel").Right().Caption('Display Settings').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.optionspanel, pinfo) self.panesToMinimise.append(pinfo) self._mgr.AddPane(self.optionspanel.CreateToolBar(self), aui.AuiPaneInfo().Name("ViewTools").Caption("View Tools").CloseButton(False). ToolbarPane().Right().GripperTop()) if self.do.ds.shape[2] > 1: from PYME.DSView.modules import playback self.playbackpanel = playback.PlayPanel(self, self) self.playbackpanel.SetSize(self.playbackpanel.GetBestSize()) pinfo1 = aui.AuiPaneInfo().Name("playbackPanel").Bottom().Caption('Playback').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.playbackpanel, pinfo1) self.do.WantChangeNotification.append(self.playbackpanel.update) #self.mWindows = wx.Menu() #self.menubar.append(self.mWindows, '&Composite With') self.do.WantChangeNotification.append(self.update) self.CreateFoldPanel() self._mgr.Update() for pn in self.panesToMinimise: self._mgr.MinimizePane(pn) #self._mgr.MinimizePane(pinfo2) self.Layout() if 'view' in dir(self): sc = pylab.floor(pylab.log2(1.0*self.view.Size[0]/self.do.ds.shape[0])) #print self.view.Size[0], self.do.ds.shape[0], sc self.do.SetScale(sc) self.view.Refresh() self.update() self.drop = dt() self.SetDropTarget(self.drop) openViewers[self.image.filename] = self
class DSViewFrame(wx.Frame): def __init__(self, image, parent=None, title='', mode='LM', size = (800,700), glCanvas=None): wx.Frame.__init__(self,parent, -1, title,size=size, pos=(1100, 300)) self.SetAutoLayout(True) self.mode = mode self.glCanvas = glCanvas self.paneHooks = [] self.updateHooks = [] self.statusHooks = [] self.installedModules = [] self.dataChangeHooks = [] self.updating = False if glCanvas: self.glCanvas.wantViewChangeNotification.add(self) self.pane0 = None self.timer = mytimer() self.timer.Start(10000) self.image = image #self.image = ImageStack(data = dstack, mdh = mdh, filename = filename, queueURI = queueURI, events = None) if not self.image.filename == None and title == '': self.SetTitle(self.image.filename) self._mgr = aui.AuiManager(agwFlags = aui.AUI_MGR_DEFAULT | aui.AUI_MGR_AUTONB_NO_CAPTION) atabstyle = self._mgr.GetAutoNotebookStyle() self._mgr.SetAutoNotebookStyle((atabstyle ^ aui.AUI_NB_BOTTOM) | aui.AUI_NB_TOP) # tell AuiManager to manage this frame self._mgr.SetManagedWindow(self) self.do = DisplayOpts(self.image.data) if self.image.data.shape[1] == 1: self.do.slice = self.do.SLICE_XZ self.do.Optimise() if self.image.mdh and 'ChannelNames' in self.image.mdh.getEntryNames(): self.do.names = self.image.mdh.getEntry('ChannelNames') #self.vp = ArraySettingsAndViewPanel(self, self.image.data, wantUpdates=[self.update], mdh=self.image.mdh) #self.view = ArrayViewPanel(self, do=self.do) #self.AddPage(self.view, True, 'Data') #self._mgr.AddPane(self.vp, aui.AuiPaneInfo(). # Name("Data").Caption("Data").Centre().CloseButton(False).CaptionVisible(False)) self.mainFrame = weakref.ref(self) #self.do = self.vp.do self._menus = {} # Menu Bar self.menubar = wx.MenuBar() self.SetMenuBar(self.menubar) tmp_menu = wx.Menu() tmp_menu.Append(wx.ID_OPEN, '&Open', "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVE, "&Save As", "", wx.ITEM_NORMAL) tmp_menu.Append(wx.ID_SAVEAS, "&Export Cropped", "", wx.ITEM_NORMAL) #a submenu for modules to hook and install saving functions into self.save_menu = wx.Menu() self._menus['Save'] = self.save_menu tmp_menu.AppendMenu(-1, 'Save &Results', self.save_menu) tmp_menu.AppendSeparator() tmp_menu.Append(wx.ID_CLOSE, "Close", "", wx.ITEM_NORMAL) self.menubar.Append(tmp_menu, "File") self.view_menu = wx.Menu() self.menubar.Append(self.view_menu, "&View") self._menus['View'] = self.view_menu #'extras' menu for modules to install stuff into self.mProcessing = wx.Menu() self.menubar.Append(self.mProcessing, "&Processing") self._menus['Processing'] = self.mProcessing # Menu Bar end wx.EVT_MENU(self, wx.ID_OPEN, self.OnOpen) wx.EVT_MENU(self, wx.ID_SAVE, self.OnSave) wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnExport) wx.EVT_CLOSE(self, self.OnCloseWindow) wx.EVT_SIZE(self, self.OnSize) self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP) self.panesToMinimise = [] modules.loadMode(self.mode, self) self.CreateModuleMenu() self.optionspanel = OptionsPanel(self, self.do, thresholdControls=True) self.optionspanel.SetSize(self.optionspanel.GetBestSize()) pinfo = aui.AuiPaneInfo().Name("optionsPanel").Right().Caption('Display Settings').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.optionspanel, pinfo) self.panesToMinimise.append(pinfo) self._mgr.AddPane(self.optionspanel.CreateToolBar(self), aui.AuiPaneInfo().Name("ViewTools").Caption("View Tools").CloseButton(False). ToolbarPane().Right().GripperTop()) if self.do.ds.shape[2] > 1: from PYME.DSView.modules import playback self.playbackpanel = playback.PlayPanel(self, self) self.playbackpanel.SetSize(self.playbackpanel.GetBestSize()) pinfo1 = aui.AuiPaneInfo().Name("playbackPanel").Bottom().Caption('Playback').CloseButton(False).MinimizeButton(True).MinimizeMode(aui.AUI_MINIMIZE_CAPT_SMART|aui.AUI_MINIMIZE_POS_RIGHT)#.CaptionVisible(False) self._mgr.AddPane(self.playbackpanel, pinfo1) self.do.WantChangeNotification.append(self.playbackpanel.update) #self.mWindows = wx.Menu() #self.menubar.append(self.mWindows, '&Composite With') self.do.WantChangeNotification.append(self.update) self.CreateFoldPanel() self._mgr.Update() for pn in self.panesToMinimise: self._mgr.MinimizePane(pn) #self._mgr.MinimizePane(pinfo2) self.Layout() if 'view' in dir(self): sc = pylab.floor(pylab.log2(1.0*self.view.Size[0]/self.do.ds.shape[0])) #print self.view.Size[0], self.do.ds.shape[0], sc self.do.SetScale(sc) self.view.Refresh() self.update() self.drop = dt() self.SetDropTarget(self.drop) openViewers[self.image.filename] = self def OnSize(self, event): #self.Layout() self._mgr.Update() #self.Refresh() #self.Update() def AddPage(self, page=None, select=True,caption='Dummy'): if self.pane0 == None: name = caption.replace(' ', '') self._mgr.AddPane(page, aui.AuiPaneInfo(). Name(name).Caption(caption).Centre().CloseButton(False).CaptionVisible(False)) self.pane0 = name else: self._mgr.Update() pn = self._mgr.GetPaneByName(self.pane0) if pn.IsNotebookPage(): print((pn.notebook_id)) nbs = self._mgr.GetNotebooks() if len(nbs) > pn.notebook_id: currPage = nbs[pn.notebook_id].GetSelection() self._mgr.AddPane(page, aui.AuiPaneInfo(). Name(caption.replace(' ', '')).Caption(caption).CloseButton(False).NotebookPage(pn.notebook_id)) if (not select) and len(nbs) > pn.notebook_id: self._mgr.Update() nbs[pn.notebook_id].SetSelection(currPage) else: self._mgr.AddPane(page, aui.AuiPaneInfo(). Name(caption.replace(' ', '')).Caption(caption).CloseButton(False), target=pn) if not select: self._mgr.Update() nb = self._mgr.GetNotebooks()[0] nb.SetSelection(0) wx.CallAfter(self._mgr.Update) #self.Layout() #self.OnSize(None) #self.OnSize(None) def CreateModuleMenu(self): self.modMenuIds = {} self.mModules = wx.Menu() for mn in modules.allmodules(): id = wx.NewId() self.mModules.AppendCheckItem(id, mn) self.modMenuIds[id] = mn if mn in self.installedModules: self.mModules.Check(id, True) wx.EVT_MENU(self, id, self.OnToggleModule) self.menubar.Append(self.mModules, "&Modules") def AddMenuItem(self, menuName, itemName='', itemCallback = None, itemType='normal', helpText = ''): mItem = None if not menuName in self._menus.keys(): menu = wx.Menu() self.menubar.Insert(self.menubar.GetMenuCount()-1, menu, menuName) self._menus[menuName] = menu else: menu = self._menus[menuName] if itemType == 'normal': mItem = menu.Append(wx.ID_ANY, itemName, helpText, wx.ITEM_NORMAL) self.Bind(wx.EVT_MENU, itemCallback, mItem) elif itemType == 'separator': menu.AppendSeparator() return mItem def OnToggleModule(self, event): id = event.GetId() mn = self.modMenuIds[id] if self.mModules.IsChecked(id): modules.loadModule(mn, self) if mn in self.installedModules: self.mModules.Check(id, True) self.CreateFoldPanel() self._mgr.Update() def GetSelectedPage(self): nbs = self._mgr.GetNotebooks() currPage = nbs[0].GetCurrentPage() return currPage def CreateFoldPanel(self): pinfo = self._mgr.GetPaneByName('sidePanel') if pinfo.IsOk(): #we already have a sidepanel, clear self.sidePanel.Clear() else: self.sidePanel = afp.foldPanel(self, -1, wx.DefaultPosition,size = wx.Size(180, 1000)) pinfo = aui.AuiPaneInfo().Name("sidePanel").Left().CloseButton(False).CaptionVisible(False) self._mgr.AddPane(self.sidePanel, pinfo) if len(self.paneHooks) > 0: pinfo.Show() for genFcn in self.paneHooks: genFcn(self.sidePanel) else: pinfo.Hide() self._mgr.Update() self.Refresh() self.Update() def update(self): if not self.updating: self.updating = True #if 'view' in dir(self): # self.view.Refresh() statusText = 'Slice No: (%d/%d) x: %d y: %d' % (self.do.zp, self.do.ds.shape[2], self.do.xp, self.do.yp) #grab status from modules which supply it for sCallback in self.statusHooks: statusText += '\t' + sCallback() #'Frames Analysed: %d Events detected: %d' % (self.vp.do.zp, self.vp.do.ds.shape[2], self.vp.do.xp, self.vp.do.yp, self.LMAnalyser.numAnalysed, self.LMAnalyser.numEvents) self.statusbar.SetStatusText(statusText) #if 'playbackpanel' in dir(self): # self.playbackpanel.update() #update any modules which require it for uCallback in self.updateHooks: #print uCallback uCallback(self) self.updating = False #def Redraw(self): # self.v def DataChanged(self): for uCallback in self.dataChangeHooks: uCallback(self) def OnOpen(self, event=None): ViewIm3D(ImageStack()) def OnSave(self, event=None): self.image.Save() self.SetTitle(self.image.filename) def OnExport(self, event=None): self.image.Save(crop = True, view = self.view) def OnCrop(self): pass #View3D(self.image.data[]) def OnCloseWindow(self, event): pylab.close('all') if (not self.image.saved): dialog = wx.MessageDialog(self, "Save data stack?", "PYME", wx.YES_NO|wx.CANCEL) ans = dialog.ShowModal() if(ans == wx.ID_YES): self.OnSave() self._cleanup() elif (ans == wx.ID_NO): self._cleanup() else: #wxID_CANCEL: if (not event.CanVeto()): self._cleanup() else: event.Veto() else: self._cleanup() def _cleanup(self): self.timer.Stop() #for some reason AUI doesn't clean itself up properly and stops the #window from being garbage collected - fix this here self._mgr.UnInit() self._mgr._frame = None #if self.glCanvas: # self.glCanvas.wantViewChangeNotification.remove(self) self.Destroy() def dsRefresh(self): #zp = self.vp.do.zp #save z -position self.do.SetDataStack(self.image.dataSource) #self.vp.do.zp = zp #restore z position self.elv.SetEventSource(self.image.dataSource.getEvents()) self.elv.SetRange([0, self.image.dataSource.getNumSlices()]) if 'ProtocolFocus' in self.elv.evKeyNames: self.zm = piecewiseMapping.GeneratePMFromEventList(self.elv.eventSource, self.mdh.getEntry('Camera.CycleTime'), self.mdh.getEntry('StartTime'), self.mdh.getEntry('Protocol.PiezoStartPos')) self.elv.SetCharts([('Focus [um]', self.zm, 'ProtocolFocus'),]) self.update()