Package topo :: Package tkgui :: Module projectionpanel
[hide private]
[frames] | no frames]

Source Code for Module topo.tkgui.projectionpanel

  1  """ 
  2  PlotgroupPanels for displaying ProjectionSheet plotgroups. 
  3   
  4  $Id: projectionpanel.py 11310 2010-07-27 16:56:14Z ceball $ 
  5  """ 
  6  __version__='$Revision: 11310 $' 
  7   
  8   
  9  import ImageTk 
 10  ### JCALERT! Try not to have to use chain and delete this import. 
 11  from itertools import chain 
 12  from Tkinter import Canvas 
 13  from numpy import sometrue 
 14   
 15  import param 
 16   
 17  import topo 
 18  from topo.base.cf import CFProjection 
 19  from topo.base.projection import ProjectionSheet, Projection 
 20  from topo.misc.generatorsheet import GeneratorSheet 
 21           
 22  from templateplotgrouppanel import TemplatePlotGroupPanel 
23 24 25 26 -def cmp_projections(p1,p2):
27 """ 28 Comparison function for Plots. 29 It compares the precedence number first and then the src_name and name attributes. 30 """ 31 if p1.src.precedence != p2.src.precedence: 32 return cmp(p1.src.precedence,p2.src.precedence) 33 else: 34 return cmp(p1,p2)
35 36 37 UNIT_PADDING = 1
38 39 40 41 -class ProjectionSheetPanel(TemplatePlotGroupPanel):
42 """ 43 Abstract base class for panels relating to ProjectionSheets. 44 """ 45 __abstract = True 46 47 sheet_type = ProjectionSheet 48 projection_type = Projection 49 50 @classmethod
51 - def valid_context(cls):
52 """ 53 Return True if there is at least one instance of 54 projection_type among all projections in the simulation. 55 """ 56 for p in chain(*[sheet.projections().values() 57 for sheet in topo.sim.objects(cls.sheet_type).values()]): 58 if isinstance(p,cls.projection_type): 59 return True 60 61 return False
62 63
64 - def __init__(self,master,plotgroup,**params):
65 super(ProjectionSheetPanel,self).__init__(master,plotgroup,**params) 66 67 self.plotgroup.auto_refresh=False 68 69 self.pack_param('sheet',parent=self.control_frame_3, 70 on_modify=self.sheet_change,side='left',expand=1, 71 widget_options={'new_default':True, 72 'sort_fn_args':{'cmp':lambda x, y: cmp(-x.precedence,-y.precedence)}})
73 74
75 - def setup_plotgroup(self):
78 79
80 - def sheet_change(self):
81 self.refresh_plots()
82 83
84 - def populate_sheet_param(self):
85 sheets = [s for s in topo.sim.objects(self.sheet_type).values() 86 if sometrue([isinstance(p,self.projection_type) 87 for p in s.in_connections])] 88 self.plotgroup.params()['sheet'].objects = sheets 89 self.plotgroup.sheet = sheets[0] # CB: necessary?
90
91 92 93 -class ProjectionActivityPanel(ProjectionSheetPanel):
94
95 - def __init__(self,master,plotgroup,**params):
96 super(ProjectionActivityPanel,self).__init__(master,plotgroup,**params) 97 self.auto_refresh = True
98
99 - def _plot_title(self):
100 return "Activity in projections to %s at time %s"%(self.plotgroup.sheet.name,topo.sim.timestr(self.plotgroup.time))
101
102 103 104 -class UnitsPanel(ProjectionSheetPanel):
105 106
107 - def __init__(self,master,plotgroup,**params):
108 self.initial_args=params # CEBALERT: store the initial arguments so we can get sheet,x,y in 109 # sheet_change if any of them were specified. Isn't there a cleaner 110 # way? 111 super(UnitsPanel,self).__init__(master,plotgroup,**params) 112 self.pack_param('x',parent=self.control_frame_4,on_set=self.refresh_plots) 113 self.pack_param('y',parent=self.control_frame_4,on_set=self.refresh_plots) 114 self.sheet_change()
115 116 117 ############################################################################## 118 # CEBALERT: 119 # - Need to couple taggedslider to a Number parameter in a better way 120 # somewhere else. 121 # - Clean up or document: passing the params, setting the bounds 122 # 123 # Also: 124 # e.g. bound on parameter is 0.5 but means <0.5, taggedslider 125 # still lets you set to 0.5 -> error 126
127 - def sheet_change(self):
128 # CEBHACKALERT: get an inconsequential but scary 129 # cf-out-of-range error if you e.g. set y < -0.4 on sheet V1 130 # and then change to V2 (which has smaller bounds). 131 # x and y don't seem to be updated in time... 132 #self.x,self.y = 0.0,0.0 133 134 # CEBALERT: need to crop x,y (for e.g. going to smaller sheet) rather 135 # than set to 0 136 137 if 'sheet' in self.initial_args: self.sheet=self.initial_args['sheet'] 138 139 for coord in ['x','y']: 140 self._tkvars[coord].set(self.initial_args.get(coord,0.0)) 141 142 l,b,r,t = self.sheet.bounds.lbrt() 143 # CEBALERT: see "CEBERRORALERT: doesn't take account of 144 # exclusive bounds" in topo/param/__init.__.py. 145 D=0.0000000001 146 bounds = {'x':(l,r-D), 147 'y':(b,t-D)} 148 149 inclusive_bounds = {'x':(True,False), # GUI knows about exclusive sheet bounds 150 'y':(False,True)} 151 152 for coord in ['x','y']: 153 param_obj=self.get_parameter_object(coord) 154 param_obj.bounds = bounds[coord] 155 param_obj.inclusive_bounds = inclusive_bounds[coord] 156 157 # (method can be called before x,y widgets added) 158 if coord in self.representations: 159 w=self.representations[coord]['widget'] 160 w.set_bounds(param_obj.bounds[0],param_obj.bounds[1], 161 inclusive_bounds=param_obj.inclusive_bounds) 162 w.tag_set() 163 164 self.initial_args = {} # reset now we've used them 165 super(UnitsPanel,self).sheet_change()
166 ##############################################################################
167 168 169 -class ConnectionFieldsPanel(UnitsPanel):
170 171 projection_type = CFProjection 172
173 - def __init__(self,master,plotgroup,**params):
174 super(ConnectionFieldsPanel,self).__init__(master,plotgroup,**params) 175 self.pack_param('situate',parent=self.control_frame_3,on_set=self.situate_change,side='left',expand=1)
176
177 - def situate_change(self):
178 self.redraw_plots()
179
180 - def _plot_title(self):
181 return 'Connection Fields of %s unit (%4.3f,%4.3f) at time %s' % \ 182 (self.sheet.name, self.plotgroup.x,self.plotgroup.y, 183 topo.sim.timestr(self.plotgroup.time))
184
185 186 -class PlotMatrixPanel(ProjectionSheetPanel):
187 """ 188 PlotGroupPanel for visualizing an array of bitmaps, such as for 189 a projection involving a matrix of units. 190 """ 191 192 gui_desired_maximum_plot_height = param.Integer(default=5,bounds=(0,None),doc=""" 193 Value to provide for PlotGroup.desired_maximum_plot_height for 194 PlotGroups opened by the GUI. Determines the initial, default 195 scaling for the PlotGroup.""") 196
197 - def sheet_change(self): # don't want to refresh_plots (measure new data) each time
198 self.redraw_plots()
199
200 - def refresh(self,update=True):
201 super(PlotMatrixPanel,self).refresh(update) 202 # take the size of the plot as the desired size 203 self.plotgroup.update_maximum_plot_height() 204 self.desired_maximum_plot_height = self.plotgroup.maximum_plot_height
205 206
207 - def display_plots(self):
208 """ 209 CFProjectionPanel requires a 2D grid of plots. 210 """ 211 plots=self.plotgroup.plots 212 # Generate the zoomed images. 213 self.zoomed_images = [ImageTk.PhotoImage(p.bitmap.image) 214 for p in plots] 215 old_canvases = self.canvases 216 217 self.canvases = [Canvas(self.plot_container, 218 width=image.width(), 219 height=image.height(), 220 borderwidth=1,highlightthickness=0, 221 relief='groove') 222 for image in self.zoomed_images] 223 224 # Lay out images 225 for i,image,canvas in zip(range(len(self.zoomed_images)), 226 self.zoomed_images,self.canvases): 227 canvas.grid(row=i//self.plotgroup.proj_plotting_shape[1], 228 column=i%self.plotgroup.proj_plotting_shape[1], 229 padx=UNIT_PADDING,pady=UNIT_PADDING) 230 canvas.create_image(1,1,anchor='nw',image=image) 231 232 233 # Delete old ones. This may resize the grid. 234 for c in old_canvases: 235 c.grid_forget() 236 237 self._add_canvas_bindings()
238 239
240 - def display_labels(self):
241 """Do not display labels for these plots.""" 242 pass
243
244 245 -class RFProjectionPanel(PlotMatrixPanel):
246 247 sheet_type = ProjectionSheet 248
249 - def __init__(self,master,plotgroup,**params):
250 super(RFProjectionPanel,self).__init__(master,plotgroup,**params) 251 self.pack_param('input_sheet',parent=self.control_frame_3, 252 on_modify=self.redraw_plots,side='left',expand=1) 253 254 self.pack_param('density',parent=self.control_frame_4)
255
256 - def setup_plotgroup(self):
259 264
265 - def _plot_title(self):
266 return 'RFs of %s on %s at time %s'%(self.sheet.name,self.plotgroup.input_sheet.name, 267 topo.sim.timestr(self.plotgroup.time))
268
269 270 -class ProjectionPanel(PlotMatrixPanel):
271 - def __init__(self,master,plotgroup,**params):
272 super(ProjectionPanel,self).__init__(master,plotgroup,**params) 273 self.pack_param('projection',parent=self.control_frame_3, 274 on_modify=self.redraw_plots,side='left',expand=1, 275 widget_options={'sort_fn_args':{'cmp':cmp_projections}, 276 'new_default':True}) 277 278 self.pack_param('density',parent=self.control_frame_4)
279 280
281 - def _plot_title(self):
282 return self.projection.name + ' projection from ' + self.projection.src.name + ' to ' \ 283 + self.sheet.name + ' at time ' + topo.sim.timestr(self.plotgroup.time)
284
285 - def setup_plotgroup(self):
288 289
290 - def sheet_change(self):
291 self.refresh_projections() 292 super(ProjectionPanel,self).sheet_change()
293 294
296 prjns = [proj for proj in self.plotgroup.sheet.projections().values() 297 if isinstance(proj,self.projection_type)] 298 self.plotgroup.params()['projection'].objects = prjns 299 self.plotgroup.projection = prjns[0] # CB: necessary?
300 301
302 - def refresh_projections(self):
303 self.populate_projection_param() 304 305 self.update_selector('projection')
306
307 ## ################# 308 ## # CEBALERT: How do you change list of tkinter.optionmenu options? Use pmw's optionmenu? 309 ## # Or search the web for a way to alter the list in the tkinter one. 310 ## # Currently, replace widget completely: looks bad and is complex. 311 ## # When fixing, remove try/except marked by the 'for projectionpanel' CEBALERT in 312 ## # tkparameterizedobject.py. 313 ## if 'projection' in self.representations: 314 ## w = self.representations['projection']['widget'] 315 ## l = self.representations['projection']['label'] 316 ## l.destroy() 317 ## w.destroy() 318 ## self.pack_param('projection',parent=self.representations['projection']['frame'], 319 ## on_modify=self.refresh_plots,side='left',expand=1, 320 ## widget_options={'sort_fn_args':{'cmp':cmp_projections}, 321 ## 'new_default':True}) 322 ## ################# 323 324 325 326 -class CFProjectionPanel(ProjectionPanel):
327 """ 328 Panel for displaying CFProjections. 329 """ 330 331 projection_type = CFProjection 332
333 - def __init__(self,master,plotgroup,**params):
334 super(CFProjectionPanel,self).__init__(master,plotgroup,**params) 335 self.pack_param('situate',parent=self.control_frame_3,on_set=self.situate_change,side='left',expand=1)
336
337 - def situate_change(self):
338 self.redraw_plots()
339 340 341 342 343 ## Need to add test file: 344 # check projection, sheet ordering 345 # check sheet changes, check projection changes 346