Source code for topo.tkgui.projectionpanel

"""
PlotgroupPanels for displaying ProjectionSheet plotgroups.
"""


import ImageTk
### JCALERT! Try not to have to use chain and delete this import.
from itertools import chain
from Tkinter import Canvas
from numpy import sometrue

import param

import topo
from topo.base.cf import CFProjection
from topo.base.projection import ProjectionSheet, Projection
from topo.base.generatorsheet import GeneratorSheet

from templateplotgrouppanel import SheetPanel



[docs]def cmp_projections(p1,p2): """ Comparison function for Plots. It compares the precedence number first and then the src_name and name attributes. """ if p1.src.precedence != p2.src.precedence: return cmp(p1.src.precedence,p2.src.precedence) else: return cmp(p1,p2)
UNIT_PADDING = 1
[docs]class ProjectionSheetPanel(SheetPanel): """ Abstract base class for panels relating to ProjectionSheets. """ __abstract = True sheet_type = ProjectionSheet projection_type = Projection @classmethod
[docs] def valid_context(cls): """ Return True if there is at least one instance of projection_type among all projections in the simulation. """ for p in chain(*[sheet.projections().values() for sheet in topo.sim.objects(cls.sheet_type).values()]): if isinstance(p,cls.projection_type): return True return False
def __init__(self,master,plotgroup,**params): super(ProjectionSheetPanel,self).__init__(master,plotgroup,**params) self.plotgroup.auto_refresh=False self.pack_param('sheet',parent=self.control_frame_3, on_modify=self.sheet_change,side='left',expand=1, widget_options={'new_default':True, 'sort_fn_args':{'cmp':lambda x, y: cmp(-x.precedence,-y.precedence)}}) def setup_plotgroup(self): super(ProjectionSheetPanel,self).setup_plotgroup() self.populate_sheet_param() self.populate_color_channel_param() def sheet_change(self): self.refresh_plots() def populate_sheet_param(self): sheets = [s for s in topo.sim.objects(self.sheet_type).values() if sometrue([isinstance(p,self.projection_type) for p in s.in_connections])] self.plotgroup.params()['sheet'].objects = sheets self.plotgroup.sheet = sheets[0] # CB: necessary?
class ProjectionActivityPanel(ProjectionSheetPanel): def __init__(self,master,plotgroup,**params): super(ProjectionActivityPanel,self).__init__(master,plotgroup,**params) self.auto_refresh = True def _plot_title(self): return "Activity in projections to %s at time %s"%(self.plotgroup.sheet.name,topo.sim.timestr(self.plotgroup.time)) class UnitsPanel(ProjectionSheetPanel): def __init__(self,master,plotgroup,**params): self.initial_args=params # CEBALERT: store the initial arguments so we can get sheet,x,y in # sheet_change if any of them were specified. Isn't there a cleaner # way? super(UnitsPanel,self).__init__(master,plotgroup,**params) self.pack_param('x',parent=self.control_frame_4,on_set=self.refresh_plots) self.pack_param('y',parent=self.control_frame_4,on_set=self.refresh_plots) self.sheet_change() ############################################################################## # CEBALERT: # - Need to couple taggedslider to a Number parameter in a better way # somewhere else. # - Clean up or document: passing the params, setting the bounds # # Also: # e.g. bound on parameter is 0.5 but means <0.5, taggedslider # still lets you set to 0.5 -> error def sheet_change(self): # CEBHACKALERT: get an inconsequential but scary # cf-out-of-range error if you e.g. set y < -0.4 on sheet V1 # and then change to V2 (which has smaller bounds). # x and y don't seem to be updated in time... #self.x,self.y = 0.0,0.0 # CEBALERT: need to crop x,y (for e.g. going to smaller sheet) rather # than set to 0 if 'sheet' in self.initial_args: self.sheet=self.initial_args['sheet'] for coord in ['x','y']: self._tkvars[coord].set(self.initial_args.get(coord,0.0)) l,b,r,t = self.sheet.bounds.lbrt() # CEBALERT: param.Number's `crop_to_bounds` does not respect exclusive bounds; # see https://github.com/ioam/param/issues/80 D=0.0000000001 bounds = {'x':(l,r-D), 'y':(b,t-D)} inclusive_bounds = {'x':(True,False), # GUI knows about exclusive sheet bounds 'y':(False,True)} for coord in ['x','y']: param_obj=self.get_parameter_object(coord) param_obj.bounds = bounds[coord] param_obj.inclusive_bounds = inclusive_bounds[coord] # (method can be called before x,y widgets added) if coord in self.representations: w=self.representations[coord]['widget'] w.set_bounds(param_obj.bounds[0],param_obj.bounds[1], inclusive_bounds=param_obj.inclusive_bounds) w.tag_set() self.initial_args = {} # reset now we've used them super(UnitsPanel,self).sheet_change() ############################################################################## class ConnectionFieldsPanel(UnitsPanel): projection_type = CFProjection def __init__(self,master,plotgroup,**params): super(ConnectionFieldsPanel,self).__init__(master,plotgroup,**params) self.pack_param('situate',parent=self.control_frame_3,on_set=self.situate_change,side='left',expand=1) def situate_change(self): self.redraw_plots() def _plot_title(self): return 'Connection Fields of %s unit (%4.3f,%4.3f) at time %s' % \ (self.sheet.name, self.plotgroup.x,self.plotgroup.y, topo.sim.timestr(self.plotgroup.time))
[docs]class PlotMatrixPanel(ProjectionSheetPanel): """ PlotGroupPanel for visualizing an array of bitmaps, such as for a projection involving a matrix of units. """ gui_desired_maximum_plot_height = param.Integer(default=5,bounds=(0,None),doc=""" Value to provide for PlotGroup.desired_maximum_plot_height for PlotGroups opened by the GUI. Determines the initial, default scaling for the PlotGroup.""") def sheet_change(self): # don't want to refresh_plots (measure new data) each time self.redraw_plots() def refresh(self,update=True): super(PlotMatrixPanel,self).refresh(update) # take the size of the plot as the desired size self.plotgroup.update_maximum_plot_height() self.desired_maximum_plot_height = self.plotgroup.maximum_plot_height
[docs] def display_plots(self): """ CFProjectionPanel requires a 2D grid of plots. """ plots=self.plotgroup.plots # Generate the zoomed images. self.zoomed_images = [ImageTk.PhotoImage(p.bitmap.image) for p in plots] old_canvases = self.canvases self.canvases = [Canvas(self.plot_container, width=image.width(), height=image.height(), borderwidth=1,highlightthickness=0, relief='groove') for image in self.zoomed_images] # Lay out images for i,image,canvas in zip(range(len(self.zoomed_images)), self.zoomed_images,self.canvases): canvas.grid(row=i//self.plotgroup.proj_plotting_shape[1], column=i%self.plotgroup.proj_plotting_shape[1], padx=UNIT_PADDING,pady=UNIT_PADDING) canvas.create_image(1,1,anchor='nw',image=image) # Delete old ones. This may resize the grid. for c in old_canvases: c.grid_forget() self._add_canvas_bindings()
[docs] def display_labels(self): """Do not display labels for these plots.""" pass
class RFProjectionPanel(PlotMatrixPanel): sheet_type = ProjectionSheet def __init__(self,master,plotgroup,**params): super(RFProjectionPanel,self).__init__(master,plotgroup,**params) self.pack_param('input_sheet',parent=self.control_frame_3, on_modify=self.redraw_plots,side='left',expand=1) self.pack_param('density',parent=self.control_frame_4) def setup_plotgroup(self): super(RFProjectionPanel,self).setup_plotgroup() self.populate_input_sheet_param() def populate_input_sheet_param(self): sheets = topo.sim.objects(GeneratorSheet).values() self.plotgroup.params()['input_sheet'].objects = sheets self.plotgroup.input_sheet=sheets[0] def _plot_title(self): return 'RFs of %s on %s at time %s'%(self.sheet.name,self.plotgroup.input_sheet.name, topo.sim.timestr(self.plotgroup.time)) class ProjectionPanel(PlotMatrixPanel): def __init__(self,master,plotgroup,**params): super(ProjectionPanel,self).__init__(master,plotgroup,**params) self.pack_param('projection',parent=self.control_frame_3, on_modify=self.redraw_plots,side='left',expand=1, widget_options={'sort_fn_args':{'cmp':cmp_projections}, 'new_default':True}) self.pack_param('density',parent=self.control_frame_4) def _plot_title(self): return self.projection.name + ' projection from ' + self.projection.src.name + ' to ' \ + self.sheet.name + ' at time ' + topo.sim.timestr(self.plotgroup.time) def setup_plotgroup(self): super(ProjectionPanel,self).setup_plotgroup() self.populate_projection_param() def sheet_change(self): self.refresh_projections() super(ProjectionPanel,self).sheet_change() def populate_projection_param(self): prjns = [proj for proj in self.plotgroup.sheet.projections().values() if isinstance(proj,self.projection_type)] self.plotgroup.params()['projection'].objects = prjns self.plotgroup.projection = prjns[0] # CB: necessary? def refresh_projections(self): self.populate_projection_param() self.update_selector('projection') ## ################# ## # CEBALERT: How do you change list of tkinter.optionmenu options? Use pmw's optionmenu? ## # Or search the web for a way to alter the list in the tkinter one. ## # Currently, replace widget completely: looks bad and is complex. ## # When fixing, remove try/except marked by the 'for projectionpanel' CEBALERT in ## # tkparameterizedobject.py. ## if 'projection' in self.representations: ## w = self.representations['projection']['widget'] ## l = self.representations['projection']['label'] ## l.destroy() ## w.destroy() ## self.pack_param('projection',parent=self.representations['projection']['frame'], ## on_modify=self.refresh_plots,side='left',expand=1, ## widget_options={'sort_fn_args':{'cmp':cmp_projections}, ## 'new_default':True}) ## #################
[docs]class CFProjectionPanel(ProjectionPanel): """ Panel for displaying CFProjections. """ projection_type = CFProjection def __init__(self,master,plotgroup,**params): super(CFProjectionPanel,self).__init__(master,plotgroup,**params) self.pack_param('situate',parent=self.control_frame_3,on_set=self.situate_change,side='left',expand=1) def situate_change(self): self.redraw_plots() ## Need to add test file: # check projection, sheet ordering # check sheet changes, check projection changes

Table Of Contents

This Page